s3c2410fb: use new margin fields
authorKrzysztof Helt <krzysztof.h1@wp.pl>
Tue, 16 Oct 2007 08:28:57 +0000 (01:28 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Tue, 16 Oct 2007 16:43:16 +0000 (09:43 -0700)
This patch makes use of margins fields in the s3c2410fb_display
structure.

Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl>
Signed-off-by: Antonino Daplas <adaplas@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/video/s3c2410fb.c

index e52ec22831615d481b2c4a1fd7b2e6f55bc1115f..04e9d7a482fab5409ae6532a637aa68219ec89d2 100644 (file)
@@ -197,6 +197,14 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var,
                return -EINVAL;
        }
 
+       /* it is always the size as the display */
+       var->xres_virtual = display->xres;
+       var->yres_virtual = display->yres;
+
+       /* copy lcd settings */
+       var->left_margin = display->left_margin;
+       var->right_margin = display->right_margin;
+
        var->transp.offset = 0;
        var->transp.length = 0;
        /* set r/g/b positions */
@@ -270,124 +278,151 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var,
        return 0;
 }
 
-/* s3c2410fb_activate_var
+/* s3c2410fb_calculate_stn_lcd_regs
  *
- * activate (set) the controller from the given framebuffer
- * information
+ * calculate register values from var settings
  */
