DSS2: OMAPFB: remove fb clearing code
[pandora-kernel.git] / drivers / video / omap2 / omapfb / omapfb-main.c
index 852abe5..76e7c6c 100644 (file)
@@ -176,15 +176,9 @@ static unsigned omapfb_get_vrfb_offset(struct omapfb_info *ofbi, int rot)
 
 static u32 omapfb_get_region_rot_paddr(struct omapfb_info *ofbi)
 {
-       if (ofbi->rotation_type == OMAPFB_ROT_VRFB) {
-               unsigned offset;
-               int rot;
-
-               rot = ofbi->rotation;
-
-               offset = omapfb_get_vrfb_offset(ofbi, rot);
-
-               return ofbi->region.vrfb.paddr[rot] + offset;
+       if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+               return ofbi->region.vrfb.paddr[ofbi->rotation]
+                       + omapfb_get_vrfb_offset(ofbi, ofbi->rotation);
        } else {
                return ofbi->region.paddr;
        }
@@ -192,7 +186,7 @@ static u32 omapfb_get_region_rot_paddr(struct omapfb_info *ofbi)
 
 u32 omapfb_get_region_paddr(struct omapfb_info *ofbi)
 {
-       if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
+       if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
                return ofbi->region.vrfb.paddr[0];
        else
                return ofbi->region.paddr;
@@ -200,7 +194,7 @@ u32 omapfb_get_region_paddr(struct omapfb_info *ofbi)
 
 void __iomem *omapfb_get_region_vaddr(struct omapfb_info *ofbi)
 {
-       if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
+       if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
                return ofbi->region.vrfb.vaddr[0];
        else
                return ofbi->region.vaddr;
@@ -370,6 +364,21 @@ static enum omap_color_mode fb_mode_to_dss_mode(struct fb_var_screeninfo *var)
        return -EINVAL;
 }
 
+static int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
+                              struct fb_var_screeninfo *var)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
+               struct omapfb_colormode *mode = &omapfb_colormodes[i];
+               if (dssmode == mode->dssmode) {
+                       assign_colormode_to_var(var, mode);
+                       return 0;
+               }
+       }
+       return -ENOENT;
+}
+
 void set_fb_fix(struct fb_info *fbi)
 {
        struct fb_fix_screeninfo *fix = &fbi->fix;
@@ -383,10 +392,19 @@ void set_fb_fix(struct fb_info *fbi)
        fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi);
 
        /* used by mmap in fbmem.c */
