aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/atmel_lcdfb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/atmel_lcdfb.c')
-rw-r--r--drivers/video/atmel_lcdfb.c120
1 files changed, 92 insertions, 28 deletions
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 025428e04c33..c1a2914447e1 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -34,6 +34,77 @@
34#define ATMEL_LCDC_DMA_BURST_LEN 8 /* words */ 34#define ATMEL_LCDC_DMA_BURST_LEN 8 /* words */
35#define ATMEL_LCDC_FIFO_SIZE 512 /* words */ 35#define ATMEL_LCDC_FIFO_SIZE 512 /* words */
36 36
37struct atmel_lcdfb_config {
38 bool have_alt_pixclock;
39 bool have_hozval;
40 bool have_intensity_bit;
41};
42
43static struct atmel_lcdfb_config at91sam9261_config = {
44 .have_hozval = true,
45 .have_intensity_bit = true,
46};
47
48static struct atmel_lcdfb_config at91sam9263_config = {
49 .have_intensity_bit = true,
50};
51
52static struct atmel_lcdfb_config at91sam9g10_config = {
53 .have_hozval = true,
54};
55
56static struct atmel_lcdfb_config at91sam9g45_config = {
57 .have_alt_pixclock = true,
58};
59
60static struct atmel_lcdfb_config at91sam9g45es_config = {
61};
62
63static struct atmel_lcdfb_config at91sam9rl_config = {
64 .have_intensity_bit = true,
65};
66
67static struct atmel_lcdfb_config at32ap_config = {
68 .have_hozval = true,
69};
70
71static const struct platform_device_id atmel_lcdfb_devtypes[] = {
72 {
73 .name = "at91sam9261-lcdfb",
74 .driver_data = (unsigned long)&at91sam9261_config,
75 }, {
76 .name = "at91sam9263-lcdfb",
77 .driver_data = (unsigned long)&at91sam9263_config,
78 }, {
79 .name = "at91sam9g10-lcdfb",
80 .driver_data = (unsigned long)&at91sam9g10_config,
81 }, {
82 .name = "at91sam9g45-lcdfb",
83 .driver_data = (unsigned long)&at91sam9g45_config,
84 }, {
85 .name = "at91sam9g45es-lcdfb",
86 .driver_data = (unsigned long)&at91sam9g45es_config,
87 }, {
88 .name = "at91sam9rl-lcdfb",
89 .driver_data = (unsigned long)&at91sam9rl_config,
90 }, {
91 .name = "at32ap-lcdfb",
92 .driver_data = (unsigned long)&at32ap_config,
93 }, {
94 /* terminator */
95 }
96};
97
98static struct atmel_lcdfb_config *
99atmel_lcdfb_get_config(struct platform_device *pdev)
100{
101 unsigned long data;
102
103 data = platform_get_device_id(pdev)->driver_data;
104
105 return (struct atmel_lcdfb_config *)data;
106}
107
37#if defined(CONFIG_ARCH_AT91) 108#if defined(CONFIG_ARCH_AT91)
38#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \ 109#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \
39 | FBINFO_PARTIAL_PAN_OK \ 110 | FBINFO_PARTIAL_PAN_OK \
@@ -193,14 +264,16 @@ static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = {
193 .accel = FB_ACCEL_NONE, 264 .accel = FB_ACCEL_NONE,
194}; 265};
195 266
196static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2) 267static unsigned long compute_hozval(struct atmel_lcdfb_info *sinfo,
268 unsigned long xres)
197{ 269{
270 unsigned long lcdcon2;
198 unsigned long value; 271 unsigned long value;
199 272
200 if (!(cpu_is_at91sam9261() || cpu_is_at91sam9g10() 273 if (!sinfo->config->have_hozval)
201 || cpu_is_at32ap7000()))
202 return xres; 274 return xres;
203 275
276 lcdcon2 = lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2);
204 value = xres; 277 value = xres;
205 if ((lcdcon2 & ATMEL_LCDC_DISTYPE) != ATMEL_LCDC_DISTYPE_TFT) { 278 if ((lcdcon2 & ATMEL_LCDC_DISTYPE) != ATMEL_LCDC_DISTYPE_TFT) {
206 /* STN display */ 279 /* STN display */
@@ -423,7 +496,7 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
423 break; 496 break;
424 case 16: 497 case 16:
425 /* Older SOCs use IBGR:555 rather than BGR:565. */ 498 /* Older SOCs use IBGR:555 rather than BGR:565. */
426 if (sinfo->have_intensity_bit) 499 if (sinfo->config->have_intensity_bit)
427 var->green.length = 5; 500 var->green.length = 5;
428 else 501 else
429 var->green.length = 6; 502 var->green.length = 6;
@@ -531,7 +604,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
531 /* Now, the LCDC core... */ 604 /* Now, the LCDC core... */
532 605
533 /* Set pixel clock */ 606 /* Set pixel clock */
534 if (cpu_is_at91sam9g45() && !cpu_is_at91sam9g45es()) 607 if (sinfo->config->have_alt_pixclock)
535 pix_factor = 1; 608 pix_factor = 1;
536 609
537 clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; 610 clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
@@ -591,8 +664,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
591 lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value); 664 lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value);
592 665
593 /* Horizontal value (aka line size) */ 666 /* Horizontal value (aka line size) */
594 hozval_linesz = compute_hozval(info->var.xres, 667 hozval_linesz = compute_hozval(sinfo, info->var.xres);
595 lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2));
596 668
597 /* Display size */ 669 /* Display size */
598 value = (hozval_linesz - 1) << ATMEL_LCDC_HOZVAL_OFFSET; 670 value = (hozval_linesz - 1) << ATMEL_LCDC_HOZVAL_OFFSET;
@@ -684,7 +756,7 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
684 756
685 case FB_VISUAL_PSEUDOCOLOR: 757 case FB_VISUAL_PSEUDOCOLOR:
686 if (regno < 256) { 758 if (regno < 256) {
687 if (sinfo->have_intensity_bit) { 759 if (sinfo->config->have_intensity_bit) {
688 /* old style I+BGR:555 */ 760 /* old style I+BGR:555 */
689 val = ((red >> 11) & 0x001f); 761 val = ((red >> 11) & 0x001f);
690 val |= ((green >> 6) & 0x03e0); 762 val |= ((green >> 6) & 0x03e0);
@@ -821,15 +893,13 @@ static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo)
821 893
822static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo) 894static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo)
823{ 895{
824 if (sinfo->bus_clk) 896 clk_enable(sinfo->bus_clk);
825 clk_enable(sinfo->bus_clk);
826 clk_enable(sinfo->lcdc_clk); 897 clk_enable(sinfo->lcdc_clk);
827} 898}
828 899
829static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo) 900static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo)
830{ 901{
831 if (sinfo->bus_clk) 902 clk_disable(sinfo->bus_clk);
832 clk_disable(sinfo->bus_clk);
833 clk_disable(sinfo->lcdc_clk); 903 clk_disable(sinfo->lcdc_clk);
834} 904}
835 905
@@ -874,10 +944,9 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
874 } 944 }
875 sinfo->info = info; 945 sinfo->info = info;
876 sinfo->pdev = pdev; 946 sinfo->pdev = pdev;
877 if (cpu_is_at91sam9261() || cpu_is_at91sam9263() || 947 sinfo->config = atmel_lcdfb_get_config(pdev);
878 cpu_is_at91sam9rl()) { 948 if (!sinfo->config)
879 sinfo->have_intensity_bit = true; 949 goto free_info;
880 }
881 950
882 strcpy(info->fix.id, sinfo->pdev->name); 951 strcpy(info->fix.id, sinfo->pdev->name);
883 info->flags = ATMEL_LCDFB_FBINFO_DEFAULT; 952 info->flags = ATMEL_LCDFB_FBINFO_DEFAULT;
@@ -888,13 +957,10 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
888 info->fix = atmel_lcdfb_fix; 957 info->fix = atmel_lcdfb_fix;
889 958
890 /* Enable LCDC Clocks */ 959 /* Enable LCDC Clocks */
891 if (cpu_is_at91sam9261() || cpu_is_at91sam9g10() 960 sinfo->bus_clk = clk_get(dev, "hclk");
892 || cpu_is_at32ap7000()) { 961 if (IS_ERR(sinfo->bus_clk)) {
893 sinfo->bus_clk = clk_get(dev, "hck1"); 962 ret = PTR_ERR(sinfo->bus_clk);
894 if (IS_ERR(sinfo->bus_clk)) { 963 goto free_info;
895 ret = PTR_ERR(sinfo->bus_clk);
896 goto free_info;
897 }
898 } 964 }
899 sinfo->lcdc_clk = clk_get(dev, "lcdc_clk"); 965 sinfo->lcdc_clk = clk_get(dev, "lcdc_clk");
900 if (IS_ERR(sinfo->lcdc_clk)) { 966 if (IS_ERR(sinfo->lcdc_clk)) {
@@ -1055,8 +1121,7 @@ stop_clk:
1055 atmel_lcdfb_stop_clock(sinfo); 1121 atmel_lcdfb_stop_clock(sinfo);
1056 clk_put(sinfo->lcdc_clk); 1122 clk_put(sinfo->lcdc_clk);
1057put_bus_clk: 1123put_bus_clk:
1058 if (sinfo->bus_clk) 1124 clk_put(sinfo->bus_clk);
1059 clk_put(sinfo->bus_clk);
1060free_info: 1125free_info:
1061 framebuffer_release(info); 1126 framebuffer_release(info);
1062out: 1127out:
@@ -1081,8 +1146,7 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
1081 unregister_framebuffer(info); 1146 unregister_framebuffer(info);
1082 atmel_lcdfb_stop_clock(sinfo); 1147 atmel_lcdfb_stop_clock(sinfo);
1083 clk_put(sinfo->lcdc_clk); 1148 clk_put(sinfo->lcdc_clk);
1084 if (sinfo->bus_clk) 1149 clk_put(sinfo->bus_clk);
1085 clk_put(sinfo->bus_clk);
1086 fb_dealloc_cmap(&info->cmap); 1150 fb_dealloc_cmap(&info->cmap);
1087 free_irq(sinfo->irq_base, info); 1151 free_irq(sinfo->irq_base, info);
1088 iounmap(sinfo->mmio); 1152 iounmap(sinfo->mmio);
@@ -1151,7 +1215,7 @@ static struct platform_driver atmel_lcdfb_driver = {
1151 .remove = __exit_p(atmel_lcdfb_remove), 1215 .remove = __exit_p(atmel_lcdfb_remove),
1152 .suspend = atmel_lcdfb_suspend, 1216 .suspend = atmel_lcdfb_suspend,
1153 .resume = atmel_lcdfb_resume, 1217 .resume = atmel_lcdfb_resume,
1154 1218 .id_table = atmel_lcdfb_devtypes,
1155 .driver = { 1219 .driver = {
1156 .name = "atmel_lcdfb", 1220 .name = "atmel_lcdfb",
1157 .owner = THIS_MODULE, 1221 .owner = THIS_MODULE,