-static void s3c2410fb_activate_var(struct fb_info *info,
-                                  struct fb_var_screeninfo *var)
+static void s3c2410fb_calculate_stn_lcd_regs(const struct fb_info *info,
+                                            struct s3c2410fb_hw *regs)
 {
-       struct s3c2410fb_info *fbi = info->par;
-       struct s3c2410fb_mach_info *mach_info = fbi->mach_info;
-       struct s3c2410fb_display *display = mach_info->displays +
-                                           fbi->current_display;
-       int hs;
-
-       fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_MODEMASK;
-       fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_TFT;
+       const struct s3c2410fb_info *fbi = info->par;
+       const struct fb_var_screeninfo *var = &info->var;
+       int type = regs->lcdcon1 & ~S3C2410_LCDCON1_TFT;
+       int hs = var->xres >> 2;
+       unsigned wdly = (var->left_margin >> 4) - 1;
 
        dprintk("%s: var->xres  = %d\n", __FUNCTION__, var->xres);
        dprintk("%s: var->yres  = %d\n", __FUNCTION__, var->yres);
        dprintk("%s: var->bpp   = %d\n", __FUNCTION__, var->bits_per_pixel);
 
-       fbi->regs.lcdcon1 |= display->type;
-
-       if (display->type == S3C2410_LCDCON1_TFT)
-               switch (var->bits_per_pixel) {
-               case 1:
-                       fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT1BPP;
-                       break;
-               case 2:
-                       fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT2BPP;
-                       break;
-               case 4:
-                       fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT4BPP;
-                       break;
-               case 8:
-                       fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT8BPP;
-                       break;
-               case 16:
-                       fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT16BPP;
-                       break;
+       if (type != S3C2410_LCDCON1_STN4)
+               hs >>= 1;
 
-               default:
-                       /* invalid pixel depth */
-                       dev_err(fbi->dev, "invalid bpp %d\n",
-                               var->bits_per_pixel);
-               }
-       else
-               switch (var->bits_per_pixel) {
-               case 1:
-                       fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN1BPP;
-                       break;
-               case 2:
-                       fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN2GREY;
-                       break;
-               case 4:
-                       fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN4GREY;
-                       break;
-               case 8:
-                       fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN8BPP;
-                       break;
-               case 12:
-                       fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN12BPP;
-                       break;
+       regs->lcdcon1 &= ~S3C2410_LCDCON1_MODEMASK;
 
-               default:
-                       /* invalid pixel depth */
-                       dev_err(fbi->dev, "invalid bpp %d\n",
-                               var->bits_per_pixel);
-               }
+       switch (var->bits_per_pixel) {
+       case 1:
+               regs->lcdcon1 |= S3C2410_LCDCON1_STN1BPP;
+               break;
+       case 2:
+               regs->lcdcon1 |= S3C2410_LCDCON1_STN2GREY;
+               break;
+       case 4:
+               regs->lcdcon1 |= S3C2410_LCDCON1_STN4GREY;
+               break;
+       case 8:
+               regs->lcdcon1 |= S3C2410_LCDCON1_STN8BPP;
+               hs *= 3;
+               break;
+       case 12:
+               regs->lcdcon1 |= S3C2410_LCDCON1_STN12BPP;
+               hs *= 3;
+               break;
 
-       /* check to see if we need to update sync/borders */
+       default:
+               /* invalid pixel depth */
+               dev_err(fbi->dev, "invalid bpp %d\n",
+                       var->bits_per_pixel);
+       }
+       /* update X/Y info */
+       dprintk("setting vert: up=%d, low=%d, sync=%d\n",
+               var->upper_margin, var->lower_margin, var->vsync_len);
 
-       if (!mach_info->fixed_syncs) {
-               dprintk("setting vert: up=%d, low=%d, sync=%d\n",
-                       var->upper_margin, var->lower_margin, var->vsync_len);
+       dprintk("setting horz: lft=%d, rt=%d, sync=%d\n",
+               var->left_margin, var->right_margin, var->hsync_len);
 
-               dprintk("setting horz: lft=%d, rt=%d, sync=%d\n",
-                       var->left_margin, var->right_margin, var->hsync_len);
+       regs->lcdcon2 &= ~S3C2410_LCDCON2_LINEVAL(0x3ff);
+       regs->lcdcon2 |=  S3C2410_LCDCON2_LINEVAL(var->yres - 1);
 
-               fbi->regs.lcdcon2 =
-                       S3C2410_LCDCON2_VBPD(var->upper_margin - 1) |
-                       S3C2410_LCDCON2_VFPD(var->lower_margin - 1) |
-                       S3C2410_LCDCON2_VSPW(var->vsync_len - 1);
+       if (wdly > 3)
+               wdly = 3;
 
-               fbi->regs.lcdcon3 =
-                       S3C2410_LCDCON3_HBPD(var->right_margin - 1) |
-                       S3C2410_LCDCON3_HFPD(var->left_margin - 1);
+       regs->lcdcon3 = S3C2410_LCDCON3_WDLY(wdly) |
+                       S3C2410_LCDCON3_LINEBLANK(var->right_margin / 8) |
+                       S3C2410_LCDCON3_HOZVAL(hs - 1);
+}
 
-               fbi->regs.lcdcon4 &= ~S3C2410_LCDCON4_HSPW(0xff);
-               fbi->regs.lcdcon4 |=  S3C2410_LCDCON4_HSPW(var->hsync_len - 1);
-       }
+/* s3c2410fb_calculate_tft_lcd_regs
+ *
+ * calculate register values from var settings
+ */
+static void s3c2410fb_calculate_tft_lcd_regs(const struct fb_info *info,
+                                            struct s3c2410fb_hw *regs)
+{
+       const struct s3c2410fb_info *fbi = info->par;
+       const struct fb_var_screeninfo *var = &info->var;
 
-       /* update X/Y info */
+       dprintk("%s: var->xres  = %d\n", __FUNCTION__, var->xres);
+       dprintk("%s: var->yres  = %d\n", __FUNCTION__, var->yres);
+       dprintk("%s: var->bpp   = %d\n", __FUNCTION__, var->bits_per_pixel);
 
-       fbi->regs.lcdcon2 &= ~S3C2410_LCDCON2_LINEVAL(0x3ff);
-       fbi->regs.lcdcon2 |=  S3C2410_LCDCON2_LINEVAL(var->yres - 1);
+       regs->lcdcon1 &= ~S3C2410_LCDCON1_MODEMASK;
 
-       switch (display->type) {
-       case S3C2410_LCDCON1_DSCAN4:
-       case S3C2410_LCDCON1_STN8:
-               hs = var->xres / 8;
+       switch (var->bits_per_pixel) {
+       case 1:
+               regs->lcdcon1 |= S3C2410_LCDCON1_TFT1BPP;
+               break;
+       case 2:
+               regs->lcdcon1 |= S3C2410_LCDCON1_TFT2BPP;
                break;
-       case S3C2410_LCDCON1_STN4:
-               hs = var->xres / 4;
+       case 4:
+               regs->lcdcon1 |= S3C2410_LCDCON1_TFT4BPP;
                break;
-       default:
-       case S3C2410_LCDCON1_TFT:
-               hs = var->xres;
+       case 8:
+               regs->lcdcon1 |= S3C2410_LCDCON1_TFT8BPP;
+               break;
+       case 16:
+               regs->lcdcon1 |= S3C2410_LCDCON1_TFT16BPP;
                break;
+
+       default:
+               /* invalid pixel depth */
+               dev_err(fbi->dev, "invalid bpp %d\n",
+                       var->bits_per_pixel);
        }
+       /* update X/Y info */
+       dprintk("setting vert: up=%d, low=%d, sync=%d\n",
+               var->upper_margin, var->lower_margin, var->vsync_len);
 
-       /* Special cases : STN color displays */
-       if (((fbi->regs.lcdcon1 & S3C2410_LCDCON1_MODEMASK) == S3C2410_LCDCON1_STN8BPP) ||
-           ((fbi->regs.lcdcon1 & S3C2410_LCDCON1_MODEMASK) == S3C2410_LCDCON1_STN12BPP))
-               hs = hs * 3;
+       dprintk("setting horz: lft=%d, rt=%d, sync=%d\n",
+               var->left_margin, var->right_margin, var->hsync_len);
 
-       fbi->regs.lcdcon3 &= ~S3C2410_LCDCON3_HOZVAL(0x7ff);
-       fbi->regs.lcdcon3 |=  S3C2410_LCDCON3_HOZVAL(hs - 1);
+       regs->lcdcon2 &= ~S3C2410_LCDCON2_LINEVAL(0x3ff);
+       regs->lcdcon2 |=  S3C2410_LCDCON2_LINEVAL(var->yres - 1);
+
+       regs->lcdcon3 = S3C2410_LCDCON3_HBPD(var->right_margin - 1) |
+                       S3C2410_LCDCON3_HFPD(var->left_margin - 1) |
+                       S3C2410_LCDCON3_HOZVAL(var->xres - 1);
+}
+
+/* s3c2410fb_activate_var
+ *
+ * activate (set) the controller from the given framebuffer
+ * information
+ */
+static void s3c2410fb_activate_var(struct fb_info *info)
+{
+       struct s3c2410fb_info *fbi = info->par;
+       struct fb_var_screeninfo *var = &info->var;
+       struct s3c2410fb_mach_info *mach_info = fbi->mach_info;
+       struct s3c2410fb_display *display = mach_info->displays +
+                                           fbi->current_display;
+
+       /* set display type */
+       fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_TFT;
+       fbi->regs.lcdcon1 |= display->type;
+
+       /* check to see if we need to update sync/borders */
+
+       if (!mach_info->fixed_syncs) {
+               fbi->regs.lcdcon2 =
+                       S3C2410_LCDCON2_VBPD(var->upper_margin - 1) |
+                       S3C2410_LCDCON2_VFPD(var->lower_margin - 1) |
+                       S3C2410_LCDCON2_VSPW(var->vsync_len - 1);
+
+               fbi->regs.lcdcon4 &= ~S3C2410_LCDCON4_HSPW(0xff);
+               fbi->regs.lcdcon4 |=  S3C2410_LCDCON4_HSPW(var->hsync_len - 1);
+       }
 
        if (var->pixclock > 0) {
                int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock);
@@ -406,6 +441,11 @@ static void s3c2410fb_activate_var(struct fb_info *info,
                fbi->regs.lcdcon1 |=  S3C2410_LCDCON1_CLKVAL(clkdiv);
        }
 
+       if (display->type == S3C2410_LCDCON1_TFT)
+               s3c2410fb_calculate_tft_lcd_regs(info, &fbi->regs);
+       else
+               s3c2410fb_calculate_stn_lcd_regs(info, &fbi->regs);
+
        /* write new registers */
 
        dprintk("new register set:\n");
@@ -452,7 +492,7 @@ static int s3c2410fb_set_par(struct fb_info *info)
 
        /* activate this new configuration */
 
-       s3c2410fb_activate_var(info, var);
+       s3c2410fb_activate_var(info);
        return 0;
 }
 
@@ -848,6 +888,8 @@ static int __init s3c2410fb_probe(struct platform_device *pdev)
        fbinfo->var.yres            = display->yres;
        fbinfo->var.yres_virtual    = display->yres;
        fbinfo->var.bits_per_pixel  = display->bpp;
+       fbinfo->var.left_margin     = display->left_margin;
+       fbinfo->var.right_margin    = display->right_margin;
 
        fbinfo->var.upper_margin    =
                                S3C2410_LCDCON2_GET_VBPD(mregs->lcdcon2) + 1;
@@ -856,10 +898,6 @@ static int __init s3c2410fb_probe(struct platform_device *pdev)
        fbinfo->var.vsync_len       =
                                S3C2410_LCDCON2_GET_VSPW(mregs->lcdcon2) + 1;
 
-       fbinfo->var.left_margin     =
-                               S3C2410_LCDCON3_GET_HFPD(mregs->lcdcon3) + 1;
-       fbinfo->var.right_margin    =
-                               S3C2410_LCDCON3_GET_HBPD(mregs->lcdcon3) + 1;
        fbinfo->var.hsync_len       =
                                S3C2410_LCDCON4_GET_HSPW(mregs->lcdcon4) + 1;