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>
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index fc12e37..6d377b4 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -273,7 +273,7 @@
 				  struct list_head *pagelist)
 {
 	struct sh_mobile_lcdc_chan *ch = info->par;
-	unsigned int nr_pages_max = info->fix.smem_len >> PAGE_SHIFT;
+	unsigned int nr_pages_max = ch->fb_size >> PAGE_SHIFT;
 	struct page *page;
 	int nr_pages = 0;
 
@@ -541,17 +541,6 @@
 	return var->grayscale > 1;
 }
 
-static bool sh_mobile_format_is_yuv(const struct fb_var_screeninfo *var)
-{
-	const struct sh_mobile_lcdc_format_info *format;
-
-	if (var->grayscale <= 1)
-		return false;
-
-	format = sh_mobile_format_info(var->grayscale);
-	return format ? format->yuv : false;
-}
-
 /* -----------------------------------------------------------------------------
  * Start, stop and IRQ
  */
@@ -650,7 +639,7 @@
 	h_total = mode->xres + mode->hsync_len + mode->left_margin
 		+ mode->right_margin;
 	tmp = h_total / 8; /* HTCN */
-	tmp |= (min(mode->xres, var->xres) / 8) << 16; /* HDCN */
+	tmp |= (min(mode->xres, ch->xres) / 8) << 16; /* HDCN */
 	lcdc_write_chan(ch, LDHCNR, tmp);
 
 	hsync_pos = mode->xres + mode->right_margin;
@@ -661,7 +650,7 @@
 	/* vertical configuration */
 	tmp = mode->yres + mode->vsync_len + mode->upper_margin
 	    + mode->lower_margin; /* VTLN */
-	tmp |= min(mode->yres, var->yres) << 16; /* VDLN */
+	tmp |= min(mode->yres, ch->yres) << 16; /* VDLN */
 	lcdc_write_chan(ch, LDVLNR, tmp);
 
 	tmp = mode->yres + mode->lower_margin; /* VSYNP */
