This source file includes following definitions.
- tc35876x_regw
- tc35876x_regr
- tc35876x_set_bridge_reset_state
- tc35876x_configure_lvds_bridge
- calc_clkdiv
- tc35876x_brightness_init
- tc35876x_brightness_control
- tc35876x_toshiba_bridge_panel_off
- tc35876x_toshiba_bridge_panel_on
- tc35876x_get_config_mode
- tc35876x_get_panel_info
- tc35876x_bridge_probe
- tc35876x_bridge_remove
- cmi_lcd_i2c_probe
- cmi_lcd_i2c_remove
- cmi_lcd_hack_create_device
- tc35876x_init
- tc35876x_exit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
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
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
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
106 #define DSIERRCNT 0x0300
107
108
109 #define APLCTRL 0x0400
110 #define RDPKTLN 0x0404
111
112
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
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
133 #define SYSSTAT 0x0500
134 #define SYSRST 0x0504
135
136
137
138 #define GPIOO 0x0524
139 #define GPIOI 0x0528
140
141
142 #define I2CTIMCTRL 0x0540
143 #define I2CMADDR 0x0544
144 #define WDATAQ 0x0548
145 #define RDATAQ 0x054C
146
147
148 #define IDREG 0x0580
149
150
151 #define DEBUG00 0x05A0
152 #define DEBUG01 0x05A4
153
154
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
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
178
179
180 enum {
181 INPUT_R0,
182 INPUT_R1,
183 INPUT_R2,
184 INPUT_R3,
185 INPUT_R4,
186 INPUT_R5,
187 INPUT_R6,
188 INPUT_R7,
189 INPUT_G0,
190 INPUT_G1,
191 INPUT_G2,
192 INPUT_G3,
193 INPUT_G4,
194 INPUT_G5,
195 INPUT_G6,
196 INPUT_G7,
197 INPUT_B0,
198 INPUT_B1,
199 INPUT_B2,
200 INPUT_B3,
201 INPUT_B4,
202 INPUT_B5,
203 INPUT_B6,
204 INPUT_B7,
205 INPUT_HSYNC,
206 INPUT_VSYNC,
207 INPUT_DE,
208 LOGIC_0,
209
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
218
219
220
221
222
223
224 static int tc35876x_regw(struct i2c_client *client, u16 reg, u32 value)
225 {
226 int r;
227 u8 tx_data[] = {
228
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
266
267
268
269
270
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
336 gpio_set_value_cansleep(pdata->gpio_bridge_reset, 0);
337 mdelay(20);
338
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
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
383 tc35876x_regw(i2c, LVPHY0, FLD_VAL(1, 20, 16) |
384 FLD_VAL(2, 15, 14) | FLD_VAL(6, 4, 0));
385
386
387 tc35876x_regw(i2c, VPCTRL, BIT(8) | BIT(5));
388
389
390 tc35876x_regw(i2c, HTIM1, FLD_VAL(40, 24, 16) | FLD_VAL(40, 8, 0));
391
392
393 tc35876x_regw(i2c, HTIM2, FLD_VAL(80, 24, 16) | FLD_VAL(1280, 10, 0));
394
395
396 tc35876x_regw(i2c, VTIM1, FLD_VAL(14, 23, 16) | FLD_VAL(10, 7, 0));
397
398
399 tc35876x_regw(i2c, VTIM2, FLD_VAL(14, 23, 16) | FLD_VAL(800, 10, 0));
400
401
402 tc35876x_regw(i2c, VFUEN, BIT(0));
403
404
405 tc35876x_regw(i2c, SYSRST, BIT(2));
406
407
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
424 tc35876x_regw(i2c, LVCFG, BIT(0));
425
426
427
428 tc35876x_regw(i2c, DSI_INTCLR, FLD_MASK(31, 30) | FLD_MASK(22, 0));
429 }
430
431 #define GPIOPWMCTRL 0x38F
432 #define PWM0CLKDIV0 0x62
433 #define PWM0CLKDIV1 0x61
434
435 #define SYSTEMCLK 19200000UL
436 #define PWM_FREQUENCY 9600
437
438
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
451
452
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
489 duty_val = level * 0x63 / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL;
490
491
492
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
550
551
552
553
554
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
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
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
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
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
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 }