diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2011-11-30 17:07:30 -0500 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2012-03-12 17:40:58 -0400 |
commit | 58f03d998de08bb15ce50ad875e41bdc281d77dd (patch) | |
tree | 9988a2afc6c5946aeec3ba2cd923fc5e82572562 | |
parent | e8363140c02c92c122210e03103aef72dd836664 (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.c | 109 | ||||
-rw-r--r-- | drivers/video/sh_mobile_lcdcfb.h | 8 |
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 | ||
544 | static 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 | |||
1338 | static int sh_mobile_set_par(struct fb_info *info) | 1321 | static 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, |