MIPS: Cavium-Octeon: Add more chip specific feature tests.
[linux-2.6] / drivers / video / sh_mobile_lcdcfb.c
1 /*
2  * SuperH Mobile LCDC Framebuffer
3  *
4  * Copyright (c) 2008 Magnus Damm
5  *
6  * This file is subject to the terms and conditions of the GNU General Public
7  * License.  See the file "COPYING" in the main directory of this archive
8  * for more details.
9  */
10
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/delay.h>
14 #include <linux/mm.h>
15 #include <linux/fb.h>
16 #include <linux/clk.h>
17 #include <linux/platform_device.h>
18 #include <linux/dma-mapping.h>
19 #include <linux/interrupt.h>
20 #include <video/sh_mobile_lcdc.h>
21 #include <asm/atomic.h>
22
23 #define PALETTE_NR 16
24
25 struct sh_mobile_lcdc_priv;
26 struct sh_mobile_lcdc_chan {
27         struct sh_mobile_lcdc_priv *lcdc;
28         unsigned long *reg_offs;
29         unsigned long ldmt1r_value;
30         unsigned long enabled; /* ME and SE in LDCNT2R */
31         struct sh_mobile_lcdc_chan_cfg cfg;
32         u32 pseudo_palette[PALETTE_NR];
33         struct fb_info info;
34         dma_addr_t dma_handle;
35         struct fb_deferred_io defio;
36         unsigned long frame_end;
37         wait_queue_head_t frame_end_wait;
38 };
39
40 struct sh_mobile_lcdc_priv {
41         void __iomem *base;
42         int irq;
43 #ifdef CONFIG_HAVE_CLK
44         atomic_t clk_usecnt;
45         struct clk *dot_clk;
46         struct clk *clk;
47 #endif
48         unsigned long lddckr;
49         struct sh_mobile_lcdc_chan ch[2];
50         int started;
51 };
52
53 /* shared registers */
54 #define _LDDCKR 0x410
55 #define _LDDCKSTPR 0x414
56 #define _LDINTR 0x468
57 #define _LDSR 0x46c
58 #define _LDCNT1R 0x470
59 #define _LDCNT2R 0x474
60 #define _LDDDSR 0x47c
61 #define _LDDWD0R 0x800
62 #define _LDDRDR 0x840
63 #define _LDDWAR 0x900
64 #define _LDDRAR 0x904
65
66 /* per-channel registers */
67 enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
68        LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR };
69
70 static unsigned long lcdc_offs_mainlcd[] = {
71         [LDDCKPAT1R] = 0x400,
72         [LDDCKPAT2R] = 0x404,
73         [LDMT1R] = 0x418,
74         [LDMT2R] = 0x41c,
75         [LDMT3R] = 0x420,
76         [LDDFR] = 0x424,
77         [LDSM1R] = 0x428,
78         [LDSM2R] = 0x42c,
79         [LDSA1R] = 0x430,
80         [LDMLSR] = 0x438,
81         [LDHCNR] = 0x448,
82         [LDHSYNR] = 0x44c,
83         [LDVLNR] = 0x450,
84         [LDVSYNR] = 0x454,
85         [LDPMR] = 0x460,
86 };
87
88 static unsigned long lcdc_offs_sublcd[] = {
89         [LDDCKPAT1R] = 0x408,
90         [LDDCKPAT2R] = 0x40c,
91         [LDMT1R] = 0x600,
92         [LDMT2R] = 0x604,
93         [LDMT3R] = 0x608,
94         [LDDFR] = 0x60c,
95         [LDSM1R] = 0x610,
96         [LDSM2R] = 0x614,
97         [LDSA1R] = 0x618,
98         [LDMLSR] = 0x620,
99         [LDHCNR] = 0x624,
100         [LDHSYNR] = 0x628,
101         [LDVLNR] = 0x62c,
102         [LDVSYNR] = 0x630,
103         [LDPMR] = 0x63c,
104 };
105
106 #define START_LCDC      0x00000001
107 #define LCDC_RESET      0x00000100
108 #define DISPLAY_BEU     0x00000008
109 #define LCDC_ENABLE     0x00000001
110 #define LDINTR_FE       0x00000400
111 #define LDINTR_FS       0x00000004
112
113 static void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan,
114                             int reg_nr, unsigned long data)
115 {
116         iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr]);
117 }
118
119 static unsigned long lcdc_read_chan(struct sh_mobile_lcdc_chan *chan,
120                                     int reg_nr)
121 {
122         return ioread32(chan->lcdc->base + chan->reg_offs[reg_nr]);
123 }
124
125 static void lcdc_write(struct sh_mobile_lcdc_priv *priv,
126                        unsigned long reg_offs, unsigned long data)
127 {
128         iowrite32(data, priv->base + reg_offs);
129 }
130
131 static unsigned long lcdc_read(struct sh_mobile_lcdc_priv *priv,
132                                unsigned long reg_offs)
133 {
134         return ioread32(priv->base + reg_offs);
135 }
136
137 static void lcdc_wait_bit(struct sh_mobile_lcdc_priv *priv,
138                           unsigned long reg_offs,
139                           unsigned long mask, unsigned long until)
140 {
141         while ((lcdc_read(priv, reg_offs) & mask) != until)
142                 cpu_relax();
143 }
144
145 static int lcdc_chan_is_sublcd(struct sh_mobile_lcdc_chan *chan)
146 {
147         return chan->cfg.chan == LCDC_CHAN_SUBLCD;
148 }
149
150 static void lcdc_sys_write_index(void *handle, unsigned long data)
151 {
152         struct sh_mobile_lcdc_chan *ch = handle;
153
154         lcdc_write(ch->lcdc, _LDDWD0R, data | 0x10000000);
155         lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
156         lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
157 }
158
159 static void lcdc_sys_write_data(void *handle, unsigned long data)
160 {
161         struct sh_mobile_lcdc_chan *ch = handle;
162
163         lcdc_write(ch->lcdc, _LDDWD0R, data | 0x11000000);
164         lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
165         lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
166 }
167
168 static unsigned long lcdc_sys_read_data(void *handle)
169 {
170         struct sh_mobile_lcdc_chan *ch = handle;
171
172         lcdc_write(ch->lcdc, _LDDRDR, 0x01000000);
173         lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
174         lcdc_write(ch->lcdc, _LDDRAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
175         udelay(1);
176
177         return lcdc_read(ch->lcdc, _LDDRDR) & 0xffff;
178 }
179
180 struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
181         lcdc_sys_write_index,
182         lcdc_sys_write_data,
183         lcdc_sys_read_data,
184 };
185
186 #ifdef CONFIG_HAVE_CLK
187 static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
188 {
189         if (atomic_inc_and_test(&priv->clk_usecnt)) {
190                 clk_enable(priv->clk);
191                 if (priv->dot_clk)
192                         clk_enable(priv->dot_clk);
193         }
194 }
195
196 static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv)
197 {
198         if (atomic_sub_return(1, &priv->clk_usecnt) == -1) {
199                 if (priv->dot_clk)
200                         clk_disable(priv->dot_clk);
201                 clk_disable(priv->clk);
202         }
203 }
204 #else
205 static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) {}
206 static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) {}
207 #endif
208
209 static void sh_mobile_lcdc_deferred_io(struct fb_info *info,
210                                        struct list_head *pagelist)
211 {
212         struct sh_mobile_lcdc_chan *ch = info->par;
213
214         /* enable clocks before accessing hardware */
215         sh_mobile_lcdc_clk_on(ch->lcdc);
216
217         /* trigger panel update */
218         lcdc_write_chan(ch, LDSM2R, 1);
219 }
220
221 static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info)
222 {
223         struct fb_deferred_io *fbdefio = info->fbdefio;
224
225         if (fbdefio)
226                 schedule_delayed_work(&info->deferred_work, fbdefio->delay);
227 }
228
229 static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
230 {
231         struct sh_mobile_lcdc_priv *priv = data;
232         struct sh_mobile_lcdc_chan *ch;
233         unsigned long tmp;
234         int is_sub;
235         int k;
236
237         /* acknowledge interrupt */
238         tmp = lcdc_read(priv, _LDINTR);
239         tmp &= 0xffffff00; /* mask in high 24 bits */
240         tmp |= 0x000000ff ^ LDINTR_FS; /* status in low 8 */
241         lcdc_write(priv, _LDINTR, tmp);
242
243         /* figure out if this interrupt is for main or sub lcd */
244         is_sub = (lcdc_read(priv, _LDSR) & (1 << 10)) ? 1 : 0;
245
246         /* wake up channel and disable clocks*/
247         for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
248                 ch = &priv->ch[k];
249
250                 if (!ch->enabled)
251                         continue;
252
253                 if (is_sub == lcdc_chan_is_sublcd(ch)) {
254                         ch->frame_end = 1;
255                         wake_up(&ch->frame_end_wait);
256
257                         sh_mobile_lcdc_clk_off(priv);
258                 }
259         }
260
261         return IRQ_HANDLED;
262 }
263
264 static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
265                                       int start)
266 {
267         unsigned long tmp = lcdc_read(priv, _LDCNT2R);
268         int k;
269
270         /* start or stop the lcdc */
271         if (start)
272                 lcdc_write(priv, _LDCNT2R, tmp | START_LCDC);
273         else
274                 lcdc_write(priv, _LDCNT2R, tmp & ~START_LCDC);
275
276         /* wait until power is applied/stopped on all channels */
277         for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
278                 if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled)
279                         while (1) {
280                                 tmp = lcdc_read_chan(&priv->ch[k], LDPMR) & 3;
281                                 if (start && tmp == 3)
282                                         break;
283                                 if (!start && tmp == 0)
284                                         break;
285                                 cpu_relax();
286                         }
287
288         if (!start)
289                 lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */
290 }
291
292 static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
293 {
294         struct sh_mobile_lcdc_chan *ch;
295         struct fb_videomode *lcd_cfg;
296         struct sh_mobile_lcdc_board_cfg *board_cfg;
297         unsigned long tmp;
298         int k, m;
299         int ret = 0;
300
301         /* enable clocks before accessing the hardware */
302         for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
303                 if (priv->ch[k].enabled)
304                         sh_mobile_lcdc_clk_on(priv);
305
306         /* reset */
307         lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LCDC_RESET);
308         lcdc_wait_bit(priv, _LDCNT2R, LCDC_RESET, 0);
309
310         /* enable LCDC channels */
311         tmp = lcdc_read(priv, _LDCNT2R);
312         tmp |= priv->ch[0].enabled;
313         tmp |= priv->ch[1].enabled;
314         lcdc_write(priv, _LDCNT2R, tmp);
315
316         /* read data from external memory, avoid using the BEU for now */
317         lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) & ~DISPLAY_BEU);
318
319         /* stop the lcdc first */
320         sh_mobile_lcdc_start_stop(priv, 0);
321
322         /* configure clocks */
323         tmp = priv->lddckr;
324         for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
325                 ch = &priv->ch[k];
326
327                 if (!priv->ch[k].enabled)
328                         continue;
329
330                 m = ch->cfg.clock_divider;
331                 if (!m)
332                         continue;
333
334                 if (m == 1)
335                         m = 1 << 6;
336                 tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0);
337
338                 lcdc_write_chan(ch, LDDCKPAT1R, 0x00000000);
339                 lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1);
340         }
341
342         lcdc_write(priv, _LDDCKR, tmp);
343
344         /* start dotclock again */
345         lcdc_write(priv, _LDDCKSTPR, 0);
346         lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0);
347
348         /* interrupts are disabled to begin with */
349         lcdc_write(priv, _LDINTR, 0);
350
351         for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
352                 ch = &priv->ch[k];
353                 lcd_cfg = &ch->cfg.lcd_cfg;
354
355                 if (!ch->enabled)
356                         continue;
357
358                 tmp = ch->ldmt1r_value;
359                 tmp |= (lcd_cfg->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28;
360                 tmp |= (lcd_cfg->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27;
361                 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0;
362                 tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0;
363                 tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0;
364                 tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0;
365                 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0;
366                 lcdc_write_chan(ch, LDMT1R, tmp);
367
368                 /* setup SYS bus */
369                 lcdc_write_chan(ch, LDMT2R, ch->cfg.sys_bus_cfg.ldmt2r);
370                 lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r);
371
372                 /* horizontal configuration */
373                 tmp = lcd_cfg->xres + lcd_cfg->hsync_len;
374                 tmp += lcd_cfg->left_margin;
375                 tmp += lcd_cfg->right_margin;
376                 tmp /= 8; /* HTCN */
377                 tmp |= (lcd_cfg->xres / 8) << 16; /* HDCN */
378                 lcdc_write_chan(ch, LDHCNR, tmp);
379
380                 tmp = lcd_cfg->xres;
381                 tmp += lcd_cfg->right_margin;
382                 tmp /= 8; /* HSYNP */
383                 tmp |= (lcd_cfg->hsync_len / 8) << 16; /* HSYNW */
384                 lcdc_write_chan(ch, LDHSYNR, tmp);
385
386                 /* power supply */
387                 lcdc_write_chan(ch, LDPMR, 0);
388
389                 /* vertical configuration */
390                 tmp = lcd_cfg->yres + lcd_cfg->vsync_len;
391                 tmp += lcd_cfg->upper_margin;
392                 tmp += lcd_cfg->lower_margin; /* VTLN */
393                 tmp |= lcd_cfg->yres << 16; /* VDLN */
394                 lcdc_write_chan(ch, LDVLNR, tmp);
395
396                 tmp = lcd_cfg->yres;
397                 tmp += lcd_cfg->lower_margin; /* VSYNP */
398                 tmp |= lcd_cfg->vsync_len << 16; /* VSYNW */
399                 lcdc_write_chan(ch, LDVSYNR, tmp);
400
401                 board_cfg = &ch->cfg.board_cfg;
402                 if (board_cfg->setup_sys)
403                         ret = board_cfg->setup_sys(board_cfg->board_data, ch,
404                                                    &sh_mobile_lcdc_sys_bus_ops);
405                 if (ret)
406                         return ret;
407         }
408
409         /* word and long word swap */
410         lcdc_write(priv, _LDDDSR, lcdc_read(priv, _LDDDSR) | 6);
411
412         for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
413                 ch = &priv->ch[k];
414
415                 if (!priv->ch[k].enabled)
416                         continue;
417
418                 /* set bpp format in PKF[4:0] */
419                 tmp = lcdc_read_chan(ch, LDDFR);
420                 tmp &= ~(0x0001001f);
421                 tmp |= (priv->ch[k].info.var.bits_per_pixel == 16) ? 3 : 0;
422                 lcdc_write_chan(ch, LDDFR, tmp);
423
424                 /* point out our frame buffer */
425                 lcdc_write_chan(ch, LDSA1R, ch->info.fix.smem_start);
426
427                 /* set line size */
428                 lcdc_write_chan(ch, LDMLSR, ch->info.fix.line_length);
429
430                 /* setup deferred io if SYS bus */
431                 tmp = ch->cfg.sys_bus_cfg.deferred_io_msec;
432                 if (ch->ldmt1r_value & (1 << 12) && tmp) {
433                         ch->defio.deferred_io = sh_mobile_lcdc_deferred_io;
434                         ch->defio.delay = msecs_to_jiffies(tmp);
435                         ch->info.fbdefio = &ch->defio;
436                         fb_deferred_io_init(&ch->info);
437
438                         /* one-shot mode */
439                         lcdc_write_chan(ch, LDSM1R, 1);
440
441                         /* enable "Frame End Interrupt Enable" bit */
442                         lcdc_write(priv, _LDINTR, LDINTR_FE);
443
444                 } else {
445                         /* continuous read mode */
446                         lcdc_write_chan(ch, LDSM1R, 0);
447                 }
448         }
449
450         /* display output */
451         lcdc_write(priv, _LDCNT1R, LCDC_ENABLE);
452
453         /* start the lcdc */
454         sh_mobile_lcdc_start_stop(priv, 1);
455         priv->started = 1;
456
457         /* tell the board code to enable the panel */
458         for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
459                 ch = &priv->ch[k];
460                 board_cfg = &ch->cfg.board_cfg;
461                 if (board_cfg->display_on)
462                         board_cfg->display_on(board_cfg->board_data);
463         }
464
465         return 0;
466 }
467
468 static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
469 {
470         struct sh_mobile_lcdc_chan *ch;
471         struct sh_mobile_lcdc_board_cfg *board_cfg;
472         int k;
473
474         /* clean up deferred io and ask board code to disable panel */
475         for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
476                 ch = &priv->ch[k];
477
478                 /* deferred io mode:
479                  * flush frame, and wait for frame end interrupt
480                  * clean up deferred io and enable clock
481                  */
482                 if (ch->info.fbdefio) {
483                         ch->frame_end = 0;
484                         schedule_delayed_work(&ch->info.deferred_work, 0);
485                         wait_event(ch->frame_end_wait, ch->frame_end);
486                         fb_deferred_io_cleanup(&ch->info);
487                         ch->info.fbdefio = NULL;
488                         sh_mobile_lcdc_clk_on(priv);
489                 }
490
491                 board_cfg = &ch->cfg.board_cfg;
492                 if (board_cfg->display_off)
493                         board_cfg->display_off(board_cfg->board_data);
494
495         }
496
497         /* stop the lcdc */
498         if (priv->started) {
499                 sh_mobile_lcdc_start_stop(priv, 0);
500                 priv->started = 0;
501         }
502
503         /* stop clocks */
504         for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
505                 if (priv->ch[k].enabled)
506                         sh_mobile_lcdc_clk_off(priv);
507 }
508
509 static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
510 {
511         int ifm, miftyp;
512
513         switch (ch->cfg.interface_type) {
514         case RGB8: ifm = 0; miftyp = 0; break;
515         case RGB9: ifm = 0; miftyp = 4; break;
516         case RGB12A: ifm = 0; miftyp = 5; break;
517         case RGB12B: ifm = 0; miftyp = 6; break;
518         case RGB16: ifm = 0; miftyp = 7; break;
519         case RGB18: ifm = 0; miftyp = 10; break;
520         case RGB24: ifm = 0; miftyp = 11; break;
521         case SYS8A: ifm = 1; miftyp = 0; break;
522         case SYS8B: ifm = 1; miftyp = 1; break;
523         case SYS8C: ifm = 1; miftyp = 2; break;
524         case SYS8D: ifm = 1; miftyp = 3; break;
525         case SYS9: ifm = 1; miftyp = 4; break;
526         case SYS12: ifm = 1; miftyp = 5; break;
527         case SYS16A: ifm = 1; miftyp = 7; break;
528         case SYS16B: ifm = 1; miftyp = 8; break;
529         case SYS16C: ifm = 1; miftyp = 9; break;
530         case SYS18: ifm = 1; miftyp = 10; break;
531         case SYS24: ifm = 1; miftyp = 11; break;
532         default: goto bad;
533         }
534
535         /* SUBLCD only supports SYS interface */
536         if (lcdc_chan_is_sublcd(ch)) {
537                 if (ifm == 0)
538                         goto bad;
539                 else
540                         ifm = 0;
541         }
542
543         ch->ldmt1r_value = (ifm << 12) | miftyp;
544         return 0;
545  bad:
546         return -EINVAL;
547 }
548
549 static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
550                                        int clock_source,
551                                        struct sh_mobile_lcdc_priv *priv)
552 {
553 #ifdef CONFIG_HAVE_CLK
554         char clk_name[8];
555 #endif
556         char *str;
557         int icksel;
558
559         switch (clock_source) {
560         case LCDC_CLK_BUS: str = "bus_clk"; icksel = 0; break;
561         case LCDC_CLK_PERIPHERAL: str = "peripheral_clk"; icksel = 1; break;
562         case LCDC_CLK_EXTERNAL: str = NULL; icksel = 2; break;
563         default:
564                 return -EINVAL;
565         }
566
567         priv->lddckr = icksel << 16;
568
569 #ifdef CONFIG_HAVE_CLK
570         atomic_set(&priv->clk_usecnt, -1);
571         snprintf(clk_name, sizeof(clk_name), "lcdc%d", pdev->id);
572         priv->clk = clk_get(&pdev->dev, clk_name);
573         if (IS_ERR(priv->clk)) {
574                 dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
575                 return PTR_ERR(priv->clk);
576         }
577         
578         if (str) {
579                 priv->dot_clk = clk_get(&pdev->dev, str);
580                 if (IS_ERR(priv->dot_clk)) {
581                         dev_err(&pdev->dev, "cannot get dot clock %s\n", str);
582                         clk_put(priv->clk);
583                         return PTR_ERR(priv->dot_clk);
584                 }
585         }
586 #endif
587
588         return 0;
589 }
590
591 static int sh_mobile_lcdc_setcolreg(u_int regno,
592                                     u_int red, u_int green, u_int blue,
593                                     u_int transp, struct fb_info *info)
594 {
595         u32 *palette = info->pseudo_palette;
596
597         if (regno >= PALETTE_NR)
598                 return -EINVAL;
599
600         /* only FB_VISUAL_TRUECOLOR supported */
601
602         red >>= 16 - info->var.red.length;
603         green >>= 16 - info->var.green.length;
604         blue >>= 16 - info->var.blue.length;
605         transp >>= 16 - info->var.transp.length;
606
607         palette[regno] = (red << info->var.red.offset) |
608           (green << info->var.green.offset) |
609           (blue << info->var.blue.offset) |
610           (transp << info->var.transp.offset);
611
612         return 0;
613 }
614
615 static struct fb_fix_screeninfo sh_mobile_lcdc_fix  = {
616         .id =           "SH Mobile LCDC",
617         .type =         FB_TYPE_PACKED_PIXELS,
618         .visual =       FB_VISUAL_TRUECOLOR,
619         .accel =        FB_ACCEL_NONE,
620 };
621
622 static void sh_mobile_lcdc_fillrect(struct fb_info *info,
623                                     const struct fb_fillrect *rect)
624 {
625         sys_fillrect(info, rect);
626         sh_mobile_lcdc_deferred_io_touch(info);
627 }
628
629 static void sh_mobile_lcdc_copyarea(struct fb_info *info,
630                                     const struct fb_copyarea *area)
631 {
632         sys_copyarea(info, area);
633         sh_mobile_lcdc_deferred_io_touch(info);
634 }
635
636 static void sh_mobile_lcdc_imageblit(struct fb_info *info,
637                                      const struct fb_image *image)
638 {
639         sys_imageblit(info, image);
640         sh_mobile_lcdc_deferred_io_touch(info);
641 }
642
643 static struct fb_ops sh_mobile_lcdc_ops = {
644         .fb_setcolreg   = sh_mobile_lcdc_setcolreg,
645         .fb_read        = fb_sys_read,
646         .fb_write       = fb_sys_write,
647         .fb_fillrect    = sh_mobile_lcdc_fillrect,
648         .fb_copyarea    = sh_mobile_lcdc_copyarea,
649         .fb_imageblit   = sh_mobile_lcdc_imageblit,
650 };
651
652 static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp)
653 {
654         switch (bpp) {
655         case 16: /* PKF[4:0] = 00011 - RGB 565 */
656                 var->red.offset = 11;
657                 var->red.length = 5;
658                 var->green.offset = 5;
659                 var->green.length = 6;
660                 var->blue.offset = 0;
661                 var->blue.length = 5;
662                 var->transp.offset = 0;
663                 var->transp.length = 0;
664                 break;
665
666         case 32: /* PKF[4:0] = 00000 - RGB 888
667                   * sh7722 pdf says 00RRGGBB but reality is GGBB00RR
668                   * this may be because LDDDSR has word swap enabled..
669                   */
670                 var->red.offset = 0;
671                 var->red.length = 8;
672                 var->green.offset = 24;
673                 var->green.length = 8;
674                 var->blue.offset = 16;
675                 var->blue.length = 8;
676                 var->transp.offset = 0;
677                 var->transp.length = 0;
678                 break;
679         default:
680                 return -EINVAL;
681         }
682         var->bits_per_pixel = bpp;
683         var->red.msb_right = 0;
684         var->green.msb_right = 0;
685         var->blue.msb_right = 0;
686         var->transp.msb_right = 0;
687         return 0;
688 }
689
690 static int sh_mobile_lcdc_suspend(struct device *dev)
691 {
692         struct platform_device *pdev = to_platform_device(dev);
693
694         sh_mobile_lcdc_stop(platform_get_drvdata(pdev));
695         return 0;
696 }
697
698 static int sh_mobile_lcdc_resume(struct device *dev)
699 {
700         struct platform_device *pdev = to_platform_device(dev);
701
702         return sh_mobile_lcdc_start(platform_get_drvdata(pdev));
703 }
704
705 static struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
706         .suspend = sh_mobile_lcdc_suspend,
707         .resume = sh_mobile_lcdc_resume,
708 };
709
710 static int sh_mobile_lcdc_remove(struct platform_device *pdev);
711
712 static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
713 {
714         struct fb_info *info;
715         struct sh_mobile_lcdc_priv *priv;
716         struct sh_mobile_lcdc_info *pdata;
717         struct sh_mobile_lcdc_chan_cfg *cfg;
718         struct resource *res;
719         int error;
720         void *buf;
721         int i, j;
722
723         if (!pdev->dev.platform_data) {
724                 dev_err(&pdev->dev, "no platform data defined\n");
725                 error = -EINVAL;
726                 goto err0;
727         }
728
729         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
730         i = platform_get_irq(pdev, 0);
731         if (!res || i < 0) {
732                 dev_err(&pdev->dev, "cannot get platform resources\n");
733                 error = -ENOENT;
734                 goto err0;
735         }
736
737         priv = kzalloc(sizeof(*priv), GFP_KERNEL);
738         if (!priv) {
739                 dev_err(&pdev->dev, "cannot allocate device data\n");
740                 error = -ENOMEM;
741                 goto err0;
742         }
743
744         error = request_irq(i, sh_mobile_lcdc_irq, IRQF_DISABLED,
745                             dev_name(&pdev->dev), priv);
746         if (error) {
747                 dev_err(&pdev->dev, "unable to request irq\n");
748                 goto err1;
749         }
750
751         priv->irq = i;
752         platform_set_drvdata(pdev, priv);
753         pdata = pdev->dev.platform_data;
754
755         j = 0;
756         for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) {
757                 priv->ch[j].lcdc = priv;
758                 memcpy(&priv->ch[j].cfg, &pdata->ch[i], sizeof(pdata->ch[i]));
759
760                 error = sh_mobile_lcdc_check_interface(&priv->ch[i]);
761                 if (error) {
762                         dev_err(&pdev->dev, "unsupported interface type\n");
763                         goto err1;
764                 }
765                 init_waitqueue_head(&priv->ch[i].frame_end_wait);
766
767                 switch (pdata->ch[i].chan) {
768                 case LCDC_CHAN_MAINLCD:
769                         priv->ch[j].enabled = 1 << 1;
770                         priv->ch[j].reg_offs = lcdc_offs_mainlcd;
771                         j++;
772                         break;
773                 case LCDC_CHAN_SUBLCD:
774                         priv->ch[j].enabled = 1 << 2;
775                         priv->ch[j].reg_offs = lcdc_offs_sublcd;
776                         j++;
777                         break;
778                 }
779         }
780
781         if (!j) {
782                 dev_err(&pdev->dev, "no channels defined\n");
783                 error = -EINVAL;
784                 goto err1;
785         }
786
787         error = sh_mobile_lcdc_setup_clocks(pdev, pdata->clock_source, priv);
788         if (error) {
789                 dev_err(&pdev->dev, "unable to setup clocks\n");
790                 goto err1;
791         }
792
793         priv->base = ioremap_nocache(res->start, (res->end - res->start) + 1);
794
795         for (i = 0; i < j; i++) {
796                 info = &priv->ch[i].info;
797                 cfg = &priv->ch[i].cfg;
798
799                 info->fbops = &sh_mobile_lcdc_ops;
800                 info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres;
801                 info->var.yres = info->var.yres_virtual = cfg->lcd_cfg.yres;
802                 info->var.width = cfg->lcd_size_cfg.width;
803                 info->var.height = cfg->lcd_size_cfg.height;
804                 info->var.activate = FB_ACTIVATE_NOW;
805                 error = sh_mobile_lcdc_set_bpp(&info->var, cfg->bpp);
806                 if (error)
807                         break;
808
809                 info->fix = sh_mobile_lcdc_fix;
810                 info->fix.line_length = cfg->lcd_cfg.xres * (cfg->bpp / 8);
811                 info->fix.smem_len = info->fix.line_length * cfg->lcd_cfg.yres;
812
813                 buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len,
814                                          &priv->ch[i].dma_handle, GFP_KERNEL);
815                 if (!buf) {
816                         dev_err(&pdev->dev, "unable to allocate buffer\n");
817                         error = -ENOMEM;
818                         break;
819                 }
820
821                 info->pseudo_palette = &priv->ch[i].pseudo_palette;
822                 info->flags = FBINFO_FLAG_DEFAULT;
823
824                 error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
825                 if (error < 0) {
826                         dev_err(&pdev->dev, "unable to allocate cmap\n");
827                         dma_free_coherent(&pdev->dev, info->fix.smem_len,
828                                           buf, priv->ch[i].dma_handle);
829                         break;
830                 }
831
832                 memset(buf, 0, info->fix.smem_len);
833                 info->fix.smem_start = priv->ch[i].dma_handle;
834                 info->screen_base = buf;
835                 info->device = &pdev->dev;
836                 info->par = &priv->ch[i];
837         }
838
839         if (error)
840                 goto err1;
841
842         error = sh_mobile_lcdc_start(priv);
843         if (error) {
844                 dev_err(&pdev->dev, "unable to start hardware\n");
845                 goto err1;
846         }
847
848         for (i = 0; i < j; i++) {
849                 error = register_framebuffer(&priv->ch[i].info);
850                 if (error < 0)
851                         goto err1;
852         }
853
854         for (i = 0; i < j; i++) {
855                 info = &priv->ch[i].info;
856                 dev_info(info->dev,
857                          "registered %s/%s as %dx%d %dbpp.\n",
858                          pdev->name,
859                          (priv->ch[i].cfg.chan == LCDC_CHAN_MAINLCD) ?
860                          "mainlcd" : "sublcd",
861                          (int) priv->ch[i].cfg.lcd_cfg.xres,
862                          (int) priv->ch[i].cfg.lcd_cfg.yres,
863                          priv->ch[i].cfg.bpp);
864
865                 /* deferred io mode: disable clock to save power */
866                 if (info->fbdefio)
867                         sh_mobile_lcdc_clk_off(priv);
868         }
869
870         return 0;
871  err1:
872         sh_mobile_lcdc_remove(pdev);
873  err0:
874         return error;
875 }
876
877 static int sh_mobile_lcdc_remove(struct platform_device *pdev)
878 {
879         struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
880         struct fb_info *info;
881         int i;
882
883         for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
884                 if (priv->ch[i].info.dev)
885                         unregister_framebuffer(&priv->ch[i].info);
886
887         sh_mobile_lcdc_stop(priv);
888
889         for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
890                 info = &priv->ch[i].info;
891
892                 if (!info->device)
893                         continue;
894
895                 dma_free_coherent(&pdev->dev, info->fix.smem_len,
896                                   info->screen_base, priv->ch[i].dma_handle);
897                 fb_dealloc_cmap(&info->cmap);
898         }
899
900 #ifdef CONFIG_HAVE_CLK
901         if (priv->dot_clk)
902                 clk_put(priv->dot_clk);
903         clk_put(priv->clk);
904 #endif
905
906         if (priv->base)
907                 iounmap(priv->base);
908
909         if (priv->irq)
910                 free_irq(priv->irq, priv);
911         kfree(priv);
912         return 0;
913 }
914
915 static struct platform_driver sh_mobile_lcdc_driver = {
916         .driver         = {
917                 .name           = "sh_mobile_lcdc_fb",
918                 .owner          = THIS_MODULE,
919                 .pm             = &sh_mobile_lcdc_dev_pm_ops,
920         },
921         .probe          = sh_mobile_lcdc_probe,
922         .remove         = sh_mobile_lcdc_remove,
923 };
924
925 static int __init sh_mobile_lcdc_init(void)
926 {
927         return platform_driver_register(&sh_mobile_lcdc_driver);
928 }
929
930 static void __exit sh_mobile_lcdc_exit(void)
931 {
932         platform_driver_unregister(&sh_mobile_lcdc_driver);
933 }
934
935 module_init(sh_mobile_lcdc_init);
936 module_exit(sh_mobile_lcdc_exit);
937
938 MODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver");
939 MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
940 MODULE_LICENSE("GPL v2");