diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-03-26 14:11:23 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-03-26 14:11:23 -0400 |
commit | 928a726b0e12184729900c076e13dbf1c511c96c (patch) | |
tree | f31a7f23c1b511ebb486598cc746786e1821d48c /drivers/video | |
parent | 8ff64b539bfd998792614481ccb67139b97075ef (diff) | |
parent | eaeed5d31d8ded02fa0a4b608f57418cc0e65b07 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6: (96 commits)
sh: add support for SMSC Polaris platform
sh: fix the HD64461 level-triggered interrupts handling
sh: sh-rtc wakeup support
sh: sh-rtc invalid time rework
sh: sh-rtc carry interrupt rework
sh: disallow kexec virtual entry
sh: kexec jump: fix for ftrace.
sh: kexec: Drop SR.BL bit toggling.
sh: add kexec jump support
sh: rework kexec segment code
sh: simplify kexec vbr code
sh: Flush only the needed range when unmapping a VMA.
sh: Update debugfs ASID dumping for 16-bit ASID support.
sh: tlb-pteaex: Kill off legacy PTEA updates.
sh: Support for extended ASIDs on PTEAEX-capable SH-X3 cores.
sh: sh7763rdp: Change IRQ number for sh_eth of sh7763rdp
sh: espt-giga board support
sh: dma: Make G2 DMA configurable.
sh: dma: Make PVR2 DMA configurable.
sh: Move IRQ multi definition of DMAC to defconfig
...
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/pvr2fb.c | 16 | ||||
-rw-r--r-- | drivers/video/sh_mobile_lcdcfb.c | 66 |
2 files changed, 67 insertions, 15 deletions
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c index 0a0fd48a8566..53f8f1100e81 100644 --- a/drivers/video/pvr2fb.c +++ b/drivers/video/pvr2fb.c | |||
@@ -61,7 +61,7 @@ | |||
61 | #include <mach-dreamcast/mach/sysasic.h> | 61 | #include <mach-dreamcast/mach/sysasic.h> |
62 | #endif | 62 | #endif |
63 | 63 | ||
64 | #ifdef CONFIG_SH_DMA | 64 | #ifdef CONFIG_PVR2_DMA |
65 | #include <linux/pagemap.h> | 65 | #include <linux/pagemap.h> |
66 | #include <mach/dma.h> | 66 | #include <mach/dma.h> |
67 | #include <asm/dma.h> | 67 | #include <asm/dma.h> |
@@ -188,7 +188,7 @@ static unsigned int is_blanked = 0; /* Is the screen blanked? */ | |||
188 | static unsigned long pvr2fb_map; | 188 | static unsigned long pvr2fb_map; |
189 | #endif | 189 | #endif |
190 | 190 | ||
191 | #ifdef CONFIG_SH_DMA | 191 | #ifdef CONFIG_PVR2_DMA |
192 | static unsigned int shdma = PVR2_CASCADE_CHAN; | 192 | static unsigned int shdma = PVR2_CASCADE_CHAN; |
193 | static unsigned int pvr2dma = ONCHIP_NR_DMA_CHANNELS; | 193 | static unsigned int pvr2dma = ONCHIP_NR_DMA_CHANNELS; |
194 | #endif | 194 | #endif |
@@ -207,7 +207,7 @@ static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id); | |||
207 | static int pvr2_init_cable(void); | 207 | static int pvr2_init_cable(void); |
208 | static int pvr2_get_param(const struct pvr2_params *p, const char *s, | 208 | static int pvr2_get_param(const struct pvr2_params *p, const char *s, |
209 | int val, int size); | 209 | int val, int size); |
210 | #ifdef CONFIG_SH_DMA | 210 | #ifdef CONFIG_PVR2_DMA |
211 | static ssize_t pvr2fb_write(struct fb_info *info, const char *buf, | 211 | static ssize_t pvr2fb_write(struct fb_info *info, const char *buf, |
212 | size_t count, loff_t *ppos); | 212 | size_t count, loff_t *ppos); |
213 | #endif | 213 | #endif |
@@ -218,7 +218,7 @@ static struct fb_ops pvr2fb_ops = { | |||
218 | .fb_blank = pvr2fb_blank, | 218 | .fb_blank = pvr2fb_blank, |
219 | .fb_check_var = pvr2fb_check_var, | 219 | .fb_check_var = pvr2fb_check_var, |
220 | .fb_set_par = pvr2fb_set_par, | 220 | .fb_set_par = pvr2fb_set_par, |
221 | #ifdef CONFIG_SH_DMA | 221 | #ifdef CONFIG_PVR2_DMA |
222 | .fb_write = pvr2fb_write, | 222 | .fb_write = pvr2fb_write, |
223 | #endif | 223 | #endif |
224 | .fb_fillrect = cfb_fillrect, | 224 | .fb_fillrect = cfb_fillrect, |
@@ -671,7 +671,7 @@ static int pvr2_init_cable(void) | |||
671 | return cable_type; | 671 | return cable_type; |
672 | } | 672 | } |
673 | 673 | ||
674 | #ifdef CONFIG_SH_DMA | 674 | #ifdef CONFIG_PVR2_DMA |
675 | static ssize_t pvr2fb_write(struct fb_info *info, const char *buf, | 675 | static ssize_t pvr2fb_write(struct fb_info *info, const char *buf, |
676 | size_t count, loff_t *ppos) | 676 | size_t count, loff_t *ppos) |
677 | { | 677 | { |
@@ -743,7 +743,7 @@ out_unmap: | |||
743 | 743 | ||
744 | return ret; | 744 | return ret; |
745 | } | 745 | } |
746 | #endif /* CONFIG_SH_DMA */ | 746 | #endif /* CONFIG_PVR2_DMA */ |
747 | 747 | ||
748 | /** | 748 | /** |
749 | * pvr2fb_common_init | 749 | * pvr2fb_common_init |
@@ -893,7 +893,7 @@ static int __init pvr2fb_dc_init(void) | |||
893 | return -EBUSY; | 893 | return -EBUSY; |
894 | } | 894 | } |
895 | 895 | ||
896 | #ifdef CONFIG_SH_DMA | 896 | #ifdef CONFIG_PVR2_DMA |
897 | if (request_dma(pvr2dma, "pvr2") != 0) { | 897 | if (request_dma(pvr2dma, "pvr2") != 0) { |
898 | free_irq(HW_EVENT_VSYNC, 0); | 898 | free_irq(HW_EVENT_VSYNC, 0); |
899 | return -EBUSY; | 899 | return -EBUSY; |
@@ -915,7 +915,7 @@ static void __exit pvr2fb_dc_exit(void) | |||
915 | } | 915 | } |
916 | 916 | ||
917 | free_irq(HW_EVENT_VSYNC, 0); | 917 | free_irq(HW_EVENT_VSYNC, 0); |
918 | #ifdef CONFIG_SH_DMA | 918 | #ifdef CONFIG_PVR2_DMA |
919 | free_dma(pvr2dma); | 919 | free_dma(pvr2dma); |
920 | #endif | 920 | #endif |
921 | } | 921 | } |
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 2c5d069e5f06..b433b8ac76d9 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c | |||
@@ -33,6 +33,8 @@ struct sh_mobile_lcdc_chan { | |||
33 | struct fb_info info; | 33 | struct fb_info info; |
34 | dma_addr_t dma_handle; | 34 | dma_addr_t dma_handle; |
35 | struct fb_deferred_io defio; | 35 | struct fb_deferred_io defio; |
36 | unsigned long frame_end; | ||
37 | wait_queue_head_t frame_end_wait; | ||
36 | }; | 38 | }; |
37 | 39 | ||
38 | struct sh_mobile_lcdc_priv { | 40 | struct sh_mobile_lcdc_priv { |
@@ -226,7 +228,10 @@ static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info) | |||
226 | static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data) | 228 | static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data) |
227 | { | 229 | { |
228 | struct sh_mobile_lcdc_priv *priv = data; | 230 | struct sh_mobile_lcdc_priv *priv = data; |
231 | struct sh_mobile_lcdc_chan *ch; | ||
229 | unsigned long tmp; | 232 | unsigned long tmp; |
233 | int is_sub; | ||
234 | int k; | ||
230 | 235 | ||
231 | /* acknowledge interrupt */ | 236 | /* acknowledge interrupt */ |
232 | tmp = lcdc_read(priv, _LDINTR); | 237 | tmp = lcdc_read(priv, _LDINTR); |
@@ -234,8 +239,24 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data) | |||
234 | tmp |= 0x000000ff ^ LDINTR_FS; /* status in low 8 */ | 239 | tmp |= 0x000000ff ^ LDINTR_FS; /* status in low 8 */ |
235 | lcdc_write(priv, _LDINTR, tmp); | 240 | lcdc_write(priv, _LDINTR, tmp); |
236 | 241 | ||
237 | /* disable clocks */ | 242 | /* figure out if this interrupt is for main or sub lcd */ |
238 | sh_mobile_lcdc_clk_off(priv); | 243 | is_sub = (lcdc_read(priv, _LDSR) & (1 << 10)) ? 1 : 0; |
244 | |||
245 | /* wake up channel and disable clocks*/ | ||
246 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | ||
247 | ch = &priv->ch[k]; | ||
248 | |||
249 | if (!ch->enabled) | ||
250 | continue; | ||
251 | |||
252 | if (is_sub == lcdc_chan_is_sublcd(ch)) { | ||
253 | ch->frame_end = 1; | ||
254 | wake_up(&ch->frame_end_wait); | ||
255 | |||
256 | sh_mobile_lcdc_clk_off(priv); | ||
257 | } | ||
258 | } | ||
259 | |||
239 | return IRQ_HANDLED; | 260 | return IRQ_HANDLED; |
240 | } | 261 | } |
241 | 262 | ||
@@ -448,18 +469,27 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) | |||
448 | struct sh_mobile_lcdc_board_cfg *board_cfg; | 469 | struct sh_mobile_lcdc_board_cfg *board_cfg; |
449 | int k; | 470 | int k; |
450 | 471 | ||
451 | /* tell the board code to disable the panel */ | 472 | /* clean up deferred io and ask board code to disable panel */ |
452 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | 473 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { |
453 | ch = &priv->ch[k]; | 474 | ch = &priv->ch[k]; |
454 | board_cfg = &ch->cfg.board_cfg; | ||
455 | if (board_cfg->display_off) | ||
456 | board_cfg->display_off(board_cfg->board_data); | ||
457 | 475 | ||
458 | /* cleanup deferred io if enabled */ | 476 | /* deferred io mode: |
477 | * flush frame, and wait for frame end interrupt | ||
478 | * clean up deferred io and enable clock | ||
479 | */ | ||
459 | if (ch->info.fbdefio) { | 480 | if (ch->info.fbdefio) { |
481 | ch->frame_end = 0; | ||
482 | schedule_delayed_work(&ch->info.deferred_work, 0); | ||
483 | wait_event(ch->frame_end_wait, ch->frame_end); | ||
460 | fb_deferred_io_cleanup(&ch->info); | 484 | fb_deferred_io_cleanup(&ch->info); |
461 | ch->info.fbdefio = NULL; | 485 | ch->info.fbdefio = NULL; |
486 | sh_mobile_lcdc_clk_on(priv); | ||
462 | } | 487 | } |
488 | |||
489 | board_cfg = &ch->cfg.board_cfg; | ||
490 | if (board_cfg->display_off) | ||
491 | board_cfg->display_off(board_cfg->board_data); | ||
492 | |||
463 | } | 493 | } |
464 | 494 | ||
465 | /* stop the lcdc */ | 495 | /* stop the lcdc */ |
@@ -652,6 +682,26 @@ static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp) | |||
652 | return 0; | 682 | return 0; |
653 | } | 683 | } |
654 | 684 | ||
685 | static int sh_mobile_lcdc_suspend(struct device *dev) | ||
686 | { | ||
687 | struct platform_device *pdev = to_platform_device(dev); | ||
688 | |||
689 | sh_mobile_lcdc_stop(platform_get_drvdata(pdev)); | ||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | static int sh_mobile_lcdc_resume(struct device *dev) | ||
694 | { | ||
695 | struct platform_device *pdev = to_platform_device(dev); | ||
696 | |||
697 | return sh_mobile_lcdc_start(platform_get_drvdata(pdev)); | ||
698 | } | ||
699 | |||
700 | static struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = { | ||
701 | .suspend = sh_mobile_lcdc_suspend, | ||
702 | .resume = sh_mobile_lcdc_resume, | ||
703 | }; | ||
704 | |||
655 | static int sh_mobile_lcdc_remove(struct platform_device *pdev); | 705 | static int sh_mobile_lcdc_remove(struct platform_device *pdev); |
656 | 706 | ||
657 | static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) | 707 | static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) |
@@ -707,6 +757,7 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
707 | dev_err(&pdev->dev, "unsupported interface type\n"); | 757 | dev_err(&pdev->dev, "unsupported interface type\n"); |
708 | goto err1; | 758 | goto err1; |
709 | } | 759 | } |
760 | init_waitqueue_head(&priv->ch[i].frame_end_wait); | ||
710 | 761 | ||
711 | switch (pdata->ch[i].chan) { | 762 | switch (pdata->ch[i].chan) { |
712 | case LCDC_CHAN_MAINLCD: | 763 | case LCDC_CHAN_MAINLCD: |
@@ -860,6 +911,7 @@ static struct platform_driver sh_mobile_lcdc_driver = { | |||
860 | .driver = { | 911 | .driver = { |
861 | .name = "sh_mobile_lcdc_fb", | 912 | .name = "sh_mobile_lcdc_fb", |
862 | .owner = THIS_MODULE, | 913 | .owner = THIS_MODULE, |
914 | .pm = &sh_mobile_lcdc_dev_pm_ops, | ||
863 | }, | 915 | }, |
864 | .probe = sh_mobile_lcdc_probe, | 916 | .probe = sh_mobile_lcdc_probe, |
865 | .remove = sh_mobile_lcdc_remove, | 917 | .remove = sh_mobile_lcdc_remove, |