Skip to content

Instantly share code, notes, and snippets.

@amery
Created August 28, 2012 16:48
Show Gist options
  • Save amery/3500413 to your computer and use it in GitHub Desktop.
Save amery/3500413 to your computer and use it in GitHub Desktop.
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