]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/video/sh_mobile_lcdcfb.c
fbdev: sh_mobile_lcdcfb: separate display variable data from framebuffer data
[net-next-2.6.git] / 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/clk.h>
16 #include <linux/pm_runtime.h>
17 #include <linux/platform_device.h>
18 #include <linux/dma-mapping.h>
19 #include <linux/interrupt.h>
20 #include <linux/vmalloc.h>
21 #include <linux/ioctl.h>
22 #include <linux/slab.h>
23 #include <video/sh_mobile_lcdc.h>
24 #include <asm/atomic.h>
25
26 #include "sh_mobile_lcdcfb.h"
27
28 #define SIDE_B_OFFSET 0x1000
29 #define MIRROR_OFFSET 0x2000
30
31 /* shared registers */
32 #define _LDDCKR 0x410
33 #define _LDDCKSTPR 0x414
34 #define _LDINTR 0x468
35 #define _LDSR 0x46c
36 #define _LDCNT1R 0x470
37 #define _LDCNT2R 0x474
38 #define _LDRCNTR 0x478
39 #define _LDDDSR 0x47c
40 #define _LDDWD0R 0x800
41 #define _LDDRDR 0x840
42 #define _LDDWAR 0x900
43 #define _LDDRAR 0x904
44
45 /* shared registers and their order for context save/restore */
46 static int lcdc_shared_regs[] = {
47         _LDDCKR,
48         _LDDCKSTPR,
49         _LDINTR,
50         _LDDDSR,
51         _LDCNT1R,
52         _LDCNT2R,
53 };
54 #define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs)
55
56 static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
57         [LDDCKPAT1R] = 0x400,
58         [LDDCKPAT2R] = 0x404,
59         [LDMT1R] = 0x418,
60         [LDMT2R] = 0x41c,
61         [LDMT3R] = 0x420,
62         [LDDFR] = 0x424,
63         [LDSM1R] = 0x428,
64         [LDSM2R] = 0x42c,
65         [LDSA1R] = 0x430,
66         [LDMLSR] = 0x438,
67         [LDHCNR] = 0x448,
68         [LDHSYNR] = 0x44c,
69         [LDVLNR] = 0x450,
70         [LDVSYNR] = 0x454,
71         [LDPMR] = 0x460,
72         [LDHAJR] = 0x4a0,
73 };
74
75 static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
76         [LDDCKPAT1R] = 0x408,
77         [LDDCKPAT2R] = 0x40c,
78         [LDMT1R] = 0x600,
79         [LDMT2R] = 0x604,
80         [LDMT3R] = 0x608,
81         [LDDFR] = 0x60c,
82         [LDSM1R] = 0x610,
83         [LDSM2R] = 0x614,
84         [LDSA1R] = 0x618,
85         [LDMLSR] = 0x620,
86         [LDHCNR] = 0x624,
87         [LDHSYNR] = 0x628,
88         [LDVLNR] = 0x62c,
89         [LDVSYNR] = 0x630,
90         [LDPMR] = 0x63c,
91 };
92
93 #define START_LCDC      0x00000001
94 #define LCDC_RESET      0x00000100
95 #define DISPLAY_BEU     0x00000008
96 #define LCDC_ENABLE     0x00000001
97 #define LDINTR_FE       0x00000400
98 #define LDINTR_VSE      0x00000200
99 #define LDINTR_VEE      0x00000100
100 #define LDINTR_FS       0x00000004
101 #define LDINTR_VSS      0x00000002
102 #define LDINTR_VES      0x00000001
103 #define LDRCNTR_SRS     0x00020000
104 #define LDRCNTR_SRC     0x00010000
105 #define LDRCNTR_MRS     0x00000002
106 #define LDRCNTR_MRC     0x00000001
107 #define LDSR_MRS        0x00000100
108
109 struct sh_mobile_lcdc_priv {
110         void __iomem *base;
111         int irq;
112         atomic_t hw_usecnt;
113         struct device *dev;
114         struct clk *dot_clk;
115         unsigned long lddckr;
116         struct sh_mobile_lcdc_chan ch[2];
117         struct notifier_block notifier;
118         unsigned long saved_shared_regs[NR_SHARED_REGS];
119         int started;
120 };
121
122 static bool banked(int reg_nr)
123 {
124         switch (reg_nr) {
125         case LDMT1R:
126         case LDMT2R:
127         case LDMT3R:
128         case LDDFR:
129         case LDSM1R:
130         case LDSA1R:
131         case LDMLSR:
132         case LDHCNR:
133         case LDHSYNR:
134         case LDVLNR:
135         case LDVSYNR:
136                 return true;
137         }
138         return false;
139 }
140
141 static void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan,
142                             int reg_nr, unsigned long data)
143 {
144         iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr]);
145         if (banked(reg_nr))
146                 iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr] +
147                           SIDE_B_OFFSET);
148 }
149
150 static void lcdc_write_chan_mirror(struct sh_mobile_lcdc_chan *chan,
151                             int reg_nr, unsigned long data)
152 {
153         iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr] +
154                   MIRROR_OFFSET);
155 }
156
157 static unsigned long lcdc_read_chan(struct sh_mobile_lcdc_chan *chan,
158                                     int reg_nr)
159 {
160         return ioread32(chan->lcdc->base + chan->reg_offs[reg_nr]);
161 }
162
163 static void lcdc_write(struct sh_mobile_lcdc_priv *priv,
164                        unsigned long reg_offs, unsigned long data)
165 {
166         iowrite32(data, priv->base + reg_offs);
167 }
168
169 static unsigned long lcdc_read(struct sh_mobile_lcdc_priv *priv,
170                                unsigned long reg_offs)
171 {
172         return ioread32(priv->base + reg_offs);
173 }
174
175 static void lcdc_wait_bit(struct sh_mobile_lcdc_priv *priv,
176                           unsigned long reg_offs,
177                           unsigned long mask, unsigned long until)
178 {
179         while ((lcdc_read(priv, reg_offs) & mask) != until)
180                 cpu_relax();
181 }
182
183 static int lcdc_chan_is_sublcd(struct sh_mobile_lcdc_chan *chan)
184 {
185         return chan->cfg.chan == LCDC_CHAN_SUBLCD;
186 }
187
188 static void lcdc_sys_write_index(void *handle, unsigned long data)
189 {
190         struct sh_mobile_lcdc_chan *ch = handle;
191
192         lcdc_write(ch->lcdc, _LDDWD0R, data | 0x10000000);
193         lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
194         lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
195         lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
196 }
197
198 static void lcdc_sys_write_data(void *handle, unsigned long data)
199 {
200         struct sh_mobile_lcdc_chan *ch = handle;
201
202         lcdc_write(ch->lcdc, _LDDWD0R, data | 0x11000000);
203         lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
204         lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
205         lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
206 }
207
208 static unsigned long lcdc_sys_read_data(void *handle)
209 {
210         struct sh_mobile_lcdc_chan *ch = handle;
211
212         lcdc_write(ch->lcdc, _LDDRDR, 0x01000000);
213         lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
214         lcdc_write(ch->lcdc, _LDDRAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
215         udelay(1);
216         lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
217
218         return lcdc_read(ch->lcdc, _LDDRDR) & 0x3ffff;
219 }
220
221 struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
222         lcdc_sys_write_index,
223         lcdc_sys_write_data,
224         lcdc_sys_read_data,
225 };
226
227 static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
228 {
229         if (atomic_inc_and_test(&priv->hw_usecnt)) {
230                 pm_runtime_get_sync(priv->dev);
231                 if (priv->dot_clk)
232                         clk_enable(priv->dot_clk);
233         }
234 }
235
236 static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv)
237 {
238         if (atomic_sub_return(1, &priv->hw_usecnt) == -1) {
239                 if (priv->dot_clk)
240                         clk_disable(priv->dot_clk);
241                 pm_runtime_put(priv->dev);
242         }
243 }
244
245 static int sh_mobile_lcdc_sginit(struct fb_info *info,
246                                   struct list_head *pagelist)
247 {
248         struct sh_mobile_lcdc_chan *ch = info->par;
249         unsigned int nr_pages_max = info->fix.smem_len >> PAGE_SHIFT;
250         struct page *page;
251         int nr_pages = 0;
252
253         sg_init_table(ch->sglist, nr_pages_max);
254
255         list_for_each_entry(page, pagelist, lru)
256                 sg_set_page(&ch->sglist[nr_pages++], page, PAGE_SIZE, 0);
257
258         return nr_pages;
259 }
260
261 static void sh_mobile_lcdc_deferred_io(struct fb_info *info,
262                                        struct list_head *pagelist)
263 {
264         struct sh_mobile_lcdc_chan *ch = info->par;
265         struct sh_mobile_lcdc_board_cfg *bcfg = &ch->cfg.board_cfg;
266
267         /* enable clocks before accessing hardware */
268         sh_mobile_lcdc_clk_on(ch->lcdc);
269
270         /*
271          * It's possible to get here without anything on the pagelist via
272          * sh_mobile_lcdc_deferred_io_touch() or via a userspace fsync()
273          * invocation. In the former case, the acceleration routines are
274          * stepped in to when using the framebuffer console causing the
275          * workqueue to be scheduled without any dirty pages on the list.
276          *
277          * Despite this, a panel update is still needed given that the
278          * acceleration routines have their own methods for writing in
279          * that still need to be updated.
280          *
281          * The fsync() and empty pagelist case could be optimized for,
282          * but we don't bother, as any application exhibiting such
283          * behaviour is fundamentally broken anyways.
284          */
285         if (!list_empty(pagelist)) {
286                 unsigned int nr_pages = sh_mobile_lcdc_sginit(info, pagelist);
287
288                 /* trigger panel update */
289                 dma_map_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
290                 if (bcfg->start_transfer)
291                         bcfg->start_transfer(bcfg->board_data, ch,
292                                              &sh_mobile_lcdc_sys_bus_ops);
293                 lcdc_write_chan(ch, LDSM2R, 1);
294                 dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
295         } else {
296                 if (bcfg->start_transfer)
297                         bcfg->start_transfer(bcfg->board_data, ch,
298                                              &sh_mobile_lcdc_sys_bus_ops);
299                 lcdc_write_chan(ch, LDSM2R, 1);
300         }
301 }
302
303 static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info)
304 {
305         struct fb_deferred_io *fbdefio = info->fbdefio;
306
307         if (fbdefio)
308                 schedule_delayed_work(&info->deferred_work, fbdefio->delay);
309 }
310
311 static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
312 {
313         struct sh_mobile_lcdc_priv *priv = data;
314         struct sh_mobile_lcdc_chan *ch;
315         unsigned long tmp;
316         unsigned long ldintr;
317         int is_sub;
318         int k;
319
320         /* acknowledge interrupt */
321         ldintr = tmp = lcdc_read(priv, _LDINTR);
322         /*
323          * disable further VSYNC End IRQs, preserve all other enabled IRQs,
324          * write 0 to bits 0-6 to ack all triggered IRQs.
325          */
326         tmp &= 0xffffff00 & ~LDINTR_VEE;
327         lcdc_write(priv, _LDINTR, tmp);
328
329         /* figure out if this interrupt is for main or sub lcd */
330         is_sub = (lcdc_read(priv, _LDSR) & (1 << 10)) ? 1 : 0;
331
332         /* wake up channel and disable clocks */
333         for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
334                 ch = &priv->ch[k];
335
336                 if (!ch->enabled)
337                         continue;
338
339                 /* Frame Start */
340                 if (ldintr & LDINTR_FS) {
341                         if (is_sub == lcdc_chan_is_sublcd(ch)) {
342                                 ch->frame_end = 1;
343                                 wake_up(&ch->frame_end_wait);
344
345                                 sh_mobile_lcdc_clk_off(priv);
346                         }
347                 }
348
349                 /* VSYNC End */
350                 if (ldintr & LDINTR_VES)
351                         complete(&ch->vsync_completion);
352         }
353
354         return IRQ_HANDLED;
355 }
356
357 static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
358                                       int start)
359 {
360         unsigned long tmp = lcdc_read(priv, _LDCNT2R);
361         int k;
362
363         /* start or stop the lcdc */
364         if (start)
365                 lcdc_write(priv, _LDCNT2R, tmp | START_LCDC);
366         else
367                 lcdc_write(priv, _LDCNT2R, tmp & ~START_LCDC);
368
369         /* wait until power is applied/stopped on all channels */
370         for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
371                 if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled)
372                         while (1) {
373                                 tmp = lcdc_read_chan(&priv->ch[k], LDPMR) & 3;
374                                 if (start && tmp == 3)
375                                         break;
376                                 if (!start && tmp == 0)
377                                         break;
378                                 cpu_relax();
379                         }
380
381         if (!start)
382                 lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */
383 }
384
385 static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
386 {
387         struct fb_var_screeninfo *var = &ch->info->var, *display_var = &ch->display_var;
388         unsigned long h_total, hsync_pos, display_h_total;
389         u32 tmp;
390
391         tmp = ch->ldmt1r_value;
392         tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28;
393         tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27;
394         tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0;
395         tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0;
396         tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0;
397         tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0;
398         tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0;
399         lcdc_write_chan(ch, LDMT1R, tmp);
400
401         /* setup SYS bus */
402         lcdc_write_chan(ch, LDMT2R, ch->cfg.sys_bus_cfg.ldmt2r);
403         lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r);
404
405         /* horizontal configuration */
406         h_total = display_var->xres + display_var->hsync_len +
407                 display_var->left_margin + display_var->right_margin;
408         tmp = h_total / 8; /* HTCN */
409         tmp |= (min(display_var->xres, var->xres) / 8) << 16; /* HDCN */
410         lcdc_write_chan(ch, LDHCNR, tmp);
411
412         hsync_pos = display_var->xres + display_var->right_margin;
413         tmp = hsync_pos / 8; /* HSYNP */
414         tmp |= (display_var->hsync_len / 8) << 16; /* HSYNW */
415         lcdc_write_chan(ch, LDHSYNR, tmp);
416
417         /* vertical configuration */
418         tmp = display_var->yres + display_var->vsync_len +
419                 display_var->upper_margin + display_var->lower_margin; /* VTLN */
420         tmp |= min(display_var->yres, var->yres) << 16; /* VDLN */
421         lcdc_write_chan(ch, LDVLNR, tmp);
422
423         tmp = display_var->yres + display_var->lower_margin; /* VSYNP */
424         tmp |= display_var->vsync_len << 16; /* VSYNW */
425         lcdc_write_chan(ch, LDVSYNR, tmp);
426
427         /* Adjust horizontal synchronisation for HDMI */
428         display_h_total = display_var->xres + display_var->hsync_len +
429                 display_var->left_margin + display_var->right_margin;
430         tmp = ((display_var->xres & 7) << 24) |
431                 ((display_h_total & 7) << 16) |
432                 ((display_var->hsync_len & 7) << 8) |
433                 hsync_pos;
434         lcdc_write_chan(ch, LDHAJR, tmp);
435 }
436
437 static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
438 {
439         struct sh_mobile_lcdc_chan *ch;
440         struct sh_mobile_lcdc_board_cfg *board_cfg;
441         unsigned long tmp;
442         int k, m;
443         int ret = 0;
444
445         /* enable clocks before accessing the hardware */
446         for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
447                 if (priv->ch[k].enabled)
448                         sh_mobile_lcdc_clk_on(priv);
449
450         /* reset */
451         lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LCDC_RESET);
452         lcdc_wait_bit(priv, _LDCNT2R, LCDC_RESET, 0);
453
454         /* enable LCDC channels */
455         tmp = lcdc_read(priv, _LDCNT2R);
456         tmp |= priv->ch[0].enabled;
457         tmp |= priv->ch[1].enabled;
458         lcdc_write(priv, _LDCNT2R, tmp);
459
460         /* read data from external memory, avoid using the BEU for now */
461         lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) & ~DISPLAY_BEU);
462
463         /* stop the lcdc first */
464         sh_mobile_lcdc_start_stop(priv, 0);
465
466         /* configure clocks */
467         tmp = priv->lddckr;
468         for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
469                 ch = &priv->ch[k];
470
471                 if (!priv->ch[k].enabled)
472                         continue;
473
474                 m = ch->cfg.clock_divider;
475                 if (!m)
476                         continue;
477
478                 if (m == 1)
479                         m = 1 << 6;
480                 tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0);
481
482                 lcdc_write_chan(ch, LDDCKPAT1R, 0);
483                 lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1);
484         }
485
486         lcdc_write(priv, _LDDCKR, tmp);
487
488         /* start dotclock again */
489         lcdc_write(priv, _LDDCKSTPR, 0);
490         lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0);
491
492         /* interrupts are disabled to begin with */
493         lcdc_write(priv, _LDINTR, 0);
494
495         for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
496                 ch = &priv->ch[k];
497
498                 if (!ch->enabled)
499                         continue;
500
501                 sh_mobile_lcdc_geometry(ch);
502
503                 /* power supply */
504                 lcdc_write_chan(ch, LDPMR, 0);
505
506                 board_cfg = &ch->cfg.board_cfg;
507                 if (board_cfg->setup_sys)
508                         ret = board_cfg->setup_sys(board_cfg->board_data, ch,
509                                                    &sh_mobile_lcdc_sys_bus_ops);
510                 if (ret)
511                         return ret;
512         }
513
514         /* word and long word swap */
515         lcdc_write(priv, _LDDDSR, lcdc_read(priv, _LDDDSR) | 6);
516
517         for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
518                 ch = &priv->ch[k];
519
520                 if (!priv->ch[k].enabled)
521                         continue;
522
523                 /* set bpp format in PKF[4:0] */
524                 tmp = lcdc_read_chan(ch, LDDFR);
525                 tmp &= ~0x0001001f;
526                 tmp |= (ch->info->var.bits_per_pixel == 16) ? 3 : 0;
527                 lcdc_write_chan(ch, LDDFR, tmp);
528
529                 /* point out our frame buffer */
530                 lcdc_write_chan(ch, LDSA1R, ch->info->fix.smem_start);
531
532                 /* set line size */
533                 lcdc_write_chan(ch, LDMLSR, ch->info->fix.line_length);
534
535                 /* setup deferred io if SYS bus */
536                 tmp = ch->cfg.sys_bus_cfg.deferred_io_msec;
537                 if (ch->ldmt1r_value & (1 << 12) && tmp) {
538                         ch->defio.deferred_io = sh_mobile_lcdc_deferred_io;
539                         ch->defio.delay = msecs_to_jiffies(tmp);
540                         ch->info->fbdefio = &ch->defio;
541                         fb_deferred_io_init(ch->info);
542
543                         /* one-shot mode */
544                         lcdc_write_chan(ch, LDSM1R, 1);
545
546                         /* enable "Frame End Interrupt Enable" bit */
547                         lcdc_write(priv, _LDINTR, LDINTR_FE);
548
549                 } else {
550                         /* continuous read mode */
551                         lcdc_write_chan(ch, LDSM1R, 0);
552                 }
553         }
554
555         /* display output */
556         lcdc_write(priv, _LDCNT1R, LCDC_ENABLE);
557
558         /* start the lcdc */
559         sh_mobile_lcdc_start_stop(priv, 1);
560         priv->started = 1;
561
562         /* tell the board code to enable the panel */
563         for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
564                 ch = &priv->ch[k];
565                 if (!ch->enabled)
566                         continue;
567
568                 board_cfg = &ch->cfg.board_cfg;
569                 if (try_module_get(board_cfg->owner) && board_cfg->display_on) {
570                         board_cfg->display_on(board_cfg->board_data, ch->info);
571                         module_put(board_cfg->owner);
572                 }
573         }
574
575         return 0;
576 }
577
578 static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
579 {
580         struct sh_mobile_lcdc_chan *ch;
581         struct sh_mobile_lcdc_board_cfg *board_cfg;
582         int k;
583
584         /* clean up deferred io and ask board code to disable panel */
585         for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
586                 ch = &priv->ch[k];
587                 if (!ch->enabled)
588                         continue;
589
590                 /* deferred io mode:
591                  * flush frame, and wait for frame end interrupt
592                  * clean up deferred io and enable clock
593                  */
594                 if (ch->info && ch->info->fbdefio) {
595                         ch->frame_end = 0;
596                         schedule_delayed_work(&ch->info->deferred_work, 0);
597                         wait_event(ch->frame_end_wait, ch->frame_end);
598                         fb_deferred_io_cleanup(ch->info);
599                         ch->info->fbdefio = NULL;
600                         sh_mobile_lcdc_clk_on(priv);
601                 }
602
603                 board_cfg = &ch->cfg.board_cfg;
604                 if (try_module_get(board_cfg->owner) && board_cfg->display_off) {
605                         board_cfg->display_off(board_cfg->board_data);
606                         module_put(board_cfg->owner);
607                 }
608         }
609
610         /* stop the lcdc */
611         if (priv->started) {
612                 sh_mobile_lcdc_start_stop(priv, 0);
613                 priv->started = 0;
614         }
615
616         /* stop clocks */
617         for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
618                 if (priv->ch[k].enabled)
619                         sh_mobile_lcdc_clk_off(priv);
620 }
621
622 static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
623 {
624         int ifm, miftyp;
625
626         switch (ch->cfg.interface_type) {
627         case RGB8: ifm = 0; miftyp = 0; break;
628         case RGB9: ifm = 0; miftyp = 4; break;
629         case RGB12A: ifm = 0; miftyp = 5; break;
630         case RGB12B: ifm = 0; miftyp = 6; break;
631         case RGB16: ifm = 0; miftyp = 7; break;
632         case RGB18: ifm = 0; miftyp = 10; break;
633         case RGB24: ifm = 0; miftyp = 11; break;
634         case SYS8A: ifm = 1; miftyp = 0; break;
635         case SYS8B: ifm = 1; miftyp = 1; break;
636         case SYS8C: ifm = 1; miftyp = 2; break;
637         case SYS8D: ifm = 1; miftyp = 3; break;
638         case SYS9: ifm = 1; miftyp = 4; break;
639         case SYS12: ifm = 1; miftyp = 5; break;
640         case SYS16A: ifm = 1; miftyp = 7; break;
641         case SYS16B: ifm = 1; miftyp = 8; break;
642         case SYS16C: ifm = 1; miftyp = 9; break;
643         case SYS18: ifm = 1; miftyp = 10; break;
644         case SYS24: ifm = 1; miftyp = 11; break;
645         default: goto bad;
646         }
647
648         /* SUBLCD only supports SYS interface */
649         if (lcdc_chan_is_sublcd(ch)) {
650                 if (ifm == 0)
651                         goto bad;
652                 else
653                         ifm = 0;
654         }
655
656         ch->ldmt1r_value = (ifm << 12) | miftyp;
657         return 0;
658  bad:
659         return -EINVAL;
660 }
661
662 static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
663                                        int clock_source,
664                                        struct sh_mobile_lcdc_priv *priv)
665 {
666         char *str;
667         int icksel;
668
669         switch (clock_source) {
670         case LCDC_CLK_BUS: str = "bus_clk"; icksel = 0; break;
671         case LCDC_CLK_PERIPHERAL: str = "peripheral_clk"; icksel = 1; break;
672         case LCDC_CLK_EXTERNAL: str = NULL; icksel = 2; break;
673         default:
674                 return -EINVAL;
675         }
676
677         priv->lddckr = icksel << 16;
678
679         if (str) {
680                 priv->dot_clk = clk_get(&pdev->dev, str);
681                 if (IS_ERR(priv->dot_clk)) {
682                         dev_err(&pdev->dev, "cannot get dot clock %s\n", str);
683                         return PTR_ERR(priv->dot_clk);
684                 }
685         }
686
687         /* Runtime PM support involves two step for this driver:
688          * 1) Enable Runtime PM
689          * 2) Force Runtime PM Resume since hardware is accessed from probe()
690          */
691         priv->dev = &pdev->dev;
692         pm_runtime_enable(priv->dev);
693         pm_runtime_resume(priv->dev);
694         return 0;
695 }
696
697 static int sh_mobile_lcdc_setcolreg(u_int regno,
698                                     u_int red, u_int green, u_int blue,
699                                     u_int transp, struct fb_info *info)
700 {
701         u32 *palette = info->pseudo_palette;
702
703         if (regno >= PALETTE_NR)
704                 return -EINVAL;
705
706         /* only FB_VISUAL_TRUECOLOR supported */
707
708         red >>= 16 - info->var.red.length;
709         green >>= 16 - info->var.green.length;
710         blue >>= 16 - info->var.blue.length;
711         transp >>= 16 - info->var.transp.length;
712
713         palette[regno] = (red << info->var.red.offset) |
714           (green << info->var.green.offset) |
715           (blue << info->var.blue.offset) |
716           (transp << info->var.transp.offset);
717
718         return 0;
719 }
720
721 static struct fb_fix_screeninfo sh_mobile_lcdc_fix  = {
722         .id =           "SH Mobile LCDC",
723         .type =         FB_TYPE_PACKED_PIXELS,
724         .visual =       FB_VISUAL_TRUECOLOR,
725         .accel =        FB_ACCEL_NONE,
726         .xpanstep =     0,
727         .ypanstep =     1,
728         .ywrapstep =    0,
729 };
730
731 static void sh_mobile_lcdc_fillrect(struct fb_info *info,
732                                     const struct fb_fillrect *rect)
733 {
734         sys_fillrect(info, rect);
735         sh_mobile_lcdc_deferred_io_touch(info);
736 }
737
738 static void sh_mobile_lcdc_copyarea(struct fb_info *info,
739                                     const struct fb_copyarea *area)
740 {
741         sys_copyarea(info, area);
742         sh_mobile_lcdc_deferred_io_touch(info);
743 }
744
745 static void sh_mobile_lcdc_imageblit(struct fb_info *info,
746                                      const struct fb_image *image)
747 {
748         sys_imageblit(info, image);
749         sh_mobile_lcdc_deferred_io_touch(info);
750 }
751
752 static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
753                                      struct fb_info *info)
754 {
755         struct sh_mobile_lcdc_chan *ch = info->par;
756         struct sh_mobile_lcdc_priv *priv = ch->lcdc;
757         unsigned long ldrcntr;
758         unsigned long new_pan_offset;
759
760         new_pan_offset = (var->yoffset * info->fix.line_length) +
761                 (var->xoffset * (info->var.bits_per_pixel / 8));
762
763         if (new_pan_offset == ch->pan_offset)
764                 return 0;       /* No change, do nothing */
765
766         ldrcntr = lcdc_read(priv, _LDRCNTR);
767
768         /* Set the source address for the next refresh */
769         lcdc_write_chan_mirror(ch, LDSA1R, ch->dma_handle + new_pan_offset);
770         if (lcdc_chan_is_sublcd(ch))
771                 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
772         else
773                 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_MRS);
774
775         ch->pan_offset = new_pan_offset;
776
777         sh_mobile_lcdc_deferred_io_touch(info);
778
779         return 0;
780 }
781
782 static int sh_mobile_wait_for_vsync(struct fb_info *info)
783 {
784         struct sh_mobile_lcdc_chan *ch = info->par;
785         unsigned long ldintr;
786         int ret;
787
788         /* Enable VSync End interrupt */
789         ldintr = lcdc_read(ch->lcdc, _LDINTR);
790         ldintr |= LDINTR_VEE;
791         lcdc_write(ch->lcdc, _LDINTR, ldintr);
792
793         ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion,
794                                                         msecs_to_jiffies(100));
795         if (!ret)
796                 return -ETIMEDOUT;
797
798         return 0;
799 }
800
801 static int sh_mobile_ioctl(struct fb_info *info, unsigned int cmd,
802                        unsigned long arg)
803 {
804         int retval;
805
806         switch (cmd) {
807         case FBIO_WAITFORVSYNC:
808                 retval = sh_mobile_wait_for_vsync(info);
809                 break;
810
811         default:
812                 retval = -ENOIOCTLCMD;
813                 break;
814         }
815         return retval;
816 }
817
818 static struct fb_ops sh_mobile_lcdc_ops = {
819         .owner          = THIS_MODULE,
820         .fb_setcolreg   = sh_mobile_lcdc_setcolreg,
821         .fb_read        = fb_sys_read,
822         .fb_write       = fb_sys_write,
823         .fb_fillrect    = sh_mobile_lcdc_fillrect,
824         .fb_copyarea    = sh_mobile_lcdc_copyarea,
825         .fb_imageblit   = sh_mobile_lcdc_imageblit,
826         .fb_pan_display = sh_mobile_fb_pan_display,
827         .fb_ioctl       = sh_mobile_ioctl,
828 };
829
830 static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp)
831 {
832         switch (bpp) {
833         case 16: /* PKF[4:0] = 00011 - RGB 565 */
834                 var->red.offset = 11;
835                 var->red.length = 5;
836                 var->green.offset = 5;
837                 var->green.length = 6;
838                 var->blue.offset = 0;
839                 var->blue.length = 5;
840                 var->transp.offset = 0;
841                 var->transp.length = 0;
842                 break;
843
844         case 32: /* PKF[4:0] = 00000 - RGB 888
845                   * sh7722 pdf says 00RRGGBB but reality is GGBB00RR
846                   * this may be because LDDDSR has word swap enabled..
847                   */
848                 var->red.offset = 0;
849                 var->red.length = 8;
850                 var->green.offset = 24;
851                 var->green.length = 8;
852                 var->blue.offset = 16;
853                 var->blue.length = 8;
854                 var->transp.offset = 0;
855                 var->transp.length = 0;
856                 break;
857         default:
858                 return -EINVAL;
859         }
860         var->bits_per_pixel = bpp;
861         var->red.msb_right = 0;
862         var->green.msb_right = 0;
863         var->blue.msb_right = 0;
864         var->transp.msb_right = 0;
865         return 0;
866 }
867
868 static int sh_mobile_lcdc_suspend(struct device *dev)
869 {
870         struct platform_device *pdev = to_platform_device(dev);
871
872         sh_mobile_lcdc_stop(platform_get_drvdata(pdev));
873         return 0;
874 }
875
876 static int sh_mobile_lcdc_resume(struct device *dev)
877 {
878         struct platform_device *pdev = to_platform_device(dev);
879
880         return sh_mobile_lcdc_start(platform_get_drvdata(pdev));
881 }
882
883 static int sh_mobile_lcdc_runtime_suspend(struct device *dev)
884 {
885         struct platform_device *pdev = to_platform_device(dev);
886         struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev);
887         struct sh_mobile_lcdc_chan *ch;
888         int k, n;
889
890         /* save per-channel registers */
891         for (k = 0; k < ARRAY_SIZE(p->ch); k++) {
892                 ch = &p->ch[k];
893                 if (!ch->enabled)
894                         continue;
895                 for (n = 0; n < NR_CH_REGS; n++)
896                         ch->saved_ch_regs[n] = lcdc_read_chan(ch, n);
897         }
898
899         /* save shared registers */
900         for (n = 0; n < NR_SHARED_REGS; n++)
901                 p->saved_shared_regs[n] = lcdc_read(p, lcdc_shared_regs[n]);
902
903         /* turn off LCDC hardware */
904         lcdc_write(p, _LDCNT1R, 0);
905         return 0;
906 }
907
908 static int sh_mobile_lcdc_runtime_resume(struct device *dev)
909 {
910         struct platform_device *pdev = to_platform_device(dev);
911         struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev);
912         struct sh_mobile_lcdc_chan *ch;
913         int k, n;
914
915         /* restore per-channel registers */
916         for (k = 0; k < ARRAY_SIZE(p->ch); k++) {
917                 ch = &p->ch[k];
918                 if (!ch->enabled)
919                         continue;
920                 for (n = 0; n < NR_CH_REGS; n++)
921                         lcdc_write_chan(ch, n, ch->saved_ch_regs[n]);
922         }
923
924         /* restore shared registers */
925         for (n = 0; n < NR_SHARED_REGS; n++)
926                 lcdc_write(p, lcdc_shared_regs[n], p->saved_shared_regs[n]);
927
928         return 0;
929 }
930
931 static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
932         .suspend = sh_mobile_lcdc_suspend,
933         .resume = sh_mobile_lcdc_resume,
934         .runtime_suspend = sh_mobile_lcdc_runtime_suspend,
935         .runtime_resume = sh_mobile_lcdc_runtime_resume,
936 };
937
938 /* locking: called with info->lock held */
939 static int sh_mobile_lcdc_notify(struct notifier_block *nb,
940                                  unsigned long action, void *data)
941 {
942         struct fb_event *event = data;
943         struct fb_info *info = event->info;
944         struct sh_mobile_lcdc_chan *ch = info->par;
945         struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
946         struct fb_var_screeninfo *var;
947
948         if (&ch->lcdc->notifier != nb)
949                 return NOTIFY_DONE;
950
951         dev_dbg(info->dev, "%s(): action = %lu, data = %p\n",
952                 __func__, action, event->data);
953
954         switch(action) {
955         case FB_EVENT_SUSPEND:
956                 if (try_module_get(board_cfg->owner) && board_cfg->display_off) {
957                         board_cfg->display_off(board_cfg->board_data);
958                         module_put(board_cfg->owner);
959                 }
960                 pm_runtime_put(info->device);
961                 break;
962         case FB_EVENT_RESUME:
963                 var = &info->var;
964
965                 /* HDMI must be enabled before LCDC configuration */
966                 if (try_module_get(board_cfg->owner) && board_cfg->display_on) {
967                         board_cfg->display_on(board_cfg->board_data, ch->info);
968                         module_put(board_cfg->owner);
969                 }
970
971                 /* Check if the new display is not in our modelist */
972                 if (ch->info->modelist.next &&
973                     !fb_match_mode(var, &ch->info->modelist)) {
974                         struct fb_videomode mode;
975                         int ret;
976
977                         /* Can we handle this display? */
978                         if (var->xres > ch->cfg.lcd_cfg[0].xres ||
979                             var->yres > ch->cfg.lcd_cfg[0].yres)
980                                 /*
981                                  * LCDC resume failed, no need to continue with
982                                  * the notifier chain
983                                  */
984                                 return notifier_from_errno(-ENOMEM);
985
986                         /* Add to the modelist */
987                         fb_var_to_videomode(&mode, var);
988                         ret = fb_add_videomode(&mode, &ch->info->modelist);
989                         if (ret < 0)
990                                 return notifier_from_errno(ret);
991                 }
992
993                 pm_runtime_get_sync(info->device);
994
995                 sh_mobile_lcdc_geometry(ch);
996         }
997
998         return NOTIFY_OK;
999 }
1000
1001 static int sh_mobile_lcdc_remove(struct platform_device *pdev);
1002
1003 static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1004 {
1005         struct fb_info *info;
1006         struct sh_mobile_lcdc_priv *priv;
1007         struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data;
1008         struct sh_mobile_lcdc_chan_cfg *cfg;
1009         struct resource *res;
1010         int error;
1011         void *buf;
1012         int i, j;
1013
1014         if (!pdata) {
1015                 dev_err(&pdev->dev, "no platform data defined\n");
1016                 return -EINVAL;
1017         }
1018
1019         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1020         i = platform_get_irq(pdev, 0);
1021         if (!res || i < 0) {
1022                 dev_err(&pdev->dev, "cannot get platform resources\n");
1023                 return -ENOENT;
1024         }
1025
1026         priv = kzalloc(sizeof(*priv), GFP_KERNEL);
1027         if (!priv) {
1028                 dev_err(&pdev->dev, "cannot allocate device data\n");
1029                 return -ENOMEM;
1030         }
1031
1032         platform_set_drvdata(pdev, priv);
1033
1034         error = request_irq(i, sh_mobile_lcdc_irq, IRQF_DISABLED,
1035                             dev_name(&pdev->dev), priv);
1036         if (error) {
1037                 dev_err(&pdev->dev, "unable to request irq\n");
1038                 goto err1;
1039         }
1040
1041         priv->irq = i;
1042         atomic_set(&priv->hw_usecnt, -1);
1043
1044         j = 0;
1045         for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) {
1046                 struct sh_mobile_lcdc_chan *ch = priv->ch + j;
1047
1048                 ch->lcdc = priv;
1049                 memcpy(&ch->cfg, &pdata->ch[i], sizeof(pdata->ch[i]));
1050
1051                 error = sh_mobile_lcdc_check_interface(ch);
1052                 if (error) {
1053                         dev_err(&pdev->dev, "unsupported interface type\n");
1054                         goto err1;
1055                 }
1056                 init_waitqueue_head(&ch->frame_end_wait);
1057                 init_completion(&ch->vsync_completion);
1058                 ch->pan_offset = 0;
1059
1060                 switch (pdata->ch[i].chan) {
1061                 case LCDC_CHAN_MAINLCD:
1062                         ch->enabled = 1 << 1;
1063                         ch->reg_offs = lcdc_offs_mainlcd;
1064                         j++;
1065                         break;
1066                 case LCDC_CHAN_SUBLCD:
1067                         ch->enabled = 1 << 2;
1068                         ch->reg_offs = lcdc_offs_sublcd;
1069                         j++;
1070                         break;
1071                 }
1072         }
1073
1074         if (!j) {
1075                 dev_err(&pdev->dev, "no channels defined\n");
1076                 error = -EINVAL;
1077                 goto err1;
1078         }
1079
1080         priv->base = ioremap_nocache(res->start, resource_size(res));
1081         if (!priv->base)
1082                 goto err1;
1083
1084         error = sh_mobile_lcdc_setup_clocks(pdev, pdata->clock_source, priv);
1085         if (error) {
1086                 dev_err(&pdev->dev, "unable to setup clocks\n");
1087                 goto err1;
1088         }
1089
1090         for (i = 0; i < j; i++) {
1091                 struct fb_var_screeninfo *var;
1092                 const struct fb_videomode *lcd_cfg, *max_cfg = NULL;
1093                 struct sh_mobile_lcdc_chan *ch = priv->ch + i;
1094                 unsigned long max_size = 0;
1095                 int k;
1096
1097                 cfg = &ch->cfg;
1098
1099                 ch->info = framebuffer_alloc(0, &pdev->dev);
1100                 if (!ch->info) {
1101                         dev_err(&pdev->dev, "unable to allocate fb_info\n");
1102                         error = -ENOMEM;
1103                         break;
1104                 }
1105
1106                 info = ch->info;
1107                 var = &info->var;
1108                 info->fbops = &sh_mobile_lcdc_ops;
1109                 fb_videomode_to_var(var, &cfg->lcd_cfg[0]);
1110                 /* Default Y virtual resolution is 2x panel size */
1111                 var->yres_virtual = var->yres * 2;
1112
1113                 error = sh_mobile_lcdc_set_bpp(var, cfg->bpp);
1114                 if (error)
1115                         break;
1116
1117                 for (k = 0, lcd_cfg = cfg->lcd_cfg;
1118                      k < cfg->num_cfg;
1119                      k++, lcd_cfg++) {
1120                         unsigned long size = lcd_cfg->yres * lcd_cfg->xres;
1121
1122                         if (size > max_size) {
1123                                 max_cfg = lcd_cfg;
1124                                 max_size = size;
1125                         }
1126                 }
1127
1128                 dev_dbg(&pdev->dev, "Found largest videomode %ux%u\n",
1129                         max_cfg->xres, max_cfg->yres);
1130
1131                 info->fix = sh_mobile_lcdc_fix;
1132                 info->fix.line_length = cfg->lcd_cfg[0].xres * (cfg->bpp / 8);
1133                 info->fix.smem_len = max_size * (cfg->bpp / 8) * 2;
1134
1135                 buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len,
1136                                          &ch->dma_handle, GFP_KERNEL);
1137                 if (!buf) {
1138                         dev_err(&pdev->dev, "unable to allocate buffer\n");
1139                         error = -ENOMEM;
1140                         break;
1141                 }
1142
1143                 info->pseudo_palette = &ch->pseudo_palette;
1144                 info->flags = FBINFO_FLAG_DEFAULT;
1145
1146                 error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
1147                 if (error < 0) {
1148                         dev_err(&pdev->dev, "unable to allocate cmap\n");
1149                         dma_free_coherent(&pdev->dev, info->fix.smem_len,
1150                                           buf, ch->dma_handle);
1151                         break;
1152                 }
1153
1154                 info->fix.smem_start = ch->dma_handle;
1155                 info->screen_base = buf;
1156                 info->device = &pdev->dev;
1157                 info->par = ch;
1158                 ch->display_var = *var;
1159         }
1160
1161         if (error)
1162                 goto err1;
1163
1164         error = sh_mobile_lcdc_start(priv);
1165         if (error) {
1166                 dev_err(&pdev->dev, "unable to start hardware\n");
1167                 goto err1;
1168         }
1169
1170         for (i = 0; i < j; i++) {
1171                 struct sh_mobile_lcdc_chan *ch = priv->ch + i;
1172
1173                 info = ch->info;
1174
1175                 if (info->fbdefio) {
1176                         ch->sglist = vmalloc(sizeof(struct scatterlist) *
1177                                         info->fix.smem_len >> PAGE_SHIFT);
1178                         if (!ch->sglist) {
1179                                 dev_err(&pdev->dev, "cannot allocate sglist\n");
1180                                 goto err1;
1181                         }
1182                 }
1183
1184                 error = register_framebuffer(info);
1185                 if (error < 0)
1186                         goto err1;
1187
1188                 dev_info(info->dev,
1189                          "registered %s/%s as %dx%d %dbpp.\n",
1190                          pdev->name,
1191                          (ch->cfg.chan == LCDC_CHAN_MAINLCD) ?
1192                          "mainlcd" : "sublcd",
1193                          (int) ch->cfg.lcd_cfg[0].xres,
1194                          (int) ch->cfg.lcd_cfg[0].yres,
1195                          ch->cfg.bpp);
1196
1197                 /* deferred io mode: disable clock to save power */
1198                 if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED)
1199                         sh_mobile_lcdc_clk_off(priv);
1200         }
1201
1202         /* Failure ignored */
1203         priv->notifier.notifier_call = sh_mobile_lcdc_notify;
1204         fb_register_client(&priv->notifier);
1205
1206         return 0;
1207 err1:
1208         sh_mobile_lcdc_remove(pdev);
1209
1210         return error;
1211 }
1212
1213 static int sh_mobile_lcdc_remove(struct platform_device *pdev)
1214 {
1215         struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
1216         struct fb_info *info;
1217         int i;
1218
1219         fb_unregister_client(&priv->notifier);
1220
1221         for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
1222                 if (priv->ch[i].info && priv->ch[i].info->dev)
1223                         unregister_framebuffer(priv->ch[i].info);
1224
1225         sh_mobile_lcdc_stop(priv);
1226
1227         for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
1228                 info = priv->ch[i].info;
1229
1230                 if (!info || !info->device)
1231                         continue;
1232
1233                 if (priv->ch[i].sglist)
1234                         vfree(priv->ch[i].sglist);
1235
1236                 dma_free_coherent(&pdev->dev, info->fix.smem_len,
1237                                   info->screen_base, priv->ch[i].dma_handle);
1238                 fb_dealloc_cmap(&info->cmap);
1239                 framebuffer_release(info);
1240         }
1241
1242         if (priv->dot_clk)
1243                 clk_put(priv->dot_clk);
1244
1245         if (priv->dev)
1246                 pm_runtime_disable(priv->dev);
1247
1248         if (priv->base)
1249                 iounmap(priv->base);
1250
1251         if (priv->irq)
1252                 free_irq(priv->irq, priv);
1253         kfree(priv);
1254         return 0;
1255 }
1256
1257 static struct platform_driver sh_mobile_lcdc_driver = {
1258         .driver         = {
1259                 .name           = "sh_mobile_lcdc_fb",
1260                 .owner          = THIS_MODULE,
1261                 .pm             = &sh_mobile_lcdc_dev_pm_ops,
1262         },
1263         .probe          = sh_mobile_lcdc_probe,
1264         .remove         = sh_mobile_lcdc_remove,
1265 };
1266
1267 static int __init sh_mobile_lcdc_init(void)
1268 {
1269         return platform_driver_register(&sh_mobile_lcdc_driver);
1270 }
1271
1272 static void __exit sh_mobile_lcdc_exit(void)
1273 {
1274         platform_driver_unregister(&sh_mobile_lcdc_driver);
1275 }
1276
1277 module_init(sh_mobile_lcdc_init);
1278 module_exit(sh_mobile_lcdc_exit);
1279
1280 MODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver");
1281 MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
1282 MODULE_LICENSE("GPL v2");