]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/video/da8xx-fb.c
8d244ba0f6019689293bb7929a60ed065de6fdca
[karo-tx-linux.git] / drivers / video / da8xx-fb.c
1 /*
2  * Copyright (C) 2008-2009 MontaVista Software Inc.
3  * Copyright (C) 2008-2009 Texas Instruments Inc
4  *
5  * Based on the LCD driver for TI Avalanche processors written by
6  * Ajay Singh and Shalom Hai.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option)any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  */
22 #include <linux/module.h>
23 #include <linux/kernel.h>
24 #include <linux/fb.h>
25 #include <linux/dma-mapping.h>
26 #include <linux/device.h>
27 #include <linux/platform_device.h>
28 #include <linux/uaccess.h>
29 #include <linux/interrupt.h>
30 #include <linux/clk.h>
31 #include <linux/cpufreq.h>
32 #include <linux/console.h>
33 #include <linux/slab.h>
34 #include <video/da8xx-fb.h>
35
36 #define DRIVER_NAME "da8xx_lcdc"
37
38 /* LCD Status Register */
39 #define LCD_END_OF_FRAME0               BIT(8)
40 #define LCD_FIFO_UNDERFLOW              BIT(5)
41 #define LCD_SYNC_LOST                   BIT(2)
42
43 /* LCD DMA Control Register */
44 #define LCD_DMA_BURST_SIZE(x)           ((x) << 4)
45 #define LCD_DMA_BURST_1                 0x0
46 #define LCD_DMA_BURST_2                 0x1
47 #define LCD_DMA_BURST_4                 0x2
48 #define LCD_DMA_BURST_8                 0x3
49 #define LCD_DMA_BURST_16                0x4
50 #define LCD_END_OF_FRAME_INT_ENA        BIT(2)
51 #define LCD_DUAL_FRAME_BUFFER_ENABLE    BIT(0)
52
53 /* LCD Control Register */
54 #define LCD_CLK_DIVISOR(x)              ((x) << 8)
55 #define LCD_RASTER_MODE                 0x01
56
57 /* LCD Raster Control Register */
58 #define LCD_PALETTE_LOAD_MODE(x)        ((x) << 20)
59 #define PALETTE_AND_DATA                0x00
60 #define PALETTE_ONLY                    0x01
61
62 #define LCD_MONO_8BIT_MODE              BIT(9)
63 #define LCD_RASTER_ORDER                BIT(8)
64 #define LCD_TFT_MODE                    BIT(7)
65 #define LCD_UNDERFLOW_INT_ENA           BIT(6)
66 #define LCD_MONOCHROME_MODE             BIT(1)
67 #define LCD_RASTER_ENABLE               BIT(0)
68 #define LCD_TFT_ALT_ENABLE              BIT(23)
69 #define LCD_STN_565_ENABLE              BIT(24)
70
71 /* LCD Raster Timing 2 Register */
72 #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x)      ((x) << 16)
73 #define LCD_AC_BIAS_FREQUENCY(x)                ((x) << 8)
74 #define LCD_SYNC_CTRL                           BIT(25)
75 #define LCD_SYNC_EDGE                           BIT(24)
76 #define LCD_INVERT_PIXEL_CLOCK                  BIT(22)
77 #define LCD_INVERT_LINE_CLOCK                   BIT(21)
78 #define LCD_INVERT_FRAME_CLOCK                  BIT(20)
79
80 /* LCD Block */
81 #define  LCD_CTRL_REG                           0x4
82 #define  LCD_STAT_REG                           0x8
83 #define  LCD_RASTER_CTRL_REG                    0x28
84 #define  LCD_RASTER_TIMING_0_REG                0x2C
85 #define  LCD_RASTER_TIMING_1_REG                0x30
86 #define  LCD_RASTER_TIMING_2_REG                0x34
87 #define  LCD_DMA_CTRL_REG                       0x40
88 #define  LCD_DMA_FRM_BUF_BASE_ADDR_0_REG        0x44
89 #define  LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG     0x48
90
91 #define WSI_TIMEOUT     50
92 #define PALETTE_SIZE    256
93 #define LEFT_MARGIN     64
94 #define RIGHT_MARGIN    64
95 #define UPPER_MARGIN    32
96 #define LOWER_MARGIN    32
97
98 static resource_size_t da8xx_fb_reg_base;
99 static struct resource *lcdc_regs;
100
101 static inline unsigned int lcdc_read(unsigned int addr)
102 {
103         return (unsigned int)__raw_readl(da8xx_fb_reg_base + (addr));
104 }
105
106 static inline void lcdc_write(unsigned int val, unsigned int addr)
107 {
108         __raw_writel(val, da8xx_fb_reg_base + (addr));
109 }
110
111 struct da8xx_fb_par {
112         resource_size_t p_palette_base;
113         unsigned char *v_palette_base;
114         struct clk *lcdc_clk;
115         int irq;
116         unsigned short pseudo_palette[16];
117         unsigned int databuf_sz;
118         unsigned int palette_sz;
119         unsigned int pxl_clk;
120         int blank;
121 #ifdef CONFIG_CPU_FREQ
122         struct notifier_block   freq_transition;
123 #endif
124         void (*panel_power_ctrl)(int);
125 };
126
127 /* Variable Screen Information */
128 static struct fb_var_screeninfo da8xx_fb_var __devinitdata = {
129         .xoffset = 0,
130         .yoffset = 0,
131         .transp = {0, 0, 0},
132         .nonstd = 0,
133         .activate = 0,
134         .height = -1,
135         .width = -1,
136         .pixclock = 46666,      /* 46us - AUO display */
137         .accel_flags = 0,
138         .left_margin = LEFT_MARGIN,
139         .right_margin = RIGHT_MARGIN,
140         .upper_margin = UPPER_MARGIN,
141         .lower_margin = LOWER_MARGIN,
142         .sync = 0,
143         .vmode = FB_VMODE_NONINTERLACED
144 };
145
146 static struct fb_fix_screeninfo da8xx_fb_fix __devinitdata = {
147         .id = "DA8xx FB Drv",
148         .type = FB_TYPE_PACKED_PIXELS,
149         .type_aux = 0,
150         .visual = FB_VISUAL_PSEUDOCOLOR,
151         .xpanstep = 1,
152         .ypanstep = 1,
153         .ywrapstep = 1,
154         .accel = FB_ACCEL_NONE
155 };
156
157 struct da8xx_panel {
158         const char      name[25];       /* Full name <vendor>_<model> */
159         unsigned short  width;
160         unsigned short  height;
161         int             hfp;            /* Horizontal front porch */
162         int             hbp;            /* Horizontal back porch */
163         int             hsw;            /* Horizontal Sync Pulse Width */
164         int             vfp;            /* Vertical front porch */
165         int             vbp;            /* Vertical back porch */
166         int             vsw;            /* Vertical Sync Pulse Width */
167         unsigned int    pxl_clk;        /* Pixel clock */
168         unsigned char   invert_pxl_clk; /* Invert Pixel clock */
169 };
170
171 static struct da8xx_panel known_lcd_panels[] = {
172         /* Sharp LCD035Q3DG01 */
173         [0] = {
174                 .name = "Sharp_LCD035Q3DG01",
175                 .width = 320,
176                 .height = 240,
177                 .hfp = 8,
178                 .hbp = 6,
179                 .hsw = 0,
180                 .vfp = 2,
181                 .vbp = 2,
182                 .vsw = 0,
183                 .pxl_clk = 4608000,
184                 .invert_pxl_clk = 1,
185         },
186         /* Sharp LK043T1DG01 */
187         [1] = {
188                 .name = "Sharp_LK043T1DG01",
189                 .width = 480,
190                 .height = 272,
191                 .hfp = 2,
192                 .hbp = 2,
193                 .hsw = 41,
194                 .vfp = 2,
195                 .vbp = 2,
196                 .vsw = 10,
197                 .pxl_clk = 7833600,
198                 .invert_pxl_clk = 0,
199         },
200 };
201
202 /* Enable the Raster Engine of the LCD Controller */
203 static inline void lcd_enable_raster(void)
204 {
205         u32 reg;
206
207         reg = lcdc_read(LCD_RASTER_CTRL_REG);
208         if (!(reg & LCD_RASTER_ENABLE))
209                 lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
210 }
211
212 /* Disable the Raster Engine of the LCD Controller */
213 static inline void lcd_disable_raster(void)
214 {
215         u32 reg;
216
217         reg = lcdc_read(LCD_RASTER_CTRL_REG);
218         if (reg & LCD_RASTER_ENABLE)
219                 lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
220 }
221
222 static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
223 {
224         u32 tmp = par->p_palette_base + par->databuf_sz - 4;
225         u32 reg;
226
227         /* Update the databuf in the hw. */
228         lcdc_write(par->p_palette_base, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
229         lcdc_write(tmp, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
230
231         /* Start the DMA. */
232         reg = lcdc_read(LCD_RASTER_CTRL_REG);
233         reg &= ~(3 << 20);
234         if (load_mode == LOAD_DATA)
235                 reg |= LCD_PALETTE_LOAD_MODE(PALETTE_AND_DATA);
236         else if (load_mode == LOAD_PALETTE)
237                 reg |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY);
238
239         lcdc_write(reg, LCD_RASTER_CTRL_REG);
240 }
241
242 /* Configure the Burst Size of DMA */
243 static int lcd_cfg_dma(int burst_size)
244 {
245         u32 reg;
246
247         reg = lcdc_read(LCD_DMA_CTRL_REG) & 0x00000001;
248         switch (burst_size) {
249         case 1:
250                 reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_1);
251                 break;
252         case 2:
253                 reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_2);
254                 break;
255         case 4:
256                 reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_4);
257                 break;
258         case 8:
259                 reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8);
260                 break;
261         case 16:
262                 reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16);
263                 break;
264         default:
265                 return -EINVAL;
266         }
267         lcdc_write(reg, LCD_DMA_CTRL_REG);
268
269         return 0;
270 }
271
272 static void lcd_cfg_ac_bias(int period, int transitions_per_int)
273 {
274         u32 reg;
275
276         /* Set the AC Bias Period and Number of Transisitons per Interrupt */
277         reg = lcdc_read(LCD_RASTER_TIMING_2_REG) & 0xFFF00000;
278         reg |= LCD_AC_BIAS_FREQUENCY(period) |
279                 LCD_AC_BIAS_TRANSITIONS_PER_INT(transitions_per_int);
280         lcdc_write(reg, LCD_RASTER_TIMING_2_REG);
281 }
282
283 static void lcd_cfg_horizontal_sync(int back_porch, int pulse_width,
284                 int front_porch)
285 {
286         u32 reg;
287
288         reg = lcdc_read(LCD_RASTER_TIMING_0_REG) & 0xf;
289         reg |= ((back_porch & 0xff) << 24)
290             | ((front_porch & 0xff) << 16)
291             | ((pulse_width & 0x3f) << 10);
292         lcdc_write(reg, LCD_RASTER_TIMING_0_REG);
293 }
294
295 static void lcd_cfg_vertical_sync(int back_porch, int pulse_width,
296                 int front_porch)
297 {
298         u32 reg;
299
300         reg = lcdc_read(LCD_RASTER_TIMING_1_REG) & 0x3ff;
301         reg |= ((back_porch & 0xff) << 24)
302             | ((front_porch & 0xff) << 16)
303             | ((pulse_width & 0x3f) << 10);
304         lcdc_write(reg, LCD_RASTER_TIMING_1_REG);
305 }
306
307 static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
308 {
309         u32 reg;
310
311         reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE |
312                                                 LCD_MONO_8BIT_MODE |
313                                                 LCD_MONOCHROME_MODE);
314
315         switch (cfg->p_disp_panel->panel_shade) {
316         case MONOCHROME:
317                 reg |= LCD_MONOCHROME_MODE;
318                 if (cfg->mono_8bit_mode)
319                         reg |= LCD_MONO_8BIT_MODE;
320                 break;
321         case COLOR_ACTIVE:
322                 reg |= LCD_TFT_MODE;
323                 if (cfg->tft_alt_mode)
324                         reg |= LCD_TFT_ALT_ENABLE;
325                 break;
326
327         case COLOR_PASSIVE:
328                 if (cfg->stn_565_mode)
329                         reg |= LCD_STN_565_ENABLE;
330                 break;
331
332         default:
333                 return -EINVAL;
334         }
335
336         /* enable additional interrupts here */
337         reg |= LCD_UNDERFLOW_INT_ENA;
338
339         lcdc_write(reg, LCD_RASTER_CTRL_REG);
340
341         reg = lcdc_read(LCD_RASTER_TIMING_2_REG);
342
343         if (cfg->sync_ctrl)
344                 reg |= LCD_SYNC_CTRL;
345         else
346                 reg &= ~LCD_SYNC_CTRL;
347
348         if (cfg->sync_edge)
349                 reg |= LCD_SYNC_EDGE;
350         else
351                 reg &= ~LCD_SYNC_EDGE;
352
353         if (cfg->invert_line_clock)
354                 reg |= LCD_INVERT_LINE_CLOCK;
355         else
356                 reg &= ~LCD_INVERT_LINE_CLOCK;
357
358         if (cfg->invert_frm_clock)
359                 reg |= LCD_INVERT_FRAME_CLOCK;
360         else
361                 reg &= ~LCD_INVERT_FRAME_CLOCK;
362
363         lcdc_write(reg, LCD_RASTER_TIMING_2_REG);
364
365         return 0;
366 }
367
368 static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
369                 u32 bpp, u32 raster_order)
370 {
371         u32 bpl, reg;
372
373         /* Disable Dual Frame Buffer. */
374         reg = lcdc_read(LCD_DMA_CTRL_REG);
375         lcdc_write(reg & ~LCD_DUAL_FRAME_BUFFER_ENABLE,
376                                                 LCD_DMA_CTRL_REG);
377         /* Set the Panel Width */
378         /* Pixels per line = (PPL + 1)*16 */
379         /*0x3F in bits 4..9 gives max horisontal resolution = 1024 pixels*/
380         width &= 0x3f0;
381         reg = lcdc_read(LCD_RASTER_TIMING_0_REG);
382         reg &= 0xfffffc00;
383         reg |= ((width >> 4) - 1) << 4;
384         lcdc_write(reg, LCD_RASTER_TIMING_0_REG);
385
386         /* Set the Panel Height */
387         reg = lcdc_read(LCD_RASTER_TIMING_1_REG);
388         reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00);
389         lcdc_write(reg, LCD_RASTER_TIMING_1_REG);
390
391         /* Set the Raster Order of the Frame Buffer */
392         reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8);
393         if (raster_order)
394                 reg |= LCD_RASTER_ORDER;
395         lcdc_write(reg, LCD_RASTER_CTRL_REG);
396
397         switch (bpp) {
398         case 1:
399         case 2:
400         case 4:
401         case 16:
402                 par->palette_sz = 16 * 2;
403                 break;
404
405         case 8:
406                 par->palette_sz = 256 * 2;
407                 break;
408
409         default:
410                 return -EINVAL;
411         }
412
413         bpl = width * bpp / 8;
414         par->databuf_sz = height * bpl + par->palette_sz;
415
416         return 0;
417 }
418
419 static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
420                               unsigned blue, unsigned transp,
421                               struct fb_info *info)
422 {
423         struct da8xx_fb_par *par = info->par;
424         unsigned short *palette = (unsigned short *)par->v_palette_base;
425         u_short pal;
426
427         if (regno > 255)
428                 return 1;
429
430         if (info->fix.visual == FB_VISUAL_DIRECTCOLOR)
431                 return 1;
432
433         if (info->var.bits_per_pixel == 8) {
434                 red >>= 4;
435                 green >>= 8;
436                 blue >>= 12;
437
438                 pal = (red & 0x0f00);
439                 pal |= (green & 0x00f0);
440                 pal |= (blue & 0x000f);
441
442                 palette[regno] = pal;
443
444         } else if ((info->var.bits_per_pixel == 16) && regno < 16) {
445                 red >>= (16 - info->var.red.length);
446                 red <<= info->var.red.offset;
447
448                 green >>= (16 - info->var.green.length);
449                 green <<= info->var.green.offset;
450
451                 blue >>= (16 - info->var.blue.length);
452                 blue <<= info->var.blue.offset;
453
454                 par->pseudo_palette[regno] = red | green | blue;
455
456                 palette[0] = 0x4000;
457         }
458
459         return 0;
460 }
461
462 static void lcd_reset(struct da8xx_fb_par *par)
463 {
464         /* Disable the Raster if previously Enabled */
465         lcd_disable_raster();
466
467         /* DMA has to be disabled */
468         lcdc_write(0, LCD_DMA_CTRL_REG);
469         lcdc_write(0, LCD_RASTER_CTRL_REG);
470 }
471
472 static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
473 {
474         unsigned int lcd_clk, div;
475
476         lcd_clk = clk_get_rate(par->lcdc_clk);
477         div = lcd_clk / par->pxl_clk;
478
479         /* Configure the LCD clock divisor. */
480         lcdc_write(LCD_CLK_DIVISOR(div) |
481                         (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
482 }
483
484 static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
485                 struct da8xx_panel *panel)
486 {
487         u32 bpp;
488         int ret = 0;
489
490         lcd_reset(par);
491
492         /* Calculate the divider */
493         lcd_calc_clk_divider(par);
494
495         if (panel->invert_pxl_clk)
496                 lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) |
497                         LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG);
498         else
499                 lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) &
500                         ~LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG);
501
502         /* Configure the DMA burst size. */
503         ret = lcd_cfg_dma(cfg->dma_burst_sz);
504         if (ret < 0)
505                 return ret;
506
507         /* Configure the AC bias properties. */
508         lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt);
509
510         /* Configure the vertical and horizontal sync properties. */
511         lcd_cfg_vertical_sync(panel->vbp, panel->vsw, panel->vfp);
512         lcd_cfg_horizontal_sync(panel->hbp, panel->hsw, panel->hfp);
513
514         /* Configure for disply */
515         ret = lcd_cfg_display(cfg);
516         if (ret < 0)
517                 return ret;
518
519         if (QVGA != cfg->p_disp_panel->panel_type)
520                 return -EINVAL;
521
522         if (cfg->bpp <= cfg->p_disp_panel->max_bpp &&
523             cfg->bpp >= cfg->p_disp_panel->min_bpp)
524                 bpp = cfg->bpp;
525         else
526                 bpp = cfg->p_disp_panel->max_bpp;
527         if (bpp == 12)
528                 bpp = 16;
529         ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->width,
530                                 (unsigned int)panel->height, bpp,
531                                 cfg->raster_order);
532         if (ret < 0)
533                 return ret;
534
535         /* Configure FDD */
536         lcdc_write((lcdc_read(LCD_RASTER_CTRL_REG) & 0xfff00fff) |
537                        (cfg->fdd << 12), LCD_RASTER_CTRL_REG);
538
539         return 0;
540 }
541
542 static irqreturn_t lcdc_irq_handler(int irq, void *arg)
543 {
544         u32 stat = lcdc_read(LCD_STAT_REG);
545
546         if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
547                 lcd_disable_raster();
548                 lcdc_write(stat, LCD_STAT_REG);
549                 lcd_enable_raster();
550         } else
551                 lcdc_write(stat, LCD_STAT_REG);
552
553         return IRQ_HANDLED;
554 }
555
556 static int fb_check_var(struct fb_var_screeninfo *var,
557                         struct fb_info *info)
558 {
559         int err = 0;
560
561         switch (var->bits_per_pixel) {
562         case 1:
563         case 8:
564                 var->red.offset = 0;
565                 var->red.length = 8;
566                 var->green.offset = 0;
567                 var->green.length = 8;
568                 var->blue.offset = 0;
569                 var->blue.length = 8;
570                 var->transp.offset = 0;
571                 var->transp.length = 0;
572                 break;
573         case 4:
574                 var->red.offset = 0;
575                 var->red.length = 4;
576                 var->green.offset = 0;
577                 var->green.length = 4;
578                 var->blue.offset = 0;
579                 var->blue.length = 4;
580                 var->transp.offset = 0;
581                 var->transp.length = 0;
582                 break;
583         case 16:                /* RGB 565 */
584                 var->red.offset = 11;
585                 var->red.length = 5;
586                 var->green.offset = 5;
587                 var->green.length = 6;
588                 var->blue.offset = 0;
589                 var->blue.length = 5;
590                 var->transp.offset = 0;
591                 var->transp.length = 0;
592                 break;
593         default:
594                 err = -EINVAL;
595         }
596
597         var->red.msb_right = 0;
598         var->green.msb_right = 0;
599         var->blue.msb_right = 0;
600         var->transp.msb_right = 0;
601         return err;
602 }
603
604 #ifdef CONFIG_CPU_FREQ
605 static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb,
606                                      unsigned long val, void *data)
607 {
608         struct da8xx_fb_par *par;
609
610         par = container_of(nb, struct da8xx_fb_par, freq_transition);
611         if (val == CPUFREQ_PRECHANGE) {
612                 lcd_disable_raster();
613         } else if (val == CPUFREQ_POSTCHANGE) {
614                 lcd_calc_clk_divider(par);
615                 lcd_enable_raster();
616         }
617
618         return 0;
619 }
620
621 static inline int lcd_da8xx_cpufreq_register(struct da8xx_fb_par *par)
622 {
623         par->freq_transition.notifier_call = lcd_da8xx_cpufreq_transition;
624
625         return cpufreq_register_notifier(&par->freq_transition,
626                                          CPUFREQ_TRANSITION_NOTIFIER);
627 }
628
629 static inline void lcd_da8xx_cpufreq_deregister(struct da8xx_fb_par *par)
630 {
631         cpufreq_unregister_notifier(&par->freq_transition,
632                                     CPUFREQ_TRANSITION_NOTIFIER);
633 }
634 #endif
635
636 static int __devexit fb_remove(struct platform_device *dev)
637 {
638         struct fb_info *info = dev_get_drvdata(&dev->dev);
639
640         if (info) {
641                 struct da8xx_fb_par *par = info->par;
642
643 #ifdef CONFIG_CPU_FREQ
644                 lcd_da8xx_cpufreq_deregister(par);
645 #endif
646                 if (par->panel_power_ctrl)
647                         par->panel_power_ctrl(0);
648
649                 lcd_disable_raster();
650                 lcdc_write(0, LCD_RASTER_CTRL_REG);
651
652                 /* disable DMA  */
653                 lcdc_write(0, LCD_DMA_CTRL_REG);
654
655                 unregister_framebuffer(info);
656                 fb_dealloc_cmap(&info->cmap);
657                 dma_free_coherent(NULL, par->databuf_sz + PAGE_SIZE,
658                                         info->screen_base - PAGE_SIZE,
659                                         info->fix.smem_start);
660                 free_irq(par->irq, par);
661                 clk_disable(par->lcdc_clk);
662                 clk_put(par->lcdc_clk);
663                 framebuffer_release(info);
664                 iounmap((void __iomem *)da8xx_fb_reg_base);
665                 release_mem_region(lcdc_regs->start, resource_size(lcdc_regs));
666
667         }
668         return 0;
669 }
670
671 static int fb_ioctl(struct fb_info *info, unsigned int cmd,
672                           unsigned long arg)
673 {
674         struct lcd_sync_arg sync_arg;
675
676         switch (cmd) {
677         case FBIOGET_CONTRAST:
678         case FBIOPUT_CONTRAST:
679         case FBIGET_BRIGHTNESS:
680         case FBIPUT_BRIGHTNESS:
681         case FBIGET_COLOR:
682         case FBIPUT_COLOR:
683                 return -ENOTTY;
684         case FBIPUT_HSYNC:
685                 if (copy_from_user(&sync_arg, (char *)arg,
686                                 sizeof(struct lcd_sync_arg)))
687                         return -EFAULT;
688                 lcd_cfg_horizontal_sync(sync_arg.back_porch,
689                                         sync_arg.pulse_width,
690                                         sync_arg.front_porch);
691                 break;
692         case FBIPUT_VSYNC:
693                 if (copy_from_user(&sync_arg, (char *)arg,
694                                 sizeof(struct lcd_sync_arg)))
695                         return -EFAULT;
696                 lcd_cfg_vertical_sync(sync_arg.back_porch,
697                                         sync_arg.pulse_width,
698                                         sync_arg.front_porch);
699                 break;
700         default:
701                 return -EINVAL;
702         }
703         return 0;
704 }
705
706 static int cfb_blank(int blank, struct fb_info *info)
707 {
708         struct da8xx_fb_par *par = info->par;
709         int ret = 0;
710
711         if (par->blank == blank)
712                 return 0;
713
714         par->blank = blank;
715         switch (blank) {
716         case FB_BLANK_UNBLANK:
717                 if (par->panel_power_ctrl)
718                         par->panel_power_ctrl(1);
719
720                 lcd_enable_raster();
721                 break;
722         case FB_BLANK_POWERDOWN:
723                 if (par->panel_power_ctrl)
724                         par->panel_power_ctrl(0);
725
726                 lcd_disable_raster();
727                 break;
728         default:
729                 ret = -EINVAL;
730         }
731
732         return ret;
733 }
734
735 static struct fb_ops da8xx_fb_ops = {
736         .owner = THIS_MODULE,
737         .fb_check_var = fb_check_var,
738         .fb_setcolreg = fb_setcolreg,
739         .fb_ioctl = fb_ioctl,
740         .fb_fillrect = cfb_fillrect,
741         .fb_copyarea = cfb_copyarea,
742         .fb_imageblit = cfb_imageblit,
743         .fb_blank = cfb_blank,
744 };
745
746 static int __init fb_probe(struct platform_device *device)
747 {
748         struct da8xx_lcdc_platform_data *fb_pdata =
749                                                 device->dev.platform_data;
750         struct lcd_ctrl_config *lcd_cfg;
751         struct da8xx_panel *lcdc_info;
752         struct fb_info *da8xx_fb_info;
753         struct clk *fb_clk = NULL;
754         struct da8xx_fb_par *par;
755         resource_size_t len;
756         int ret, i;
757
758         if (fb_pdata == NULL) {
759                 dev_err(&device->dev, "Can not get platform data\n");
760                 return -ENOENT;
761         }
762
763         lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0);
764         if (!lcdc_regs) {
765                 dev_err(&device->dev,
766                         "Can not get memory resource for LCD controller\n");
767                 return -ENOENT;
768         }
769
770         len = resource_size(lcdc_regs);
771
772         lcdc_regs = request_mem_region(lcdc_regs->start, len, lcdc_regs->name);
773         if (!lcdc_regs)
774                 return -EBUSY;
775
776         da8xx_fb_reg_base = (resource_size_t)ioremap(lcdc_regs->start, len);
777         if (!da8xx_fb_reg_base) {
778                 ret = -EBUSY;
779                 goto err_request_mem;
780         }
781
782         fb_clk = clk_get(&device->dev, NULL);
783         if (IS_ERR(fb_clk)) {
784                 dev_err(&device->dev, "Can not get device clock\n");
785                 ret = -ENODEV;
786                 goto err_ioremap;
787         }
788         ret = clk_enable(fb_clk);
789         if (ret)
790                 goto err_clk_put;
791
792         for (i = 0, lcdc_info = known_lcd_panels;
793                 i < ARRAY_SIZE(known_lcd_panels);
794                 i++, lcdc_info++) {
795                 if (strcmp(fb_pdata->type, lcdc_info->name) == 0)
796                         break;
797         }
798
799         if (i == ARRAY_SIZE(known_lcd_panels)) {
800                 dev_err(&device->dev, "GLCD: No valid panel found\n");
801                 ret = -ENODEV;
802                 goto err_clk_disable;
803         } else
804                 dev_info(&device->dev, "GLCD: Found %s panel\n",
805                                         fb_pdata->type);
806
807         lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data;
808
809         da8xx_fb_info = framebuffer_alloc(sizeof(struct da8xx_fb_par),
810                                         &device->dev);
811         if (!da8xx_fb_info) {
812                 dev_dbg(&device->dev, "Memory allocation failed for fb_info\n");
813                 ret = -ENOMEM;
814                 goto err_clk_disable;
815         }
816
817         par = da8xx_fb_info->par;
818         par->lcdc_clk = fb_clk;
819         par->pxl_clk = lcdc_info->pxl_clk;
820         if (fb_pdata->panel_power_ctrl) {
821                 par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
822                 par->panel_power_ctrl(1);
823         }
824
825         if (lcd_init(par, lcd_cfg, lcdc_info) < 0) {
826                 dev_err(&device->dev, "lcd_init failed\n");
827                 ret = -EFAULT;
828                 goto err_release_fb;
829         }
830
831         /* allocate frame buffer */
832         da8xx_fb_info->screen_base = dma_alloc_coherent(NULL,
833                                         par->databuf_sz + PAGE_SIZE,
834                                         (resource_size_t *)
835                                         &da8xx_fb_info->fix.smem_start,
836                                         GFP_KERNEL | GFP_DMA);
837
838         if (!da8xx_fb_info->screen_base) {
839                 dev_err(&device->dev,
840                         "GLCD: kmalloc for frame buffer failed\n");
841                 ret = -EINVAL;
842                 goto err_release_fb;
843         }
844
845         /* move palette base pointer by (PAGE_SIZE - palette_sz) bytes */
846         par->v_palette_base = da8xx_fb_info->screen_base +
847                                 (PAGE_SIZE - par->palette_sz);
848         par->p_palette_base = da8xx_fb_info->fix.smem_start +
849                                 (PAGE_SIZE - par->palette_sz);
850
851         /* the rest of the frame buffer is pixel data */
852         da8xx_fb_info->screen_base = par->v_palette_base + par->palette_sz;
853         da8xx_fb_fix.smem_start = par->p_palette_base + par->palette_sz;
854         da8xx_fb_fix.smem_len = par->databuf_sz - par->palette_sz;
855         da8xx_fb_fix.line_length = (lcdc_info->width * lcd_cfg->bpp) / 8;
856
857         par->irq = platform_get_irq(device, 0);
858         if (par->irq < 0) {
859                 ret = -ENOENT;
860                 goto err_release_fb_mem;
861         }
862
863         ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par);
864         if (ret)
865                 goto err_release_fb_mem;
866
867         /* Initialize par */
868         da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp;
869
870         da8xx_fb_var.xres = lcdc_info->width;
871         da8xx_fb_var.xres_virtual = lcdc_info->width;
872
873         da8xx_fb_var.yres = lcdc_info->height;
874         da8xx_fb_var.yres_virtual = lcdc_info->height;
875
876         da8xx_fb_var.grayscale =
877             lcd_cfg->p_disp_panel->panel_shade == MONOCHROME ? 1 : 0;
878         da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp;
879
880         da8xx_fb_var.hsync_len = lcdc_info->hsw;
881         da8xx_fb_var.vsync_len = lcdc_info->vsw;
882
883         /* Initialize fbinfo */
884         da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT;
885         da8xx_fb_info->fix = da8xx_fb_fix;
886         da8xx_fb_info->var = da8xx_fb_var;
887         da8xx_fb_info->fbops = &da8xx_fb_ops;
888         da8xx_fb_info->pseudo_palette = par->pseudo_palette;
889         da8xx_fb_info->fix.visual = (da8xx_fb_info->var.bits_per_pixel <= 8) ?
890                                 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
891
892         ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0);
893         if (ret)
894                 goto err_free_irq;
895
896         /* First palette_sz byte of the frame buffer is the palette */
897         da8xx_fb_info->cmap.len = par->palette_sz;
898
899         /* Flush the buffer to the screen. */
900         lcd_blit(LOAD_DATA, par);
901
902         /* initialize var_screeninfo */
903         da8xx_fb_var.activate = FB_ACTIVATE_FORCE;
904         fb_set_var(da8xx_fb_info, &da8xx_fb_var);
905
906         dev_set_drvdata(&device->dev, da8xx_fb_info);
907         /* Register the Frame Buffer  */
908         if (register_framebuffer(da8xx_fb_info) < 0) {
909                 dev_err(&device->dev,
910                         "GLCD: Frame Buffer Registration Failed!\n");
911                 ret = -EINVAL;
912                 goto err_dealloc_cmap;
913         }
914
915 #ifdef CONFIG_CPU_FREQ
916         ret = lcd_da8xx_cpufreq_register(par);
917         if (ret) {
918                 dev_err(&device->dev, "failed to register cpufreq\n");
919                 goto err_cpu_freq;
920         }
921 #endif
922
923         /* enable raster engine */
924         lcd_enable_raster();
925
926         return 0;
927
928 #ifdef CONFIG_CPU_FREQ
929 err_cpu_freq:
930         unregister_framebuffer(da8xx_fb_info);
931 #endif
932
933 err_dealloc_cmap:
934         fb_dealloc_cmap(&da8xx_fb_info->cmap);
935
936 err_free_irq:
937         free_irq(par->irq, par);
938
939 err_release_fb_mem:
940         dma_free_coherent(NULL, par->databuf_sz + PAGE_SIZE,
941                                 da8xx_fb_info->screen_base - PAGE_SIZE,
942                                 da8xx_fb_info->fix.smem_start);
943
944 err_release_fb:
945         framebuffer_release(da8xx_fb_info);
946
947 err_clk_disable:
948         clk_disable(fb_clk);
949
950 err_clk_put:
951         clk_put(fb_clk);
952
953 err_ioremap:
954         iounmap((void __iomem *)da8xx_fb_reg_base);
955
956 err_request_mem:
957         release_mem_region(lcdc_regs->start, len);
958
959         return ret;
960 }
961
962 #ifdef CONFIG_PM
963 static int fb_suspend(struct platform_device *dev, pm_message_t state)
964 {
965         struct fb_info *info = platform_get_drvdata(dev);
966         struct da8xx_fb_par *par = info->par;
967
968         acquire_console_sem();
969         if (par->panel_power_ctrl)
970                 par->panel_power_ctrl(0);
971
972         fb_set_suspend(info, 1);
973         lcd_disable_raster();
974         clk_disable(par->lcdc_clk);
975         release_console_sem();
976
977         return 0;
978 }
979 static int fb_resume(struct platform_device *dev)
980 {
981         struct fb_info *info = platform_get_drvdata(dev);
982         struct da8xx_fb_par *par = info->par;
983
984         acquire_console_sem();
985         if (par->panel_power_ctrl)
986                 par->panel_power_ctrl(1);
987
988         clk_enable(par->lcdc_clk);
989         lcd_enable_raster();
990         fb_set_suspend(info, 0);
991         release_console_sem();
992
993         return 0;
994 }
995 #else
996 #define fb_suspend NULL
997 #define fb_resume NULL
998 #endif
999
1000 static struct platform_driver da8xx_fb_driver = {
1001         .probe = fb_probe,
1002         .remove = fb_remove,
1003         .suspend = fb_suspend,
1004         .resume = fb_resume,
1005         .driver = {
1006                    .name = DRIVER_NAME,
1007                    .owner = THIS_MODULE,
1008                    },
1009 };
1010
1011 static int __init da8xx_fb_init(void)
1012 {
1013         return platform_driver_register(&da8xx_fb_driver);
1014 }
1015
1016 static void __exit da8xx_fb_cleanup(void)
1017 {
1018         platform_driver_unregister(&da8xx_fb_driver);
1019 }
1020
1021 module_init(da8xx_fb_init);
1022 module_exit(da8xx_fb_cleanup);
1023
1024 MODULE_DESCRIPTION("Framebuffer driver for TI da8xx/omap-l1xx");
1025 MODULE_AUTHOR("Texas Instruments");
1026 MODULE_LICENSE("GPL");