diff options
Diffstat (limited to 'drivers/video/s3c-fb.c')
-rw-r--r-- | drivers/video/s3c-fb.c | 202 |
1 files changed, 90 insertions, 112 deletions
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 0753b1cfcb8b..0c63b69b6340 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c | |||
@@ -192,6 +192,7 @@ struct s3c_fb_vsync { | |||
192 | * @regs: The mapped hardware registers. | 192 | * @regs: The mapped hardware registers. |
193 | * @variant: Variant information for this hardware. | 193 | * @variant: Variant information for this hardware. |
194 | * @enabled: A bitmask of enabled hardware windows. | 194 | * @enabled: A bitmask of enabled hardware windows. |
195 | * @output_on: Flag if the physical output is enabled. | ||
195 | * @pdata: The platform configuration data passed with the device. | 196 | * @pdata: The platform configuration data passed with the device. |
196 | * @windows: The hardware windows that have been claimed. | 197 | * @windows: The hardware windows that have been claimed. |
197 | * @irq_no: IRQ line number | 198 | * @irq_no: IRQ line number |
@@ -208,6 +209,7 @@ struct s3c_fb { | |||
208 | struct s3c_fb_variant variant; | 209 | struct s3c_fb_variant variant; |
209 | 210 | ||
210 | unsigned char enabled; | 211 | unsigned char enabled; |
212 | bool output_on; | ||
211 | 213 | ||
212 | struct s3c_fb_platdata *pdata; | 214 | struct s3c_fb_platdata *pdata; |
213 | struct s3c_fb_win *windows[S3C_FB_MAX_WIN]; | 215 | struct s3c_fb_win *windows[S3C_FB_MAX_WIN]; |
@@ -441,6 +443,39 @@ static void shadow_protect_win(struct s3c_fb_win *win, bool protect) | |||
441 | } | 443 | } |
442 | 444 | ||
443 | /** | 445 | /** |
446 | * s3c_fb_enable() - Set the state of the main LCD output | ||
447 | * @sfb: The main framebuffer state. | ||
448 | * @enable: The state to set. | ||
449 | */ | ||
450 | static void s3c_fb_enable(struct s3c_fb *sfb, int enable) | ||
451 | { | ||
452 | u32 vidcon0 = readl(sfb->regs + VIDCON0); | ||
453 | |||
454 | if (enable && !sfb->output_on) | ||
455 | pm_runtime_get_sync(sfb->dev); | ||
456 | |||
457 | if (enable) { | ||
458 | vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F; | ||
459 | } else { | ||
460 | /* see the note in the framebuffer datasheet about | ||
461 | * why you cannot take both of these bits down at the | ||
462 | * same time. */ | ||
463 | |||
464 | if (vidcon0 & VIDCON0_ENVID) { | ||
465 | vidcon0 |= VIDCON0_ENVID; | ||
466 | vidcon0 &= ~VIDCON0_ENVID_F; | ||
467 | } | ||
468 | } | ||
469 | |||
470 | writel(vidcon0, sfb->regs + VIDCON0); | ||
471 | |||
472 | if (!enable && sfb->output_on) | ||
473 | pm_runtime_put_sync(sfb->dev); | ||
474 | |||
475 | sfb->output_on = enable; | ||
476 | } | ||
477 | |||
478 | /** | ||
444 | * s3c_fb_set_par() - framebuffer request to set new framebuffer state. | 479 | * s3c_fb_set_par() - framebuffer request to set new framebuffer state. |
445 | * @info: The framebuffer to change. | 480 | * @info: The framebuffer to change. |
446 | * | 481 | * |
@@ -461,6 +496,8 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
461 | 496 | ||
462 | dev_dbg(sfb->dev, "setting framebuffer parameters\n"); | 497 | dev_dbg(sfb->dev, "setting framebuffer parameters\n"); |
463 | 498 | ||
499 | pm_runtime_get_sync(sfb->dev); | ||
500 | |||
464 | shadow_protect_win(win, 1); | 501 | shadow_protect_win(win, 1); |
465 | 502 | ||
466 | switch (var->bits_per_pixel) { | 503 | switch (var->bits_per_pixel) { |
@@ -510,9 +547,10 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
510 | if (sfb->variant.is_2443) | 547 | if (sfb->variant.is_2443) |
511 | data |= (1 << 5); | 548 | data |= (1 << 5); |
512 | 549 | ||
513 | data |= VIDCON0_ENVID | VIDCON0_ENVID_F; | ||
514 | writel(data, regs + VIDCON0); | 550 | writel(data, regs + VIDCON0); |
515 | 551 | ||
552 | s3c_fb_enable(sfb, 1); | ||
553 | |||
516 | data = VIDTCON0_VBPD(var->upper_margin - 1) | | 554 | data = VIDTCON0_VBPD(var->upper_margin - 1) | |
517 | VIDTCON0_VFPD(var->lower_margin - 1) | | 555 | VIDTCON0_VFPD(var->lower_margin - 1) | |
518 | VIDTCON0_VSPW(var->vsync_len - 1); | 556 | VIDTCON0_VSPW(var->vsync_len - 1); |
@@ -574,6 +612,7 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
574 | } | 612 | } |
575 | 613 | ||
576 | data = WINCONx_ENWIN; | 614 | data = WINCONx_ENWIN; |
615 | sfb->enabled |= (1 << win->index); | ||
577 | 616 | ||
578 | /* note, since we have to round up the bits-per-pixel, we end up | 617 | /* note, since we have to round up the bits-per-pixel, we end up |
579 | * relying on the bitfield information for r/g/b/a to work out | 618 | * relying on the bitfield information for r/g/b/a to work out |
@@ -621,7 +660,8 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
621 | } else if (var->transp.length == 1) | 660 | } else if (var->transp.length == 1) |
622 | data |= WINCON1_BPPMODE_25BPP_A1888 | 661 | data |= WINCON1_BPPMODE_25BPP_A1888 |
623 | | WINCON1_BLD_PIX; | 662 | | WINCON1_BLD_PIX; |
624 | else if (var->transp.length == 4) | 663 | else if ((var->transp.length == 4) || |
664 | (var->transp.length == 8)) | ||
625 | data |= WINCON1_BPPMODE_28BPP_A4888 | 665 | data |= WINCON1_BPPMODE_28BPP_A4888 |
626 | | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL; | 666 | | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL; |
627 | else | 667 | else |
@@ -654,6 +694,8 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
654 | 694 | ||
655 | shadow_protect_win(win, 0); | 695 | shadow_protect_win(win, 0); |
656 | 696 | ||
697 | pm_runtime_put_sync(sfb->dev); | ||
698 | |||
657 | return 0; | 699 | return 0; |
658 | } | 700 | } |
659 | 701 | ||
@@ -725,6 +767,8 @@ static int s3c_fb_setcolreg(unsigned regno, | |||
725 | dev_dbg(sfb->dev, "%s: win %d: %d => rgb=%d/%d/%d\n", | 767 | dev_dbg(sfb->dev, "%s: win %d: %d => rgb=%d/%d/%d\n", |
726 | __func__, win->index, regno, red, green, blue); | 768 | __func__, win->index, regno, red, green, blue); |
727 | 769 | ||
770 | pm_runtime_get_sync(sfb->dev); | ||
771 | |||
728 | switch (info->fix.visual) { | 772 | switch (info->fix.visual) { |
729 | case FB_VISUAL_TRUECOLOR: | 773 | case FB_VISUAL_TRUECOLOR: |
730 | /* true-colour, use pseudo-palette */ | 774 | /* true-colour, use pseudo-palette */ |
@@ -752,39 +796,15 @@ static int s3c_fb_setcolreg(unsigned regno, | |||
752 | break; | 796 | break; |
753 | 797 | ||
754 | default: | 798 | default: |
799 | pm_runtime_put_sync(sfb->dev); | ||
755 | return 1; /* unknown type */ | 800 | return 1; /* unknown type */ |
756 | } | 801 | } |
757 | 802 | ||
803 | pm_runtime_put_sync(sfb->dev); | ||
758 | return 0; | 804 | return 0; |
759 | } | 805 | } |
760 | 806 | ||
761 | /** | 807 | /** |
762 | * s3c_fb_enable() - Set the state of the main LCD output | ||
763 | * @sfb: The main framebuffer state. | ||
764 | * @enable: The state to set. | ||
765 | */ | ||
766 | static void s3c_fb_enable(struct s3c_fb *sfb, int enable) | ||
767 | { | ||
768 | u32 vidcon0 = readl(sfb->regs + VIDCON0); | ||
769 | |||
770 | if (enable) | ||
771 | vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F; | ||
772 | else { | ||
773 | /* see the note in the framebuffer datasheet about | ||
774 | * why you cannot take both of these bits down at the | ||
775 | * same time. */ | ||
776 | |||
777 | if (!(vidcon0 & VIDCON0_ENVID)) | ||
778 | return; | ||
779 | |||
780 | vidcon0 |= VIDCON0_ENVID; | ||
781 | vidcon0 &= ~VIDCON0_ENVID_F; | ||
782 | } | ||
783 | |||
784 | writel(vidcon0, sfb->regs + VIDCON0); | ||
785 | } | ||
786 | |||
787 | /** | ||
788 | * s3c_fb_blank() - blank or unblank the given window | 808 | * s3c_fb_blank() - blank or unblank the given window |
789 | * @blank_mode: The blank state from FB_BLANK_* | 809 | * @blank_mode: The blank state from FB_BLANK_* |
790 | * @info: The framebuffer to blank. | 810 | * @info: The framebuffer to blank. |
@@ -800,6 +820,8 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info) | |||
800 | 820 | ||
801 | dev_dbg(sfb->dev, "blank mode %d\n", blank_mode); | 821 | dev_dbg(sfb->dev, "blank mode %d\n", blank_mode); |
802 | 822 | ||
823 | pm_runtime_get_sync(sfb->dev); | ||
824 | |||
803 | wincon = readl(sfb->regs + sfb->variant.wincon + (index * 4)); | 825 | wincon = readl(sfb->regs + sfb->variant.wincon + (index * 4)); |
804 | 826 | ||
805 | switch (blank_mode) { | 827 | switch (blank_mode) { |
@@ -810,12 +832,16 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info) | |||
810 | 832 | ||
811 | case FB_BLANK_NORMAL: | 833 | case FB_BLANK_NORMAL: |
812 | /* disable the DMA and display 0x0 (black) */ | 834 | /* disable the DMA and display 0x0 (black) */ |
835 | shadow_protect_win(win, 1); | ||
813 | writel(WINxMAP_MAP | WINxMAP_MAP_COLOUR(0x0), | 836 | writel(WINxMAP_MAP | WINxMAP_MAP_COLOUR(0x0), |
814 | sfb->regs + sfb->variant.winmap + (index * 4)); | 837 | sfb->regs + sfb->variant.winmap + (index * 4)); |
838 | shadow_protect_win(win, 0); | ||
815 | break; | 839 | break; |
816 | 840 | ||
817 | case FB_BLANK_UNBLANK: | 841 | case FB_BLANK_UNBLANK: |
842 | shadow_protect_win(win, 1); | ||
818 | writel(0x0, sfb->regs + sfb->variant.winmap + (index * 4)); | 843 | writel(0x0, sfb->regs + sfb->variant.winmap + (index * 4)); |
844 | shadow_protect_win(win, 0); | ||
819 | wincon |= WINCONx_ENWIN; | 845 | wincon |= WINCONx_ENWIN; |
820 | sfb->enabled |= (1 << index); | 846 | sfb->enabled |= (1 << index); |
821 | break; | 847 | break; |
@@ -823,10 +849,13 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info) | |||
823 | case FB_BLANK_VSYNC_SUSPEND: | 849 | case FB_BLANK_VSYNC_SUSPEND: |
824 | case FB_BLANK_HSYNC_SUSPEND: | 850 | case FB_BLANK_HSYNC_SUSPEND: |
825 | default: | 851 | default: |
852 | pm_runtime_put_sync(sfb->dev); | ||
826 | return 1; | 853 | return 1; |
827 | } | 854 | } |
828 | 855 | ||
856 | shadow_protect_win(win, 1); | ||
829 | writel(wincon, sfb->regs + sfb->variant.wincon + (index * 4)); | 857 | writel(wincon, sfb->regs + sfb->variant.wincon + (index * 4)); |
858 | shadow_protect_win(win, 0); | ||
830 | 859 | ||
831 | /* Check the enabled state to see if we need to be running the | 860 | /* Check the enabled state to see if we need to be running the |
832 | * main LCD interface, as if there are no active windows then | 861 | * main LCD interface, as if there are no active windows then |
@@ -845,8 +874,13 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info) | |||
845 | /* we're stuck with this until we can do something about overriding | 874 | /* we're stuck with this until we can do something about overriding |
846 | * the power control using the blanking event for a single fb. | 875 | * the power control using the blanking event for a single fb. |
847 | */ | 876 | */ |
848 | if (index == sfb->pdata->default_win) | 877 | if (index == sfb->pdata->default_win) { |
878 | shadow_protect_win(win, 1); | ||
849 | s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0); | 879 | s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0); |
880 | shadow_protect_win(win, 0); | ||
881 | } | ||
882 | |||
883 | pm_runtime_put_sync(sfb->dev); | ||
850 | 884 | ||
851 | return 0; | 885 | return 0; |
852 | } | 886 | } |
@@ -870,6 +904,8 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var, | |||
870 | void __iomem *buf = sfb->regs + win->index * 8; | 904 | void __iomem *buf = sfb->regs + win->index * 8; |
871 | unsigned int start_boff, end_boff; | 905 | unsigned int start_boff, end_boff; |
872 | 906 | ||
907 | pm_runtime_get_sync(sfb->dev); | ||
908 | |||
873 | /* Offset in bytes to the start of the displayed area */ | 909 | /* Offset in bytes to the start of the displayed area */ |
874 | start_boff = var->yoffset * info->fix.line_length; | 910 | start_boff = var->yoffset * info->fix.line_length; |
875 | /* X offset depends on the current bpp */ | 911 | /* X offset depends on the current bpp */ |
@@ -888,6 +924,7 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var, | |||
888 | break; | 924 | break; |
889 | default: | 925 | default: |
890 | dev_err(sfb->dev, "invalid bpp\n"); | 926 | dev_err(sfb->dev, "invalid bpp\n"); |
927 | pm_runtime_put_sync(sfb->dev); | ||
891 | return -EINVAL; | 928 | return -EINVAL; |
892 | } | 929 | } |
893 | } | 930 | } |
@@ -903,6 +940,7 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var, | |||
903 | 940 | ||
904 | shadow_protect_win(win, 0); | 941 | shadow_protect_win(win, 0); |
905 | 942 | ||
943 | pm_runtime_put_sync(sfb->dev); | ||
906 | return 0; | 944 | return 0; |
907 | } | 945 | } |
908 | 946 | ||
@@ -992,11 +1030,16 @@ static int s3c_fb_wait_for_vsync(struct s3c_fb *sfb, u32 crtc) | |||
992 | if (crtc != 0) | 1030 | if (crtc != 0) |
993 | return -ENODEV; | 1031 | return -ENODEV; |
994 | 1032 | ||
1033 | pm_runtime_get_sync(sfb->dev); | ||
1034 | |||
995 | count = sfb->vsync_info.count; | 1035 | count = sfb->vsync_info.count; |
996 | s3c_fb_enable_irq(sfb); | 1036 | s3c_fb_enable_irq(sfb); |
997 | ret = wait_event_interruptible_timeout(sfb->vsync_info.wait, | 1037 | ret = wait_event_interruptible_timeout(sfb->vsync_info.wait, |
998 | count != sfb->vsync_info.count, | 1038 | count != sfb->vsync_info.count, |
999 | msecs_to_jiffies(VSYNC_TIMEOUT_MSEC)); | 1039 | msecs_to_jiffies(VSYNC_TIMEOUT_MSEC)); |
1040 | |||
1041 | pm_runtime_put_sync(sfb->dev); | ||
1042 | |||
1000 | if (ret == 0) | 1043 | if (ret == 0) |
1001 | return -ETIMEDOUT; | 1044 | return -ETIMEDOUT; |
1002 | 1045 | ||
@@ -1027,30 +1070,8 @@ static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
1027 | return ret; | 1070 | return ret; |
1028 | } | 1071 | } |
1029 | 1072 | ||
1030 | static int s3c_fb_open(struct fb_info *info, int user) | ||
1031 | { | ||
1032 | struct s3c_fb_win *win = info->par; | ||
1033 | struct s3c_fb *sfb = win->parent; | ||
1034 | |||
1035 | pm_runtime_get_sync(sfb->dev); | ||
1036 | |||
1037 | return 0; | ||
1038 | } | ||
1039 | |||
1040 | static int s3c_fb_release(struct fb_info *info, int user) | ||
1041 | { | ||
1042 | struct s3c_fb_win *win = info->par; | ||
1043 | struct s3c_fb *sfb = win->parent; | ||
1044 | |||
1045 | pm_runtime_put_sync(sfb->dev); | ||
1046 | |||
1047 | return 0; | ||
1048 | } | ||
1049 | |||
1050 | static struct fb_ops s3c_fb_ops = { | 1073 | static struct fb_ops s3c_fb_ops = { |
1051 | .owner = THIS_MODULE, | 1074 | .owner = THIS_MODULE, |
1052 | .fb_open = s3c_fb_open, | ||
1053 | .fb_release = s3c_fb_release, | ||
1054 | .fb_check_var = s3c_fb_check_var, | 1075 | .fb_check_var = s3c_fb_check_var, |
1055 | .fb_set_par = s3c_fb_set_par, | 1076 | .fb_set_par = s3c_fb_set_par, |
1056 | .fb_blank = s3c_fb_blank, | 1077 | .fb_blank = s3c_fb_blank, |
@@ -1452,7 +1473,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev) | |||
1452 | dev_err(dev, "failed to create window %d\n", win); | 1473 | dev_err(dev, "failed to create window %d\n", win); |
1453 | for (; win >= 0; win--) | 1474 | for (; win >= 0; win--) |
1454 | s3c_fb_release_win(sfb, sfb->windows[win]); | 1475 | s3c_fb_release_win(sfb, sfb->windows[win]); |
1455 | goto err_irq; | 1476 | goto err_pm_runtime; |
1456 | } | 1477 | } |
1457 | } | 1478 | } |
1458 | 1479 | ||
@@ -1461,7 +1482,8 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev) | |||
1461 | 1482 | ||
1462 | return 0; | 1483 | return 0; |
1463 | 1484 | ||
1464 | err_irq: | 1485 | err_pm_runtime: |
1486 | pm_runtime_put_sync(sfb->dev); | ||
1465 | free_irq(sfb->irq_no, sfb); | 1487 | free_irq(sfb->irq_no, sfb); |
1466 | 1488 | ||
1467 | err_ioremap: | 1489 | err_ioremap: |
@@ -1471,6 +1493,8 @@ err_req_region: | |||
1471 | release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res)); | 1493 | release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res)); |
1472 | 1494 | ||
1473 | err_lcd_clk: | 1495 | err_lcd_clk: |
1496 | pm_runtime_disable(sfb->dev); | ||
1497 | |||
1474 | if (!sfb->variant.has_clksel) { | 1498 | if (!sfb->variant.has_clksel) { |
1475 | clk_disable(sfb->lcd_clk); | 1499 | clk_disable(sfb->lcd_clk); |
1476 | clk_put(sfb->lcd_clk); | 1500 | clk_put(sfb->lcd_clk); |
@@ -1524,7 +1548,7 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev) | |||
1524 | return 0; | 1548 | return 0; |
1525 | } | 1549 | } |
1526 | 1550 | ||
1527 | #ifdef CONFIG_PM | 1551 | #ifdef CONFIG_PM_SLEEP |
1528 | static int s3c_fb_suspend(struct device *dev) | 1552 | static int s3c_fb_suspend(struct device *dev) |
1529 | { | 1553 | { |
1530 | struct platform_device *pdev = to_platform_device(dev); | 1554 | struct platform_device *pdev = to_platform_device(dev); |
@@ -1571,10 +1595,15 @@ static int s3c_fb_resume(struct device *dev) | |||
1571 | 1595 | ||
1572 | for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) { | 1596 | for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) { |
1573 | void __iomem *regs = sfb->regs + sfb->variant.keycon; | 1597 | void __iomem *regs = sfb->regs + sfb->variant.keycon; |
1598 | win = sfb->windows[win_no]; | ||
1599 | if (!win) | ||
1600 | continue; | ||
1574 | 1601 | ||
1602 | shadow_protect_win(win, 1); | ||
1575 | regs += (win_no * 8); | 1603 | regs += (win_no * 8); |
1576 | writel(0xffffff, regs + WKEYCON0); | 1604 | writel(0xffffff, regs + WKEYCON0); |
1577 | writel(0xffffff, regs + WKEYCON1); | 1605 | writel(0xffffff, regs + WKEYCON1); |
1606 | shadow_protect_win(win, 0); | ||
1578 | } | 1607 | } |
1579 | 1608 | ||
1580 | /* restore framebuffers */ | 1609 | /* restore framebuffers */ |
@@ -1589,27 +1618,19 @@ static int s3c_fb_resume(struct device *dev) | |||
1589 | 1618 | ||
1590 | return 0; | 1619 | return 0; |
1591 | } | 1620 | } |
1621 | #endif | ||
1592 | 1622 | ||
1623 | #ifdef CONFIG_PM_RUNTIME | ||
1593 | static int s3c_fb_runtime_suspend(struct device *dev) | 1624 | static int s3c_fb_runtime_suspend(struct device *dev) |
1594 | { | 1625 | { |
1595 | struct platform_device *pdev = to_platform_device(dev); | 1626 | struct platform_device *pdev = to_platform_device(dev); |
1596 | struct s3c_fb *sfb = platform_get_drvdata(pdev); | 1627 | struct s3c_fb *sfb = platform_get_drvdata(pdev); |
1597 | struct s3c_fb_win *win; | ||
1598 | int win_no; | ||
1599 | |||
1600 | for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) { | ||
1601 | win = sfb->windows[win_no]; | ||
1602 | if (!win) | ||
1603 | continue; | ||
1604 | |||
1605 | /* use the blank function to push into power-down */ | ||
1606 | s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo); | ||
1607 | } | ||
1608 | 1628 | ||
1609 | if (!sfb->variant.has_clksel) | 1629 | if (!sfb->variant.has_clksel) |
1610 | clk_disable(sfb->lcd_clk); | 1630 | clk_disable(sfb->lcd_clk); |
1611 | 1631 | ||
1612 | clk_disable(sfb->bus_clk); | 1632 | clk_disable(sfb->bus_clk); |
1633 | |||
1613 | return 0; | 1634 | return 0; |
1614 | } | 1635 | } |
1615 | 1636 | ||
@@ -1618,8 +1639,6 @@ static int s3c_fb_runtime_resume(struct device *dev) | |||
1618 | struct platform_device *pdev = to_platform_device(dev); | 1639 | struct platform_device *pdev = to_platform_device(dev); |
1619 | struct s3c_fb *sfb = platform_get_drvdata(pdev); | 1640 | struct s3c_fb *sfb = platform_get_drvdata(pdev); |
1620 | struct s3c_fb_platdata *pd = sfb->pdata; | 1641 | struct s3c_fb_platdata *pd = sfb->pdata; |
1621 | struct s3c_fb_win *win; | ||
1622 | int win_no; | ||
1623 | 1642 | ||
1624 | clk_enable(sfb->bus_clk); | 1643 | clk_enable(sfb->bus_clk); |
1625 | 1644 | ||
@@ -1630,39 +1649,10 @@ static int s3c_fb_runtime_resume(struct device *dev) | |||
1630 | pd->setup_gpio(); | 1649 | pd->setup_gpio(); |
1631 | writel(pd->vidcon1, sfb->regs + VIDCON1); | 1650 | writel(pd->vidcon1, sfb->regs + VIDCON1); |
1632 | 1651 | ||
1633 | /* zero all windows before we do anything */ | ||
1634 | for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++) | ||
1635 | s3c_fb_clear_win(sfb, win_no); | ||
1636 | |||
1637 | for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) { | ||
1638 | void __iomem *regs = sfb->regs + sfb->variant.keycon; | ||
1639 | |||
1640 | regs += (win_no * 8); | ||
1641 | writel(0xffffff, regs + WKEYCON0); | ||
1642 | writel(0xffffff, regs + WKEYCON1); | ||
1643 | } | ||
1644 | |||
1645 | /* restore framebuffers */ | ||
1646 | for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) { | ||
1647 | win = sfb->windows[win_no]; | ||
1648 | if (!win) | ||
1649 | continue; | ||
1650 | |||
1651 | dev_dbg(&pdev->dev, "resuming window %d\n", win_no); | ||
1652 | s3c_fb_set_par(win->fbinfo); | ||
1653 | } | ||
1654 | |||
1655 | return 0; | 1652 | return 0; |
1656 | } | 1653 | } |
1657 | |||
1658 | #else | ||
1659 | #define s3c_fb_suspend NULL | ||
1660 | #define s3c_fb_resume NULL | ||
1661 | #define s3c_fb_runtime_suspend NULL | ||
1662 | #define s3c_fb_runtime_resume NULL | ||
1663 | #endif | 1654 | #endif |
1664 | 1655 | ||
1665 | |||
1666 | #define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4)) | 1656 | #define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4)) |
1667 | #define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8)) | 1657 | #define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8)) |
1668 | 1658 | ||
@@ -1985,10 +1975,9 @@ static struct platform_device_id s3c_fb_driver_ids[] = { | |||
1985 | MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids); | 1975 | MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids); |
1986 | 1976 | ||
1987 | static const struct dev_pm_ops s3cfb_pm_ops = { | 1977 | static const struct dev_pm_ops s3cfb_pm_ops = { |
1988 | .suspend = s3c_fb_suspend, | 1978 | SET_SYSTEM_SLEEP_PM_OPS(s3c_fb_suspend, s3c_fb_resume) |
1989 | .resume = s3c_fb_resume, | 1979 | SET_RUNTIME_PM_OPS(s3c_fb_runtime_suspend, s3c_fb_runtime_resume, |
1990 | .runtime_suspend = s3c_fb_runtime_suspend, | 1980 | NULL) |
1991 | .runtime_resume = s3c_fb_runtime_resume, | ||
1992 | }; | 1981 | }; |
1993 | 1982 | ||
1994 | static struct platform_driver s3c_fb_driver = { | 1983 | static struct platform_driver s3c_fb_driver = { |
@@ -2002,18 +1991,7 @@ static struct platform_driver s3c_fb_driver = { | |||
2002 | }, | 1991 | }, |
2003 | }; | 1992 | }; |
2004 | 1993 | ||
2005 | static int __init s3c_fb_init(void) | 1994 | module_platform_driver(s3c_fb_driver); |
2006 | { | ||
2007 | return platform_driver_register(&s3c_fb_driver); | ||
2008 | } | ||
2009 | |||
2010 | static void __exit s3c_fb_cleanup(void) | ||
2011 | { | ||
2012 | platform_driver_unregister(&s3c_fb_driver); | ||
2013 | } | ||
2014 | |||
2015 | module_init(s3c_fb_init); | ||
2016 | module_exit(s3c_fb_cleanup); | ||
2017 | 1995 | ||
2018 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | 1996 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); |
2019 | MODULE_DESCRIPTION("Samsung S3C SoC Framebuffer driver"); | 1997 | MODULE_DESCRIPTION("Samsung S3C SoC Framebuffer driver"); |