Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 58f03d99 authored by Laurent Pinchart's avatar Laurent Pinchart
Browse files

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: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
parent e8363140
Loading
Loading
Loading
Loading
+54 −55
Original line number Original line Diff line number Diff line
@@ -273,7 +273,7 @@ static int sh_mobile_lcdc_sginit(struct fb_info *info,
				  struct list_head *pagelist)
				  struct list_head *pagelist)
{
{
	struct sh_mobile_lcdc_chan *ch = info->par;
	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;
	struct page *page;
	int nr_pages = 0;
	int nr_pages = 0;


@@ -541,17 +541,6 @@ static int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var)
	return var->grayscale > 1;
	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
 * Start, stop and IRQ
 */
 */
@@ -650,7 +639,7 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
	h_total = mode->xres + mode->hsync_len + mode->left_margin
	h_total = mode->xres + mode->hsync_len + mode->left_margin
		+ mode->right_margin;
		+ mode->right_margin;
	tmp = h_total / 8; /* HTCN */
	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);
	lcdc_write_chan(ch, LDHCNR, tmp);


	hsync_pos = mode->xres + mode->right_margin;
	hsync_pos = mode->xres + mode->right_margin;
@@ -661,7 +650,7 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
	/* vertical configuration */
	/* vertical configuration */
	tmp = mode->yres + mode->vsync_len + mode->upper_margin
	tmp = mode->yres + mode->vsync_len + mode->upper_margin
	    + mode->lower_margin; /* VTLN */
	    + 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);
	lcdc_write_chan(ch, LDVLNR, tmp);


	tmp = mode->yres + mode->lower_margin; /* VSYNP */
	tmp = mode->yres + mode->lower_margin; /* VSYNP */
