aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2011-11-30 17:07:30 -0500
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-03-12 17:40:58 -0400
commit58f03d998de08bb15ce50ad875e41bdc281d77dd (patch)
tree9988a2afc6c5946aeec3ba2cd923fc5e82572562
parente8363140c02c92c122210e03103aef72dd836664 (diff)
fbdev: sh_mobile_lcdc: Store configuration in channel structure
Store the frame buffer configuration (colorspace, visible/virtual horizontal and vertical resolutions and line pitch) in the sh_mobile_lcdc_chan structure, and use it instead of accessing fb_info. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c109
-rw-r--r--drivers/video/sh_mobile_lcdcfb.h8
2 files changed, 61 insertions, 56 deletions
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index fc12e37b55ce..6d377b48c138 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -273,7 +273,7 @@ static int sh_mobile_lcdc_sginit(struct fb_info *info,
273 struct list_head *pagelist) 273 struct list_head *pagelist)
274{ 274{
275 struct sh_mobile_lcdc_chan *ch = info->par; 275 struct sh_mobile_lcdc_chan *ch = info->par;
276 unsigned int nr_pages_max = info->fix.smem_len >> PAGE_SHIFT; 276 unsigned int nr_pages_max = ch->fb_size >> PAGE_SHIFT;
277 struct page *page; 277 struct page *page;
278 int nr_pages = 0; 278 int nr_pages = 0;
279 279
@@ -541,17 +541,6 @@ static int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var)
541 return var->grayscale > 1; 541 return var->grayscale > 1;
542} 542}
543 543
544static bool sh_mobile_format_is_yuv(const struct fb_var_screeninfo *var)
545{
546 const struct sh_mobile_lcdc_format_info *format;
547
548 if (var->grayscale <= 1)
549 return false;
550
551 format = sh_mobile_format_info(var->grayscale);
552 return format ? format->yuv : false;
553}
554
555/* ----------------------------------------------------------------------------- 544/* -----------------------------------------------------------------------------
556 * Start, stop and IRQ 545 * Start, stop and IRQ
557 */ 546 */
@@ -650,7 +639,7 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
650 h_total = mode->xres + mode->hsync_len + mode->left_margin 639 h_total = mode->xres + mode->hsync_len + mode->left_margin
651 + mode->right_margin; 640 + mode->right_margin;
652 tmp = h_total / 8; /* HTCN */ 641 tmp = h_total / 8; /* HTCN */
653 tmp |= (min(mode->xres, var->xres) / 8) << 16; /* HDCN */ 642 tmp |= (min(mode->xres, ch->xres) / 8) << 16; /* HDCN */
654 lcdc_write_chan(ch, LDHCNR, tmp); 643 lcdc_write_chan(ch, LDHCNR, tmp);
655 644
656 hsync_pos = mode->xres + mode->right_margin; 645 hsync_pos = mode->xres + mode->right_margin;
@@ -661,7 +650,7 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
661 /* vertical configuration */ 650 /* vertical configuration */
662 tmp = mode->yres + mode->vsync_len + mode->upper_margin 651 tmp = mode->yres + mode->vsync_len + mode->upper_margin
663 + mode->lower_margin; /* VTLN */ 652 + mode->lower_margin; /* VTLN */
664 tmp |= min(mode->yres, var->yres) << 16; /* VDLN */ 653 tmp |= min(mode->yres, ch->yres) << 16; /* VDLN */
665 lcdc_write_chan(ch, LDVLNR, tmp); 654 lcdc_write_chan(ch, LDVLNR, tmp);
666 655
667 tmp = mode->yres + mode->lower_margin; /* VSYNP */ 656 tmp = mode->yres + mode->lower_margin; /* VSYNP */
@@ -738,7 +727,7 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
738 tmp = ch->format->lddfr; 727 tmp = ch->format->lddfr;
739 728
740 if (ch->format->yuv) { 729 if (ch->format->yuv) {
741 switch (ch->info->var.colorspace) { 730 switch (ch->colorspace) {
742 case V4L2_COLORSPACE_REC709: 731 case V4L2_COLORSPACE_REC709:
743 tmp |= LDDFR_CF1; 732 tmp |= LDDFR_CF1;
744 break; 733 break;
@@ -836,11 +825,8 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
836 if (!ch->enabled) 825 if (!ch->enabled)
837 continue; 826 continue;
838 827
839 ch->base_addr_y = ch->info->fix.smem_start; 828 ch->base_addr_y = ch->dma_handle;
840 ch->base_addr_c = ch->base_addr_y 829 ch->base_addr_c = ch->base_addr_y + ch->xres * ch->yres_virtual;
841 + ch->info->var.xres
842 * ch->info->var.yres_virtual;
843 ch->pitch = ch->info->fix.line_length;
844 830
845 /* Enable MERAM if possible. */ 831 /* Enable MERAM if possible. */
846 cfg = ch->cfg.meram_cfg; 832 cfg = ch->cfg.meram_cfg;
@@ -875,7 +861,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
875 } 861 }
876 862
877 ret = mdev->ops->meram_register(mdev, cfg, ch->pitch, 863 ret = mdev->ops->meram_register(mdev, cfg, ch->pitch,
878 ch->info->var.yres, pixelformat, 864 ch->yres, pixelformat,
879 ch->base_addr_y, ch->base_addr_c, 865 ch->base_addr_y, ch->base_addr_c,
880 &ch->base_addr_y, &ch->base_addr_c, 866 &ch->base_addr_y, &ch->base_addr_c,
881 &ch->pitch); 867 &ch->pitch);
@@ -1037,14 +1023,12 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
1037 unsigned long new_pan_offset; 1023 unsigned long new_pan_offset;
1038 unsigned long base_addr_y, base_addr_c; 1024 unsigned long base_addr_y, base_addr_c;
1039 unsigned long c_offset; 1025 unsigned long c_offset;
1040 bool yuv = sh_mobile_format_is_yuv(&info->var);
1041 1026
1042 if (!yuv) 1027 if (!ch->format->yuv)
1043 new_pan_offset = var->yoffset * info->fix.line_length 1028 new_pan_offset = var->yoffset * ch->pitch
1044 + var->xoffset * (info->var.bits_per_pixel / 8); 1029 + var->xoffset * (ch->format->bpp / 8);
1045 else 1030 else
1046 new_pan_offset = var->yoffset * info->fix.line_length 1031 new_pan_offset = var->yoffset * ch->pitch + var->xoffset;
1047 + var->xoffset;
1048 1032
1049 if (new_pan_offset == ch->pan_offset) 1033 if (new_pan_offset == ch->pan_offset)
1050 return 0; /* No change, do nothing */ 1034 return 0; /* No change, do nothing */
@@ -1053,12 +1037,11 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
1053 1037
1054 /* Set the source address for the next refresh */ 1038 /* Set the source address for the next refresh */
1055 base_addr_y = ch->dma_handle + new_pan_offset; 1039 base_addr_y = ch->dma_handle + new_pan_offset;
1056 if (yuv) { 1040 if (ch->format->yuv) {
1057 /* Set y offset */ 1041 /* Set y offset */
1058 c_offset = var->yoffset * info->fix.line_length 1042 c_offset = var->yoffset * ch->pitch
1059 * (info->var.bits_per_pixel - 8) / 8; 1043 * (ch->format->bpp - 8) / 8;
1060 base_addr_c = ch->dma_handle 1044 base_addr_c = ch->dma_handle + ch->xres * ch->yres_virtual
1061 + info->var.xres * info->var.yres_virtual
1062 + c_offset; 1045 + c_offset;
1063 /* Set x offset */ 1046 /* Set x offset */
1064 if (ch->format->fourcc == V4L2_PIX_FMT_NV24) 1047 if (ch->format->fourcc == V4L2_PIX_FMT_NV24)
@@ -1085,7 +1068,7 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
1085 ch->base_addr_c = base_addr_c; 1068 ch->base_addr_c = base_addr_c;
1086 1069
1087 lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y); 1070 lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
1088 if (yuv) 1071 if (ch->format->yuv)
1089 lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c); 1072 lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
1090 1073
1091 if (lcdc_chan_is_sublcd(ch)) 1074 if (lcdc_chan_is_sublcd(ch))
@@ -1338,24 +1321,28 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
1338static int sh_mobile_set_par(struct fb_info *info) 1321static int sh_mobile_set_par(struct fb_info *info)
1339{ 1322{
1340 struct sh_mobile_lcdc_chan *ch = info->par; 1323 struct sh_mobile_lcdc_chan *ch = info->par;
1341 u32 line_length = info->fix.line_length;
1342 int ret; 1324 int ret;
1343 1325
1344 sh_mobile_lcdc_stop(ch->lcdc); 1326 sh_mobile_lcdc_stop(ch->lcdc);
1345 1327
1346 if (sh_mobile_format_is_yuv(&info->var))
1347 info->fix.line_length = info->var.xres;
1348 else
1349 info->fix.line_length = info->var.xres
1350 * info->var.bits_per_pixel / 8;
1351
1352 ch->format = sh_mobile_format_info(sh_mobile_format_fourcc(&info->var)); 1328 ch->format = sh_mobile_format_info(sh_mobile_format_fourcc(&info->var));
1329 ch->colorspace = info->var.colorspace;
1330
1331 ch->xres = info->var.xres;
1332 ch->xres_virtual = info->var.xres_virtual;
1333 ch->yres = info->var.yres;
1334 ch->yres_virtual = info->var.yres_virtual;
1335
1336 if (ch->format->yuv)
1337 ch->pitch = info->var.xres;
1338 else
1339 ch->pitch = info->var.xres * ch->format->bpp / 8;
1353 1340
1354 ret = sh_mobile_lcdc_start(ch->lcdc); 1341 ret = sh_mobile_lcdc_start(ch->lcdc);
1355 if (ret < 0) { 1342 if (ret < 0)
1356 dev_err(info->dev, "%s: unable to restart LCDC\n", __func__); 1343 dev_err(info->dev, "%s: unable to restart LCDC\n", __func__);
1357 info->fix.line_length = line_length; 1344
1358 } 1345 info->fix.line_length = ch->pitch;
1359 1346
1360 if (sh_mobile_format_is_fourcc(&info->var)) { 1347 if (sh_mobile_format_is_fourcc(&info->var)) {
1361 info->fix.type = FB_TYPE_FOURCC; 1348 info->fix.type = FB_TYPE_FOURCC;
@@ -1384,8 +1371,8 @@ static int sh_mobile_lcdc_blank(int blank, struct fb_info *info)
1384 /* blank the screen? */ 1371 /* blank the screen? */
1385 if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) { 1372 if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) {
1386 struct fb_fillrect rect = { 1373 struct fb_fillrect rect = {
1387 .width = info->var.xres, 1374 .width = ch->xres,
1388 .height = info->var.yres, 1375 .height = ch->yres,
1389 }; 1376 };
1390 sh_mobile_lcdc_fillrect(info, &rect); 1377 sh_mobile_lcdc_fillrect(info, &rect);
1391 } 1378 }
@@ -1525,6 +1512,13 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
1525 info->fix = sh_mobile_lcdc_fix; 1512 info->fix = sh_mobile_lcdc_fix;
1526 info->fix.smem_start = ch->dma_handle; 1513 info->fix.smem_start = ch->dma_handle;
1527 info->fix.smem_len = ch->fb_size; 1514 info->fix.smem_len = ch->fb_size;
1515 info->fix.line_length = ch->pitch;
1516
1517 if (ch->format->yuv)
1518 info->fix.visual = FB_VISUAL_FOURCC;
1519 else
1520 info->fix.visual = FB_VISUAL_TRUECOLOR;
1521
1528 if (ch->format->fourcc == V4L2_PIX_FMT_NV12 || 1522 if (ch->format->fourcc == V4L2_PIX_FMT_NV12 ||
1529 ch->format->fourcc == V4L2_PIX_FMT_NV21) 1523 ch->format->fourcc == V4L2_PIX_FMT_NV21)
1530 info->fix.ypanstep = 2; 1524 info->fix.ypanstep = 2;
@@ -1552,14 +1546,6 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
1552 if (ret) 1546 if (ret)
1553 return ret; 1547 return ret;
1554 1548
1555 if (ch->format->yuv) {
1556 info->fix.line_length = var->xres;
1557 info->fix.visual = FB_VISUAL_FOURCC;
1558 } else {
1559 info->fix.line_length = var->xres * ch->format->bpp / 8;
1560 info->fix.visual = FB_VISUAL_TRUECOLOR;
1561 }
1562
1563 return 0; 1549 return 0;
1564} 1550}
1565 1551
@@ -1836,8 +1822,6 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
1836 return -EINVAL; 1822 return -EINVAL;
1837 } 1823 }
1838 1824
1839 ch->format = format;
1840
1841 /* Iterate through the modes to validate them and find the highest 1825 /* Iterate through the modes to validate them and find the highest
1842 * resolution. 1826 * resolution.
1843 */ 1827 */
@@ -1875,6 +1859,21 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
1875 num_modes = cfg->num_modes; 1859 num_modes = cfg->num_modes;
1876 } 1860 }
1877 1861
1862 /* Use the first mode as default. */
1863 ch->format = format;
1864 ch->xres = mode->xres;
1865 ch->xres_virtual = mode->xres;
1866 ch->yres = mode->yres;
1867 ch->yres_virtual = mode->yres * 2;
1868
1869 if (!format->yuv) {
1870 ch->colorspace = V4L2_COLORSPACE_SRGB;
1871 ch->pitch = ch->xres * format->bpp / 8;
1872 } else {
1873 ch->colorspace = V4L2_COLORSPACE_REC709;
1874 ch->pitch = ch->xres;
1875 }
1876
1878 ch->display.width = cfg->panel_cfg.width; 1877 ch->display.width = cfg->panel_cfg.width;
1879 ch->display.height = cfg->panel_cfg.height; 1878 ch->display.height = cfg->panel_cfg.height;
1880 ch->display.mode = *mode; 1879 ch->display.mode = *mode;
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
index cc22b9eaaf0a..19a4cd74c89a 100644
--- a/drivers/video/sh_mobile_lcdcfb.h
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -74,9 +74,15 @@ struct sh_mobile_lcdc_chan {
74 struct completion vsync_completion; 74 struct completion vsync_completion;
75 75
76 const struct sh_mobile_lcdc_format_info *format; 76 const struct sh_mobile_lcdc_format_info *format;
77 u32 colorspace;
78 unsigned int xres;
79 unsigned int xres_virtual;
80 unsigned int yres;
81 unsigned int yres_virtual;
82 unsigned int pitch;
83
77 unsigned long base_addr_y; 84 unsigned long base_addr_y;
78 unsigned long base_addr_c; 85 unsigned long base_addr_c;
79 unsigned int pitch;
80 86
81 int (*notify)(struct sh_mobile_lcdc_chan *ch, 87 int (*notify)(struct sh_mobile_lcdc_chan *ch,
82 enum sh_mobile_lcdc_entity_event event, 88 enum sh_mobile_lcdc_entity_event event,