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

Commit 92e1f9a7 authored by Phil Edworthy's avatar Phil Edworthy Committed by Paul Mundt
Browse files

video: sh_mobile_lcdcfb: Fix panning.



Fixed SH-Mobile panning. Previously the address of the frame to be displayed
was updated in the VSync end interrupt. This meant there was a minimum of 1
frame bewteen calling FBIOPAN_DISPLAY ioctl and the pan occuring. This meant
that apps were not able to use the FBIO_WAITFORVSYNC ioctl to wait for the
pan to complete. This patch moves the write to LDSA1R mirror reg into the
pan ioctl.  Tested on MS7724 board against 2.6.33-rc7

Signed-off-by: default avatarPhil Edworthy <phil.edworthy@renesas.com>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 40331b21
Loading
Loading
Loading
Loading
+18 −28
Original line number Diff line number Diff line
@@ -124,7 +124,6 @@ struct sh_mobile_lcdc_chan {
	struct scatterlist *sglist;
	unsigned long frame_end;
	unsigned long pan_offset;
	unsigned long new_pan_offset;
	wait_queue_head_t frame_end_wait;
	struct completion vsync_completion;
};
@@ -369,21 +368,6 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
		}

		/* VSYNC End */
		if ((ldintr & LDINTR_VES) &&
		    (ch->pan_offset != ch->new_pan_offset)) {
			unsigned long ldrcntr = lcdc_read(priv, _LDRCNTR);
			/* Set the source address for the next refresh */
			lcdc_write_chan_mirror(ch, LDSA1R, ch->dma_handle +
					       ch->new_pan_offset);
			if (lcdc_chan_is_sublcd(ch))
				lcdc_write(ch->lcdc, _LDRCNTR,
					   ldrcntr ^ LDRCNTR_SRS);
			else
				lcdc_write(ch->lcdc, _LDRCNTR,
					   ldrcntr ^ LDRCNTR_MRS);
			ch->pan_offset = ch->new_pan_offset;
		}

		if (ldintr & LDINTR_VES)
			complete(&ch->vsync_completion);
	}
@@ -774,21 +758,28 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
				     struct fb_info *info)
{
	struct sh_mobile_lcdc_chan *ch = info->par;
	struct sh_mobile_lcdc_priv *priv = ch->lcdc;
	unsigned long ldrcntr;
	unsigned long new_pan_offset;

	if (info->var.xoffset == var->xoffset &&
	    info->var.yoffset == var->yoffset)
	new_pan_offset = (var->yoffset * info->fix.line_length) +
		(var->xoffset * (info->var.bits_per_pixel / 8));

	if (new_pan_offset == ch->pan_offset)
		return 0;	/* No change, do nothing */

	ch->new_pan_offset = (var->yoffset * info->fix.line_length) +
		(var->xoffset * (info->var.bits_per_pixel / 8));
	ldrcntr = lcdc_read(priv, _LDRCNTR);

	/* Set the source address for the next refresh */
	lcdc_write_chan_mirror(ch, LDSA1R, ch->dma_handle + new_pan_offset);
	if (lcdc_chan_is_sublcd(ch))
		lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
	else
		lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_MRS);

	ch->pan_offset = new_pan_offset;

	if (ch->new_pan_offset != ch->pan_offset) {
		unsigned long ldintr;
		ldintr = lcdc_read(ch->lcdc, _LDINTR);
		ldintr |= LDINTR_VEE;
		lcdc_write(ch->lcdc, _LDINTR, ldintr);
	sh_mobile_lcdc_deferred_io_touch(info);
	}

	return 0;
}
@@ -1009,7 +1000,6 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
		init_waitqueue_head(&priv->ch[i].frame_end_wait);
		init_completion(&priv->ch[i].vsync_completion);
		priv->ch[j].pan_offset = 0;
		priv->ch[j].new_pan_offset = 0;

		switch (pdata->ch[i].chan) {
		case LCDC_CHAN_MAINLCD: