sh_mobile_meram: Add support for NV24 framebuffers
authorDamian <dhobsong@igel.co.jp>
Wed, 18 May 2011 11:10:08 +0000 (11:10 +0000)
committerPaul Mundt <lethal@linux-sh.org>
Mon, 23 May 2011 07:06:26 +0000 (16:06 +0900)
Since the NV24 framebuffer has a CbCr plane that is twice as wide
as the Y plane, it needs to be handled as a special case.

Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
drivers/video/sh_mobile_lcdcfb.c
drivers/video/sh_mobile_meram.c
include/video/sh_mobile_meram.h

index 3a2cbd1..1c652da 100644 (file)
@@ -627,10 +627,14 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 
                        ch->meram_enabled = 0;
 
-                       if (ch->info->var.nonstd)
-                               pf = SH_MOBILE_MERAM_PF_NV;
-                       else
+                       if (ch->info->var.nonstd) {
+                               if (ch->info->var.bits_per_pixel == 24)
+                                       pf = SH_MOBILE_MERAM_PF_NV24;
+                               else
+                                       pf = SH_MOBILE_MERAM_PF_NV;
+                       } else {
                                pf = SH_MOBILE_MERAM_PF_RGB;
+                       }
 
                        ret = mdev->ops->meram_register(mdev, cfg, pitch,
                                                ch->info->var.yres,
index bd68f3d..9170c82 100644 (file)
@@ -164,6 +164,16 @@ static inline void meram_unmark(struct sh_mobile_meram_priv *priv,
        }
 }
 
+/*
+ * is this a YCbCr(NV12, NV16 or NV24) colorspace
+ */
+static inline int is_nvcolor(int cspace)
+{
+       if (cspace == SH_MOBILE_MERAM_PF_NV ||
+                       cspace == SH_MOBILE_MERAM_PF_NV24)
+               return 1;
+       return 0;
+}
 
 /*
  * set the next address to fetch
@@ -184,7 +194,7 @@ static inline void meram_set_next_addr(struct sh_mobile_meram_priv *priv,
        meram_write_icb(priv->base, cfg->icb[0].marker_icb, target,
                        base_addr_y + cfg->icb[0].cache_unit);
 
-       if (cfg->pixelformat == SH_MOBILE_MERAM_PF_NV) {
+       if (is_nvcolor(cfg->pixelformat)) {
                meram_write_icb(priv->base, cfg->icb[1].cache_icb,  target,
                                base_addr_c);
                meram_write_icb(priv->base, cfg->icb[1].marker_icb, target,
@@ -208,7 +218,7 @@ static inline void meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
                icb_offset = 0xc0000000 | (cfg->current_reg << 23);
 
        *icb_addr_y = icb_offset | (cfg->icb[0].marker_icb << 24);
-       if ((*icb_addr_c) && cfg->pixelformat == SH_MOBILE_MERAM_PF_NV)
+       if ((*icb_addr_c) && is_nvcolor(cfg->pixelformat))
                *icb_addr_c = icb_offset | (cfg->icb[1].marker_icb << 24);
 }
 
@@ -316,6 +326,7 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
                return -EINVAL;
 
        if (pixelformat != SH_MOBILE_MERAM_PF_NV &&
+           pixelformat != SH_MOBILE_MERAM_PF_NV24 &&
            pixelformat != SH_MOBILE_MERAM_PF_RGB)
                return -EINVAL;
 
@@ -366,7 +377,7 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
                n = 2;
        }
 
-       if (pixelformat == SH_MOBILE_MERAM_PF_NV && n != 2) {
+       if (is_nvcolor(pixelformat) && n != 2) {
                dev_err(&pdev->dev, "requires two ICB sets for planar Y/C.");
                error =  -EINVAL;
                goto err;
@@ -375,7 +386,7 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
        /* we now register the ICB */
        cfg->pixelformat = pixelformat;
        meram_mark(priv, &cfg->icb[0]);
-       if (pixelformat == SH_MOBILE_MERAM_PF_NV)
+       if (is_nvcolor(pixelformat))
                meram_mark(priv, &cfg->icb[1]);
 
        /* initialize MERAM */
@@ -384,6 +395,9 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
        if (pixelformat == SH_MOBILE_MERAM_PF_NV)
                meram_init(priv, &cfg->icb[1], xres, (yres + 1) / 2,
                        &out_pitch);
+       else if (pixelformat == SH_MOBILE_MERAM_PF_NV24)
+               meram_init(priv, &cfg->icb[1], 2 * xres, (yres + 1) / 2,
+                       &out_pitch);
 
        cfg->current_reg = 1;
        meram_set_next_addr(priv, cfg, base_addr_y, base_addr_c);
@@ -410,7 +424,7 @@ static int sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata,
        mutex_lock(&priv->lock);
 
        /* deinit & unmark */
-       if (cfg->pixelformat == SH_MOBILE_MERAM_PF_NV) {
+       if (is_nvcolor(cfg->pixelformat)) {
                meram_deinit(priv, &cfg->icb[1]);
                meram_unmark(priv, &cfg->icb[1]);
        }
index 15fbb3d..af602d6 100644 (file)
@@ -9,7 +9,8 @@ enum {
 
 enum {
        SH_MOBILE_MERAM_PF_NV = 0,
-       SH_MOBILE_MERAM_PF_RGB
+       SH_MOBILE_MERAM_PF_RGB,
+       SH_MOBILE_MERAM_PF_NV24
 };