-       if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
-               fix->line_length =
-                       (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
-       else
+       if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+               switch (var->nonstd) {
+               case OMAPFB_COLOR_YUV422:
+               case OMAPFB_COLOR_YUY422:
+                       fix->line_length =
+                               (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
+                       break;
+               default:
+                       fix->line_length =
+                               (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
+                       break;
+               }
+       } else
                fix->line_length =
                        (var->xres_virtual * var->bits_per_pixel) >> 3;
        fix->smem_start = omapfb_get_region_paddr(ofbi);
@@ -419,11 +437,14 @@ void set_fb_fix(struct fb_info *fbi)
        fix->xpanstep = 1;
        fix->ypanstep = 1;
 
-       if (rg->size) {
-               if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
-                       omap_vrfb_setup(&rg->vrfb, rg->paddr,
-                                       var->xres_virtual, var->yres_virtual,
-                                       var->bits_per_pixel >> 3);
+       if (rg->size && ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+               enum omap_color_mode mode = 0;
+               mode = fb_mode_to_dss_mode(var);
+
+               omap_vrfb_setup(&rg->vrfb, rg->paddr,
+                               var->xres_virtual,
+                               var->yres_virtual,
+                               mode);
        }
 }
 
@@ -512,7 +533,7 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
        if (var->yres > var->yres_virtual)
                var->yres = var->yres_virtual;
 
-       if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
+       if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
                line_size = OMAP_VRFB_LINE_LEN * bytespp;
        else
                line_size = var->xres_virtual * bytespp;
@@ -534,7 +555,7 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
 
        if (line_size * var->yres_virtual > max_frame_size) {
                DBG("can't fit FB into memory, reducing x\n");
-               if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
+               if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
                        return -EINVAL;
 
                var->xres_virtual = max_frame_size / var->yres_virtual /
@@ -657,7 +678,7 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
        struct omap_overlay_info info;
        int xres, yres;
        int screen_width;
-       int rot, mirror;
+       int mirror;
 
        DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id,
                        posx, posy, outw, outh);
@@ -673,7 +694,7 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
        offset = ((var->yoffset * var->xres_virtual +
                                var->xoffset) * var->bits_per_pixel) >> 3;
 
-       if (ofbi->rotation_type == OMAPFB_ROT_VRFB) {
+       if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
                data_start_p = omapfb_get_region_rot_paddr(ofbi);
                data_start_v = NULL;
        } else {
@@ -692,17 +713,25 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
                goto err;
        }
 
-       screen_width = fix->line_length / (var->bits_per_pixel >> 3);
+       switch (var->nonstd) {
+       case OMAPFB_COLOR_YUV422:
+       case OMAPFB_COLOR_YUY422:
+               if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+                       screen_width = fix->line_length
+                               / (var->bits_per_pixel >> 2);
+                       break;
+               }
+       default:
+               screen_width = fix->line_length / (var->bits_per_pixel >> 3);
+               break;
+       }
 
        ovl->get_overlay_info(ovl, &info);
 
-       if (ofbi->rotation_type == OMAPFB_ROT_VRFB) {
-               rot = 0;
+       if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
                mirror = 0;
-       } else {
-               rot = ofbi->rotation;
+       else
                mirror = ofbi->mirror;
-       }
 
        info.paddr = data_start_p;
        info.vaddr = data_start_v;
@@ -710,7 +739,8 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
        info.width = xres;
        info.height = yres;
        info.color_mode = mode;
-       info.rotation = rot;
+       info.rotation_type = ofbi->rotation_type;
+       info.rotation = ofbi->rotation;
        info.mirror = mirror;
 
        info.pos_x = posx;
@@ -1106,7 +1136,7 @@ static void omapfb_free_fbmem(struct fb_info *fbi)
        if (rg->vaddr)
                iounmap(rg->vaddr);
 
-       if (ofbi->rotation_type == OMAPFB_ROT_VRFB) {
+       if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
                /* unmap the 0 angle rotation */
                if (rg->vrfb.vaddr[0]) {
                        iounmap(rg->vrfb.vaddr[0]);
@@ -1144,7 +1174,6 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
        struct omapfb2_mem_region *rg;
        void __iomem *vaddr;
        int r;
-       int clear = 0;
 
        rg = &ofbi->region;
        memset(rg, 0, sizeof(*rg));
@@ -1154,7 +1183,6 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
        if (!paddr) {
                DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
                r = omap_vram_alloc(OMAPFB_MEMTYPE_SDRAM, size, &paddr);
-               clear = 1;
        } else {
                DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr,
                                ofbi->id);
@@ -1166,7 +1194,7 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
                return -ENOMEM;
        }
 
-       if (ofbi->rotation_type != OMAPFB_ROT_VRFB) {
+       if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) {
                vaddr = ioremap_wc(paddr, size);
 
                if (!vaddr) {
@@ -1176,9 +1204,6 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
                }
 
                DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr);
-
-               if (clear)
-                       memset_io(vaddr, 0, size);
        } else {
                void __iomem *va;
 
@@ -1193,6 +1218,7 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
 
                if(!va) {
                        printk(KERN_ERR "vrfb: ioremap failed\n");
+                       omap_vrfb_release_ctx(&rg->vrfb);
                        return -ENOMEM;
                }
 
@@ -1201,9 +1227,6 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
                rg->vrfb.vaddr[0] = va;
 
                vaddr = NULL;
-
-               if (clear)
-                       memset_io(va, 0, size);
        }
 
        rg->paddr = paddr;
@@ -1244,8 +1267,10 @@ static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
 
                display->get_resolution(display, &w, &h);
 
-               if (ofbi->rotation_type == OMAPFB_ROT_VRFB) {
+               if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+#ifdef DEBUG
                        int oldw = w, oldh = h;
+#endif
 
                        omap_vrfb_adjust_size(&w, &h, bytespp);
 
@@ -1264,6 +1289,60 @@ static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
        return omapfb_alloc_fbmem(fbi, size, paddr);
 }
 
+static enum omap_color_mode fb_format_to_dss_mode(enum omapfb_color_format format)
+{
+       enum omap_color_mode mode;
+
+       switch (format) {
+       case OMAPFB_COLOR_RGB565:
+               mode = OMAP_DSS_COLOR_RGB16;
+               break;
+       case OMAPFB_COLOR_YUV422:
+               mode = OMAP_DSS_COLOR_YUV2;
+               break;
+       case OMAPFB_COLOR_CLUT_8BPP:
+               mode = OMAP_DSS_COLOR_CLUT8;
+               break;
+       case OMAPFB_COLOR_CLUT_4BPP:
+               mode = OMAP_DSS_COLOR_CLUT4;
+               break;
+       case OMAPFB_COLOR_CLUT_2BPP:
+               mode = OMAP_DSS_COLOR_CLUT2;
+               break;
+       case OMAPFB_COLOR_CLUT_1BPP:
+               mode = OMAP_DSS_COLOR_CLUT1;
+               break;
+       case OMAPFB_COLOR_RGB444:
+               mode = OMAP_DSS_COLOR_RGB12U;
+               break;
+       case OMAPFB_COLOR_YUY422:
+               mode = OMAP_DSS_COLOR_UYVY;
+               break;
+       case OMAPFB_COLOR_ARGB16:
+               mode = OMAP_DSS_COLOR_ARGB16;
+               break;
+       case OMAPFB_COLOR_RGB24U:
+               mode = OMAP_DSS_COLOR_RGB24U;
+               break;
+       case OMAPFB_COLOR_RGB24P:
+               mode = OMAP_DSS_COLOR_RGB24P;
+               break;
+       case OMAPFB_COLOR_ARGB32:
+               mode = OMAP_DSS_COLOR_ARGB32;
+               break;
+       case OMAPFB_COLOR_RGBA32:
+               mode = OMAP_DSS_COLOR_RGBA32;
+               break;
+       case OMAPFB_COLOR_RGBX32:
+               mode = OMAP_DSS_COLOR_RGBX32;
+               break;
+       default:
+               mode = -EINVAL;
+       }
+
+       return mode;
+}
+
 static int omapfb_parse_vram_param(const char *param, int max_entries,
                unsigned long *sizes, unsigned long *paddrs)
 {
@@ -1480,9 +1559,36 @@ int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
        }
 
        var->nonstd = 0;
+       var->bits_per_pixel = 0;
 
        var->rotate = ofbi->rotation;
 
+       /*
+        * Check if there is a default color format set in the board file,
+        * and use this format instead the default deducted from the
+        * display bpp.
+        */
+       if (fbdev->dev->platform_data) {
+               struct omapfb_platform_data *opd;
+               int id = ofbi->id;
+
+               opd = fbdev->dev->platform_data;
+               if (opd->mem_desc.region[id].format_used) {
+                       enum omap_color_mode mode;
+                       enum omapfb_color_format format;
+
+                       format = opd->mem_desc.region[id].format;
+                       mode = fb_format_to_dss_mode(format);
+                       if (mode < 0) {
+                               r = mode;
+                               goto err;
+                       }
+                       r = dss_mode_to_fb_mode(mode, var);
+                       if (r < 0)
+                               goto err;
+               }
+       }
+
        if (display) {
                u16 w, h;
                display->get_resolution(display, &w, &h);
@@ -1499,16 +1605,18 @@ int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
                var->xres_virtual = var->xres;
                var->yres_virtual = var->yres;
 
-               switch (display->get_recommended_bpp(display)) {
-               case 16:
-                       var->bits_per_pixel = 16;
-                       break;
-               case 24:
-                       var->bits_per_pixel = 32;
-                       break;
-               default:
-                       dev_err(fbdev->dev, "illegal display bpp\n");
-                       return -EINVAL;
+               if (!var->bits_per_pixel) {
+                       switch (display->get_recommended_bpp(display)) {
+                               case 16:
+                                       var->bits_per_pixel = 16;
+                                       break;
+                               case 24:
+                                       var->bits_per_pixel = 32;
+                                       break;
+                               default:
+                                       dev_err(fbdev->dev, "illegal display bpp\n");
+                                       return -EINVAL;
+                       }
                }
        } else {
                /* if there's no display, let's just guess some basic values */
@@ -1516,7 +1624,8 @@ int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
                var->yres = 240;
                var->xres_virtual = var->xres;
                var->yres_virtual = var->yres;
-               var->bits_per_pixel = 16;
+               if (!var->bits_per_pixel)
+                       var->bits_per_pixel = 16;
        }
 
        r = check_fb_var(fbi, var);
@@ -1524,6 +1633,11 @@ int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
                goto err;
 
        set_fb_fix(fbi);
+
+       r = fb_alloc_cmap(&fbi->cmap, 256, 0);
+       if (r)
+               dev_err(fbdev->dev, "unable to allocate color map memory\n");
+
 err:
        return r;
 }
@@ -1594,8 +1708,8 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
                ofbi->id = i;
 
                /* assign these early, so that fb alloc can use them */
-               ofbi->rotation_type = def_vrfb ? OMAPFB_ROT_VRFB :
-                       OMAPFB_ROT_DMA;
+               ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
+                       OMAP_DSS_ROT_DMA;
                ofbi->rotation = def_rotate;
                ofbi->mirror = def_mirror;