@@ -738,7 +727,7 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
		tmp = ch->format->lddfr;
		tmp = ch->format->lddfr;


		if (ch->format->yuv) {
		if (ch->format->yuv) {
			switch (ch->info->var.colorspace) {
			switch (ch->colorspace) {
			case V4L2_COLORSPACE_REC709:
			case V4L2_COLORSPACE_REC709:
				tmp |= LDDFR_CF1;
				tmp |= LDDFR_CF1;
				break;
				break;
@@ -836,11 +825,8 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
		if (!ch->enabled)
		if (!ch->enabled)
			continue;
			continue;


		ch->base_addr_y = ch->info->fix.smem_start;
		ch->base_addr_y = ch->dma_handle;
		ch->base_addr_c = ch->base_addr_y
		ch->base_addr_c = ch->base_addr_y + ch->xres * ch->yres_virtual;
				+ ch->info->var.xres
				* ch->info->var.yres_virtual;
		ch->pitch = ch->info->fix.line_length;


		/* Enable MERAM if possible. */
		/* Enable MERAM if possible. */
		cfg = ch->cfg.meram_cfg;
		cfg = ch->cfg.meram_cfg;
@@ -875,7 +861,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
		}
		}


		ret = mdev->ops->meram_register(mdev, cfg, ch->pitch,
		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->base_addr_y, &ch->base_addr_c,
					&ch->base_addr_y, &ch->base_addr_c,
					&ch->pitch);
					&ch->pitch);
@@ -1037,14 +1023,12 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
	unsigned long new_pan_offset;
	unsigned long new_pan_offset;
	unsigned long base_addr_y, base_addr_c;
	unsigned long base_addr_y, base_addr_c;
	unsigned long c_offset;
	unsigned long c_offset;
	bool yuv = sh_mobile_format_is_yuv(&info->var);


	if (!yuv)
	if (!ch->format->yuv)
		new_pan_offset = var->yoffset * info->fix.line_length
		new_pan_offset = var->yoffset * ch->pitch
			       + var->xoffset * (info->var.bits_per_pixel / 8);
			       + var->xoffset * (ch->format->bpp / 8);
	else
	else
		new_pan_offset = var->yoffset * info->fix.line_length
		new_pan_offset = var->yoffset * ch->pitch + var->xoffset;
			       + var->xoffset;


	if (new_pan_offset == ch->pan_offset)
	if (new_pan_offset == ch->pan_offset)
		return 0;	/* No change, do nothing */
		return 0;	/* No change, do nothing */
@@ -1053,12 +1037,11 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,


	/* Set the source address for the next refresh */
	/* Set the source address for the next refresh */
	base_addr_y = ch->dma_handle + new_pan_offset;
	base_addr_y = ch->dma_handle + new_pan_offset;
	if (yuv) {
	if (ch->format->yuv) {
		/* Set y offset */
		/* Set y offset */
		c_offset = var->yoffset * info->fix.line_length
		c_offset = var->yoffset * ch->pitch
			 * (info->var.bits_per_pixel - 8) / 8;
			 * (ch->format->bpp - 8) / 8;
		base_addr_c = ch->dma_handle
		base_addr_c = ch->dma_handle + ch->xres * ch->yres_virtual
			    + info->var.xres * info->var.yres_virtual
			    + c_offset;
			    + c_offset;
		/* Set x offset */
		/* Set x offset */
		if (ch->format->fourcc == V4L2_PIX_FMT_NV24)
		if (ch->format->fourcc == V4L2_PIX_FMT_NV24)
@@ -1085,7 +1068,7 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
	ch->base_addr_c = base_addr_c;
	ch->base_addr_c = base_addr_c;


	lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
	lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
	if (yuv)
	if (ch->format->yuv)
		lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
		lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);


	if (lcdc_chan_is_sublcd(ch))
	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
static int sh_mobile_set_par(struct fb_info *info)
static int sh_mobile_set_par(struct fb_info *info)
{
{
	struct sh_mobile_lcdc_chan *ch = info->par;
	struct sh_mobile_lcdc_chan *ch = info->par;
	u32 line_length = info->fix.line_length;
	int ret;
	int ret;


	sh_mobile_lcdc_stop(ch->lcdc);
	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->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);
	ret = sh_mobile_lcdc_start(ch->lcdc);
	if (ret < 0) {
	if (ret < 0)
		dev_err(info->dev, "%s: unable to restart LCDC\n", __func__);
		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)) {
	if (sh_mobile_format_is_fourcc(&info->var)) {
		info->fix.type = FB_TYPE_FOURCC;
		info->fix.type = FB_TYPE_FOURCC;
@@ -1384,8 +1371,8 @@ static int sh_mobile_lcdc_blank(int blank, struct fb_info *info)
	/* blank the screen? */
	/* blank the screen? */
	if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) {
	if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) {
		struct fb_fillrect rect = {
		struct fb_fillrect rect = {
			.width = info->var.xres,
			.width = ch->xres,
			.height = info->var.yres,
			.height = ch->yres,
		};
		};
		sh_mobile_lcdc_fillrect(info, &rect);
		sh_mobile_lcdc_fillrect(info, &rect);
	}
	}
@@ -1525,6 +1512,13 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
	info->fix = sh_mobile_lcdc_fix;
	info->fix = sh_mobile_lcdc_fix;
	info->fix.smem_start = ch->dma_handle;
	info->fix.smem_start = ch->dma_handle;
	info->fix.smem_len = ch->fb_size;
	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 ||
	if (ch->format->fourcc == V4L2_PIX_FMT_NV12 ||
	    ch->format->fourcc == V4L2_PIX_FMT_NV21)
	    ch->format->fourcc == V4L2_PIX_FMT_NV21)
		info->fix.ypanstep = 2;
		info->fix.ypanstep = 2;
@@ -1552,14 +1546,6 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
	if (ret)
	if (ret)
		return 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;
	return 0;
}
}


@@ -1836,8 +1822,6 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
		return -EINVAL;
		return -EINVAL;
	}
	}


	ch->format = format;

	/* Iterate through the modes to validate them and find the highest
	/* Iterate through the modes to validate them and find the highest
	 * resolution.
	 * resolution.
	 */
	 */
@@ -1875,6 +1859,21 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
		num_modes = cfg->num_modes;
		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.width = cfg->panel_cfg.width;
	ch->display.height = cfg->panel_cfg.height;
	ch->display.height = cfg->panel_cfg.height;
	ch->display.mode = *mode;
	ch->display.mode = *mode;
+7 −1
Original line number Original line Diff line number Diff line
@@ -74,9 +74,15 @@ struct sh_mobile_lcdc_chan {
	struct completion vsync_completion;
	struct completion vsync_completion;


	const struct sh_mobile_lcdc_format_info *format;
	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_y;
	unsigned long base_addr_c;
	unsigned long base_addr_c;
	unsigned int pitch;


	int (*notify)(struct sh_mobile_lcdc_chan *ch,
	int (*notify)(struct sh_mobile_lcdc_chan *ch,
		      enum sh_mobile_lcdc_entity_event event,
		      enum sh_mobile_lcdc_entity_event event,