linux/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c
<<
>>
Prefs
   1/*
   2 * Copyright © 2011 Intel Corporation
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice (including the next
  12 * paragraph) shall be included in all copies or substantial portions of the
  13 * Software.
  14 *
  15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21 * DEALINGS IN THE SOFTWARE.
  22 *
  23 */
  24
  25#include "mdfld_dsi_dpi.h"
  26#include "mdfld_output.h"
  27#include "mdfld_dsi_pkg_sender.h"
  28#include "tc35876x-dsi-lvds.h"
  29#include <linux/platform_data/tc35876x.h>
  30#include <linux/kernel.h>
  31#include <linux/module.h>
  32#include <asm/intel_scu_ipc.h>
  33
  34static struct i2c_client *tc35876x_client;
  35static struct i2c_client *cmi_lcd_i2c_client;
  36
  37#define FLD_MASK(start, end)    (((1 << ((start) - (end) + 1)) - 1) << (end))
  38#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
  39
  40/* DSI D-PHY Layer Registers */
  41#define D0W_DPHYCONTTX          0x0004
  42#define CLW_DPHYCONTRX          0x0020
  43#define D0W_DPHYCONTRX          0x0024
  44#define D1W_DPHYCONTRX          0x0028
  45#define D2W_DPHYCONTRX          0x002C
  46#define D3W_DPHYCONTRX          0x0030
  47#define COM_DPHYCONTRX          0x0038
  48#define CLW_CNTRL               0x0040
  49#define D0W_CNTRL               0x0044
  50#define D1W_CNTRL               0x0048
  51#define D2W_CNTRL               0x004C
  52#define D3W_CNTRL               0x0050
  53#define DFTMODE_CNTRL           0x0054
  54
  55/* DSI PPI Layer Registers */
  56#define PPI_STARTPPI            0x0104
  57#define PPI_BUSYPPI             0x0108
  58#define PPI_LINEINITCNT         0x0110
  59#define PPI_LPTXTIMECNT         0x0114
  60#define PPI_LANEENABLE          0x0134
  61#define PPI_TX_RX_TA            0x013C
  62#define PPI_CLS_ATMR            0x0140
  63#define PPI_D0S_ATMR            0x0144
  64#define PPI_D1S_ATMR            0x0148
  65#define PPI_D2S_ATMR            0x014C
  66#define PPI_D3S_ATMR            0x0150
  67#define PPI_D0S_CLRSIPOCOUNT    0x0164
  68#define PPI_D1S_CLRSIPOCOUNT    0x0168
  69#define PPI_D2S_CLRSIPOCOUNT    0x016C
  70#define PPI_D3S_CLRSIPOCOUNT    0x0170
  71#define CLS_PRE                 0x0180
  72#define D0S_PRE                 0x0184
  73#define D1S_PRE                 0x0188
  74#define D2S_PRE                 0x018C
  75#define D3S_PRE                 0x0190
  76#define CLS_PREP                0x01A0
  77#define D0S_PREP                0x01A4
  78#define D1S_PREP                0x01A8
  79#define D2S_PREP                0x01AC
  80#define D3S_PREP                0x01B0
  81#define CLS_ZERO                0x01C0
  82#define D0S_ZERO                0x01C4
  83#define D1S_ZERO                0x01C8
  84#define D2S_ZERO                0x01CC
  85#define D3S_ZERO                0x01D0
  86#define PPI_CLRFLG              0x01E0
  87#define PPI_CLRSIPO             0x01E4
  88#define HSTIMEOUT               0x01F0
  89#define HSTIMEOUTENABLE         0x01F4
  90
  91/* DSI Protocol Layer Registers */
  92#define DSI_STARTDSI            0x0204
  93#define DSI_BUSYDSI             0x0208
  94#define DSI_LANEENABLE          0x0210
  95#define DSI_LANESTATUS0         0x0214
  96#define DSI_LANESTATUS1         0x0218
  97#define DSI_INTSTATUS           0x0220
  98#define DSI_INTMASK             0x0224
  99#define DSI_INTCLR              0x0228
 100#define DSI_LPTXTO              0x0230
 101
 102/* DSI General Registers */
 103#define DSIERRCNT               0x0300
 104
 105/* DSI Application Layer Registers */
 106#define APLCTRL                 0x0400
 107#define RDPKTLN                 0x0404
 108
 109/* Video Path Registers */
 110#define VPCTRL                  0x0450
 111#define HTIM1                   0x0454
 112#define HTIM2                   0x0458
 113#define VTIM1                   0x045C
 114#define VTIM2                   0x0460
 115#define VFUEN                   0x0464
 116
 117/* LVDS Registers */
 118#define LVMX0003                0x0480
 119#define LVMX0407                0x0484
 120#define LVMX0811                0x0488
 121#define LVMX1215                0x048C
 122#define LVMX1619                0x0490
 123#define LVMX2023                0x0494
 124#define LVMX2427                0x0498
 125#define LVCFG                   0x049C
 126#define LVPHY0                  0x04A0
 127#define LVPHY1                  0x04A4
 128
 129/* System Registers */
 130#define SYSSTAT                 0x0500
 131#define SYSRST                  0x0504
 132
 133/* GPIO Registers */
 134/*#define GPIOC                 0x0520*/
 135#define GPIOO                   0x0524
 136#define GPIOI                   0x0528
 137
 138/* I2C Registers */
 139#define I2CTIMCTRL              0x0540
 140#define I2CMADDR                0x0544
 141#define WDATAQ                  0x0548
 142#define RDATAQ                  0x054C
 143
 144/* Chip/Rev Registers */
 145#define IDREG                   0x0580
 146
 147/* Debug Registers */
 148#define DEBUG00                 0x05A0
 149#define DEBUG01                 0x05A4
 150
 151/* Panel CABC registers */
 152#define PANEL_PWM_CONTROL       0x90
 153#define PANEL_FREQ_DIVIDER_HI   0x91
 154#define PANEL_FREQ_DIVIDER_LO   0x92
 155#define PANEL_DUTY_CONTROL      0x93
 156#define PANEL_MODIFY_RGB        0x94
 157#define PANEL_FRAMERATE_CONTROL 0x96
 158#define PANEL_PWM_MIN           0x97
 159#define PANEL_PWM_REF           0x98
 160#define PANEL_PWM_MAX           0x99
 161#define PANEL_ALLOW_DISTORT     0x9A
 162#define PANEL_BYPASS_PWMI       0x9B
 163
 164/* Panel color management registers */
 165#define PANEL_CM_ENABLE         0x700
 166#define PANEL_CM_HUE            0x701
 167#define PANEL_CM_SATURATION     0x702
 168#define PANEL_CM_INTENSITY      0x703
 169#define PANEL_CM_BRIGHTNESS     0x704
 170#define PANEL_CM_CE_ENABLE      0x705
 171#define PANEL_CM_PEAK_EN        0x710
 172#define PANEL_CM_GAIN           0x711
 173#define PANEL_CM_HUETABLE_START 0x730
 174#define PANEL_CM_HUETABLE_END   0x747 /* inclusive */
 175
 176/* Input muxing for registers LVMX0003...LVMX2427 */
 177enum {
 178        INPUT_R0,       /* 0 */
 179        INPUT_R1,
 180        INPUT_R2,
 181        INPUT_R3,
 182        INPUT_R4,
 183        INPUT_R5,
 184        INPUT_R6,
 185        INPUT_R7,
 186        INPUT_G0,       /* 8 */
 187        INPUT_G1,
 188        INPUT_G2,
 189        INPUT_G3,
 190        INPUT_G4,
 191        INPUT_G5,
 192        INPUT_G6,
 193        INPUT_G7,
 194        INPUT_B0,       /* 16 */
 195        INPUT_B1,
 196        INPUT_B2,
 197        INPUT_B3,
 198        INPUT_B4,
 199        INPUT_B5,
 200        INPUT_B6,
 201        INPUT_B7,
 202        INPUT_HSYNC,    /* 24 */
 203        INPUT_VSYNC,
 204        INPUT_DE,
 205        LOGIC_0,
 206        /* 28...31 undefined */
 207};
 208
 209#define INPUT_MUX(lvmx03, lvmx02, lvmx01, lvmx00)               \
 210        (FLD_VAL(lvmx03, 29, 24) | FLD_VAL(lvmx02, 20, 16) |    \
 211        FLD_VAL(lvmx01, 12, 8) | FLD_VAL(lvmx00, 4, 0))
 212
 213/**
 214 * tc35876x_regw - Write DSI-LVDS bridge register using I2C
 215 * @client: struct i2c_client to use
 216 * @reg: register address
 217 * @value: value to write
 218 *
 219 * Returns 0 on success, or a negative error value.
 220 */
 221static int tc35876x_regw(struct i2c_client *client, u16 reg, u32 value)
 222{
 223        int r;
 224        u8 tx_data[] = {
 225                /* NOTE: Register address big-endian, data little-endian. */
 226                (reg >> 8) & 0xff,
 227                reg & 0xff,
 228                value & 0xff,
 229                (value >> 8) & 0xff,
 230                (value >> 16) & 0xff,
 231                (value >> 24) & 0xff,
 232        };
 233        struct i2c_msg msgs[] = {
 234                {
 235                        .addr = client->addr,
 236                        .flags = 0,
 237                        .buf = tx_data,
 238                        .len = ARRAY_SIZE(tx_data),
 239                },
 240        };
 241
 242        r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
 243        if (r < 0) {
 244                dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x error %d\n",
 245                        __func__, reg, value, r);
 246                return r;
 247        }
 248
 249        if (r < ARRAY_SIZE(msgs)) {
 250                dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x msgs %d\n",
 251                        __func__, reg, value, r);
 252                return -EAGAIN;
 253        }
 254
 255        dev_dbg(&client->dev, "%s: reg 0x%04x val 0x%08x\n",
 256                        __func__, reg, value);
 257
 258        return 0;
 259}
 260
 261/**
 262 * tc35876x_regr - Read DSI-LVDS bridge register using I2C
 263 * @client: struct i2c_client to use
 264 * @reg: register address
 265 * @value: pointer for storing the value
 266 *
 267 * Returns 0 on success, or a negative error value.
 268 */
 269static int tc35876x_regr(struct i2c_client *client, u16 reg, u32 *value)
 270{
 271        int r;
 272        u8 tx_data[] = {
 273                (reg >> 8) & 0xff,
 274                reg & 0xff,
 275        };
 276        u8 rx_data[4];
 277        struct i2c_msg msgs[] = {
 278                {
 279                        .addr = client->addr,
 280                        .flags = 0,
 281                        .buf = tx_data,
 282                        .len = ARRAY_SIZE(tx_data),
 283                },
 284                {
 285                        .addr = client->addr,
 286                        .flags = I2C_M_RD,
 287                        .buf = rx_data,
 288                        .len = ARRAY_SIZE(rx_data),
 289                 },
 290        };
 291
 292        r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
 293        if (r < 0) {
 294                dev_err(&client->dev, "%s: reg 0x%04x error %d\n", __func__,
 295                        reg, r);
 296                return r;
 297        }
 298
 299        if (r < ARRAY_SIZE(msgs)) {
 300                dev_err(&client->dev, "%s: reg 0x%04x msgs %d\n", __func__,
 301                        reg, r);
 302                return -EAGAIN;
 303        }
 304
 305        *value = rx_data[0] << 24 | rx_data[1] << 16 |
 306                rx_data[2] << 8 | rx_data[3];
 307
 308        dev_dbg(&client->dev, "%s: reg 0x%04x value 0x%08x\n", __func__,
 309                reg, *value);
 310
 311        return 0;
 312}
 313
 314void tc35876x_set_bridge_reset_state(struct drm_device *dev, int state)
 315{
 316        struct tc35876x_platform_data *pdata;
 317
 318        if (WARN(!tc35876x_client, "%s called before probe", __func__))
 319                return;
 320
 321        dev_dbg(&tc35876x_client->dev, "%s: state %d\n", __func__, state);
 322
 323        pdata = dev_get_platdata(&tc35876x_client->dev);
 324
 325        if (pdata->gpio_bridge_reset == -1)
 326                return;
 327
 328        if (state) {
 329                gpio_set_value_cansleep(pdata->gpio_bridge_reset, 0);
 330                mdelay(10);
 331        } else {
 332                /* Pull MIPI Bridge reset pin to Low */
 333                gpio_set_value_cansleep(pdata->gpio_bridge_reset, 0);
 334                mdelay(20);
 335                /* Pull MIPI Bridge reset pin to High */
 336                gpio_set_value_cansleep(pdata->gpio_bridge_reset, 1);
 337                mdelay(40);
 338        }
 339}
 340
 341void tc35876x_configure_lvds_bridge(struct drm_device *dev)
 342{
 343        struct i2c_client *i2c = tc35876x_client;
 344        u32 ppi_lptxtimecnt;
 345        u32 txtagocnt;
 346        u32 txtasurecnt;
 347        u32 id;
 348
 349        if (WARN(!tc35876x_client, "%s called before probe", __func__))
 350                return;
 351
 352        dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
 353
 354        if (!tc35876x_regr(i2c, IDREG, &id))
 355                dev_info(&tc35876x_client->dev, "tc35876x ID 0x%08x\n", id);
 356        else
 357                dev_err(&tc35876x_client->dev, "Cannot read ID\n");
 358
 359        ppi_lptxtimecnt = 4;
 360        txtagocnt = (5 * ppi_lptxtimecnt - 3) / 4;
 361        txtasurecnt = 3 * ppi_lptxtimecnt / 2;
 362        tc35876x_regw(i2c, PPI_TX_RX_TA, FLD_VAL(txtagocnt, 26, 16) |
 363                FLD_VAL(txtasurecnt, 10, 0));
 364        tc35876x_regw(i2c, PPI_LPTXTIMECNT, FLD_VAL(ppi_lptxtimecnt, 10, 0));
 365
 366        tc35876x_regw(i2c, PPI_D0S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
 367        tc35876x_regw(i2c, PPI_D1S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
 368        tc35876x_regw(i2c, PPI_D2S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
 369        tc35876x_regw(i2c, PPI_D3S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
 370
 371        /* Enabling MIPI & PPI lanes, Enable 4 lanes */
 372        tc35876x_regw(i2c, PPI_LANEENABLE,
 373                BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
 374        tc35876x_regw(i2c, DSI_LANEENABLE,
 375                BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
 376        tc35876x_regw(i2c, PPI_STARTPPI, BIT(0));
 377        tc35876x_regw(i2c, DSI_STARTDSI, BIT(0));
 378
 379        /* Setting LVDS output frequency */
 380        tc35876x_regw(i2c, LVPHY0, FLD_VAL(1, 20, 16) |
 381                FLD_VAL(2, 15, 14) | FLD_VAL(6, 4, 0)); /* 0x00048006 */
 382
 383        /* Setting video panel control register,0x00000120 VTGen=ON ?!?!? */
 384        tc35876x_regw(i2c, VPCTRL, BIT(8) | BIT(5));
 385
 386        /* Horizontal back porch and horizontal pulse width. 0x00280028 */
 387        tc35876x_regw(i2c, HTIM1, FLD_VAL(40, 24, 16) | FLD_VAL(40, 8, 0));
 388
 389        /* Horizontal front porch and horizontal active video size. 0x00500500*/
 390        tc35876x_regw(i2c, HTIM2, FLD_VAL(80, 24, 16) | FLD_VAL(1280, 10, 0));
 391
 392        /* Vertical back porch and vertical sync pulse width. 0x000e000a */
 393        tc35876x_regw(i2c, VTIM1, FLD_VAL(14, 23, 16) | FLD_VAL(10, 7, 0));
 394
 395        /* Vertical front porch and vertical display size. 0x000e0320 */
 396        tc35876x_regw(i2c, VTIM2, FLD_VAL(14, 23, 16) | FLD_VAL(800, 10, 0));
 397
 398        /* Set above HTIM1, HTIM2, VTIM1, and VTIM2 at next VSYNC. */
 399        tc35876x_regw(i2c, VFUEN, BIT(0));
 400
 401        /* Soft reset LCD controller. */
 402        tc35876x_regw(i2c, SYSRST, BIT(2));
 403
 404        /* LVDS-TX input muxing */
 405        tc35876x_regw(i2c, LVMX0003,
 406                INPUT_MUX(INPUT_R5, INPUT_R4, INPUT_R3, INPUT_R2));
 407        tc35876x_regw(i2c, LVMX0407,
 408                INPUT_MUX(INPUT_G2, INPUT_R7, INPUT_R1, INPUT_R6));
 409        tc35876x_regw(i2c, LVMX0811,
 410                INPUT_MUX(INPUT_G1, INPUT_G0, INPUT_G4, INPUT_G3));
 411        tc35876x_regw(i2c, LVMX1215,
 412                INPUT_MUX(INPUT_B2, INPUT_G7, INPUT_G6, INPUT_G5));
 413        tc35876x_regw(i2c, LVMX1619,
 414                INPUT_MUX(INPUT_B4, INPUT_B3, INPUT_B1, INPUT_B0));
 415        tc35876x_regw(i2c, LVMX2023,
 416                INPUT_MUX(LOGIC_0,  INPUT_B7, INPUT_B6, INPUT_B5));
 417        tc35876x_regw(i2c, LVMX2427,
 418                INPUT_MUX(INPUT_R0, INPUT_DE, INPUT_VSYNC, INPUT_HSYNC));
 419
 420        /* Enable LVDS transmitter. */
 421        tc35876x_regw(i2c, LVCFG, BIT(0));
 422
 423        /* Clear notifications. Don't write reserved bits. Was write 0xffffffff
 424         * to 0x0288, must be in error?! */
 425        tc35876x_regw(i2c, DSI_INTCLR, FLD_MASK(31, 30) | FLD_MASK(22, 0));
 426}
 427
 428#define GPIOPWMCTRL     0x38F
 429#define PWM0CLKDIV0     0x62 /* low byte */
 430#define PWM0CLKDIV1     0x61 /* high byte */
 431
 432#define SYSTEMCLK       19200000UL /* 19.2 MHz */
 433#define PWM_FREQUENCY   9600 /* Hz */
 434
 435/* f = baseclk / (clkdiv + 1) => clkdiv = (baseclk - f) / f */
 436static inline u16 calc_clkdiv(unsigned long baseclk, unsigned int f)
 437{
 438        return (baseclk - f) / f;
 439}
 440
 441static void tc35876x_brightness_init(struct drm_device *dev)
 442{
 443        int ret;
 444        u8 pwmctrl;
 445        u16 clkdiv;
 446
 447        /* Make sure the PWM reference is the 19.2 MHz system clock. Read first
 448         * instead of setting directly to catch potential conflicts between PWM
 449         * users. */
 450        ret = intel_scu_ipc_ioread8(GPIOPWMCTRL, &pwmctrl);
 451        if (ret || pwmctrl != 0x01) {
 452                if (ret)
 453                        dev_err(&dev->pdev->dev, "GPIOPWMCTRL read failed\n");
 454                else
 455                        dev_warn(&dev->pdev->dev, "GPIOPWMCTRL was not set to system clock (pwmctrl = 0x%02x)\n", pwmctrl);
 456
 457                ret = intel_scu_ipc_iowrite8(GPIOPWMCTRL, 0x01);
 458                if (ret)
 459                        dev_err(&dev->pdev->dev, "GPIOPWMCTRL set failed\n");
 460        }
 461
 462        clkdiv = calc_clkdiv(SYSTEMCLK, PWM_FREQUENCY);
 463
 464        ret = intel_scu_ipc_iowrite8(PWM0CLKDIV1, (clkdiv >> 8) & 0xff);
 465        if (!ret)
 466                ret = intel_scu_ipc_iowrite8(PWM0CLKDIV0, clkdiv & 0xff);
 467
 468        if (ret)
 469                dev_err(&dev->pdev->dev, "PWM0CLKDIV set failed\n");
 470        else
 471                dev_dbg(&dev->pdev->dev, "PWM0CLKDIV set to 0x%04x (%d Hz)\n",
 472                        clkdiv, PWM_FREQUENCY);
 473}
 474
 475#define PWM0DUTYCYCLE                   0x67
 476
 477void tc35876x_brightness_control(struct drm_device *dev, int level)
 478{
 479        int ret;
 480        u8 duty_val;
 481        u8 panel_duty_val;
 482
 483        level = clamp(level, 0, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
 484
 485        /* PWM duty cycle 0x00...0x63 corresponds to 0...99% */
 486        duty_val = level * 0x63 / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL;
 487
 488        /* I won't pretend to understand this formula. The panel spec is quite
 489         * bad engrish.
 490         */
 491        panel_duty_val = (2 * level - 100) * 0xA9 /
 492                         MDFLD_DSI_BRIGHTNESS_MAX_LEVEL + 0x56;
 493
 494        ret = intel_scu_ipc_iowrite8(PWM0DUTYCYCLE, duty_val);
 495        if (ret)
 496                dev_err(&tc35876x_client->dev, "%s: ipc write fail\n",
 497                        __func__);
 498
 499        if (cmi_lcd_i2c_client) {
 500                ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
 501                                                PANEL_PWM_MAX, panel_duty_val);
 502                if (ret < 0)
 503                        dev_err(&cmi_lcd_i2c_client->dev, "%s: i2c write failed\n",
 504                                __func__);
 505        }
 506}
 507
 508void tc35876x_toshiba_bridge_panel_off(struct drm_device *dev)
 509{
 510        struct tc35876x_platform_data *pdata;
 511
 512        if (WARN(!tc35876x_client, "%s called before probe", __func__))
 513                return;
 514
 515        dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
 516
 517        pdata = dev_get_platdata(&tc35876x_client->dev);
 518
 519        if (pdata->gpio_panel_bl_en != -1)
 520                gpio_set_value_cansleep(pdata->gpio_panel_bl_en, 0);
 521
 522        if (pdata->gpio_panel_vadd != -1)
 523                gpio_set_value_cansleep(pdata->gpio_panel_vadd, 0);
 524}
 525
 526void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev)
 527{
 528        struct tc35876x_platform_data *pdata;
 529        struct drm_psb_private *dev_priv = dev->dev_private;
 530
 531        if (WARN(!tc35876x_client, "%s called before probe", __func__))
 532                return;
 533
 534        dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
 535
 536        pdata = dev_get_platdata(&tc35876x_client->dev);
 537
 538        if (pdata->gpio_panel_vadd != -1) {
 539                gpio_set_value_cansleep(pdata->gpio_panel_vadd, 1);
 540                msleep(260);
 541        }
 542
 543        if (cmi_lcd_i2c_client) {
 544                int ret;
 545                dev_dbg(&cmi_lcd_i2c_client->dev, "setting TCON\n");
 546                /* Bit 4 is average_saving. Setting it to 1, the brightness is
 547                 * referenced to the average of the frame content. 0 means
 548                 * reference to the maximum of frame contents. Bits 3:0 are
 549                 * allow_distort. When set to a nonzero value, all color values
 550                 * between 255-allow_distort*2 and 255 are mapped to the
 551                 * 255-allow_distort*2 value.
 552                 */
 553                ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
 554                                                PANEL_ALLOW_DISTORT, 0x10);
 555                if (ret < 0)
 556                        dev_err(&cmi_lcd_i2c_client->dev,
 557                                "i2c write failed (%d)\n", ret);
 558                ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
 559                                                PANEL_BYPASS_PWMI, 0);
 560                if (ret < 0)
 561                        dev_err(&cmi_lcd_i2c_client->dev,
 562                                "i2c write failed (%d)\n", ret);
 563                /* Set minimum brightness value - this is tunable */
 564                ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
 565                                                PANEL_PWM_MIN, 0x35);
 566                if (ret < 0)
 567                        dev_err(&cmi_lcd_i2c_client->dev,
 568                                "i2c write failed (%d)\n", ret);
 569        }
 570
 571        if (pdata->gpio_panel_bl_en != -1)
 572                gpio_set_value_cansleep(pdata->gpio_panel_bl_en, 1);
 573
 574        tc35876x_brightness_control(dev, dev_priv->brightness_adjusted);
 575}
 576
 577static struct drm_display_mode *tc35876x_get_config_mode(struct drm_device *dev)
 578{
 579        struct drm_display_mode *mode;
 580
 581        dev_dbg(&dev->pdev->dev, "%s\n", __func__);
 582
 583        mode = kzalloc(sizeof(*mode), GFP_KERNEL);
 584        if (!mode)
 585                return NULL;
 586
 587        /* FIXME: do this properly. */
 588        mode->hdisplay = 1280;
 589        mode->vdisplay = 800;
 590        mode->hsync_start = 1360;
 591        mode->hsync_end = 1400;
 592        mode->htotal = 1440;
 593        mode->vsync_start = 814;
 594        mode->vsync_end = 824;
 595        mode->vtotal = 838;
 596        mode->clock = 33324 << 1;
 597
 598        dev_info(&dev->pdev->dev, "hdisplay(w) = %d\n", mode->hdisplay);
 599        dev_info(&dev->pdev->dev, "vdisplay(h) = %d\n", mode->vdisplay);
 600        dev_info(&dev->pdev->dev, "HSS = %d\n", mode->hsync_start);
 601        dev_info(&dev->pdev->dev, "HSE = %d\n", mode->hsync_end);
 602        dev_info(&dev->pdev->dev, "htotal = %d\n", mode->htotal);
 603        dev_info(&dev->pdev->dev, "VSS = %d\n", mode->vsync_start);
 604        dev_info(&dev->pdev->dev, "VSE = %d\n", mode->vsync_end);
 605        dev_info(&dev->pdev->dev, "vtotal = %d\n", mode->vtotal);
 606        dev_info(&dev->pdev->dev, "clock = %d\n", mode->clock);
 607
 608        drm_mode_set_name(mode);
 609        drm_mode_set_crtcinfo(mode, 0);
 610
 611        mode->type |= DRM_MODE_TYPE_PREFERRED;
 612
 613        return mode;
 614}
 615
 616/* DV1 Active area 216.96 x 135.6 mm */
 617#define DV1_PANEL_WIDTH 217
 618#define DV1_PANEL_HEIGHT 136
 619
 620static int tc35876x_get_panel_info(struct drm_device *dev, int pipe,
 621                                struct panel_info *pi)
 622{
 623        if (!dev || !pi)
 624                return -EINVAL;
 625
 626        pi->width_mm = DV1_PANEL_WIDTH;
 627        pi->height_mm = DV1_PANEL_HEIGHT;
 628
 629        return 0;
 630}
 631
 632static int tc35876x_bridge_probe(struct i2c_client *client,
 633                                const struct i2c_device_id *id)
 634{
 635        struct tc35876x_platform_data *pdata;
 636
 637        dev_info(&client->dev, "%s\n", __func__);
 638
 639        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 640                dev_err(&client->dev, "%s: i2c_check_functionality() failed\n",
 641                        __func__);
 642                return -ENODEV;
 643        }
 644
 645        pdata = dev_get_platdata(&client->dev);
 646        if (!pdata) {
 647                dev_err(&client->dev, "%s: no platform data\n", __func__);
 648                return -ENODEV;
 649        }
 650
 651        if (pdata->gpio_bridge_reset != -1) {
 652                gpio_request(pdata->gpio_bridge_reset, "tc35876x bridge reset");
 653                gpio_direction_output(pdata->gpio_bridge_reset, 0);
 654        }
 655
 656        if (pdata->gpio_panel_bl_en != -1) {
 657                gpio_request(pdata->gpio_panel_bl_en, "tc35876x panel bl en");
 658                gpio_direction_output(pdata->gpio_panel_bl_en, 0);
 659        }
 660
 661        if (pdata->gpio_panel_vadd != -1) {
 662                gpio_request(pdata->gpio_panel_vadd, "tc35876x panel vadd");
 663                gpio_direction_output(pdata->gpio_panel_vadd, 0);
 664        }
 665
 666        tc35876x_client = client;
 667
 668        return 0;
 669}
 670
 671static int tc35876x_bridge_remove(struct i2c_client *client)
 672{
 673        struct tc35876x_platform_data *pdata = dev_get_platdata(&client->dev);
 674
 675        dev_dbg(&client->dev, "%s\n", __func__);
 676
 677        if (pdata->gpio_bridge_reset != -1)
 678                gpio_free(pdata->gpio_bridge_reset);
 679
 680        if (pdata->gpio_panel_bl_en != -1)
 681                gpio_free(pdata->gpio_panel_bl_en);
 682
 683        if (pdata->gpio_panel_vadd != -1)
 684                gpio_free(pdata->gpio_panel_vadd);
 685
 686        tc35876x_client = NULL;
 687
 688        return 0;
 689}
 690
 691static const struct i2c_device_id tc35876x_bridge_id[] = {
 692        { "i2c_disp_brig", 0 },
 693        { }
 694};
 695MODULE_DEVICE_TABLE(i2c, tc35876x_bridge_id);
 696
 697static struct i2c_driver tc35876x_bridge_i2c_driver = {
 698        .driver = {
 699                .name = "i2c_disp_brig",
 700        },
 701        .id_table = tc35876x_bridge_id,
 702        .probe = tc35876x_bridge_probe,
 703        .remove = tc35876x_bridge_remove,
 704};
 705
 706/* LCD panel I2C */
 707static int cmi_lcd_i2c_probe(struct i2c_client *client,
 708                             const struct i2c_device_id *id)
 709{
 710        dev_info(&client->dev, "%s\n", __func__);
 711
 712        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 713                dev_err(&client->dev, "%s: i2c_check_functionality() failed\n",
 714                        __func__);
 715                return -ENODEV;
 716        }
 717
 718        cmi_lcd_i2c_client = client;
 719
 720        return 0;
 721}
 722
 723static int cmi_lcd_i2c_remove(struct i2c_client *client)
 724{
 725        dev_dbg(&client->dev, "%s\n", __func__);
 726
 727        cmi_lcd_i2c_client = NULL;
 728
 729        return 0;
 730}
 731
 732static const struct i2c_device_id cmi_lcd_i2c_id[] = {
 733        { "cmi-lcd", 0 },
 734        { }
 735};
 736MODULE_DEVICE_TABLE(i2c, cmi_lcd_i2c_id);
 737
 738static struct i2c_driver cmi_lcd_i2c_driver = {
 739        .driver = {
 740                .name = "cmi-lcd",
 741        },
 742        .id_table = cmi_lcd_i2c_id,
 743        .probe = cmi_lcd_i2c_probe,
 744        .remove = cmi_lcd_i2c_remove,
 745};
 746
 747/* HACK to create I2C device while it's not created by platform code */
 748#define CMI_LCD_I2C_ADAPTER     2
 749#define CMI_LCD_I2C_ADDR        0x60
 750
 751static int cmi_lcd_hack_create_device(void)
 752{
 753        struct i2c_adapter *adapter;
 754        struct i2c_client *client;
 755        struct i2c_board_info info = {
 756                .type = "cmi-lcd",
 757                .addr = CMI_LCD_I2C_ADDR,
 758        };
 759
 760        pr_debug("%s\n", __func__);
 761
 762        adapter = i2c_get_adapter(CMI_LCD_I2C_ADAPTER);
 763        if (!adapter) {
 764                pr_err("%s: i2c_get_adapter(%d) failed\n", __func__,
 765                        CMI_LCD_I2C_ADAPTER);
 766                return -EINVAL;
 767        }
 768
 769        client = i2c_new_device(adapter, &info);
 770        if (!client) {
 771                pr_err("%s: i2c_new_device() failed\n", __func__);
 772                i2c_put_adapter(adapter);
 773                return -EINVAL;
 774        }
 775
 776        return 0;
 777}
 778
 779static const struct drm_encoder_helper_funcs tc35876x_encoder_helper_funcs = {
 780        .dpms = mdfld_dsi_dpi_dpms,
 781        .mode_fixup = mdfld_dsi_dpi_mode_fixup,
 782        .prepare = mdfld_dsi_dpi_prepare,
 783        .mode_set = mdfld_dsi_dpi_mode_set,
 784        .commit = mdfld_dsi_dpi_commit,
 785};
 786
 787static const struct drm_encoder_funcs tc35876x_encoder_funcs = {
 788        .destroy = drm_encoder_cleanup,
 789};
 790
 791const struct panel_funcs mdfld_tc35876x_funcs = {
 792        .encoder_funcs = &tc35876x_encoder_funcs,
 793        .encoder_helper_funcs = &tc35876x_encoder_helper_funcs,
 794        .get_config_mode = tc35876x_get_config_mode,
 795        .get_panel_info = tc35876x_get_panel_info,
 796};
 797
 798void tc35876x_init(struct drm_device *dev)
 799{
 800        int r;
 801
 802        dev_dbg(&dev->pdev->dev, "%s\n", __func__);
 803
 804        cmi_lcd_hack_create_device();
 805
 806        r = i2c_add_driver(&cmi_lcd_i2c_driver);
 807        if (r < 0)
 808                dev_err(&dev->pdev->dev,
 809                        "%s: i2c_add_driver() for %s failed (%d)\n",
 810                        __func__, cmi_lcd_i2c_driver.driver.name, r);
 811
 812        r = i2c_add_driver(&tc35876x_bridge_i2c_driver);
 813        if (r < 0)
 814                dev_err(&dev->pdev->dev,
 815                        "%s: i2c_add_driver() for %s failed (%d)\n",
 816                        __func__, tc35876x_bridge_i2c_driver.driver.name, r);
 817
 818        tc35876x_brightness_init(dev);
 819}
 820
 821void tc35876x_exit(void)
 822{
 823        pr_debug("%s\n", __func__);
 824
 825        i2c_del_driver(&tc35876x_bridge_i2c_driver);
 826
 827        if (cmi_lcd_i2c_client)
 828                i2c_del_driver(&cmi_lcd_i2c_driver);
 829}
 830