@@ -738,7 +727,7 @@
 		tmp = ch->format->lddfr;
 
 		if (ch->format->yuv) {
-			switch (ch->info->var.colorspace) {
+			switch (ch->colorspace) {
 			case V4L2_COLORSPACE_REC709:
 				tmp |= LDDFR_CF1;
 				break;
@@ -836,11 +825,8 @@
 		if (!ch->enabled)
 			continue;
 
-		ch->base_addr_y = ch->info->fix.smem_start;
-		ch->base_addr_c = ch->base_addr_y
-				+ ch->info->var.xres
-				* ch->info->var.yres_virtual;
-		ch->pitch = ch->info->fix.line_length;
+		ch->base_addr_y = ch->dma_handle;
+		ch->base_addr_c = ch->base_addr_y + ch->xres * ch->yres_virtual;
 
 		/* Enable MERAM if possible. */
 		cfg = ch->cfg.meram_cfg;
@@ -875,7 +861,7 @@
 		}
 
 		ret = mdev->ops->meram_register(mdev, cfg, ch->pitch,
-					ch->info->var.yres, pixelformat,
+					ch->yres, pixelformat,
 					ch->base_addr_y, ch->base_addr_c,
 					&ch->base_addr_y, &ch->base_addr_c,
 					&ch->pitch);
@@ -1037,14 +1023,12 @@
 	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);
 
-	if (!yuv)
-		new_pan_offset = var->yoffset * info->fix.line_length
-			       + var->xoffset * (info->var.bits_per_pixel / 8);
+	if (!ch->format->yuv)
+		new_pan_offset = var->yoffset * ch->pitch
+			       + var->xoffset * (ch->format->bpp / 8);
 	else
-		new_pan_offset = var->yoffset * info->fix.line_length
-			       + var->xoffset;
+		new_pan_offset = var->yoffset * ch->pitch + var->xoffset;
 
 	if (new_pan_offset == ch->pan_offset)
 		return 0;	/* No change, do nothing */
@@ -1053,12 +1037,11 @@
 
 	/* Set the source address for the next refresh */
 	base_addr_y = ch->dma_handle + new_pan_offset;
-	if (yuv) {
+	if (ch->format->yuv) {
 		/* Set y offset */
-		c_offset = var->yoffset * info->fix.line_length
-			 * (info->var.bits_per_pixel - 8) / 8;
-		base_addr_c = ch->dma_handle
-			    + info->var.xres * info->var.yres_virtual
+		c_offset = var->yoffset * ch->pitch
+			 * (ch->format->bpp - 8) / 8;
+		base_addr_c = ch->dma_handle + ch->xres * ch->yres_virtual
 			    + c_offset;
 		/* Set x offset */
 		if (ch->format->fourcc == V4L2_PIX_FMT_NV24)
@@ -1085,7 +1068,7 @@
 	ch->base_addr_c = base_addr_c;
 
 	lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
-	if (yuv)
+	if (ch->format->yuv)
 		lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
 
 	if (lcdc_chan_is_sublcd(ch))
@@ -1338,24 +1321,28 @@
 static int sh_mobile_set_par(struct fb_info *info)
 {
 	struct sh_mobile_lcdc_chan *ch = info->par;
-	u32 line_length = info->fix.line_length;
 	int ret;
 
 	sh_mobile_lcdc_stop(ch->lcdc);
 
-	if (sh_mobile_format_is_yuv(&info->var))
-		info->fix.line_length = info->var.xres;
-	else
-		info->fix.line_length = info->var.xres
-				      * info->var.bits_per_pixel / 8;
-
 	ch->format = sh_mobile_format_info(sh_mobile_format_fourcc(&info->var));
+	ch->colorspace = info->var.colorspace;
+
+	ch->xres = info->var.xres;
+	ch->xres_virtual = info->var.xres_virtual;
+	ch->yres = info->var.yres;
+	ch->yres_virtual = info->var.yres_virtual;
+
+	if (ch->format->yuv)
+		ch->pitch = info->var.xres;
+	else
+		ch->pitch = info->var.xres * ch->format->bpp / 8;
 
 	ret = sh_mobile_lcdc_start(ch->lcdc);
-	if (ret < 0) {
+	if (ret < 0)
 		dev_err(info->dev, "%s: unable to restart LCDC\n", __func__);
-		info->fix.line_length = line_length;
-	}
+
+	info->fix.line_length = ch->pitch;
 
 	if (sh_mobile_format_is_fourcc(&info->var)) {
 		info->fix.type = FB_TYPE_FOURCC;
@@ -1384,8 +1371,8 @@
 	/* blank the screen? */
 	if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) {
 		struct fb_fillrect rect = {
-			.width = info->var.xres,
-			.height = info->var.yres,
+			.width = ch->xres,
+			.height = ch->yres,
 		};
 		sh_mobile_lcdc_fillrect(info, &rect);
 	}
@@ -1525,6 +1512,13 @@
 	info->fix = sh_mobile_lcdc_fix;
 	info->fix.smem_start = ch->dma_handle;
 	info->fix.smem_len = ch->fb_size;
+	info->fix.line_length = ch->pitch;
+
+	if (ch->format->yuv)
+		info->fix.visual = FB_VISUAL_FOURCC;
+	else
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+
 	if (ch->format->fourcc == V4L2_PIX_FMT_NV12 ||
 	    ch->format->fourcc == V4L2_PIX_FMT_NV21)
 		info->fix.ypanstep = 2;
@@ -1552,14 +1546,6 @@
 	if (ret)
 		return ret;
 
-	if (ch->format->yuv) {
-		info->fix.line_length = var->xres;
-		info->fix.visual = FB_VISUAL_FOURCC;
-	} else {
-		info->fix.line_length = var->xres * ch->format->bpp / 8;
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-	}
-
 	return 0;
 }
 
@@ -1836,8 +1822,6 @@
 		return -EINVAL;
 	}
 
-	ch->format = format;
-
 	/* Iterate through the modes to validate them and find the highest
 	 * resolution.
 	 */
@@ -1875,6 +1859,21 @@
 		num_modes = cfg->num_modes;
 	}
 
+	/* Use the first mode as default. */
+	ch->format = format;
+	ch->xres = mode->xres;
+	ch->xres_virtual = mode->xres;
+	ch->yres = mode->yres;
+	ch->yres_virtual = mode->yres * 2;
+
+	if (!format->yuv) {
+		ch->colorspace = V4L2_COLORSPACE_SRGB;
+		ch->pitch = ch->xres * format->bpp / 8;
+	} else {
+		ch->colorspace = V4L2_COLORSPACE_REC709;
+		ch->pitch = ch->xres;
+	}
+
 	ch->display.width = cfg->panel_cfg.width;
 	ch->display.height = cfg->panel_cfg.height;
 	ch->display.mode = *mode;
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
index cc22b9e..19a4cd7 100644
--- a/drivers/video/sh_mobile_lcdcfb.h
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -74,9 +74,15 @@
 	struct completion vsync_completion;
 
 	const struct sh_mobile_lcdc_format_info *format;
+	u32 colorspace;
+	unsigned int xres;
+	unsigned int xres_virtual;
+	unsigned int yres;
+	unsigned int yres_virtual;
+	unsigned int pitch;
+
 	unsigned long base_addr_y;
 	unsigned long base_addr_c;
-	unsigned int pitch;
 
 	int (*notify)(struct sh_mobile_lcdc_chan *ch,
 		      enum sh_mobile_lcdc_entity_event event,