2 * Copyright © 2011 Intel Corporation
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:
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
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.
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/i2c/tc35876x.h>
30 #include <linux/kernel.h>
31 #include <linux/module.h>
32 #include <asm/intel_scu_ipc.h>
34 static struct i2c_client
*tc35876x_client
;
35 static struct i2c_client
*cmi_lcd_i2c_client
;
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))
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
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
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
102 /* DSI General Registers */
103 #define DSIERRCNT 0x0300
105 /* DSI Application Layer Registers */
106 #define APLCTRL 0x0400
107 #define RDPKTLN 0x0404
109 /* Video Path Registers */
110 #define VPCTRL 0x0450
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
126 #define LVPHY0 0x04A0
127 #define LVPHY1 0x04A4
129 /* System Registers */
130 #define SYSSTAT 0x0500
131 #define SYSRST 0x0504
134 /*#define GPIOC 0x0520*/
139 #define I2CTIMCTRL 0x0540
140 #define I2CMADDR 0x0544
141 #define WDATAQ 0x0548
142 #define RDATAQ 0x054C
144 /* Chip/Rev Registers */
147 /* Debug Registers */
148 #define DEBUG00 0x05A0
149 #define DEBUG01 0x05A4
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
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 */
176 /* Input muxing for registers LVMX0003...LVMX2427 */
202 INPUT_HSYNC
, /* 24 */
206 /* 28...31 undefined */
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))
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
219 * Returns 0 on success, or a negative error value.
221 static int tc35876x_regw(struct i2c_client
*client
, u16 reg
, u32 value
)
225 /* NOTE: Register address big-endian, data little-endian. */
230 (value
>> 16) & 0xff,
231 (value
>> 24) & 0xff,
233 struct i2c_msg msgs
[] = {
235 .addr
= client
->addr
,
238 .len
= ARRAY_SIZE(tx_data
),
242 r
= i2c_transfer(client
->adapter
, msgs
, ARRAY_SIZE(msgs
));
244 dev_err(&client
->dev
, "%s: reg 0x%04x val 0x%08x error %d\n",
245 __func__
, reg
, value
, r
);
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
);
255 dev_dbg(&client
->dev
, "%s: reg 0x%04x val 0x%08x\n",
256 __func__
, reg
, value
);
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
267 * Returns 0 on success, or a negative error value.
269 static int tc35876x_regr(struct i2c_client
*client
, u16 reg
, u32
*value
)
277 struct i2c_msg msgs
[] = {
279 .addr
= client
->addr
,
282 .len
= ARRAY_SIZE(tx_data
),
285 .addr
= client
->addr
,
288 .len
= ARRAY_SIZE(rx_data
),
292 r
= i2c_transfer(client
->adapter
, msgs
, ARRAY_SIZE(msgs
));
294 dev_err(&client
->dev
, "%s: reg 0x%04x error %d\n", __func__
,
299 if (r
< ARRAY_SIZE(msgs
)) {
300 dev_err(&client
->dev
, "%s: reg 0x%04x msgs %d\n", __func__
,
305 *value
= rx_data
[0] << 24 | rx_data
[1] << 16 |
306 rx_data
[2] << 8 | rx_data
[3];
308 dev_dbg(&client
->dev
, "%s: reg 0x%04x value 0x%08x\n", __func__
,
314 void tc35876x_set_bridge_reset_state(struct drm_device
*dev
, int state
)
316 struct tc35876x_platform_data
*pdata
;
318 if (WARN(!tc35876x_client
, "%s called before probe", __func__
))
321 dev_dbg(&tc35876x_client
->dev
, "%s: state %d\n", __func__
, state
);
323 pdata
= dev_get_platdata(&tc35876x_client
->dev
);
325 if (pdata
->gpio_bridge_reset
== -1)
329 gpio_set_value_cansleep(pdata
->gpio_bridge_reset
, 0);
332 /* Pull MIPI Bridge reset pin to Low */
333 gpio_set_value_cansleep(pdata
->gpio_bridge_reset
, 0);
335 /* Pull MIPI Bridge reset pin to High */
336 gpio_set_value_cansleep(pdata
->gpio_bridge_reset
, 1);
341 void tc35876x_configure_lvds_bridge(struct drm_device
*dev
)
343 struct i2c_client
*i2c
= tc35876x_client
;
349 if (WARN(!tc35876x_client
, "%s called before probe", __func__
))
352 dev_dbg(&tc35876x_client
->dev
, "%s\n", __func__
);
354 if (!tc35876x_regr(i2c
, IDREG
, &id
))
355 dev_info(&tc35876x_client
->dev
, "tc35876x ID 0x%08x\n", id
);
357 dev_err(&tc35876x_client
->dev
, "Cannot read ID\n");
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));
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));
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));
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 */
383 /* Setting video panel control register,0x00000120 VTGen=ON ?!?!? */
384 tc35876x_regw(i2c
, VPCTRL
, BIT(8) | BIT(5));
386 /* Horizontal back porch and horizontal pulse width. 0x00280028 */
387 tc35876x_regw(i2c
, HTIM1
, FLD_VAL(40, 24, 16) | FLD_VAL(40, 8, 0));
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));
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));
395 /* Vertical front porch and vertical display size. 0x000e0320 */
396 tc35876x_regw(i2c
, VTIM2
, FLD_VAL(14, 23, 16) | FLD_VAL(800, 10, 0));
398 /* Set above HTIM1, HTIM2, VTIM1, and VTIM2 at next VSYNC. */
399 tc35876x_regw(i2c
, VFUEN
, BIT(0));
401 /* Soft reset LCD controller. */
402 tc35876x_regw(i2c
, SYSRST
, BIT(2));
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
));
420 /* Enable LVDS transmitter. */
421 tc35876x_regw(i2c
, LVCFG
, BIT(0));
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));
428 #define GPIOPWMCTRL 0x38F
429 #define PWM0CLKDIV0 0x62 /* low byte */
430 #define PWM0CLKDIV1 0x61 /* high byte */
432 #define SYSTEMCLK 19200000UL /* 19.2 MHz */
433 #define PWM_FREQUENCY 9600 /* Hz */
435 /* f = baseclk / (clkdiv + 1) => clkdiv = (baseclk - f) / f */
436 static inline u16
calc_clkdiv(unsigned long baseclk
, unsigned int f
)
438 return (baseclk
- f
) / f
;
441 static void tc35876x_brightness_init(struct drm_device
*dev
)
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
450 ret
= intel_scu_ipc_ioread8(GPIOPWMCTRL
, &pwmctrl
);
451 if (ret
|| pwmctrl
!= 0x01) {
453 dev_err(&dev
->pdev
->dev
, "GPIOPWMCTRL read failed\n");
455 dev_warn(&dev
->pdev
->dev
, "GPIOPWMCTRL was not set to system clock (pwmctrl = 0x%02x)\n", pwmctrl
);
457 ret
= intel_scu_ipc_iowrite8(GPIOPWMCTRL
, 0x01);
459 dev_err(&dev
->pdev
->dev
, "GPIOPWMCTRL set failed\n");
462 clkdiv
= calc_clkdiv(SYSTEMCLK
, PWM_FREQUENCY
);
464 ret
= intel_scu_ipc_iowrite8(PWM0CLKDIV1
, (clkdiv
>> 8) & 0xff);
466 ret
= intel_scu_ipc_iowrite8(PWM0CLKDIV0
, clkdiv
& 0xff);
469 dev_err(&dev
->pdev
->dev
, "PWM0CLKDIV set failed\n");
471 dev_dbg(&dev
->pdev
->dev
, "PWM0CLKDIV set to 0x%04x (%d Hz)\n",
472 clkdiv
, PWM_FREQUENCY
);
475 #define PWM0DUTYCYCLE 0x67
477 void tc35876x_brightness_control(struct drm_device
*dev
, int level
)
483 level
= clamp(level
, 0, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL
);
485 /* PWM duty cycle 0x00...0x63 corresponds to 0...99% */
486 duty_val
= level
* 0x63 / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL
;
488 /* I won't pretend to understand this formula. The panel spec is quite
491 panel_duty_val
= (2 * level
- 100) * 0xA9 /
492 MDFLD_DSI_BRIGHTNESS_MAX_LEVEL
+ 0x56;
494 ret
= intel_scu_ipc_iowrite8(PWM0DUTYCYCLE
, duty_val
);
496 dev_err(&tc35876x_client
->dev
, "%s: ipc write fail\n",
499 if (cmi_lcd_i2c_client
) {
500 ret
= i2c_smbus_write_byte_data(cmi_lcd_i2c_client
,
501 PANEL_PWM_MAX
, panel_duty_val
);
503 dev_err(&cmi_lcd_i2c_client
->dev
, "%s: i2c write failed\n",
508 void tc35876x_toshiba_bridge_panel_off(struct drm_device
*dev
)
510 struct tc35876x_platform_data
*pdata
;
512 if (WARN(!tc35876x_client
, "%s called before probe", __func__
))
515 dev_dbg(&tc35876x_client
->dev
, "%s\n", __func__
);
517 pdata
= dev_get_platdata(&tc35876x_client
->dev
);
519 if (pdata
->gpio_panel_bl_en
!= -1)
520 gpio_set_value_cansleep(pdata
->gpio_panel_bl_en
, 0);
522 if (pdata
->gpio_panel_vadd
!= -1)
523 gpio_set_value_cansleep(pdata
->gpio_panel_vadd
, 0);
526 void tc35876x_toshiba_bridge_panel_on(struct drm_device
*dev
)
528 struct tc35876x_platform_data
*pdata
;
529 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
531 if (WARN(!tc35876x_client
, "%s called before probe", __func__
))
534 dev_dbg(&tc35876x_client
->dev
, "%s\n", __func__
);
536 pdata
= dev_get_platdata(&tc35876x_client
->dev
);
538 if (pdata
->gpio_panel_vadd
!= -1) {
539 gpio_set_value_cansleep(pdata
->gpio_panel_vadd
, 1);
543 if (cmi_lcd_i2c_client
) {
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.
553 ret
= i2c_smbus_write_byte_data(cmi_lcd_i2c_client
,
554 PANEL_ALLOW_DISTORT
, 0x10);
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);
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);
567 dev_err(&cmi_lcd_i2c_client
->dev
,
568 "i2c write failed (%d)\n", ret
);
571 if (pdata
->gpio_panel_bl_en
!= -1)
572 gpio_set_value_cansleep(pdata
->gpio_panel_bl_en
, 1);
574 tc35876x_brightness_control(dev
, dev_priv
->brightness_adjusted
);
577 static struct drm_display_mode
*tc35876x_get_config_mode(struct drm_device
*dev
)
579 struct drm_display_mode
*mode
;
581 dev_dbg(&dev
->pdev
->dev
, "%s\n", __func__
);
583 mode
= kzalloc(sizeof(*mode
), GFP_KERNEL
);
587 /* FIXME: do this properly. */
588 mode
->hdisplay
= 1280;
589 mode
->vdisplay
= 800;
590 mode
->hsync_start
= 1360;
591 mode
->hsync_end
= 1400;
593 mode
->vsync_start
= 814;
594 mode
->vsync_end
= 824;
596 mode
->clock
= 33324 << 1;
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
);
608 drm_mode_set_name(mode
);
609 drm_mode_set_crtcinfo(mode
, 0);
611 mode
->type
|= DRM_MODE_TYPE_PREFERRED
;
616 /* DV1 Active area 216.96 x 135.6 mm */
617 #define DV1_PANEL_WIDTH 217
618 #define DV1_PANEL_HEIGHT 136
620 static int tc35876x_get_panel_info(struct drm_device
*dev
, int pipe
,
621 struct panel_info
*pi
)
626 pi
->width_mm
= DV1_PANEL_WIDTH
;
627 pi
->height_mm
= DV1_PANEL_HEIGHT
;
632 static int tc35876x_bridge_probe(struct i2c_client
*client
,
633 const struct i2c_device_id
*id
)
635 struct tc35876x_platform_data
*pdata
;
637 dev_info(&client
->dev
, "%s\n", __func__
);
639 if (!i2c_check_functionality(client
->adapter
, I2C_FUNC_I2C
)) {
640 dev_err(&client
->dev
, "%s: i2c_check_functionality() failed\n",
645 pdata
= dev_get_platdata(&client
->dev
);
647 dev_err(&client
->dev
, "%s: no platform data\n", __func__
);
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);
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);
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);
666 tc35876x_client
= client
;
671 static int tc35876x_bridge_remove(struct i2c_client
*client
)
673 struct tc35876x_platform_data
*pdata
= dev_get_platdata(&client
->dev
);
675 dev_dbg(&client
->dev
, "%s\n", __func__
);
677 if (pdata
->gpio_bridge_reset
!= -1)
678 gpio_free(pdata
->gpio_bridge_reset
);
680 if (pdata
->gpio_panel_bl_en
!= -1)
681 gpio_free(pdata
->gpio_panel_bl_en
);
683 if (pdata
->gpio_panel_vadd
!= -1)
684 gpio_free(pdata
->gpio_panel_vadd
);
686 tc35876x_client
= NULL
;
691 static const struct i2c_device_id tc35876x_bridge_id
[] = {
692 { "i2c_disp_brig", 0 },
695 MODULE_DEVICE_TABLE(i2c
, tc35876x_bridge_id
);
697 static struct i2c_driver tc35876x_bridge_i2c_driver
= {
699 .name
= "i2c_disp_brig",
701 .id_table
= tc35876x_bridge_id
,
702 .probe
= tc35876x_bridge_probe
,
703 .remove
= tc35876x_bridge_remove
,
707 static int cmi_lcd_i2c_probe(struct i2c_client
*client
,
708 const struct i2c_device_id
*id
)
710 dev_info(&client
->dev
, "%s\n", __func__
);
712 if (!i2c_check_functionality(client
->adapter
, I2C_FUNC_I2C
)) {
713 dev_err(&client
->dev
, "%s: i2c_check_functionality() failed\n",
718 cmi_lcd_i2c_client
= client
;
723 static int cmi_lcd_i2c_remove(struct i2c_client
*client
)
725 dev_dbg(&client
->dev
, "%s\n", __func__
);
727 cmi_lcd_i2c_client
= NULL
;
732 static const struct i2c_device_id cmi_lcd_i2c_id
[] = {
736 MODULE_DEVICE_TABLE(i2c
, cmi_lcd_i2c_id
);
738 static struct i2c_driver cmi_lcd_i2c_driver
= {
742 .id_table
= cmi_lcd_i2c_id
,
743 .probe
= cmi_lcd_i2c_probe
,
744 .remove
= cmi_lcd_i2c_remove
,
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
751 static int cmi_lcd_hack_create_device(void)
753 struct i2c_adapter
*adapter
;
754 struct i2c_client
*client
;
755 struct i2c_board_info info
= {
757 .addr
= CMI_LCD_I2C_ADDR
,
760 pr_debug("%s\n", __func__
);
762 adapter
= i2c_get_adapter(CMI_LCD_I2C_ADAPTER
);
764 pr_err("%s: i2c_get_adapter(%d) failed\n", __func__
,
765 CMI_LCD_I2C_ADAPTER
);
769 client
= i2c_new_device(adapter
, &info
);
771 pr_err("%s: i2c_new_device() failed\n", __func__
);
772 i2c_put_adapter(adapter
);
779 static 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
,
787 static const struct drm_encoder_funcs tc35876x_encoder_funcs
= {
788 .destroy
= drm_encoder_cleanup
,
791 const 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
,
798 void tc35876x_init(struct drm_device
*dev
)
802 dev_dbg(&dev
->pdev
->dev
, "%s\n", __func__
);
804 cmi_lcd_hack_create_device();
806 r
= i2c_add_driver(&cmi_lcd_i2c_driver
);
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
);
812 r
= i2c_add_driver(&tc35876x_bridge_i2c_driver
);
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
);
818 tc35876x_brightness_init(dev
);
821 void tc35876x_exit(void)
823 pr_debug("%s\n", __func__
);
825 i2c_del_driver(&tc35876x_bridge_i2c_driver
);
827 if (cmi_lcd_i2c_client
)
828 i2c_del_driver(&cmi_lcd_i2c_driver
);