aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/sh_mobile_lcdcfb.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-07-03 18:13:18 -0400
committerTejun Heo <tj@kernel.org>2009-07-03 18:13:18 -0400
commitc43768cbb7655ea5ff782ae250f6e2ef4297cf98 (patch)
tree3982e41dde3eecaa3739a5d1a8ed18d04bd74f01 /drivers/video/sh_mobile_lcdcfb.c
parent1a8dd307cc0a2119be4e578c517795464e6dabba (diff)
parent746a99a5af60ee676afa2ba469ccd1373493c7e7 (diff)
Merge branch 'master' into for-next
Pull linus#master to merge PER_CPU_DEF_ATTRIBUTES and alpha build fix changes. As alpha in percpu tree uses 'weak' attribute instead of inline assembly, there's no need for __used attribute. Conflicts: arch/alpha/include/asm/percpu.h arch/mn10300/kernel/vmlinux.lds.S include/linux/percpu-defs.h
Diffstat (limited to 'drivers/video/sh_mobile_lcdcfb.c')
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c53
1 files changed, 45 insertions, 8 deletions
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index f10d2fbeda06..da983b720f08 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -17,6 +17,7 @@
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/dma-mapping.h> 18#include <linux/dma-mapping.h>
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20#include <linux/vmalloc.h>
20#include <video/sh_mobile_lcdc.h> 21#include <video/sh_mobile_lcdc.h>
21#include <asm/atomic.h> 22#include <asm/atomic.h>
22 23
@@ -33,6 +34,7 @@ struct sh_mobile_lcdc_chan {
33 struct fb_info info; 34 struct fb_info info;
34 dma_addr_t dma_handle; 35 dma_addr_t dma_handle;
35 struct fb_deferred_io defio; 36 struct fb_deferred_io defio;
37 struct scatterlist *sglist;
36 unsigned long frame_end; 38 unsigned long frame_end;
37 wait_queue_head_t frame_end_wait; 39 wait_queue_head_t frame_end_wait;
38}; 40};
@@ -206,16 +208,38 @@ static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) {}
206static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) {} 208static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) {}
207#endif 209#endif
208 210
211static int sh_mobile_lcdc_sginit(struct fb_info *info,
212 struct list_head *pagelist)
213{
214 struct sh_mobile_lcdc_chan *ch = info->par;
215 unsigned int nr_pages_max = info->fix.smem_len >> PAGE_SHIFT;
216 struct page *page;
217 int nr_pages = 0;
218
219 sg_init_table(ch->sglist, nr_pages_max);
220
221 list_for_each_entry(page, pagelist, lru)
222 sg_set_page(&ch->sglist[nr_pages++], page, PAGE_SIZE, 0);
223
224 return nr_pages;
225}
226
209static void sh_mobile_lcdc_deferred_io(struct fb_info *info, 227static void sh_mobile_lcdc_deferred_io(struct fb_info *info,
210 struct list_head *pagelist) 228 struct list_head *pagelist)
211{ 229{
212 struct sh_mobile_lcdc_chan *ch = info->par; 230 struct sh_mobile_lcdc_chan *ch = info->par;
231 unsigned int nr_pages;
213 232
214 /* enable clocks before accessing hardware */ 233 /* enable clocks before accessing hardware */
215 sh_mobile_lcdc_clk_on(ch->lcdc); 234 sh_mobile_lcdc_clk_on(ch->lcdc);
216 235
236 nr_pages = sh_mobile_lcdc_sginit(info, pagelist);
237 dma_map_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
238
217 /* trigger panel update */ 239 /* trigger panel update */
218 lcdc_write_chan(ch, LDSM2R, 1); 240 lcdc_write_chan(ch, LDSM2R, 1);
241
242 dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
219} 243}
220 244
221static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info) 245static 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)
846 } 870 }
847 871
848 for (i = 0; i < j; i++) { 872 for (i = 0; i < j; i++) {
849 error = register_framebuffer(&priv->ch[i].info); 873 struct sh_mobile_lcdc_chan *ch = priv->ch + i;
874
875 info = &ch->info;
876
877 if (info->fbdefio) {
878 priv->ch->sglist = vmalloc(sizeof(struct scatterlist) *
879 info->fix.smem_len >> PAGE_SHIFT);
880 if (!priv->ch->sglist) {
881 dev_err(&pdev->dev, "cannot allocate sglist\n");
882 goto err1;
883 }
884 }
885
886 error = register_framebuffer(info);
850 if (error < 0) 887 if (error < 0)
851 goto err1; 888 goto err1;
852 }
853 889
854 for (i = 0; i < j; i++) {
855 info = &priv->ch[i].info;
856 dev_info(info->dev, 890 dev_info(info->dev,
857 "registered %s/%s as %dx%d %dbpp.\n", 891 "registered %s/%s as %dx%d %dbpp.\n",
858 pdev->name, 892 pdev->name,
859 (priv->ch[i].cfg.chan == LCDC_CHAN_MAINLCD) ? 893 (ch->cfg.chan == LCDC_CHAN_MAINLCD) ?
860 "mainlcd" : "sublcd", 894 "mainlcd" : "sublcd",
861 (int) priv->ch[i].cfg.lcd_cfg.xres, 895 (int) ch->cfg.lcd_cfg.xres,
862 (int) priv->ch[i].cfg.lcd_cfg.yres, 896 (int) ch->cfg.lcd_cfg.yres,
863 priv->ch[i].cfg.bpp); 897 ch->cfg.bpp);
864 898
865 /* deferred io mode: disable clock to save power */ 899 /* deferred io mode: disable clock to save power */
866 if (info->fbdefio) 900 if (info->fbdefio)
@@ -892,6 +926,9 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
892 if (!info->device) 926 if (!info->device)
893 continue; 927 continue;
894 928
929 if (priv->ch[i].sglist)
930 vfree(priv->ch[i].sglist);
931
895 dma_free_coherent(&pdev->dev, info->fix.smem_len, 932 dma_free_coherent(&pdev->dev, info->fix.smem_len,
896 info->screen_base, priv->ch[i].dma_handle); 933 info->screen_base, priv->ch[i].dma_handle);
897 fb_dealloc_cmap(&info->cmap); 934 fb_dealloc_cmap(&info->cmap);