linux/drivers/video/omap/rfbi.c
<<
>>
Prefs
   1/*
   2 * OMAP2 Remote Frame Buffer Interface support
   3 *
   4 * Copyright (C) 2005 Nokia Corporation
   5 * Author: Juha Yrjölä <juha.yrjola@nokia.com>
   6 *         Imre Deak <imre.deak@nokia.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify it
   9 * under the terms of the GNU General Public License as published by the
  10 * Free Software Foundation; either version 2 of the License, or (at your
  11 * option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful, but
  14 * WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16 * General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License along
  19 * with this program; if not, write to the Free Software Foundation, Inc.,
  20 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  21 */
  22#include <linux/module.h>
  23#include <linux/delay.h>
  24#include <linux/i2c.h>
  25#include <linux/err.h>
  26#include <linux/interrupt.h>
  27#include <linux/clk.h>
  28#include <linux/io.h>
  29
  30#include <mach/omapfb.h>
  31
  32#include "dispc.h"
  33
  34/* To work around an RFBI transfer rate limitation */
  35#define OMAP_RFBI_RATE_LIMIT    1
  36
  37#define RFBI_BASE               0x48050800
  38#define RFBI_REVISION           0x0000
  39#define RFBI_SYSCONFIG          0x0010
  40#define RFBI_SYSSTATUS          0x0014
  41#define RFBI_CONTROL            0x0040
  42#define RFBI_PIXEL_CNT          0x0044
  43#define RFBI_LINE_NUMBER        0x0048
  44#define RFBI_CMD                0x004c
  45#define RFBI_PARAM              0x0050
  46#define RFBI_DATA               0x0054
  47#define RFBI_READ               0x0058
  48#define RFBI_STATUS             0x005c
  49#define RFBI_CONFIG0            0x0060
  50#define RFBI_ONOFF_TIME0        0x0064
  51#define RFBI_CYCLE_TIME0        0x0068
  52#define RFBI_DATA_CYCLE1_0      0x006c
  53#define RFBI_DATA_CYCLE2_0      0x0070
  54#define RFBI_DATA_CYCLE3_0      0x0074
  55#define RFBI_VSYNC_WIDTH        0x0090
  56#define RFBI_HSYNC_WIDTH        0x0094
  57
  58#define DISPC_BASE              0x48050400
  59#define DISPC_CONTROL           0x0040
  60#define DISPC_IRQ_FRAMEMASK     0x0001
  61
  62static struct {
  63        void __iomem    *base;
  64        void            (*lcdc_callback)(void *data);
  65        void            *lcdc_callback_data;
  66        unsigned long   l4_khz;
  67        int             bits_per_cycle;
  68        struct omapfb_device *fbdev;
  69        struct clk      *dss_ick;
  70        struct clk      *dss1_fck;
  71        unsigned        tearsync_pin_cnt;
  72        unsigned        tearsync_mode;
  73} rfbi;
  74
  75static inline void rfbi_write_reg(int idx, u32 val)
  76{
  77        __raw_writel(val, rfbi.base + idx);
  78}
  79
  80static inline u32 rfbi_read_reg(int idx)
  81{
  82        return __raw_readl(rfbi.base + idx);
  83}
  84
  85static int rfbi_get_clocks(void)
  86{
  87        rfbi.dss_ick = clk_get(rfbi.fbdev->dev, "ick");
  88        if (IS_ERR(rfbi.dss_ick)) {
  89                dev_err(rfbi.fbdev->dev, "can't get ick\n");
  90                return PTR_ERR(rfbi.dss_ick);
  91        }
  92
  93        rfbi.dss1_fck = clk_get(rfbi.fbdev->dev, "dss1_fck");
  94        if (IS_ERR(rfbi.dss1_fck)) {
  95                dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n");
  96                clk_put(rfbi.dss_ick);
  97                return PTR_ERR(rfbi.dss1_fck);
  98        }
  99
 100        return 0;
 101}
 102
 103static void rfbi_put_clocks(void)
 104{
 105        clk_put(rfbi.dss1_fck);
 106        clk_put(rfbi.dss_ick);
 107}
 108
 109static void rfbi_enable_clocks(int enable)
 110{
 111        if (enable) {
 112                clk_enable(rfbi.dss_ick);
 113                clk_enable(rfbi.dss1_fck);
 114        } else {
 115                clk_disable(rfbi.dss1_fck);
 116                clk_disable(rfbi.dss_ick);
 117        }
 118}
 119
 120
 121#ifdef VERBOSE
 122static void rfbi_print_timings(void)
 123{
 124        u32 l;
 125        u32 time;
 126
 127        l = rfbi_read_reg(RFBI_CONFIG0);
 128        time = 1000000000 / rfbi.l4_khz;
 129        if (l & (1 << 4))
 130                time *= 2;
 131
 132        dev_dbg(rfbi.fbdev->dev, "Tick time %u ps\n", time);
 133        l = rfbi_read_reg(RFBI_ONOFF_TIME0);
 134        dev_dbg(rfbi.fbdev->dev,
 135                "CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
 136                "REONTIME %d, REOFFTIME %d\n",
 137                l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
 138                (l >> 20) & 0x0f, (l >> 24) & 0x3f);
 139
 140        l = rfbi_read_reg(RFBI_CYCLE_TIME0);
 141        dev_dbg(rfbi.fbdev->dev,
 142                "WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
 143                "ACCESSTIME %d\n",
 144                (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f,
 145                (l >> 22) & 0x3f);
 146}
 147#else
 148static void rfbi_print_timings(void) {}
 149#endif
 150
 151static void rfbi_set_timings(const struct extif_timings *t)
 152{
 153        u32 l;
 154
 155        BUG_ON(!t->converted);
 156
 157        rfbi_enable_clocks(1);
 158        rfbi_write_reg(RFBI_ONOFF_TIME0, t->tim[0]);
 159        rfbi_write_reg(RFBI_CYCLE_TIME0, t->tim[1]);
 160
 161        l = rfbi_read_reg(RFBI_CONFIG0);
 162        l &= ~(1 << 4);
 163        l |= (t->tim[2] ? 1 : 0) << 4;
 164        rfbi_write_reg(RFBI_CONFIG0, l);
 165
 166        rfbi_print_timings();
 167        rfbi_enable_clocks(0);
 168}
 169
 170static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
 171{
 172        *clk_period = 1000000000 / rfbi.l4_khz;
 173        *max_clk_div = 2;
 174}
 175
 176static int ps_to_rfbi_ticks(int time, int div)
 177{
 178        unsigned long tick_ps;
 179        int ret;
 180
 181        /* Calculate in picosecs to yield more exact results */
 182        tick_ps = 1000000000 / (rfbi.l4_khz) * div;
 183
 184        ret = (time + tick_ps - 1) / tick_ps;
 185
 186        return ret;
 187}
 188
 189#ifdef OMAP_RFBI_RATE_LIMIT
 190static unsigned long rfbi_get_max_tx_rate(void)
 191{
 192        unsigned long   l4_rate, dss1_rate;
 193        int             min_l4_ticks = 0;
 194        int             i;
 195
 196        /* According to TI this can't be calculated so make the
 197         * adjustments for a couple of known frequencies and warn for
 198         * others.
 199         */
 200        static const struct {
 201                unsigned long l4_clk;           /* HZ */
 202                unsigned long dss1_clk;         /* HZ */
 203                unsigned long min_l4_ticks;
 204        } ftab[] = {
 205                { 55,   132,    7, },           /* 7.86 MPix/s */
 206                { 110,  110,    12, },          /* 9.16 MPix/s */
 207                { 110,  132,    10, },          /* 11   Mpix/s */
 208                { 120,  120,    10, },          /* 12   Mpix/s */
 209                { 133,  133,    10, },          /* 13.3 Mpix/s */
 210        };
 211
 212        l4_rate = rfbi.l4_khz / 1000;
 213        dss1_rate = clk_get_rate(rfbi.dss1_fck) / 1000000;
 214
 215        for (i = 0; i < ARRAY_SIZE(ftab); i++) {
 216                /* Use a window instead of an exact match, to account
 217                 * for different DPLL multiplier / divider pairs.
 218                 */
 219                if (abs(ftab[i].l4_clk - l4_rate) < 3 &&
 220                    abs(ftab[i].dss1_clk - dss1_rate) < 3) {
 221                        min_l4_ticks = ftab[i].min_l4_ticks;
 222                        break;
 223                }
 224        }
 225        if (i == ARRAY_SIZE(ftab)) {
 226                /* Can't be sure, return anyway the maximum not
 227                 * rate-limited. This might cause a problem only for the
 228                 * tearing synchronisation.
 229                 */
 230                dev_err(rfbi.fbdev->dev,
 231                        "can't determine maximum RFBI transfer rate\n");
 232                return rfbi.l4_khz * 1000;
 233        }
 234        return rfbi.l4_khz * 1000 / min_l4_ticks;
 235}
 236#else
 237static int rfbi_get_max_tx_rate(void)
 238{
 239        return rfbi.l4_khz * 1000;
 240}
 241#endif
 242
 243
 244static int rfbi_convert_timings(struct extif_timings *t)
 245{
 246        u32 l;
 247        int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
 248        int actim, recyc, wecyc;
 249        int div = t->clk_div;
 250
 251        if (div <= 0 || div > 2)
 252                return -1;
 253
 254        /* Make sure that after conversion it still holds that:
 255         * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff,
 256         * csoff > cson, csoff >= max(weoff, reoff), actim > reon
 257         */
 258        weon = ps_to_rfbi_ticks(t->we_on_time, div);
 259        weoff = ps_to_rfbi_ticks(t->we_off_time, div);
 260        if (weoff <= weon)
 261                weoff = weon + 1;
 262        if (weon > 0x0f)
 263                return -1;
 264        if (weoff > 0x3f)
 265                return -1;
 266
 267        reon = ps_to_rfbi_ticks(t->re_on_time, div);
 268        reoff = ps_to_rfbi_ticks(t->re_off_time, div);
 269        if (reoff <= reon)
 270                reoff = reon + 1;
 271        if (reon > 0x0f)
 272                return -1;
 273        if (reoff > 0x3f)
 274                return -1;
 275
 276        cson = ps_to_rfbi_ticks(t->cs_on_time, div);
 277        csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
 278        if (csoff <= cson)
 279                csoff = cson + 1;
 280        if (csoff < max(weoff, reoff))
 281                csoff = max(weoff, reoff);
 282        if (cson > 0x0f)
 283                return -1;
 284        if (csoff > 0x3f)
 285                return -1;
 286
 287        l =  cson;
 288        l |= csoff << 4;
 289        l |= weon  << 10;
 290        l |= weoff << 14;
 291        l |= reon  << 20;
 292        l |= reoff << 24;
 293
 294        t->tim[0] = l;
 295
 296        actim = ps_to_rfbi_ticks(t->access_time, div);
 297        if (actim <= reon)
 298                actim = reon + 1;
 299        if (actim > 0x3f)
 300                return -1;
 301
 302        wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
 303        if (wecyc < weoff)
 304                wecyc = weoff;
 305        if (wecyc > 0x3f)
 306                return -1;
 307
 308        recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
 309        if (recyc < reoff)
 310                recyc = reoff;
 311        if (recyc > 0x3f)
 312                return -1;
 313
 314        cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
 315        if (cs_pulse > 0x3f)
 316                return -1;
 317
 318        l =  wecyc;
 319        l |= recyc    << 6;
 320        l |= cs_pulse << 12;
 321        l |= actim    << 22;
 322
 323        t->tim[1] = l;
 324
 325        t->tim[2] = div - 1;
 326
 327        t->converted = 1;
 328
 329        return 0;
 330}
 331
 332static int rfbi_setup_tearsync(unsigned pin_cnt,
 333                               unsigned hs_pulse_time, unsigned vs_pulse_time,
 334                               int hs_pol_inv, int vs_pol_inv, int extif_div)
 335{
 336        int hs, vs;
 337        int min;
 338        u32 l;
 339
 340        if (pin_cnt != 1 && pin_cnt != 2)
 341                return -EINVAL;
 342
 343        hs = ps_to_rfbi_ticks(hs_pulse_time, 1);
 344        vs = ps_to_rfbi_ticks(vs_pulse_time, 1);
 345        if (hs < 2)
 346                return -EDOM;
 347        if (pin_cnt == 2)
 348                min = 2;
 349        else
 350                min = 4;
 351        if (vs < min)
 352                return -EDOM;
 353        if (vs == hs)
 354                return -EINVAL;
 355        rfbi.tearsync_pin_cnt = pin_cnt;
 356        dev_dbg(rfbi.fbdev->dev,
 357                "setup_tearsync: pins %d hs %d vs %d hs_inv %d vs_inv %d\n",
 358                pin_cnt, hs, vs, hs_pol_inv, vs_pol_inv);
 359
 360        rfbi_enable_clocks(1);
 361        rfbi_write_reg(RFBI_HSYNC_WIDTH, hs);
 362        rfbi_write_reg(RFBI_VSYNC_WIDTH, vs);
 363
 364        l = rfbi_read_reg(RFBI_CONFIG0);
 365        if (hs_pol_inv)
 366                l &= ~(1 << 21);
 367        else
 368                l |= 1 << 21;
 369        if (vs_pol_inv)
 370                l &= ~(1 << 20);
 371        else
 372                l |= 1 << 20;
 373        rfbi_enable_clocks(0);
 374
 375        return 0;
 376}
 377
 378static int rfbi_enable_tearsync(int enable, unsigned line)
 379{
 380        u32 l;
 381
 382        dev_dbg(rfbi.fbdev->dev, "tearsync %d line %d mode %d\n",
 383                enable, line, rfbi.tearsync_mode);
 384        if (line > (1 << 11) - 1)
 385                return -EINVAL;
 386
 387        rfbi_enable_clocks(1);
 388        l = rfbi_read_reg(RFBI_CONFIG0);
 389        l &= ~(0x3 << 2);
 390        if (enable) {
 391                rfbi.tearsync_mode = rfbi.tearsync_pin_cnt;
 392                l |= rfbi.tearsync_mode << 2;
 393        } else
 394                rfbi.tearsync_mode = 0;
 395        rfbi_write_reg(RFBI_CONFIG0, l);
 396        rfbi_write_reg(RFBI_LINE_NUMBER, line);
 397        rfbi_enable_clocks(0);
 398
 399        return 0;
 400}
 401
 402static void rfbi_write_command(const void *buf, unsigned int len)
 403{
 404        rfbi_enable_clocks(1);
 405        if (rfbi.bits_per_cycle == 16) {
 406                const u16 *w = buf;
 407                BUG_ON(len & 1);
 408                for (; len; len -= 2)
 409                        rfbi_write_reg(RFBI_CMD, *w++);
 410        } else {
 411                const u8 *b = buf;
 412                BUG_ON(rfbi.bits_per_cycle != 8);
 413                for (; len; len--)
 414                        rfbi_write_reg(RFBI_CMD, *b++);
 415        }
 416        rfbi_enable_clocks(0);
 417}
 418
 419static void rfbi_read_data(void *buf, unsigned int len)
 420{
 421        rfbi_enable_clocks(1);
 422        if (rfbi.bits_per_cycle == 16) {
 423                u16 *w = buf;
 424                BUG_ON(len & ~1);
 425                for (; len; len -= 2) {
 426                        rfbi_write_reg(RFBI_READ, 0);
 427                        *w++ = rfbi_read_reg(RFBI_READ);
 428                }
 429        } else {
 430                u8 *b = buf;
 431                BUG_ON(rfbi.bits_per_cycle != 8);
 432                for (; len; len--) {
 433                        rfbi_write_reg(RFBI_READ, 0);
 434                        *b++ = rfbi_read_reg(RFBI_READ);
 435                }
 436        }
 437        rfbi_enable_clocks(0);
 438}
 439
 440static void rfbi_write_data(const void *buf, unsigned int len)
 441{
 442        rfbi_enable_clocks(1);
 443        if (rfbi.bits_per_cycle == 16) {
 444                const u16 *w = buf;
 445                BUG_ON(len & 1);
 446                for (; len; len -= 2)
 447                        rfbi_write_reg(RFBI_PARAM, *w++);
 448        } else {
 449                const u8 *b = buf;
 450                BUG_ON(rfbi.bits_per_cycle != 8);
 451                for (; len; len--)
 452                        rfbi_write_reg(RFBI_PARAM, *b++);
 453        }
 454        rfbi_enable_clocks(0);
 455}
 456
 457static void rfbi_transfer_area(int width, int height,
 458                                void (callback)(void * data), void *data)
 459{
 460        u32 w;
 461
 462        BUG_ON(callback == NULL);
 463
 464        rfbi_enable_clocks(1);
 465        omap_dispc_set_lcd_size(width, height);
 466
 467        rfbi.lcdc_callback = callback;
 468        rfbi.lcdc_callback_data = data;
 469
 470        rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
 471
 472        w = rfbi_read_reg(RFBI_CONTROL);
 473        w |= 1;                         /* enable */
 474        if (!rfbi.tearsync_mode)
 475                w |= 1 << 4;            /* internal trigger, reset by HW */
 476        rfbi_write_reg(RFBI_CONTROL, w);
 477
 478        omap_dispc_enable_lcd_out(1);
 479}
 480
 481static inline void _stop_transfer(void)
 482{
 483        u32 w;
 484
 485        w = rfbi_read_reg(RFBI_CONTROL);
 486        rfbi_write_reg(RFBI_CONTROL, w & ~(1 << 0));
 487        rfbi_enable_clocks(0);
 488}
 489
 490static void rfbi_dma_callback(void *data)
 491{
 492        _stop_transfer();
 493        rfbi.lcdc_callback(rfbi.lcdc_callback_data);
 494}
 495
 496static void rfbi_set_bits_per_cycle(int bpc)
 497{
 498        u32 l;
 499
 500        rfbi_enable_clocks(1);
 501        l = rfbi_read_reg(RFBI_CONFIG0);
 502        l &= ~(0x03 << 0);
 503
 504        switch (bpc) {
 505        case 8:
 506                break;
 507        case 16:
 508                l |= 3;
 509                break;
 510        default:
 511                BUG();
 512        }
 513        rfbi_write_reg(RFBI_CONFIG0, l);
 514        rfbi.bits_per_cycle = bpc;
 515        rfbi_enable_clocks(0);
 516}
 517
 518static int rfbi_init(struct omapfb_device *fbdev)
 519{
 520        u32 l;
 521        int r;
 522
 523        rfbi.fbdev = fbdev;
 524        rfbi.base = ioremap(RFBI_BASE, SZ_1K);
 525        if (!rfbi.base) {
 526                dev_err(fbdev->dev, "can't ioremap RFBI\n");
 527                return -ENOMEM;
 528        }
 529
 530        if ((r = rfbi_get_clocks()) < 0)
 531                return r;
 532        rfbi_enable_clocks(1);
 533
 534        rfbi.l4_khz = clk_get_rate(rfbi.dss_ick) / 1000;
 535
 536        /* Reset */
 537        rfbi_write_reg(RFBI_SYSCONFIG, 1 << 1);
 538        while (!(rfbi_read_reg(RFBI_SYSSTATUS) & (1 << 0)));
 539
 540        l = rfbi_read_reg(RFBI_SYSCONFIG);
 541        /* Enable autoidle and smart-idle */
 542        l |= (1 << 0) | (2 << 3);
 543        rfbi_write_reg(RFBI_SYSCONFIG, l);
 544
 545        /* 16-bit interface, ITE trigger mode, 16-bit data */
 546        l = (0x03 << 0) | (0x00 << 2) | (0x01 << 5) | (0x02 << 7);
 547        l |= (0 << 9) | (1 << 20) | (1 << 21);
 548        rfbi_write_reg(RFBI_CONFIG0, l);
 549
 550        rfbi_write_reg(RFBI_DATA_CYCLE1_0, 0x00000010);
 551
 552        l = rfbi_read_reg(RFBI_CONTROL);
 553        /* Select CS0, clear bypass mode */
 554        l = (0x01 << 2);
 555        rfbi_write_reg(RFBI_CONTROL, l);
 556
 557        r = omap_dispc_request_irq(DISPC_IRQ_FRAMEMASK, rfbi_dma_callback,
 558                                   NULL);
 559        if (r < 0) {
 560                dev_err(fbdev->dev, "can't get DISPC irq\n");
 561                rfbi_enable_clocks(0);
 562                return r;
 563        }
 564
 565        l = rfbi_read_reg(RFBI_REVISION);
 566        pr_info("omapfb: RFBI version %d.%d initialized\n",
 567                (l >> 4) & 0x0f, l & 0x0f);
 568
 569        rfbi_enable_clocks(0);
 570
 571        return 0;
 572}
 573
 574static void rfbi_cleanup(void)
 575{
 576        omap_dispc_free_irq(DISPC_IRQ_FRAMEMASK, rfbi_dma_callback, NULL);
 577        rfbi_put_clocks();
 578        iounmap(rfbi.base);
 579}
 580
 581const struct lcd_ctrl_extif omap2_ext_if = {
 582        .init                   = rfbi_init,
 583        .cleanup                = rfbi_cleanup,
 584        .get_clk_info           = rfbi_get_clk_info,
 585        .get_max_tx_rate        = rfbi_get_max_tx_rate,
 586        .set_bits_per_cycle     = rfbi_set_bits_per_cycle,
 587        .convert_timings        = rfbi_convert_timings,
 588        .set_timings            = rfbi_set_timings,
 589        .write_command          = rfbi_write_command,
 590        .read_data              = rfbi_read_data,
 591        .write_data             = rfbi_write_data,
 592        .transfer_area          = rfbi_transfer_area,
 593        .setup_tearsync         = rfbi_setup_tearsync,
 594        .enable_tearsync        = rfbi_enable_tearsync,
 595
 596        .max_transmit_size      = (u32) ~0,
 597};
 598
 599