summaryrefslogtreecommitdiff
path: root/drivers/video/mcde
diff options
context:
space:
mode:
authorPhilippe Langlais <philippe.langlais@linaro.org>2011-05-11 10:04:48 +0200
committerPhilippe Langlais <philippe.langlais@stericsson.com>2011-12-06 10:58:45 +0100
commitdc65db3632b2a9168e3145e51bfeeeb9ec3287d6 (patch)
tree2702232d9187be293619e390589c2cc5d6447f4d /drivers/video/mcde
parentdb1da30923d823134c460d7f7ba846992580c309 (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
Diffstat (limited to 'drivers/video/mcde')
-rw-r--r--drivers/video/mcde/mcde_display.c8
-rw-r--r--drivers/video/mcde/mcde_dss.c5
-rw-r--r--drivers/video/mcde/mcde_fb.c5
-rw-r--r--drivers/video/mcde/mcde_hw.c29
4 files changed, 29 insertions, 18 deletions
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);