From a77c874f9b85691ea4af5362e2b5c9fc55a76acc Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Wed, 18 Aug 2010 13:22:28 +0200 Subject: MCDE Fixes: Added http://gerrit.lud.stericsson.com/gerrit/#change,3792 patchset Added patch set: http://gerrit.lud.stericsson.com/gerrit/#change,3751 Enabled single buffered fb in config. Change-Id: I59ed2dcd1d45f896177f0f3be425b158f03fd0ee Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/4097 Tested-by: Robert MARKLUND Reviewed-by: Robert ROSENGREN --- arch/arm/mach-ux500/Kconfig-arch | 14 ++ arch/arm/mach-ux500/board-mop500-mcde.c | 144 ++++++++++++++---- drivers/video/av8100/av8100.c | 14 +- drivers/video/av8100/hdmi.c | 13 +- drivers/video/mcde/display-ab8500.c | 1 + drivers/video/mcde/display-av8100.c | 2 + drivers/video/mcde/display-generic_dsi.c | 17 +-- drivers/video/mcde/mcde_display.c | 6 +- drivers/video/mcde/mcde_fb.c | 6 +- drivers/video/mcde/mcde_hw.c | 251 ++++++++++++++++++++++++++----- include/video/mcde.h | 35 ++--- include/video/mcde_fb.h | 1 + kernel.spec | 5 +- 13 files changed, 397 insertions(+), 112 deletions(-) diff --git a/arch/arm/mach-ux500/Kconfig-arch b/arch/arm/mach-ux500/Kconfig-arch index 3e6d35c5c46..8e478c923dd 100755 --- a/arch/arm/mach-ux500/Kconfig-arch +++ b/arch/arm/mach-ux500/Kconfig-arch @@ -55,6 +55,13 @@ config DISPLAY_GENERIC_DSI_PRIMARY_VSYNC help Say yes to enable v-sync for primary display +config DISPLAY_GENERIC_DSI_PRIMARY_AUTO_SYNC + bool "Enable auto sync for primary display" + depends on DISPLAY_GENERIC_DSI_PRIMARY + default n + help + Say yes to enable auto sync for primary display + config DISPLAY_GENERIC_DSI_SECONDARY bool "Sub display support" depends on MACH_U8500_MOP && FB_MCDE @@ -70,6 +77,13 @@ config DISPLAY_GENERIC_DSI_SECONDARY_VSYNC help Say yes to enable v-sync for secondary display +config DISPLAY_GENERIC_DSI_SECONDARY_AUTO_SYNC + bool "Enable auto sync for secondary display" + depends on DISPLAY_GENERIC_DSI_SECONDARY + default n + help + Say yes to enable auto sync for secondary display + config DISPLAY_AB8500_TERTIARY bool "AB8500 TVout display support" depends on MACH_U8500_MOP && !AV8100_SDTV && FB_MCDE diff --git a/arch/arm/mach-ux500/board-mop500-mcde.c b/arch/arm/mach-ux500/board-mop500-mcde.c index eb13cbf9a5e..e8e0acb440b 100644 --- a/arch/arm/mach-ux500/board-mop500-mcde.c +++ b/arch/arm/mach-ux500/board-mop500-mcde.c @@ -21,6 +21,10 @@ #define DSI_UNIT_INTERVAL_1 0x9 #define DSI_UNIT_INTERVAL_2 0x6 +#define PRIMARY_DISPLAY_ID 0 +#define SECONDARY_DISPLAY_ID 1 +#define TERTIARY_DISPLAY_ID 2 + static bool rotate_main = true; static bool display_initialized_during_boot; @@ -54,8 +58,13 @@ static struct mcde_port port0 = { .pixel_format = MCDE_PORTPIXFMT_DSI_24BPP, .ifc = 1, .link = 0, +#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_AUTO_SYNC + .sync_src = MCDE_SYNCSRC_OFF, + .update_auto_trig = true, +#else .sync_src = MCDE_SYNCSRC_BTA, .update_auto_trig = false, +#endif .phy = { .dsi = { .virt_id = 0, @@ -78,7 +87,7 @@ struct mcde_display_generic_platform_data generic_display0_pdata = { struct mcde_display_device generic_display0 = { .name = "mcde_disp_generic", - .id = 0, + .id = PRIMARY_DISPLAY_ID, .port = &port0, .chnl_id = MCDE_CHNL_A, .fifo = MCDE_FIFO_C0, @@ -106,8 +115,13 @@ static struct mcde_port subdisplay_port = { .pixel_format = MCDE_PORTPIXFMT_DSI_24BPP, .ifc = 1, .link = 1, +#ifdef CONFIG_DISPLAY_GENERIC_DSI_SECONDARY_AUTO_SYNC + .sync_src = MCDE_SYNCSRC_OFF, + .update_auto_trig = true, +#else .sync_src = MCDE_SYNCSRC_BTA, .update_auto_trig = false, +#endif .phy = { .dsi = { .virt_id = 0, @@ -131,7 +145,7 @@ static struct mcde_display_generic_platform_data generic_subdisplay_pdata = { static struct mcde_display_device generic_subdisplay = { .name = "mcde_disp_generic_subdisplay", - .id = 1, + .id = SECONDARY_DISPLAY_ID, .port = &subdisplay_port, .chnl_id = MCDE_CHNL_C1, .fifo = MCDE_FIFO_C1, @@ -237,7 +251,7 @@ alt_func_failed: static struct mcde_display_device tvout_ab8500_display = { .name = "mcde_tv_ab8500", - .id = 2, + .id = TERTIARY_DISPLAY_ID, .port = &port_tvout1, .chnl_id = MCDE_CHNL_B, .fifo = MCDE_FIFO_B, @@ -347,7 +361,7 @@ alt_func_failed: static struct mcde_display_device av8100_hdmi = { .name = "av8100_hdmi", - .id = 2, + .id = TERTIARY_DISPLAY_ID, .port = &port2, .chnl_id = MCDE_CHNL_B, .fifo = MCDE_FIFO_B, @@ -376,29 +390,40 @@ static int display_registered_callback(struct notifier_block *nb, { struct mcde_display_device *ddev = dev; u16 width, height; + u16 virtual_width, virtual_height; bool rotate; if (event != MCDE_DSS_EVENT_DISPLAY_REGISTERED) return 0; - if (ddev->id < 0 || ddev->id >= ARRAY_SIZE(fbs)) + if (ddev->id < PRIMARY_DISPLAY_ID || ddev->id >= ARRAY_SIZE(fbs)) return 0; mcde_dss_get_native_resolution(ddev, &width, &height); - rotate = (ddev->id == 0 && rotate_main); - if (rotate) { - u16 tmp = height; - height = width; - width = tmp; - } + rotate = (ddev->id == PRIMARY_DISPLAY_ID && rotate_main); + if (rotate) + swap(width, height); + + virtual_width = width; + virtual_height = height * 2; +#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_AUTO_SYNC + if (ddev->id == PRIMARY_DISPLAY_ID) + virtual_height = height; +#endif + +#ifdef CONFIG_DISPLAY_GENERIC_DSI_SECONDARY_AUTO_SYNC + if (ddev->id == SECONDARY_DISPLAY_ID) + virtual_height = height; +#endif /* Create frame buffer */ fbs[ddev->id] = mcde_fb_create(ddev, width, height, - width, height * 2, + virtual_width, virtual_height, ddev->default_pixel_format, rotate ? FB_ROTATE_CW : FB_ROTATE_UR); + if (IS_ERR(fbs[ddev->id])) pr_warning("Failed to create fb for display %s\n", ddev->name); else @@ -411,6 +436,8 @@ static struct notifier_block display_nb = { .notifier_call = display_registered_callback, }; +#if defined(CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_AUTO_SYNC) || \ + defined(CONFIG_DISPLAY_GENERIC_DSI_SECONDARY_AUTO_SYNC) static int framebuffer_registered_callback(struct notifier_block *nb, unsigned long event, void *data) { @@ -419,28 +446,85 @@ static int framebuffer_registered_callback(struct notifier_block *nb, struct fb_info *info; struct fb_var_screeninfo var; struct fb_fix_screeninfo fix; + struct mcde_fb *mfb; + u8 *addr; + int i; + + if (event != FB_EVENT_FB_REGISTERED) + return 0; + + if (!event_data) + return 0; - if (event == FB_EVENT_FB_REGISTERED && - !display_initialized_during_boot) { - if (event_data) { - u8 *addr; - info = event_data->info; - if (!lock_fb_info(info)) - return -ENODEV; - var = info->var; - fix = info->fix; - addr = ioremap(fix.smem_start, - var.yres_virtual * fix.line_length); - memset(addr, 0x00, - var.yres_virtual * fix.line_length); - var.yoffset = var.yoffset ? 0 : var.yres; - if (info->fbops->fb_pan_display) - ret = info->fbops->fb_pan_display(&var, info); - unlock_fb_info(info); - } + info = event_data->info; + mfb = to_mcde_fb(info); + var = info->var; + fix = info->fix; + addr = ioremap(fix.smem_start, + var.yres_virtual * fix.line_length); + memset(addr, 0x00, + var.yres_virtual * fix.line_length); + /* Apply overlay info */ + for (i = 0; i < mfb->num_ovlys; i++) { + struct mcde_overlay *ovly = mfb->ovlys[i]; + struct mcde_overlay_info ovly_info; + struct mcde_fb *mfb = to_mcde_fb(info); + memset(&ovly_info, 0, sizeof(ovly_info)); + ovly_info.paddr = fix.smem_start + + fix.line_length * var.yoffset; + if (ovly_info.paddr + fix.line_length * var.yres + > fix.smem_start + fix.smem_len) + ovly_info.paddr = fix.smem_start; + ovly_info.fmt = mfb->pix_fmt; + ovly_info.stride = fix.line_length; + ovly_info.w = var.xres; + ovly_info.h = var.yres; + ovly_info.dirty.w = var.xres; + ovly_info.dirty.h = var.yres; + (void) mcde_dss_apply_overlay(ovly, &ovly_info); + ret = mcde_dss_update_overlay(ovly); } + return ret; } +#else +static int framebuffer_registered_callback(struct notifier_block *nb, + unsigned long event, void *data) +{ + int ret = 0; + struct fb_event *event_data = data; + struct fb_info *info; + struct fb_var_screeninfo var; + struct fb_fix_screeninfo fix; + struct mcde_fb *mfb; + u8 *addr; + + if (event != FB_EVENT_FB_REGISTERED) + return 0; + + if (!event_data) + return 0; + + info = event_data->info; + mfb = to_mcde_fb(info); + if (mfb->id == 0 && display_initialized_during_boot) + goto out; + + + var = info->var; + fix = info->fix; + addr = ioremap(fix.smem_start, + var.yres_virtual * fix.line_length); + memset(addr, 0x00, + var.yres_virtual * fix.line_length); + var.yoffset = var.yoffset ? 0 : var.yres; + if (info->fbops->fb_pan_display) + ret = info->fbops->fb_pan_display(&var, info); +out: + return ret; +} +#endif + static struct notifier_block framebuffer_nb = { .notifier_call = framebuffer_registered_callback, diff --git a/drivers/video/av8100/av8100.c b/drivers/video/av8100/av8100.c index e4df11441a1..47e3c633deb 100644 --- a/drivers/video/av8100/av8100.c +++ b/drivers/video/av8100/av8100.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "av8100_regs.h" #include