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