diff mbox

sh: LCDC dcache flush for deferred io

Message ID 20090701065031.GA29429@linux-sh.org (mailing list archive)
State Accepted
Headers show

Commit Message

Paul Mundt July 1, 2009, 6:50 a.m. UTC
On Wed, Jul 01, 2009 at 02:04:05PM +0900, Magnus Damm wrote:
> From: Magnus Damm <damm@igel.co.jp>
> 
> Since writenotify on uncached vmas is unsupported in 2.6.31,
> live with cached framebuffer memory in the deferred io
> case for now and flush the dcache before forcing refresh.
> 
> Signed-off-by: Magnus Damm <damm@igel.co.jp>

Lets try this instead..

---

 drivers/video/sh_mobile_lcdcfb.c |   53 +++++++++++++++++++++++++++++++++------
 1 file changed, 45 insertions(+), 8 deletions(-)

--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Magnus Damm July 1, 2009, 8:12 a.m. UTC | #1
On Wed, Jul 1, 2009 at 3:50 PM, Paul Mundt<lethal@linux-sh.org> wrote:
> On Wed, Jul 01, 2009 at 02:04:05PM +0900, Magnus Damm wrote:
>> From: Magnus Damm <damm@igel.co.jp>
>>
>> Since writenotify on uncached vmas is unsupported in 2.6.31,
>> live with cached framebuffer memory in the deferred io
>> case for now and flush the dcache before forcing refresh.
>>
>> Signed-off-by: Magnus Damm <damm@igel.co.jp>
>
> Lets try this instead..

That's better, but slightly more complex. =)

Acked-by: Magnus damm <damm@igel.co.jp>
--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index f10d2fb..da983b7 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -17,6 +17,7 @@ 
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
+#include <linux/vmalloc.h>
 #include <video/sh_mobile_lcdc.h>
 #include <asm/atomic.h>
 
@@ -33,6 +34,7 @@  struct sh_mobile_lcdc_chan {
 	struct fb_info info;
 	dma_addr_t dma_handle;
 	struct fb_deferred_io defio;
+	struct scatterlist *sglist;
 	unsigned long frame_end;
 	wait_queue_head_t frame_end_wait;
 };
@@ -206,16 +208,38 @@  static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) {}
 static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) {}
 #endif
 
+static int sh_mobile_lcdc_sginit(struct fb_info *info,
+				  struct list_head *pagelist)
+{
+	struct sh_mobile_lcdc_chan *ch = info->par;
+	unsigned int nr_pages_max = info->fix.smem_len >> PAGE_SHIFT;
+	struct page *page;
+	int nr_pages = 0;
+
+	sg_init_table(ch->sglist, nr_pages_max);
+
+	list_for_each_entry(page, pagelist, lru)
+		sg_set_page(&ch->sglist[nr_pages++], page, PAGE_SIZE, 0);
+
+	return nr_pages;
+}
+
 static void sh_mobile_lcdc_deferred_io(struct fb_info *info,
 				       struct list_head *pagelist)
 {
 	struct sh_mobile_lcdc_chan *ch = info->par;
+	unsigned int nr_pages;
 
 	/* enable clocks before accessing hardware */
 	sh_mobile_lcdc_clk_on(ch->lcdc);
 
+	nr_pages = sh_mobile_lcdc_sginit(info, pagelist);
+	dma_map_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
+
 	/* trigger panel update */
 	lcdc_write_chan(ch, LDSM2R, 1);
+
+	dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
 }
 
 static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info)
@@ -846,21 +870,31 @@  static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
 	}
 
 	for (i = 0; i < j; i++) {
-		error = register_framebuffer(&priv->ch[i].info);
+		struct sh_mobile_lcdc_chan *ch = priv->ch + i;
+
+		info = &ch->info;
+
+		if (info->fbdefio) {
+			priv->ch->sglist = vmalloc(sizeof(struct scatterlist) *
+					info->fix.smem_len >> PAGE_SHIFT);
+			if (!priv->ch->sglist) {
+				dev_err(&pdev->dev, "cannot allocate sglist\n");
+				goto err1;
+			}
+		}
+
+		error = register_framebuffer(info);
 		if (error < 0)
 			goto err1;
-	}
 
-	for (i = 0; i < j; i++) {
-		info = &priv->ch[i].info;
 		dev_info(info->dev,
 			 "registered %s/%s as %dx%d %dbpp.\n",
 			 pdev->name,
-			 (priv->ch[i].cfg.chan == LCDC_CHAN_MAINLCD) ?
+			 (ch->cfg.chan == LCDC_CHAN_MAINLCD) ?
 			 "mainlcd" : "sublcd",
-			 (int) priv->ch[i].cfg.lcd_cfg.xres,
-			 (int) priv->ch[i].cfg.lcd_cfg.yres,
-			 priv->ch[i].cfg.bpp);
+			 (int) ch->cfg.lcd_cfg.xres,
+			 (int) ch->cfg.lcd_cfg.yres,
+			 ch->cfg.bpp);
 
 		/* deferred io mode: disable clock to save power */
 		if (info->fbdefio)
@@ -892,6 +926,9 @@  static int sh_mobile_lcdc_remove(struct platform_device *pdev)
 		if (!info->device)
 			continue;
 
+		if (priv->ch[i].sglist)
+			vfree(priv->ch[i].sglist);
+
 		dma_free_coherent(&pdev->dev, info->fix.smem_len,
 				  info->screen_base, priv->ch[i].dma_handle);
 		fb_dealloc_cmap(&info->cmap);