diff options
| -rw-r--r-- | drivers/video/s3c2410fb.c | 67 | ||||
| -rw-r--r-- | drivers/video/s3c2410fb.h | 5 |
2 files changed, 70 insertions, 2 deletions
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index b0b4513ba537..7da0027e2409 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
| 25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
| 26 | #include <linux/clk.h> | 26 | #include <linux/clk.h> |
| 27 | #include <linux/cpufreq.h> | ||
| 27 | 28 | ||
| 28 | #include <asm/io.h> | 29 | #include <asm/io.h> |
| 29 | #include <asm/div64.h> | 30 | #include <asm/div64.h> |
| @@ -89,7 +90,7 @@ static void s3c2410fb_set_lcdaddr(struct fb_info *info) | |||
| 89 | static unsigned int s3c2410fb_calc_pixclk(struct s3c2410fb_info *fbi, | 90 | static unsigned int s3c2410fb_calc_pixclk(struct s3c2410fb_info *fbi, |
| 90 | unsigned long pixclk) | 91 | unsigned long pixclk) |
| 91 | { | 92 | { |
| 92 | unsigned long clk = clk_get_rate(fbi->clk); | 93 | unsigned long clk = fbi->clk_rate; |
| 93 | unsigned long long div; | 94 | unsigned long long div; |
| 94 | 95 | ||
| 95 | /* pixclk is in picoseconds, our clock is in Hz | 96 | /* pixclk is in picoseconds, our clock is in Hz |
| @@ -758,6 +759,57 @@ static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) | |||
| 758 | return IRQ_HANDLED; | 759 | return IRQ_HANDLED; |
| 759 | } | 760 | } |
| 760 | 761 | ||
| 762 | #ifdef CONFIG_CPU_FREQ | ||
| 763 | |||
| 764 | static int s3c2410fb_cpufreq_transition(struct notifier_block *nb, | ||
| 765 | unsigned long val, void *data) | ||
| 766 | { | ||
| 767 | struct cpufreq_freqs *freqs = data; | ||
| 768 | struct s3c2410fb_info *info; | ||
| 769 | struct fb_info *fbinfo; | ||
| 770 | long delta_f; | ||
| 771 | |||
| 772 | info = container_of(nb, struct s3c2410fb_info, freq_transition); | ||
| 773 | fbinfo = platform_get_drvdata(to_platform_device(info->dev)); | ||
| 774 | |||
| 775 | /* work out change, <0 for speed-up */ | ||
| 776 | delta_f = info->clk_rate - clk_get_rate(info->clk); | ||
| 777 | |||
| 778 | if ((val == CPUFREQ_POSTCHANGE && delta_f > 0) || | ||
| 779 | (val == CPUFREQ_PRECHANGE && delta_f < 0)) { | ||
| 780 | info->clk_rate = clk_get_rate(info->clk); | ||
| 781 | s3c2410fb_activate_var(fbinfo); | ||
| 782 | } | ||
| 783 | |||
| 784 | return 0; | ||
| 785 | } | ||
| 786 | |||
| 787 | static inline int s3c2410fb_cpufreq_register(struct s3c2410fb_info *info) | ||
| 788 | { | ||
| 789 | info->freq_transition.notifier_call = s3c2410fb_cpufreq_transition; | ||
| 790 | |||
| 791 | return cpufreq_register_notifier(&info->freq_transition, | ||
| 792 | CPUFREQ_TRANSITION_NOTIFIER); | ||
| 793 | } | ||
| 794 | |||
| 795 | static inline void s3c2410fb_cpufreq_deregister(struct s3c2410fb_info *info) | ||
| 796 | { | ||
| 797 | cpufreq_unregister_notifier(&info->freq_transition, | ||
| 798 | CPUFREQ_TRANSITION_NOTIFIER); | ||
| 799 | } | ||
| 800 | |||
| 801 | #else | ||
| 802 | static inline int s3c2410fb_cpufreq_register(struct s3c2410fb_info *info) | ||
| 803 | { | ||
| 804 | return 0; | ||
| 805 | } | ||
| 806 | |||
| 807 | static inline void s3c2410fb_cpufreq_deregister(struct s3c2410fb_info *info) | ||
| 808 | { | ||
| 809 | } | ||
| 810 | #endif | ||
| 811 | |||
| 812 | |||
| 761 | static char driver_name[] = "s3c2410fb"; | 813 | static char driver_name[] = "s3c2410fb"; |
| 762 | 814 | ||
| 763 | static int __init s3c24xxfb_probe(struct platform_device *pdev, | 815 | static int __init s3c24xxfb_probe(struct platform_device *pdev, |
| @@ -875,6 +927,8 @@ static int __init s3c24xxfb_probe(struct platform_device *pdev, | |||
| 875 | 927 | ||
| 876 | msleep(1); | 928 | msleep(1); |
| 877 | 929 | ||
| 930 | info->clk_rate = clk_get_rate(info->clk); | ||
| 931 | |||
| 878 | /* find maximum required memory size for display */ | 932 | /* find maximum required memory size for display */ |
| 879 | for (i = 0; i < mach_info->num_displays; i++) { | 933 | for (i = 0; i < mach_info->num_displays; i++) { |
| 880 | unsigned long smem_len = mach_info->displays[i].xres; | 934 | unsigned long smem_len = mach_info->displays[i].xres; |
| @@ -904,11 +958,17 @@ static int __init s3c24xxfb_probe(struct platform_device *pdev, | |||
| 904 | 958 | ||
| 905 | s3c2410fb_check_var(&fbinfo->var, fbinfo); | 959 | s3c2410fb_check_var(&fbinfo->var, fbinfo); |
| 906 | 960 | ||
| 961 | ret = s3c2410fb_cpufreq_register(info); | ||
| 962 | if (ret < 0) { | ||
| 963 | dev_err(&pdev->dev, "Failed to register cpufreq\n"); | ||
| 964 | goto free_video_memory; | ||
| 965 | } | ||
| 966 | |||
| 907 | ret = register_framebuffer(fbinfo); | 967 | ret = register_framebuffer(fbinfo); |
| 908 | if (ret < 0) { | 968 | if (ret < 0) { |
| 909 | printk(KERN_ERR "Failed to register framebuffer device: %d\n", | 969 | printk(KERN_ERR "Failed to register framebuffer device: %d\n", |
| 910 | ret); | 970 | ret); |
| 911 | goto free_video_memory; | 971 | goto free_cpufreq; |
| 912 | } | 972 | } |
| 913 | 973 | ||
| 914 | /* create device files */ | 974 | /* create device files */ |
| @@ -922,6 +982,8 @@ static int __init s3c24xxfb_probe(struct platform_device *pdev, | |||
| 922 | 982 | ||
| 923 | return 0; | 983 | return 0; |
| 924 | 984 | ||
| 985 | free_cpufreq: | ||
| 986 | s3c2410fb_cpufreq_deregister(info); | ||
| 925 | free_video_memory: | 987 | free_video_memory: |
| 926 | s3c2410fb_unmap_video_memory(fbinfo); | 988 | s3c2410fb_unmap_video_memory(fbinfo); |
| 927 | release_clock: | 989 | release_clock: |
| @@ -961,6 +1023,7 @@ static int s3c2410fb_remove(struct platform_device *pdev) | |||
| 961 | int irq; | 1023 | int irq; |
| 962 | 1024 | ||
| 963 | unregister_framebuffer(fbinfo); | 1025 | unregister_framebuffer(fbinfo); |
| 1026 | s3c2410fb_cpufreq_deregister(info); | ||
| 964 | 1027 | ||
| 965 | s3c2410fb_lcd_enable(info, 0); | 1028 | s3c2410fb_lcd_enable(info, 0); |
| 966 | msleep(1); | 1029 | msleep(1); |
diff --git a/drivers/video/s3c2410fb.h b/drivers/video/s3c2410fb.h index 9a6ba3e9d1b8..47a17bd23011 100644 --- a/drivers/video/s3c2410fb.h +++ b/drivers/video/s3c2410fb.h | |||
| @@ -29,8 +29,13 @@ struct s3c2410fb_info { | |||
| 29 | enum s3c_drv_type drv_type; | 29 | enum s3c_drv_type drv_type; |
| 30 | struct s3c2410fb_hw regs; | 30 | struct s3c2410fb_hw regs; |
| 31 | 31 | ||
| 32 | unsigned long clk_rate; | ||
| 32 | unsigned int palette_ready; | 33 | unsigned int palette_ready; |
| 33 | 34 | ||
| 35 | #ifdef CONFIG_CPU_FREQ | ||
| 36 | struct notifier_block freq_transition; | ||
| 37 | #endif | ||
| 38 | |||
| 34 | /* keep these registers in case we need to re-write palette */ | 39 | /* keep these registers in case we need to re-write palette */ |
| 35 | u32 palette_buffer[256]; | 40 | u32 palette_buffer[256]; |
| 36 | u32 pseudo_pal[16]; | 41 | u32 pseudo_pal[16]; |
