--- v5
+++ v3
@@ -8,15 +8,15 @@
arch/sh/boards/mach-kfr2r09/setup.c | 2 +-
arch/sh/boards/mach-migor/setup.c | 4 +-
arch/sh/boards/mach-se/7724/setup.c | 2 +-
- drivers/video/sh_mobile_lcdcfb.c | 360 ++++++++++++++++++++----------
+ drivers/video/sh_mobile_lcdcfb.c | 362 +++++++++++++++++++++----------
include/video/sh_mobile_lcdc.h | 4 +-
- 10 files changed, 253 insertions(+), 133 deletions(-)
+ 10 files changed, 255 insertions(+), 133 deletions(-)
diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c
-index 7e3dd73..80319f2 100644
+index ce5c251..e6dabaa 100644
--- a/arch/arm/mach-shmobile/board-ag5evm.c
+++ b/arch/arm/mach-shmobile/board-ag5evm.c
-@@ -271,7 +271,7 @@ static struct sh_mobile_lcdc_info lcdc0_info = {
+@@ -270,7 +270,7 @@ static struct sh_mobile_lcdc_info lcdc0_info = {
.flags = LCDC_FLAGS_DWPOL,
.lcd_size_cfg.width = 44,
.lcd_size_cfg.height = 79,
@@ -26,10 +26,10 @@
.num_cfg = ARRAY_SIZE(lcdc0_modes),
.board_cfg = {
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
-index 904b608..42b4dda 100644
+index 9e0856b..6f5db07 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
-@@ -491,7 +491,7 @@ static struct sh_mobile_lcdc_info lcdc_info = {
+@@ -489,7 +489,7 @@ static struct sh_mobile_lcdc_info lcdc_info = {
.meram_dev = &meram_info,
.ch[0] = {
.chan = LCDC_CHAN_MAINLCD,
@@ -38,7 +38,7 @@
.lcd_cfg = ap4evb_lcdc_modes,
.num_cfg = ARRAY_SIZE(ap4evb_lcdc_modes),
.meram_cfg = &lcd_meram_cfg,
-@@ -813,7 +813,7 @@ static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = {
+@@ -783,7 +783,7 @@ static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = {
.meram_dev = &meram_info,
.ch[0] = {
.chan = LCDC_CHAN_MAINLCD,
@@ -48,10 +48,10 @@
.clock_divider = 1,
.flags = LCDC_FLAGS_DWPOL,
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
-index 9c5e598..7db6a17 100644
+index 6e3c2df..6e36349 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
-@@ -388,7 +388,7 @@ static struct sh_mobile_lcdc_info lcdc_info = {
+@@ -387,7 +387,7 @@ static struct sh_mobile_lcdc_info lcdc_info = {
.clock_source = LCDC_CLK_BUS,
.ch[0] = {
.chan = LCDC_CHAN_MAINLCD,
@@ -60,7 +60,7 @@
.lcd_cfg = mackerel_lcdc_modes,
.num_cfg = ARRAY_SIZE(mackerel_lcdc_modes),
.interface_type = RGB24,
-@@ -451,7 +451,7 @@ static struct sh_mobile_lcdc_info hdmi_lcdc_info = {
+@@ -450,7 +450,7 @@ static struct sh_mobile_lcdc_info hdmi_lcdc_info = {
.clock_source = LCDC_CLK_EXTERNAL,
.ch[0] = {
.chan = LCDC_CHAN_MAINLCD,
@@ -70,7 +70,7 @@
.clock_divider = 1,
.flags = LCDC_FLAGS_DWPOL,
diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c
-index 7030f4c..7977911 100644
+index d362657..0a53ecd 100644
--- a/arch/sh/boards/mach-ap325rxa/setup.c
+++ b/arch/sh/boards/mach-ap325rxa/setup.c
@@ -207,7 +207,7 @@ static struct sh_mobile_lcdc_info lcdc_info = {
@@ -83,10 +83,10 @@
.clock_divider = 1,
.lcd_cfg = ap325rxa_lcdc_modes,
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
-index 92ddce4..1d4a706 100644
+index b24d69d..75e466f 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
-@@ -330,7 +330,7 @@ static struct sh_mobile_lcdc_info lcdc_info = {
+@@ -326,7 +326,7 @@ static struct sh_mobile_lcdc_info lcdc_info = {
.ch[0] = {
.interface_type = RGB18,
.chan = LCDC_CHAN_MAINLCD,
@@ -109,7 +109,7 @@
.clock_divider = 6,
.flags = LCDC_FLAGS_DWPOL,
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
-index e4c8119..ccf61fb 100644
+index 2d4c9c8..69f8d7d 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -244,7 +244,7 @@ static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = {
@@ -131,7 +131,7 @@
.clock_divider = 10,
.lcd_cfg = migor_lcd_modes,
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
-index b747c0a..3aab70c 100644
+index d007567..ab81abd 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -179,7 +179,7 @@ static struct sh_mobile_lcdc_info lcdc_info = {
@@ -144,7 +144,7 @@
.lcd_size_cfg = { /* 7.0 inch */
.width = 152,
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
-index a264ebf..aac5b36 100644
+index 97ab8ba..6e4c292 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -17,6 +17,7 @@
@@ -155,7 +155,7 @@
#include <linux/vmalloc.h>
#include <linux/ioctl.h>
#include <linux/slab.h>
-@@ -102,7 +103,7 @@ struct sh_mobile_lcdc_priv {
+@@ -101,7 +102,7 @@ struct sh_mobile_lcdc_priv {
struct sh_mobile_lcdc_chan ch[2];
struct notifier_block notifier;
int started;
@@ -164,14 +164,14 @@
struct sh_mobile_meram_info *meram_dev;
};
-@@ -215,6 +216,47 @@ struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
+@@ -214,6 +215,42 @@ struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
lcdc_sys_read_data,
};
+static int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var)
+{
-+ if (var->grayscale > 1)
-+ return var->grayscale;
++ if (var->fourcc.fourcc > 1)
++ return var->fourcc.fourcc;
+
+ switch (var->bits_per_pixel) {
+ case 16:
@@ -185,17 +185,12 @@
+ }
+}
+
-+static int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var)
++static bool sh_mobile_format_yuv(const struct fb_var_screeninfo *var)
+{
-+ return var->grayscale > 1;
-+}
-+
-+static bool sh_mobile_format_is_yuv(const struct fb_var_screeninfo *var)
-+{
-+ if (var->grayscale <= 1)
++ if (var->fourcc.fourcc <= 1)
+ return false;
+
-+ switch (var->grayscale) {
++ switch (var->fourcc.fourcc) {
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV16:
@@ -212,7 +207,7 @@
static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
{
if (atomic_inc_and_test(&priv->hw_usecnt)) {
-@@ -435,7 +477,6 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+@@ -434,7 +471,6 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
{
struct sh_mobile_lcdc_chan *ch;
unsigned long tmp;
@@ -220,7 +215,7 @@
int k, m;
/* Enable LCDC channels. Read data from external memory, avoid using the
-@@ -454,9 +495,6 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+@@ -453,9 +489,6 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
if (!ch->enabled)
continue;
@@ -230,7 +225,7 @@
/* Power supply */
lcdc_write_chan(ch, LDPMR, 0);
-@@ -487,31 +525,37 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+@@ -486,31 +519,37 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
sh_mobile_lcdc_geometry(ch);
@@ -279,8 +274,8 @@
+ break;
+ }
+
-+ if (sh_mobile_format_is_yuv(&ch->info->var)) {
-+ switch (ch->info->var.colorspace) {
++ if (sh_mobile_format_yuv(&ch->info->var)) {
++ switch (ch->info->var.fourcc.colorspace) {
+ case V4L2_COLORSPACE_REC709:
+ tmp |= LDDFR_CF1;
break;
@@ -292,16 +287,16 @@
break;
}
}
-@@ -519,7 +563,7 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+@@ -518,7 +557,7 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
lcdc_write_chan(ch, LDDFR, tmp);
lcdc_write_chan(ch, LDMLSR, ch->pitch);
lcdc_write_chan(ch, LDSA1R, ch->base_addr_y);
- if (ch->info->var.nonstd)
-+ if (sh_mobile_format_is_yuv(&ch->info->var))
++ if (sh_mobile_format_yuv(&ch->info->var))
lcdc_write_chan(ch, LDSA2R, ch->base_addr_c);
/* When using deferred I/O mode, configure the LCDC for one-shot
-@@ -536,21 +580,23 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+@@ -535,21 +574,23 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
}
/* Word and long word swap. */
@@ -339,7 +334,7 @@
}
lcdc_write(priv, _LDDDSR, tmp);
-@@ -622,12 +668,24 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+@@ -621,12 +662,24 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
ch->meram_enabled = 0;
}
@@ -369,7 +364,7 @@
ret = mdev->ops->meram_register(mdev, cfg, ch->pitch,
ch->info->var.yres, pixelformat,
-@@ -845,6 +903,7 @@ static struct fb_fix_screeninfo sh_mobile_lcdc_fix = {
+@@ -844,6 +897,7 @@ static struct fb_fix_screeninfo sh_mobile_lcdc_fix = {
.xpanstep = 0,
.ypanstep = 1,
.ywrapstep = 0,
@@ -377,18 +372,18 @@
};
static void sh_mobile_lcdc_fillrect(struct fb_info *info,
-@@ -877,8 +936,9 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
+@@ -876,8 +930,9 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
unsigned long new_pan_offset;
unsigned long base_addr_y, base_addr_c;
unsigned long c_offset;
-+ bool yuv = sh_mobile_format_is_yuv(&info->var);
++ bool yuv = sh_mobile_format_yuv(&info->var);
- if (!info->var.nonstd)
+ if (!yuv)
new_pan_offset = var->yoffset * info->fix.line_length
+ var->xoffset * (info->var.bits_per_pixel / 8);
else
-@@ -892,7 +952,7 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
+@@ -891,7 +946,7 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
/* Set the source address for the next refresh */
base_addr_y = ch->dma_handle + new_pan_offset;
@@ -397,7 +392,7 @@
/* Set y offset */
c_offset = var->yoffset * info->fix.line_length
* (info->var.bits_per_pixel - 8) / 8;
-@@ -900,7 +960,7 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
+@@ -899,7 +954,7 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
+ info->var.xres * info->var.yres_virtual
+ c_offset;
/* Set x offset */
@@ -406,7 +401,7 @@
base_addr_c += 2 * var->xoffset;
else
base_addr_c += var->xoffset;
-@@ -924,7 +984,7 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
+@@ -923,7 +978,7 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
ch->base_addr_c = base_addr_c;
lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
@@ -415,7 +410,7 @@
lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
if (lcdc_chan_is_sublcd(ch))
-@@ -1100,51 +1160,84 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
+@@ -1099,51 +1154,91 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
if (var->yres_virtual < var->yres)
var->yres_virtual = var->yres;
@@ -451,8 +446,19 @@
- var->transp.length = 8;
- } else
- return -EINVAL;
-+ if (sh_mobile_format_is_fourcc(var)) {
-+ switch (var->grayscale) {
++ if (var->fourcc.fourcc > 1) {
++ unsigned int fourcc = var->fourcc.fourcc;
++ unsigned int colorspace = var->fourcc.colorspace;
++
++ memset(&var->fourcc, 0, sizeof(var->fourcc));
++ var->fourcc.fourcc = fourcc;
++ var->fourcc.colorspace = colorspace;
+
+- var->red.msb_right = 0;
+- var->green.msb_right = 0;
+- var->blue.msb_right = 0;
+- var->transp.msb_right = 0;
++ switch (var->fourcc.fourcc) {
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ var->bits_per_pixel = 12;
@@ -477,10 +483,10 @@
+ /* Default to RGB and JPEG color-spaces for RGB and YUV formats
+ * respectively.
+ */
-+ if (!sh_mobile_format_is_yuv(var))
-+ var->colorspace = V4L2_COLORSPACE_SRGB;
-+ else if (var->colorspace != V4L2_COLORSPACE_REC709)
-+ var->colorspace = V4L2_COLORSPACE_JPEG;
++ if (!sh_mobile_format_yuv(var))
++ var->fourcc.colorspace = V4L2_COLORSPACE_SRGB;
++ else if (var->fourcc.colorspace != V4L2_COLORSPACE_REC709)
++ var->fourcc.colorspace = V4L2_COLORSPACE_JPEG;
+ } else {
+ if (var->bits_per_pixel <= 16) { /* RGB 565 */
+ var->bits_per_pixel = 16;
@@ -514,11 +520,7 @@
+ var->transp.length = 8;
+ } else
+ return -EINVAL;
-
-- var->red.msb_right = 0;
-- var->green.msb_right = 0;
-- var->blue.msb_right = 0;
-- var->transp.msb_right = 0;
++
+ var->red.msb_right = 0;
+ var->green.msb_right = 0;
+ var->blue.msb_right = 0;
@@ -538,20 +540,20 @@
return -EINVAL;
return 0;
-@@ -1158,7 +1251,7 @@ static int sh_mobile_set_par(struct fb_info *info)
+@@ -1157,7 +1252,7 @@ static int sh_mobile_set_par(struct fb_info *info)
sh_mobile_lcdc_stop(ch->lcdc);
- if (info->var.nonstd)
-+ if (sh_mobile_format_is_yuv(&info->var))
++ if (sh_mobile_format_yuv(&info->var))
info->fix.line_length = info->var.xres;
else
info->fix.line_length = info->var.xres
-@@ -1170,6 +1263,14 @@ static int sh_mobile_set_par(struct fb_info *info)
+@@ -1169,6 +1264,14 @@ static int sh_mobile_set_par(struct fb_info *info)
info->fix.line_length = line_length;
}
-+ if (sh_mobile_format_is_fourcc(&info->var)) {
++ if (info->var.fourcc.fourcc > 1) {
+ info->fix.type = FB_TYPE_FOURCC;
+ info->fix.visual = FB_VISUAL_FOURCC;
+ } else {
@@ -562,7 +564,7 @@
return ret;
}
-@@ -1464,9 +1565,9 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
+@@ -1463,9 +1566,9 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
for (i = 0, mode = cfg->lcd_cfg; i < cfg->num_cfg; i++, mode++) {
unsigned int size = mode->yres * mode->xres;
@@ -575,7 +577,7 @@
dev_err(dev, "yres must be multiple of 2 for YCbCr420 "
"mode.\n");
return -EINVAL;
-@@ -1484,14 +1585,6 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
+@@ -1483,14 +1586,6 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
dev_dbg(dev, "Found largest videomode %ux%u\n",
max_mode->xres, max_mode->yres);
@@ -590,7 +592,7 @@
/* Create the mode list. */
if (cfg->lcd_cfg == NULL) {
mode = &default_720p;
-@@ -1509,19 +1602,38 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
+@@ -1508,19 +1603,38 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
*/
var = &info->var;
fb_videomode_to_var(var, mode);
@@ -611,7 +613,7 @@
+ var->bits_per_pixel = 32;
+ break;
+ default:
-+ var->grayscale = cfg->fourcc;
++ var->fourcc.fourcc = cfg->fourcc;
+ break;
+ }
+
@@ -632,7 +634,7 @@
if (!buf) {
dev_err(dev, "unable to allocate buffer\n");
return -ENOMEM;
-@@ -1530,16 +1642,27 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
+@@ -1529,16 +1643,27 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
if (ret < 0) {
dev_err(dev, "unable to allocate cmap\n");
@@ -653,7 +655,7 @@
+ cfg->fourcc == V4L2_PIX_FMT_NV21)
+ info->fix.ypanstep = 2;
+
-+ if (sh_mobile_format_is_yuv(var)) {
++ if (sh_mobile_format_yuv(var)) {
info->fix.line_length = var->xres;
- else
- info->fix.line_length = var->xres * (cfg->bpp / 8);
@@ -665,7 +667,7 @@
info->screen_base = buf;
info->device = dev;
-@@ -1626,9 +1749,9 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
+@@ -1625,9 +1750,9 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
goto err1;
}
@@ -677,7 +679,7 @@
priv->base = ioremap_nocache(res->start, resource_size(res));
if (!priv->base)
-@@ -1675,13 +1798,10 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
+@@ -1674,13 +1799,10 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
if (error < 0)
goto err1;