Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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