root/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tc35876x_regw
  2. tc35876x_regr
  3. tc35876x_set_bridge_reset_state
  4. tc35876x_configure_lvds_bridge
  5. calc_clkdiv
  6. tc35876x_brightness_init
  7. tc35876x_brightness_control
  8. tc35876x_toshiba_bridge_panel_off
  9. tc35876x_toshiba_bridge_panel_on
  10. tc35876x_get_config_mode
  11. tc35876x_get_panel_info
  12. tc35876x_bridge_probe
  13. tc35876x_bridge_remove
  14. cmi_lcd_i2c_probe
  15. cmi_lcd_i2c_remove
  16. cmi_lcd_hack_create_device
  17. tc35876x_init
  18. tc35876x_exit

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

/* [<][>][^][v][top][bottom][index][help] */