diff options
author | Philippe Langlais <philippe.langlais@linaro.org> | 2011-05-11 10:04:48 +0200 |
---|---|---|
committer | Henrik Aberg <henrik.aberg@stericsson.com> | 2011-05-18 09:40:12 +0200 |
commit | 428e324db4b71e5e85b74fb9c5c1a5851c5b7c55 (patch) | |
tree | 2c2213cbd9218d3c0a37575e47d239d405ba3366 | |
parent | f123fcd6bcd2033cb1c96eedacbaf765957fd6b6 (diff) |
video: mcde: Add tripple buffer support
This patch adds tripple buffer support to the mcde
driver. Useful for video mode devices (e.g. HDMI)
where a missed v-sync leads to half frame rate
(the client has to wait for the next v-sync).
Tripple buffering solves this problem since there
are two back buffers the client can use.
Tripple buffering for HDMI is activated in
menuconfig by enabling:
System Type -> Display selection -> Enable tripple
buffer for HDMI display
ST-Ericsson ID: 335004
ST-Ericsson Linux next: Not tested, ER 282779
ST-Ericsson FOSS-OUT ID: Trivial
Change-Id: Ice1f936a8a00e2fbc8fdf7e8c6621c539efe0ac4
Signed-off-by: Jimmy Rubin <jimmy.rubin@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/21839
Reviewed-by: QATOOLS
Reviewed-by: Per PERSSON <per.xb.persson@stericsson.com>
Reviewed-by: QATEST
Reviewed-by: Marcel TUNNISSEN <marcel.tuennissen@stericsson.com>
Conflicts:
arch/arm/configs/u8500_defconfig
drivers/misc/dispdev/dispdev.c
-rw-r--r-- | arch/arm/mach-ux500/Kconfig-arch | 6 | ||||
-rw-r--r-- | arch/arm/mach-ux500/board-mop500-mcde.c | 6 | ||||
-rw-r--r-- | drivers/video/mcde/mcde_display.c | 8 | ||||
-rw-r--r-- | drivers/video/mcde/mcde_dss.c | 5 | ||||
-rw-r--r-- | drivers/video/mcde/mcde_fb.c | 5 | ||||
-rw-r--r-- | drivers/video/mcde/mcde_hw.c | 29 | ||||
-rw-r--r-- | include/video/mcde.h | 3 | ||||
-rw-r--r-- | include/video/mcde_display.h | 2 | ||||
-rw-r--r-- | include/video/mcde_dss.h | 2 |
9 files changed, 45 insertions, 21 deletions
diff --git a/arch/arm/mach-ux500/Kconfig-arch b/arch/arm/mach-ux500/Kconfig-arch index cfdf0ea1265..d16bf788392 100644 --- a/arch/arm/mach-ux500/Kconfig-arch +++ b/arch/arm/mach-ux500/Kconfig-arch @@ -143,6 +143,12 @@ config DISPLAY_AV8100_TERTIARY help Say yes here if HDMI output support +config DISPLAY_AV8100_TRIPPLE_BUFFER + bool "Enable tripple buffer for HDMI display" + depends on DISPLAY_AV8100_TERTIARY + help + Say yes to enable tripple buffer. You'll get double buffer otherwise + endmenu endif diff --git a/arch/arm/mach-ux500/board-mop500-mcde.c b/arch/arm/mach-ux500/board-mop500-mcde.c index bc7d596d88f..edf603dd0ce 100644 --- a/arch/arm/mach-ux500/board-mop500-mcde.c +++ b/arch/arm/mach-ux500/board-mop500-mcde.c @@ -462,6 +462,7 @@ static int display_postregistered_callback(struct notifier_block *nb, virtual_width = width; virtual_height = height * 2; + #ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_AUTO_SYNC if (ddev->id == PRIMARY_DISPLAY_ID) virtual_height = height; @@ -472,6 +473,11 @@ static int display_postregistered_callback(struct notifier_block *nb, virtual_height = height; #endif +#ifdef CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER + if (ddev->id == TERTIARY_DISPLAY_ID) + virtual_height = height * 3; +#endif + if (ddev->id == TERTIARY_DISPLAY_ID) { #ifdef CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE hdmi_fb_onoff(ddev, 1, 0, 0); diff --git a/drivers/video/mcde/mcde_display.c b/drivers/video/mcde/mcde_display.c index 521446dc26f..144a1a67d02 100644 --- a/drivers/video/mcde/mcde_display.c +++ b/drivers/video/mcde/mcde_display.c @@ -328,9 +328,10 @@ static int mcde_display_invalidate_area_default( return 0; } -static int mcde_display_update_default(struct mcde_display_device *ddev) +static int mcde_display_update_default(struct mcde_display_device *ddev, + bool tripple_buffer) { - int ret; + int ret = 0; /* TODO: Dirty */ if (ddev->prepare_for_update) { @@ -344,7 +345,8 @@ static int mcde_display_update_default(struct mcde_display_device *ddev) } } /* TODO: Calculate & set update rect */ - ret = mcde_chnl_update(ddev->chnl_state, &ddev->update_area); + ret = mcde_chnl_update(ddev->chnl_state, &ddev->update_area, + tripple_buffer); if (ret < 0) { dev_warn(&ddev->dev, "%s:Failed to update channel\n", __func__); return ret; diff --git a/drivers/video/mcde/mcde_dss.c b/drivers/video/mcde/mcde_dss.c index a53040f48e1..361510b46fc 100644 --- a/drivers/video/mcde/mcde_dss.c +++ b/drivers/video/mcde/mcde_dss.c @@ -242,10 +242,9 @@ void mcde_dss_disable_overlay(struct mcde_overlay *ovly) } EXPORT_SYMBOL(mcde_dss_disable_overlay); -int mcde_dss_update_overlay(struct mcde_overlay *ovly) +int mcde_dss_update_overlay(struct mcde_overlay *ovly, bool tripple_buffer) { int ret; - dev_vdbg(&ovly->ddev->dev, "Overlay update, chnl=%d\n", ovly->ddev->chnl_id); @@ -256,7 +255,7 @@ int mcde_dss_update_overlay(struct mcde_overlay *ovly) if (ovly->ddev->get_power_mode(ovly->ddev) == MCDE_DISPLAY_PM_OFF) return 0; - ret = ovly->ddev->update(ovly->ddev); + ret = ovly->ddev->update(ovly->ddev, tripple_buffer); if (ret) return ret; diff --git a/drivers/video/mcde/mcde_fb.c b/drivers/video/mcde/mcde_fb.c index 039a60ad05c..dc0812761c7 100644 --- a/drivers/video/mcde/mcde_fb.c +++ b/drivers/video/mcde/mcde_fb.c @@ -507,10 +507,13 @@ static int apply_var(struct fb_info *fbi, struct mcde_display_device *ddev) for (i = 0; i < mfb->num_ovlys; i++) { struct mcde_overlay *ovly = mfb->ovlys[i]; struct mcde_overlay_info info; + int num_buffers; get_ovly_info(fbi, ovly, &info); (void) mcde_dss_apply_overlay(ovly, &info); - ret = mcde_dss_update_overlay(ovly); + + num_buffers = var->yres_virtual / var->yres; + mcde_dss_update_overlay(ovly, num_buffers == 3); } return 0; diff --git a/drivers/video/mcde/mcde_hw.c b/drivers/video/mcde/mcde_hw.c index 7a0208df66e..9844dc1b2f7 100644 --- a/drivers/video/mcde/mcde_hw.c +++ b/drivers/video/mcde/mcde_hw.c @@ -964,18 +964,19 @@ static irqreturn_t mcde_irq_handler(int irq, void *dev) static void wait_for_channel(struct mcde_chnl_state *chnl) { int ret; + u32 id = chnl->transactionid_regs; - if (chnl->transactionid_hw >= chnl->transactionid_regs) + if (chnl->transactionid_hw >= id) return; ret = wait_event_timeout(chnl->waitq_hw, - chnl->transactionid_hw == chnl->transactionid_regs, + chnl->transactionid_hw == id, msecs_to_jiffies(CHNL_TIMEOUT)); if (!ret) dev_warn(&mcde_dev->dev, "Wait for channel timeout (chnl=%d,%d<%d)!\n", chnl->id, chnl->transactionid_hw, - chnl->transactionid_regs); + id); } static int update_channel_static_registers(struct mcde_chnl_state *chnl) @@ -2318,12 +2319,14 @@ static void chnl_update_registers(struct mcde_chnl_state *chnl) chnl->transactionid_regs = chnl->transactionid; } -static void chnl_update_continous(struct mcde_chnl_state *chnl) +static void chnl_update_continous(struct mcde_chnl_state *chnl, + bool tripple_buffer) { if (chnl->continous_running) { chnl->transactionid_regs = chnl->transactionid; - wait_for_channel(chnl); + if (!tripple_buffer) + wait_for_channel(chnl); } if (!chnl->continous_running) { @@ -2410,7 +2413,8 @@ static void chnl_update_overlay(struct mcde_chnl_state *chnl, } static int _mcde_chnl_update(struct mcde_chnl_state *chnl, - struct mcde_rectangle *update_area) + struct mcde_rectangle *update_area, + bool tripple_buffer) { dev_vdbg(&mcde_dev->dev, "%s\n", __func__); @@ -2420,6 +2424,9 @@ static int _mcde_chnl_update(struct mcde_chnl_state *chnl, return -EINVAL; } + if (chnl->port.update_auto_trig && tripple_buffer) + wait_for_channel(chnl); + chnl->regs.x = update_area->x; chnl->regs.y = update_area->y; /* TODO Crop against video_mode.xres and video_mode.yres */ @@ -2439,7 +2446,7 @@ static int _mcde_chnl_update(struct mcde_chnl_state *chnl, chnl_update_overlay(chnl, chnl->ovly1); if (chnl->port.update_auto_trig) - chnl_update_continous(chnl); + chnl_update_continous(chnl, tripple_buffer); else chnl_update_non_continous(chnl); @@ -2608,10 +2615,10 @@ int mcde_chnl_apply(struct mcde_chnl_state *chnl) } int mcde_chnl_update(struct mcde_chnl_state *chnl, - struct mcde_rectangle *update_area) + struct mcde_rectangle *update_area, + bool tripple_buffer) { int ret; - dev_vdbg(&mcde_dev->dev, "%s\n", __func__); if (!chnl->reserved) @@ -2623,7 +2630,6 @@ int mcde_chnl_update(struct mcde_chnl_state *chnl, (void)update_channel_static_registers(chnl); if (chnl->regs.roten && !chnl->esram_is_enabled) { - int ret; ret = regulator_enable(chnl->port.reg_esram); if (ret < 0) { dev_warn(&mcde_dev->dev, "%s: disable failed\n", @@ -2632,7 +2638,8 @@ int mcde_chnl_update(struct mcde_chnl_state *chnl, chnl->esram_is_enabled = true; } - ret = _mcde_chnl_update(chnl, update_area); + ret = _mcde_chnl_update(chnl, update_area, tripple_buffer); + mutex_unlock(&mcde_hw_lock); dev_vdbg(&mcde_dev->dev, "%s exit with ret %d\n", __func__, ret); diff --git a/include/video/mcde.h b/include/video/mcde.h index ef828f0d560..4803779b36f 100644 --- a/include/video/mcde.h +++ b/include/video/mcde.h @@ -332,7 +332,8 @@ int mcde_chnl_set_power_mode(struct mcde_chnl_state *chnl, int mcde_chnl_apply(struct mcde_chnl_state *chnl); int mcde_chnl_update(struct mcde_chnl_state *chnl, - struct mcde_rectangle *update_area); + struct mcde_rectangle *update_area, + bool tripple_buffer); void mcde_chnl_put(struct mcde_chnl_state *chnl); void mcde_chnl_stop_flow(struct mcde_chnl_state *chnl); diff --git a/include/video/mcde_display.h b/include/video/mcde_display.h index 69ff1de4ef2..524e62904fc 100644 --- a/include/video/mcde_display.h +++ b/include/video/mcde_display.h @@ -97,7 +97,7 @@ struct mcde_display_device { int (*apply_config)(struct mcde_display_device *dev); int (*invalidate_area)(struct mcde_display_device *dev, struct mcde_rectangle *area); - int (*update)(struct mcde_display_device *dev); + int (*update)(struct mcde_display_device *dev, bool tripple_buffer); int (*prepare_for_update)(struct mcde_display_device *dev, u16 x, u16 y, u16 w, u16 h); int (*on_first_update)(struct mcde_display_device *dev); diff --git a/include/video/mcde_dss.h b/include/video/mcde_dss.h index 6a149a5dee6..c2603b87235 100644 --- a/include/video/mcde_dss.h +++ b/include/video/mcde_dss.h @@ -30,7 +30,7 @@ int mcde_dss_enable_overlay(struct mcde_overlay *ovl); void mcde_dss_disable_overlay(struct mcde_overlay *ovl); int mcde_dss_apply_overlay(struct mcde_overlay *ovl, struct mcde_overlay_info *info); -int mcde_dss_update_overlay(struct mcde_overlay *ovl); +int mcde_dss_update_overlay(struct mcde_overlay *ovl, bool tripple_buffer); void mcde_dss_get_native_resolution(struct mcde_display_device *ddev, u16 *x_res, u16 *y_res); |