Created
August 28, 2012 16:48
-
-
Save amery/3500413 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 0a1e4e50023066f4a0615a4c9bdec248e06ba9f5 Mon Sep 17 00:00:00 2001 | |
From: Jari Helaakoski <tekkuli@gmail.com> | |
Date: Sun, 19 Aug 2012 20:02:59 +0300 | |
Subject: [PATCH] sun4i: disp: initial Fbcon support | |
--- | |
arch/arm/configs/sun4i_defconfig | 13 ++- | |
drivers/video/Kconfig | 3 + | |
drivers/video/sun4i/disp/dev_disp.h | 1 + | |
drivers/video/sun4i/disp/dev_fb.c | 152 ++++++++++++++++++++--------------- | |
4 files changed, 100 insertions(+), 69 deletions(-) | |
diff --git a/arch/arm/configs/sun4i_defconfig b/arch/arm/configs/sun4i_defconfig | |
index 8824667..f5b9a376 100644 | |
--- a/arch/arm/configs/sun4i_defconfig | |
+++ b/arch/arm/configs/sun4i_defconfig | |
@@ -1194,9 +1194,9 @@ CONFIG_FB=y | |
# CONFIG_FIRMWARE_EDID is not set | |
# CONFIG_FB_DDC is not set | |
# CONFIG_FB_BOOT_VESA_SUPPORT is not set | |
-# CONFIG_FB_CFB_FILLRECT is not set | |
-# CONFIG_FB_CFB_COPYAREA is not set | |
-# CONFIG_FB_CFB_IMAGEBLIT is not set | |
+CONFIG_FB_CFB_FILLRECT=y | |
+CONFIG_FB_CFB_COPYAREA=y | |
+CONFIG_FB_CFB_IMAGEBLIT=y | |
# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set | |
# CONFIG_FB_SYS_FILLRECT is not set | |
# CONFIG_FB_SYS_COPYAREA is not set | |
@@ -1235,7 +1235,12 @@ CONFIG_LYCHEE_HDMI_SUN4I=m | |
# Console display driver support | |
# | |
CONFIG_DUMMY_CONSOLE=y | |
-# CONFIG_FRAMEBUFFER_CONSOLE is not set | |
+CONFIG_FRAMEBUFFER_CONSOLE=y | |
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set | |
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set | |
+# CONFIG_FONTS is not set | |
+CONFIG_FONT_8x8=y | |
+CONFIG_FONT_8x16=y | |
# CONFIG_LOGO is not set | |
CONFIG_SOUND=y | |
# CONFIG_SOUND_OSS_CORE is not set | |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig | |
index ac1c4f1..5e25b5c 100755 | |
--- a/drivers/video/Kconfig | |
+++ b/drivers/video/Kconfig | |
@@ -278,6 +278,9 @@ config LYCHEE_HDMI_SUN3I | |
config LYCHEE_FB_SUN4I | |
tristate "DISP Driver Support(sun4i)" | |
depends on FB && ARCH_SUN4I | |
+ select FB_CFB_FILLRECT | |
+ select FB_CFB_COPYAREA | |
+ select FB_CFB_IMAGEBLIT | |
---help--- | |
default m | |
diff --git a/drivers/video/sun4i/disp/dev_disp.h b/drivers/video/sun4i/disp/dev_disp.h | |
index cc75f2e..56ac351 100644 | |
--- a/drivers/video/sun4i/disp/dev_disp.h | |
+++ b/drivers/video/sun4i/disp/dev_disp.h | |
@@ -66,6 +66,7 @@ typedef struct | |
__disp_fb_create_para_t fb_para[FB_MAX]; | |
wait_queue_head_t wait[2]; | |
unsigned long wait_count[2]; | |
+ __u32 pseudo_palette [FB_MAX][16]; | |
}fb_info_t; | |
typedef struct | |
diff --git a/drivers/video/sun4i/disp/dev_fb.c b/drivers/video/sun4i/disp/dev_fb.c | |
index cfba27e..7f46887 100755 | |
--- a/drivers/video/sun4i/disp/dev_fb.c | |
+++ b/drivers/video/sun4i/disp/dev_fb.c | |
@@ -23,6 +23,9 @@ | |
#include "drv_disp_i.h" | |
#include "dev_disp.h" | |
+#include <linux/module.h> | |
+#include <linux/kernel.h> | |
+#include <linux/fb.h> | |
#ifdef CONFIG_LYCHEE_FB_UMP_SUN4I | |
#include <ump/ump_kernel_interface.h> | |
@@ -706,13 +709,20 @@ __s32 var_to_disp_fb(__disp_fb_t *fb, struct fb_var_screeninfo *var, struct fb_f | |
var->red.length = 8; | |
var->green.length = 8; | |
var->blue.length = 8; | |
- var->reserved[1] = DISP_FORMAT_ARGB8888; | |
+ if (var->transp.offset == var->blue.offset || | |
+ var->transp.offset == var->red.offset) { | |
+ var->reserved[1] = DISP_FORMAT_ARGB888; | |
+ __inf("Mode: ARGB888"); | |
+ } else { | |
+ var->reserved[1] = DISP_FORMAT_ARGB8888; | |
+ __inf("Mode: ARGB8888"); | |
+ } | |
if(var->red.offset == 16 && var->green.offset == 8 && var->blue.offset == 0)//argb | |
{ | |
var->reserved[2] = DISP_SEQ_ARGB; | |
var->reserved[3] = 0; | |
- } | |
+ } | |
else if(var->blue.offset == 24 && var->green.offset == 16 && var->red.offset == 8)//bgra | |
{ | |
var->reserved[2] = DISP_SEQ_BGRA; | |
@@ -833,6 +843,20 @@ static int Fb_pan_display(struct fb_var_screeninfo *var,struct fb_info *info) | |
static int Fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)//todo | |
{ | |
+ __inf("Fb_check_var: %dx%d %dbits\n", var->xres, var->yres, var->bits_per_pixel); | |
+ switch (var->bits_per_pixel) { | |
+ case 16: | |
+ disp_fb_to_var(DISP_FORMAT_ARGB1555, DISP_SEQ_ARGB, 0, var); | |
+ break; | |
+ case 24: | |
+ disp_fb_to_var(DISP_FORMAT_RGB888, DISP_SEQ_ARGB, 0, var); | |
+ break; | |
+ case 32: | |
+ disp_fb_to_var(DISP_FORMAT_ARGB8888, DISP_SEQ_ARGB, 0, var); | |
+ break; | |
+ default: | |
+ return -EINVAL; | |
+ } | |
return 0; | |
} | |
@@ -880,78 +904,64 @@ static int Fb_set_par(struct fb_info *info)//todo | |
return 0; | |
} | |
+static inline u32 convert_bitfield(int val, struct fb_bitfield *bf) | |
+{ | |
+ u32 mask = ((1 << bf->length) - 1) << bf->offset; | |
+ return (val << bf->offset) & mask; | |
+} | |
static int Fb_setcolreg(unsigned regno,unsigned red, unsigned green, unsigned blue,unsigned transp, struct fb_info *info) | |
{ | |
__u32 sel = 0; | |
- | |
- __inf("Fb_setcolreg,regno=%d,a=%d,r=%d,g=%d,b=%d\n",regno, transp,red, green, blue); | |
+ __inf("Fb_setcolreg,regno=%2d,a=%2X,r=%2X,g=%2X,b=%2X\n",regno, transp,red, green, blue); | |
- for(sel = 0; sel < 2; sel++) | |
- { | |
- if(((sel==0) && (g_fbi.fb_mode[info->node] != FB_MODE_SCREEN1)) | |
- || ((sel==1) && (g_fbi.fb_mode[info->node] != FB_MODE_SCREEN0))) | |
- { | |
- unsigned int val; | |
+ unsigned int val; | |
- switch (info->fix.visual) | |
- { | |
- case FB_VISUAL_PSEUDOCOLOR: | |
- if (regno < 256) | |
- { | |
- val = (transp<<24) | (red<<16) | (green<<8) | blue; | |
- BSP_disp_set_palette_table(sel, &val, regno*4, 4); | |
- } | |
- break; | |
- | |
- default: | |
- break; | |
- } | |
- } | |
+ if (info->fix.visual != FB_VISUAL_TRUECOLOR) | |
+ return -EINVAL; | |
+ | |
+ | |
+ if (regno < 16) { | |
+ val = (convert_bitfield(transp, &info->var.transp) | | |
+ convert_bitfield(red, &info->var.red) | | |
+ convert_bitfield(green, &info->var.green) | | |
+ convert_bitfield(blue, &info->var.blue)); | |
+ | |
+ ((u32 *)info->pseudo_palette)[regno] = val; | |
} | |
+ val = (transp<<24) | (red<<16) | (green<<8) | blue; | |
+ BSP_disp_set_palette_table(sel, &val, regno*4, 4); | |
+ | |
return 0; | |
} | |
static int Fb_setcmap(struct fb_cmap *cmap, struct fb_info *info) | |
{ | |
- __u32 sel = 0; | |
- | |
- __inf("Fb_setcmap\n"); | |
- | |
- for(sel = 0; sel < 2; sel++) | |
- { | |
- if(((sel==0) && (g_fbi.fb_mode[info->node] != FB_MODE_SCREEN1)) | |
- || ((sel==1) && (g_fbi.fb_mode[info->node] != FB_MODE_SCREEN0))) | |
- { | |
- unsigned int j = 0, val = 0; | |
- unsigned char hred, hgreen, hblue, htransp = 0xff; | |
- unsigned short *red, *green, *blue, *transp; | |
- | |
- red = cmap->red; | |
- green = cmap->green; | |
- blue = cmap->blue; | |
- transp = cmap->transp; | |
- | |
- for (j = 0; j < cmap->len; j++) | |
- { | |
- hred = (*red++)&0xff; | |
- hgreen = (*green++)&0xff; | |
- hblue = (*blue++)&0xff; | |
- if (transp) | |
- { | |
- htransp = (*transp++)&0xff; | |
- } | |
- else | |
- { | |
- htransp = 0xff; | |
- } | |
- | |
- val = (htransp<<24) | (hred<<16) | (hgreen<<8) |hblue; | |
- BSP_disp_set_palette_table(sel, &val, (cmap->start + j) * 4, 4); | |
- } | |
- } | |
+ __inf("Fb_setcmap, cmap start:%d len:%d, %dbpp\n", cmap->start, cmap->len, info->var.bits_per_pixel); | |
+ unsigned int j, r = 0; | |
+ unsigned char hred, hgreen, hblue, htransp = 0xff; | |
+ unsigned short *red, *green, *blue, *transp; | |
+ | |
+ red = cmap->red; | |
+ green = cmap->green; | |
+ blue = cmap->blue; | |
+ transp = cmap->transp; | |
+ | |
+ for (j = 0; j < cmap->len; j++) { | |
+ hred = *red++; | |
+ hgreen = *green++; | |
+ hblue = *blue++; | |
+ if (transp) | |
+ htransp = (*transp++)&0xff; | |
+ else | |
+ htransp = 0xff; | |
+ | |
+ r = Fb_setcolreg(cmap->start + j, hred, hgreen, hblue, htransp, info); | |
+ if (r) | |
+ return r; | |
} | |
+ | |
return 0; | |
} | |
@@ -984,9 +994,7 @@ int Fb_blank(int blank_mode, struct fb_info *info) | |
static int Fb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |
{ | |
- __inf("Fb_cursor\n"); | |
- | |
- return 0; | |
+ return -EINVAL; | |
} | |
static int Fb_wait_for_vsync(struct fb_info *info) | |
@@ -1127,6 +1135,9 @@ static struct fb_ops dispfb_ops = | |
.fb_setcolreg = Fb_setcolreg, | |
.fb_setcmap = Fb_setcmap, | |
.fb_blank = Fb_blank, | |
+ .fb_fillrect = cfb_fillrect, | |
+ .fb_copyarea = cfb_copyarea, | |
+ .fb_imageblit = cfb_imageblit, | |
.fb_cursor = Fb_cursor, | |
}; | |
@@ -1273,8 +1284,8 @@ __s32 Display_Fb_Release(__u32 fb_id) | |
memset(&g_fbi.fb_para[fb_id], 0, sizeof(__disp_fb_create_para_t)); | |
g_fbi.fb_enable[fb_id] = 0; | |
+ fb_dealloc_cmap(&info->cmap); | |
Fb_unmap_video_memory(info); | |
- | |
return DIS_SUCCESS; | |
} | |
else | |
@@ -1369,6 +1380,7 @@ __s32 Fb_Init(__u32 from) | |
g_fbi.fbinfo[i]->var.xres_virtual = 800; | |
g_fbi.fbinfo[i]->var.yres_virtual = 480*2; | |
g_fbi.fbinfo[i]->var.nonstd = 0; | |
+ g_fbi.fbinfo[i]->var.grayscale = 0; | |
g_fbi.fbinfo[i]->var.bits_per_pixel = 32; | |
g_fbi.fbinfo[i]->var.transp.length = 8; | |
g_fbi.fbinfo[i]->var.red.length = 8; | |
@@ -1389,9 +1401,15 @@ __s32 Fb_Init(__u32 from) | |
g_fbi.fbinfo[i]->fix.line_length = g_fbi.fbinfo[i]->var.xres_virtual * 4; | |
g_fbi.fbinfo[i]->fix.smem_len = g_fbi.fbinfo[i]->fix.line_length * g_fbi.fbinfo[i]->var.yres_virtual * 2; | |
g_fbi.fbinfo[i]->screen_base = 0x0; | |
+ g_fbi.fbinfo[i]->pseudo_palette = g_fbi.pseudo_palette[i]; | |
g_fbi.fbinfo[i]->fix.smem_start = 0x0; | |
+ g_fbi.fbinfo[i]->fix.mmio_start = 0; | |
+ g_fbi.fbinfo[i]->fix.mmio_len = 0; | |
+ | |
+ if (fb_alloc_cmap(&g_fbi.fbinfo[i]->cmap, 256, 1) < 0) { | |
+ return -ENOMEM; | |
+ } | |
- register_framebuffer(g_fbi.fbinfo[i]); | |
} | |
parser_disp_init_para(&(g_fbi.disp_init)); | |
} | |
@@ -1508,6 +1526,10 @@ __s32 Fb_Init(__u32 from) | |
//fb_draw_colorbar((__u32)g_fbi.fbinfo[i]->screen_base, fb_para.width, fb_para.height*fb_para.buffer_num, &(g_fbi.fbinfo[i]->var)); | |
} | |
+ for(i=0; i<8; i++) { | |
+ /* Register framebuffers after they are initialized */ | |
+ register_framebuffer(g_fbi.fbinfo[i]); | |
+ } | |
if(g_fbi.disp_init.scaler_mode[0]) | |
{ | |
-- | |
1.7.10 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment