linux/drivers/video/sh_mobile_lcdcfb.c
<<
>>
Prefs
   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        unsigned int nr_pages;
 285
 286        /* enable clocks before accessing hardware */
 287        sh_mobile_lcdc_clk_on(ch->lcdc);
 288
 289        nr_pages = sh_mobile_lcdc_sginit(info, pagelist);
 290        dma_map_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
 291
 292        /* trigger panel update */
 293        lcdc_write_chan(ch, LDSM2R, 1);
 294
 295        dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
 296}
 297
 298static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info)
 299{
 300        struct fb_deferred_io *fbdefio = info->fbdefio;
 301
 302        if (fbdefio)
 303                schedule_delayed_work(&info->deferred_work, fbdefio->delay);
 304}
 305
 306static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
 307{
 308        struct sh_mobile_lcdc_priv *priv = data;
 309        struct sh_mobile_lcdc_chan *ch;
 310        unsigned long tmp;
 311        unsigned long ldintr;
 312        int is_sub;
 313        int k;
 314
 315        /* acknowledge interrupt */
 316        ldintr = tmp = lcdc_read(priv, _LDINTR);
 317        /*
 318         * disable further VSYNC End IRQs, preserve all other enabled IRQs,
 319         * write 0 to bits 0-6 to ack all triggered IRQs.
 320         */
 321        tmp &= 0xffffff00 & ~LDINTR_VEE;
 322        lcdc_write(priv, _LDINTR, tmp);
 323
 324        /* figure out if this interrupt is for main or sub lcd */
 325        is_sub = (lcdc_read(priv, _LDSR) & (1 << 10)) ? 1 : 0;
 326
 327        /* wake up channel and disable clocks */
 328        for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
 329                ch = &priv->ch[k];
 330
 331                if (!ch->enabled)
 332                        continue;
 333
 334                /* Frame Start */
 335                if (ldintr & LDINTR_FS) {
 336                        if (is_sub == lcdc_chan_is_sublcd(ch)) {
 337                                ch->frame_end = 1;
 338                                wake_up(&ch->frame_end_wait);
 339
 340                                sh_mobile_lcdc_clk_off(priv);
 341                        }
 342                }
 343
 344                /* VSYNC End */
 345                if (ldintr & LDINTR_VES) {
 346                        unsigned long ldrcntr = lcdc_read(priv, _LDRCNTR);
 347                        /* Set the source address for the next refresh */
 348                        lcdc_write_chan_mirror(ch, LDSA1R, ch->dma_handle +
 349                                               ch->new_pan_offset);
 350                        if (lcdc_chan_is_sublcd(ch))
 351                                lcdc_write(ch->lcdc, _LDRCNTR,
 352                                           ldrcntr ^ LDRCNTR_SRS);
 353                        else
 354                                lcdc_write(ch->lcdc, _LDRCNTR,
 355                                           ldrcntr ^ LDRCNTR_MRS);
 356                        ch->pan_offset = ch->new_pan_offset;
 357                }
 358        }
 359
 360        return IRQ_HANDLED;
 361}
 362
 363static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
 364                                      int start)
 365{
 366        unsigned long tmp = lcdc_read(priv, _LDCNT2R);
 367        int k;
 368
 369        /* start or stop the lcdc */
 370        if (start)
 371                lcdc_write(priv, _LDCNT2R, tmp | START_LCDC);
 372        else
 373                lcdc_write(priv, _LDCNT2R, tmp & ~START_LCDC);
 374
 375        /* wait until power is applied/stopped on all channels */
 376        for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
 377                if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled)
 378                        while (1) {
 379                                tmp = lcdc_read_chan(&priv->ch[k], LDPMR) & 3;
 380                                if (start && tmp == 3)
 381                                        break;
 382                                if (!start && tmp == 0)
 383                                        break;
 384                                cpu_relax();
 385                        }
 386
 387        if (!start)
 388                lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */
 389}
 390
 391static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 392{
 393        struct sh_mobile_lcdc_chan *ch;
 394        struct fb_videomode *lcd_cfg;
 395        struct sh_mobile_lcdc_board_cfg *board_cfg;
 396        unsigned long tmp;
 397        int k, m;
 398        int ret = 0;
 399
 400        /* enable clocks before accessing the hardware */
 401        for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
 402                if (priv->ch[k].enabled)
 403                        sh_mobile_lcdc_clk_on(priv);
 404
 405        /* reset */
 406        lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LCDC_RESET);
 407        lcdc_wait_bit(priv, _LDCNT2R, LCDC_RESET, 0);
 408
 409        /* enable LCDC channels */
 410        tmp = lcdc_read(priv, _LDCNT2R);
 411        tmp |= priv->ch[0].enabled;
 412        tmp |= priv->ch[1].enabled;
 413        lcdc_write(priv, _LDCNT2R, tmp);
 414
 415        /* read data from external memory, avoid using the BEU for now */
 416        lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) & ~DISPLAY_BEU);
 417
 418        /* stop the lcdc first */
 419        sh_mobile_lcdc_start_stop(priv, 0);
 420
 421        /* configure clocks */
 422        tmp = priv->lddckr;
 423        for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
 424                ch = &priv->ch[k];
 425
 426                if (!priv->ch[k].enabled)
 427                        continue;
 428
 429                m = ch->cfg.clock_divider;
 430                if (!m)
 431                        continue;
 432
 433                if (m == 1)
 434                        m = 1 << 6;
 435                tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0);
 436
 437                lcdc_write_chan(ch, LDDCKPAT1R, 0x00000000);
 438                lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1);
 439        }
 440
 441        lcdc_write(priv, _LDDCKR, tmp);
 442
 443        /* start dotclock again */
 444        lcdc_write(priv, _LDDCKSTPR, 0);
 445        lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0);
 446
 447        /* interrupts are disabled to begin with */
 448        lcdc_write(priv, _LDINTR, 0);
 449
 450        for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
 451                ch = &priv->ch[k];
 452                lcd_cfg = &ch->cfg.lcd_cfg;
 453
 454                if (!ch->enabled)
 455                        continue;
 456
 457                tmp = ch->ldmt1r_value;
 458                tmp |= (lcd_cfg->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28;
 459                tmp |= (lcd_cfg->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27;
 460                tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0;
 461                tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0;
 462                tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0;
 463                tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0;
 464                tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0;
 465                lcdc_write_chan(ch, LDMT1R, tmp);
 466
 467                /* setup SYS bus */
 468                lcdc_write_chan(ch, LDMT2R, ch->cfg.sys_bus_cfg.ldmt2r);
 469                lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r);
 470
 471                /* horizontal configuration */
 472                tmp = lcd_cfg->xres + lcd_cfg->hsync_len;
 473                tmp += lcd_cfg->left_margin;
 474                tmp += lcd_cfg->right_margin;
 475                tmp /= 8; /* HTCN */
 476                tmp |= (lcd_cfg->xres / 8) << 16; /* HDCN */
 477                lcdc_write_chan(ch, LDHCNR, tmp);
 478
 479                tmp = lcd_cfg->xres;
 480                tmp += lcd_cfg->right_margin;
 481                tmp /= 8; /* HSYNP */
 482                tmp |= (lcd_cfg->hsync_len / 8) << 16; /* HSYNW */
 483                lcdc_write_chan(ch, LDHSYNR, tmp);
 484
 485                /* power supply */
 486                lcdc_write_chan(ch, LDPMR, 0);
 487
 488                /* vertical configuration */
 489                tmp = lcd_cfg->yres + lcd_cfg->vsync_len;
 490                tmp += lcd_cfg->upper_margin;
 491                tmp += lcd_cfg->lower_margin; /* VTLN */
 492                tmp |= lcd_cfg->yres << 16; /* VDLN */
 493                lcdc_write_chan(ch, LDVLNR, tmp);
 494
 495                tmp = lcd_cfg->yres;
 496                tmp += lcd_cfg->lower_margin; /* VSYNP */
 497                tmp |= lcd_cfg->vsync_len << 16; /* VSYNW */
 498                lcdc_write_chan(ch, LDVSYNR, tmp);
 499
 500                board_cfg = &ch->cfg.board_cfg;
 501                if (board_cfg->setup_sys)
 502                        ret = board_cfg->setup_sys(board_cfg->board_data, ch,
 503                                                   &sh_mobile_lcdc_sys_bus_ops);
 504                if (ret)
 505                        return ret;
 506        }
 507
 508        /* word and long word swap */
 509        lcdc_write(priv, _LDDDSR, lcdc_read(priv, _LDDDSR) | 6);
 510
 511        for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
 512                ch = &priv->ch[k];
 513
 514                if (!priv->ch[k].enabled)
 515                        continue;
 516
 517                /* set bpp format in PKF[4:0] */
 518                tmp = lcdc_read_chan(ch, LDDFR);
 519                tmp &= ~(0x0001001f);
 520                tmp |= (ch->info->var.bits_per_pixel == 16) ? 3 : 0;
 521                lcdc_write_chan(ch, LDDFR, tmp);
 522
 523                /* point out our frame buffer */
 524                lcdc_write_chan(ch, LDSA1R, ch->info->fix.smem_start);
 525
 526                /* set line size */
 527                lcdc_write_chan(ch, LDMLSR, ch->info->fix.line_length);
 528
 529                /* setup deferred io if SYS bus */
 530                tmp = ch->cfg.sys_bus_cfg.deferred_io_msec;
 531                if (ch->ldmt1r_value & (1 << 12) && tmp) {
 532                        ch->defio.deferred_io = sh_mobile_lcdc_deferred_io;
 533                        ch->defio.delay = msecs_to_jiffies(tmp);
 534                        ch->info->fbdefio = &ch->defio;
 535                        fb_deferred_io_init(ch->info);
 536
 537                        /* one-shot mode */
 538                        lcdc_write_chan(ch, LDSM1R, 1);
 539
 540                        /* enable "Frame End Interrupt Enable" bit */
 541                        lcdc_write(priv, _LDINTR, LDINTR_FE);
 542
 543                } else {
 544                        /* continuous read mode */
 545                        lcdc_write_chan(ch, LDSM1R, 0);
 546                }
 547        }
 548
 549        /* display output */
 550        lcdc_write(priv, _LDCNT1R, LCDC_ENABLE);
 551
 552        /* start the lcdc */
 553        sh_mobile_lcdc_start_stop(priv, 1);
 554        priv->started = 1;
 555
 556        /* tell the board code to enable the panel */
 557        for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
 558                ch = &priv->ch[k];
 559                if (!ch->enabled)
 560                        continue;
 561
 562                board_cfg = &ch->cfg.board_cfg;
 563                if (board_cfg->display_on)
 564                        board_cfg->display_on(board_cfg->board_data);
 565        }
 566
 567        return 0;
 568}
 569
 570static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
 571{
 572        struct sh_mobile_lcdc_chan *ch;
 573        struct sh_mobile_lcdc_board_cfg *board_cfg;
 574        int k;
 575
 576        /* clean up deferred io and ask board code to disable panel */
 577        for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
 578                ch = &priv->ch[k];
 579                if (!ch->enabled)
 580                        continue;
 581
 582                /* deferred io mode:
 583                 * flush frame, and wait for frame end interrupt
 584                 * clean up deferred io and enable clock
 585                 */
 586                if (ch->info->fbdefio) {
 587                        ch->frame_end = 0;
 588                        schedule_delayed_work(&ch->info->deferred_work, 0);
 589                        wait_event(ch->frame_end_wait, ch->frame_end);
 590                        fb_deferred_io_cleanup(ch->info);
 591                        ch->info->fbdefio = NULL;
 592                        sh_mobile_lcdc_clk_on(priv);
 593                }
 594
 595                board_cfg = &ch->cfg.board_cfg;
 596                if (board_cfg->display_off)
 597                        board_cfg->display_off(board_cfg->board_data);
 598        }
 599
 600        /* stop the lcdc */
 601        if (priv->started) {
 602                sh_mobile_lcdc_start_stop(priv, 0);
 603                priv->started = 0;
 604        }
 605
 606        /* stop clocks */
 607        for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
 608                if (priv->ch[k].enabled)
 609                        sh_mobile_lcdc_clk_off(priv);
 610}
 611
 612static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
 613{
 614        int ifm, miftyp;
 615
 616        switch (ch->cfg.interface_type) {
 617        case RGB8: ifm = 0; miftyp = 0; break;
 618        case RGB9: ifm = 0; miftyp = 4; break;
 619        case RGB12A: ifm = 0; miftyp = 5; break;
 620        case RGB12B: ifm = 0; miftyp = 6; break;
 621        case RGB16: ifm = 0; miftyp = 7; break;
 622        case RGB18: ifm = 0; miftyp = 10; break;
 623        case RGB24: ifm = 0; miftyp = 11; break;
 624        case SYS8A: ifm = 1; miftyp = 0; break;
 625        case SYS8B: ifm = 1; miftyp = 1; break;
 626        case SYS8C: ifm = 1; miftyp = 2; break;
 627        case SYS8D: ifm = 1; miftyp = 3; break;
 628        case SYS9: ifm = 1; miftyp = 4; break;
 629        case SYS12: ifm = 1; miftyp = 5; break;
 630        case SYS16A: ifm = 1; miftyp = 7; break;
 631        case SYS16B: ifm = 1; miftyp = 8; break;
 632        case SYS16C: ifm = 1; miftyp = 9; break;
 633        case SYS18: ifm = 1; miftyp = 10; break;
 634        case SYS24: ifm = 1; miftyp = 11; break;
 635        default: goto bad;
 636        }
 637
 638        /* SUBLCD only supports SYS interface */
 639        if (lcdc_chan_is_sublcd(ch)) {
 640                if (ifm == 0)
 641                        goto bad;
 642                else
 643                        ifm = 0;
 644        }
 645
 646        ch->ldmt1r_value = (ifm << 12) | miftyp;
 647        return 0;
 648 bad:
 649        return -EINVAL;
 650}
 651
 652static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
 653                                       int clock_source,
 654                                       struct sh_mobile_lcdc_priv *priv)
 655{
 656        char *str;
 657        int icksel;
 658
 659        switch (clock_source) {
 660        case LCDC_CLK_BUS: str = "bus_clk"; icksel = 0; break;
 661        case LCDC_CLK_PERIPHERAL: str = "peripheral_clk"; icksel = 1; break;
 662        case LCDC_CLK_EXTERNAL: str = NULL; icksel = 2; break;
 663        default:
 664                return -EINVAL;
 665        }
 666
 667        priv->lddckr = icksel << 16;
 668
 669        if (str) {
 670                priv->dot_clk = clk_get(&pdev->dev, str);
 671                if (IS_ERR(priv->dot_clk)) {
 672                        dev_err(&pdev->dev, "cannot get dot clock %s\n", str);
 673                        return PTR_ERR(priv->dot_clk);
 674                }
 675        }
 676        atomic_set(&priv->hw_usecnt, -1);
 677
 678        /* Runtime PM support involves two step for this driver:
 679         * 1) Enable Runtime PM
 680         * 2) Force Runtime PM Resume since hardware is accessed from probe()
 681         */
 682        pm_runtime_enable(priv->dev);
 683        pm_runtime_resume(priv->dev);
 684        return 0;
 685}
 686
 687static int sh_mobile_lcdc_setcolreg(u_int regno,
 688                                    u_int red, u_int green, u_int blue,
 689                                    u_int transp, struct fb_info *info)
 690{
 691        u32 *palette = info->pseudo_palette;
 692
 693        if (regno >= PALETTE_NR)
 694                return -EINVAL;
 695
 696        /* only FB_VISUAL_TRUECOLOR supported */
 697
 698        red >>= 16 - info->var.red.length;
 699        green >>= 16 - info->var.green.length;
 700        blue >>= 16 - info->var.blue.length;
 701        transp >>= 16 - info->var.transp.length;
 702
 703        palette[regno] = (red << info->var.red.offset) |
 704          (green << info->var.green.offset) |
 705          (blue << info->var.blue.offset) |
 706          (transp << info->var.transp.offset);
 707
 708        return 0;
 709}
 710
 711static struct fb_fix_screeninfo sh_mobile_lcdc_fix  = {
 712        .id =           "SH Mobile LCDC",
 713        .type =         FB_TYPE_PACKED_PIXELS,
 714        .visual =       FB_VISUAL_TRUECOLOR,
 715        .accel =        FB_ACCEL_NONE,
 716        .xpanstep =     0,
 717        .ypanstep =     1,
 718        .ywrapstep =    0,
 719};
 720
 721static void sh_mobile_lcdc_fillrect(struct fb_info *info,
 722                                    const struct fb_fillrect *rect)
 723{
 724        sys_fillrect(info, rect);
 725        sh_mobile_lcdc_deferred_io_touch(info);
 726}
 727
 728static void sh_mobile_lcdc_copyarea(struct fb_info *info,
 729                                    const struct fb_copyarea *area)
 730{
 731        sys_copyarea(info, area);
 732        sh_mobile_lcdc_deferred_io_touch(info);
 733}
 734
 735static void sh_mobile_lcdc_imageblit(struct fb_info *info,
 736                                     const struct fb_image *image)
 737{
 738        sys_imageblit(info, image);
 739        sh_mobile_lcdc_deferred_io_touch(info);
 740}
 741
 742static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
 743                                     struct fb_info *info)
 744{
 745        struct sh_mobile_lcdc_chan *ch = info->par;
 746
 747        if (info->var.xoffset == var->xoffset &&
 748            info->var.yoffset == var->yoffset)
 749                return 0;       /* No change, do nothing */
 750
 751        ch->new_pan_offset = (var->yoffset * info->fix.line_length) +
 752                (var->xoffset * (info->var.bits_per_pixel / 8));
 753
 754        if (ch->new_pan_offset != ch->pan_offset) {
 755                unsigned long ldintr;
 756                ldintr = lcdc_read(ch->lcdc, _LDINTR);
 757                ldintr |= LDINTR_VEE;
 758                lcdc_write(ch->lcdc, _LDINTR, ldintr);
 759                sh_mobile_lcdc_deferred_io_touch(info);
 760        }
 761
 762        return 0;
 763}
 764
 765static struct fb_ops sh_mobile_lcdc_ops = {
 766        .owner          = THIS_MODULE,
 767        .fb_setcolreg   = sh_mobile_lcdc_setcolreg,
 768        .fb_read        = fb_sys_read,
 769        .fb_write       = fb_sys_write,
 770        .fb_fillrect    = sh_mobile_lcdc_fillrect,
 771        .fb_copyarea    = sh_mobile_lcdc_copyarea,
 772        .fb_imageblit   = sh_mobile_lcdc_imageblit,
 773        .fb_pan_display = sh_mobile_fb_pan_display,
 774};
 775
 776static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp)
 777{
 778        switch (bpp) {
 779        case 16: /* PKF[4:0] = 00011 - RGB 565 */
 780                var->red.offset = 11;
 781                var->red.length = 5;
 782                var->green.offset = 5;
 783                var->green.length = 6;
 784                var->blue.offset = 0;
 785                var->blue.length = 5;
 786                var->transp.offset = 0;
 787                var->transp.length = 0;
 788                break;
 789
 790        case 32: /* PKF[4:0] = 00000 - RGB 888
 791                  * sh7722 pdf says 00RRGGBB but reality is GGBB00RR
 792                  * this may be because LDDDSR has word swap enabled..
 793                  */
 794                var->red.offset = 0;
 795                var->red.length = 8;
 796                var->green.offset = 24;
 797                var->green.length = 8;
 798                var->blue.offset = 16;
 799                var->blue.length = 8;
 800                var->transp.offset = 0;
 801                var->transp.length = 0;
 802                break;
 803        default:
 804                return -EINVAL;
 805        }
 806        var->bits_per_pixel = bpp;
 807        var->red.msb_right = 0;
 808        var->green.msb_right = 0;
 809        var->blue.msb_right = 0;
 810        var->transp.msb_right = 0;
 811        return 0;
 812}
 813
 814static int sh_mobile_lcdc_suspend(struct device *dev)
 815{
 816        struct platform_device *pdev = to_platform_device(dev);
 817
 818        sh_mobile_lcdc_stop(platform_get_drvdata(pdev));
 819        return 0;
 820}
 821
 822static int sh_mobile_lcdc_resume(struct device *dev)
 823{
 824        struct platform_device *pdev = to_platform_device(dev);
 825
 826        return sh_mobile_lcdc_start(platform_get_drvdata(pdev));
 827}
 828
 829static int sh_mobile_lcdc_runtime_suspend(struct device *dev)
 830{
 831        struct platform_device *pdev = to_platform_device(dev);
 832        struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev);
 833        struct sh_mobile_lcdc_chan *ch;
 834        int k, n;
 835
 836        /* save per-channel registers */
 837        for (k = 0; k < ARRAY_SIZE(p->ch); k++) {
 838                ch = &p->ch[k];
 839                if (!ch->enabled)
 840                        continue;
 841                for (n = 0; n < NR_CH_REGS; n++)
 842                        ch->saved_ch_regs[n] = lcdc_read_chan(ch, n);
 843        }
 844
 845        /* save shared registers */
 846        for (n = 0; n < NR_SHARED_REGS; n++)
 847                p->saved_shared_regs[n] = lcdc_read(p, lcdc_shared_regs[n]);
 848
 849        /* turn off LCDC hardware */
 850        lcdc_write(p, _LDCNT1R, 0);
 851        return 0;
 852}
 853
 854static int sh_mobile_lcdc_runtime_resume(struct device *dev)
 855{
 856        struct platform_device *pdev = to_platform_device(dev);
 857        struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev);
 858        struct sh_mobile_lcdc_chan *ch;
 859        int k, n;
 860
 861        /* restore per-channel registers */
 862        for (k = 0; k < ARRAY_SIZE(p->ch); k++) {
 863                ch = &p->ch[k];
 864                if (!ch->enabled)
 865                        continue;
 866                for (n = 0; n < NR_CH_REGS; n++)
 867                        lcdc_write_chan(ch, n, ch->saved_ch_regs[n]);
 868        }
 869
 870        /* restore shared registers */
 871        for (n = 0; n < NR_SHARED_REGS; n++)
 872                lcdc_write(p, lcdc_shared_regs[n], p->saved_shared_regs[n]);
 873
 874        return 0;
 875}
 876
 877static struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
 878        .suspend = sh_mobile_lcdc_suspend,
 879        .resume = sh_mobile_lcdc_resume,
 880        .runtime_suspend = sh_mobile_lcdc_runtime_suspend,
 881        .runtime_resume = sh_mobile_lcdc_runtime_resume,
 882};
 883
 884static int sh_mobile_lcdc_remove(struct platform_device *pdev);
 885
 886static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
 887{
 888        struct fb_info *info;
 889        struct sh_mobile_lcdc_priv *priv;
 890        struct sh_mobile_lcdc_info *pdata;
 891        struct sh_mobile_lcdc_chan_cfg *cfg;
 892        struct resource *res;
 893        int error;
 894        void *buf;
 895        int i, j;
 896
 897        if (!pdev->dev.platform_data) {
 898                dev_err(&pdev->dev, "no platform data defined\n");
 899                error = -EINVAL;
 900                goto err0;
 901        }
 902
 903        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 904        i = platform_get_irq(pdev, 0);
 905        if (!res || i < 0) {
 906                dev_err(&pdev->dev, "cannot get platform resources\n");
 907                error = -ENOENT;
 908                goto err0;
 909        }
 910
 911        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 912        if (!priv) {
 913                dev_err(&pdev->dev, "cannot allocate device data\n");
 914                error = -ENOMEM;
 915                goto err0;
 916        }
 917
 918        error = request_irq(i, sh_mobile_lcdc_irq, IRQF_DISABLED,
 919                            dev_name(&pdev->dev), priv);
 920        if (error) {
 921                dev_err(&pdev->dev, "unable to request irq\n");
 922                goto err1;
 923        }
 924
 925        priv->irq = i;
 926        priv->dev = &pdev->dev;
 927        platform_set_drvdata(pdev, priv);
 928        pdata = pdev->dev.platform_data;
 929
 930        j = 0;
 931        for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) {
 932                priv->ch[j].lcdc = priv;
 933                memcpy(&priv->ch[j].cfg, &pdata->ch[i], sizeof(pdata->ch[i]));
 934
 935                error = sh_mobile_lcdc_check_interface(&priv->ch[i]);
 936                if (error) {
 937                        dev_err(&pdev->dev, "unsupported interface type\n");
 938                        goto err1;
 939                }
 940                init_waitqueue_head(&priv->ch[i].frame_end_wait);
 941                priv->ch[j].pan_offset = 0;
 942                priv->ch[j].new_pan_offset = 0;
 943
 944                switch (pdata->ch[i].chan) {
 945                case LCDC_CHAN_MAINLCD:
 946                        priv->ch[j].enabled = 1 << 1;
 947                        priv->ch[j].reg_offs = lcdc_offs_mainlcd;
 948                        j++;
 949                        break;
 950                case LCDC_CHAN_SUBLCD:
 951                        priv->ch[j].enabled = 1 << 2;
 952                        priv->ch[j].reg_offs = lcdc_offs_sublcd;
 953                        j++;
 954                        break;
 955                }
 956        }
 957
 958        if (!j) {
 959                dev_err(&pdev->dev, "no channels defined\n");
 960                error = -EINVAL;
 961                goto err1;
 962        }
 963
 964        error = sh_mobile_lcdc_setup_clocks(pdev, pdata->clock_source, priv);
 965        if (error) {
 966                dev_err(&pdev->dev, "unable to setup clocks\n");
 967                goto err1;
 968        }
 969
 970        priv->base = ioremap_nocache(res->start, (res->end - res->start) + 1);
 971
 972        for (i = 0; i < j; i++) {
 973                cfg = &priv->ch[i].cfg;
 974
 975                priv->ch[i].info = framebuffer_alloc(0, &pdev->dev);
 976                if (!priv->ch[i].info) {
 977                        dev_err(&pdev->dev, "unable to allocate fb_info\n");
 978                        error = -ENOMEM;
 979                        break;
 980                }
 981
 982                info = priv->ch[i].info;
 983                info->fbops = &sh_mobile_lcdc_ops;
 984                info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres;
 985                info->var.yres = cfg->lcd_cfg.yres;
 986                /* Default Y virtual resolution is 2x panel size */
 987                info->var.yres_virtual = info->var.yres * 2;
 988                info->var.width = cfg->lcd_size_cfg.width;
 989                info->var.height = cfg->lcd_size_cfg.height;
 990                info->var.activate = FB_ACTIVATE_NOW;
 991                error = sh_mobile_lcdc_set_bpp(&info->var, cfg->bpp);
 992                if (error)
 993                        break;
 994
 995                info->fix = sh_mobile_lcdc_fix;
 996                info->fix.line_length = cfg->lcd_cfg.xres * (cfg->bpp / 8);
 997                info->fix.smem_len = info->fix.line_length *
 998                        info->var.yres_virtual;
 999
1000                buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len,
1001                                         &priv->ch[i].dma_handle, GFP_KERNEL);
1002                if (!buf) {
1003                        dev_err(&pdev->dev, "unable to allocate buffer\n");
1004                        error = -ENOMEM;
1005                        break;
1006                }
1007
1008                info->pseudo_palette = &priv->ch[i].pseudo_palette;
1009                info->flags = FBINFO_FLAG_DEFAULT;
1010
1011                error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
1012                if (error < 0) {
1013                        dev_err(&pdev->dev, "unable to allocate cmap\n");
1014                        dma_free_coherent(&pdev->dev, info->fix.smem_len,
1015                                          buf, priv->ch[i].dma_handle);
1016                        break;
1017                }
1018
1019                memset(buf, 0, info->fix.smem_len);
1020                info->fix.smem_start = priv->ch[i].dma_handle;
1021                info->screen_base = buf;
1022                info->device = &pdev->dev;
1023                info->par = &priv->ch[i];
1024        }
1025
1026        if (error)
1027                goto err1;
1028
1029        error = sh_mobile_lcdc_start(priv);
1030        if (error) {
1031                dev_err(&pdev->dev, "unable to start hardware\n");
1032                goto err1;
1033        }
1034
1035        for (i = 0; i < j; i++) {
1036                struct sh_mobile_lcdc_chan *ch = priv->ch + i;
1037
1038                info = ch->info;
1039
1040                if (info->fbdefio) {
1041                        priv->ch->sglist = vmalloc(sizeof(struct scatterlist) *
1042                                        info->fix.smem_len >> PAGE_SHIFT);
1043                        if (!priv->ch->sglist) {
1044                                dev_err(&pdev->dev, "cannot allocate sglist\n");
1045                                goto err1;
1046                        }
1047                }
1048
1049                error = register_framebuffer(info);
1050                if (error < 0)
1051                        goto err1;
1052
1053                dev_info(info->dev,
1054                         "registered %s/%s as %dx%d %dbpp.\n",
1055                         pdev->name,
1056                         (ch->cfg.chan == LCDC_CHAN_MAINLCD) ?
1057                         "mainlcd" : "sublcd",
1058                         (int) ch->cfg.lcd_cfg.xres,
1059                         (int) ch->cfg.lcd_cfg.yres,
1060                         ch->cfg.bpp);
1061
1062                /* deferred io mode: disable clock to save power */
1063                if (info->fbdefio)
1064                        sh_mobile_lcdc_clk_off(priv);
1065        }
1066
1067        return 0;
1068 err1:
1069        sh_mobile_lcdc_remove(pdev);
1070 err0:
1071        return error;
1072}
1073
1074static int sh_mobile_lcdc_remove(struct platform_device *pdev)
1075{
1076        struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
1077        struct fb_info *info;
1078        int i;
1079
1080        for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
1081                if (priv->ch[i].info->dev)
1082                        unregister_framebuffer(priv->ch[i].info);
1083
1084        sh_mobile_lcdc_stop(priv);
1085
1086        for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
1087                info = priv->ch[i].info;
1088
1089                if (!info || !info->device)
1090                        continue;
1091
1092                if (priv->ch[i].sglist)
1093                        vfree(priv->ch[i].sglist);
1094
1095                dma_free_coherent(&pdev->dev, info->fix.smem_len,
1096                                  info->screen_base, priv->ch[i].dma_handle);
1097                fb_dealloc_cmap(&info->cmap);
1098                framebuffer_release(info);
1099        }
1100
1101        if (priv->dot_clk)
1102                clk_put(priv->dot_clk);
1103
1104        pm_runtime_disable(priv->dev);
1105
1106        if (priv->base)
1107                iounmap(priv->base);
1108
1109        if (priv->irq)
1110                free_irq(priv->irq, priv);
1111        kfree(priv);
1112        return 0;
1113}
1114
1115static struct platform_driver sh_mobile_lcdc_driver = {
1116        .driver         = {
1117                .name           = "sh_mobile_lcdc_fb",
1118                .owner          = THIS_MODULE,
1119                .pm             = &sh_mobile_lcdc_dev_pm_ops,
1120        },
1121        .probe          = sh_mobile_lcdc_probe,
1122        .remove         = sh_mobile_lcdc_remove,
1123};
1124
1125static int __init sh_mobile_lcdc_init(void)
1126{
1127        return platform_driver_register(&sh_mobile_lcdc_driver);
1128}
1129
1130static void __exit sh_mobile_lcdc_exit(void)
1131{
1132        platform_driver_unregister(&sh_mobile_lcdc_driver);
1133}
1134
1135module_init(sh_mobile_lcdc_init);
1136module_exit(sh_mobile_lcdc_exit);
1137
1138MODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver");
1139MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
1140MODULE_LICENSE("GPL v2");
1141