Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/gpu/drm/bridge/lontium-lt8912b.c
51805 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
4
*/
5
6
#include <linux/device.h>
7
#include <linux/delay.h>
8
#include <linux/gpio/consumer.h>
9
#include <linux/i2c.h>
10
#include <linux/media-bus-format.h>
11
#include <linux/regmap.h>
12
13
#include <drm/drm_probe_helper.h>
14
#include <drm/drm_atomic_helper.h>
15
#include <drm/drm_edid.h>
16
#include <drm/drm_mipi_dsi.h>
17
#include <drm/drm_of.h>
18
19
#include <video/videomode.h>
20
21
#define I2C_MAIN 0
22
#define I2C_ADDR_MAIN 0x48
23
24
#define I2C_CEC_DSI 1
25
#define I2C_ADDR_CEC_DSI 0x49
26
27
#define I2C_MAX_IDX 2
28
29
struct lt8912 {
30
struct device *dev;
31
struct drm_bridge bridge;
32
struct drm_connector connector;
33
34
struct i2c_client *i2c_client[I2C_MAX_IDX];
35
struct regmap *regmap[I2C_MAX_IDX];
36
37
struct device_node *host_node;
38
39
struct mipi_dsi_device *dsi;
40
41
struct gpio_desc *gp_reset;
42
43
struct videomode mode;
44
45
struct regulator_bulk_data supplies[7];
46
47
u8 data_lanes;
48
bool is_power_on;
49
};
50
51
static int lt8912_write_init_config(struct lt8912 *lt)
52
{
53
const struct reg_sequence seq[] = {
54
/* Digital clock en*/
55
{0x08, 0xff},
56
{0x09, 0xff},
57
{0x0a, 0xff},
58
{0x0b, 0x7c},
59
{0x0c, 0xff},
60
{0x42, 0x04},
61
62
/*Tx Analog*/
63
{0x31, 0xb1},
64
{0x32, 0xb1},
65
{0x33, 0x0e},
66
{0x37, 0x00},
67
{0x38, 0x22},
68
{0x60, 0x82},
69
70
/*Cbus Analog*/
71
{0x39, 0x45},
72
{0x3a, 0x00},
73
{0x3b, 0x00},
74
75
/*HDMI Pll Analog*/
76
{0x44, 0x31},
77
{0x55, 0x44},
78
{0x57, 0x01},
79
{0x5a, 0x02},
80
81
/*MIPI Analog*/
82
{0x3e, 0xd6},
83
{0x3f, 0xd4},
84
{0x41, 0x3c},
85
{0xB2, 0x00},
86
};
87
88
return regmap_multi_reg_write(lt->regmap[I2C_MAIN], seq, ARRAY_SIZE(seq));
89
}
90
91
static int lt8912_write_mipi_basic_config(struct lt8912 *lt)
92
{
93
const struct reg_sequence seq[] = {
94
{0x12, 0x04},
95
{0x14, 0x00},
96
{0x15, 0x00},
97
{0x1a, 0x03},
98
{0x1b, 0x03},
99
};
100
101
return regmap_multi_reg_write(lt->regmap[I2C_CEC_DSI], seq, ARRAY_SIZE(seq));
102
};
103
104
static int lt8912_write_dds_config(struct lt8912 *lt)
105
{
106
const struct reg_sequence seq[] = {
107
{0x4e, 0xff},
108
{0x4f, 0x56},
109
{0x50, 0x69},
110
{0x51, 0x80},
111
{0x1f, 0x5e},
112
{0x20, 0x01},
113
{0x21, 0x2c},
114
{0x22, 0x01},
115
{0x23, 0xfa},
116
{0x24, 0x00},
117
{0x25, 0xc8},
118
{0x26, 0x00},
119
{0x27, 0x5e},
120
{0x28, 0x01},
121
{0x29, 0x2c},
122
{0x2a, 0x01},
123
{0x2b, 0xfa},
124
{0x2c, 0x00},
125
{0x2d, 0xc8},
126
{0x2e, 0x00},
127
{0x42, 0x64},
128
{0x43, 0x00},
129
{0x44, 0x04},
130
{0x45, 0x00},
131
{0x46, 0x59},
132
{0x47, 0x00},
133
{0x48, 0xf2},
134
{0x49, 0x06},
135
{0x4a, 0x00},
136
{0x4b, 0x72},
137
{0x4c, 0x45},
138
{0x4d, 0x00},
139
{0x52, 0x08},
140
{0x53, 0x00},
141
{0x54, 0xb2},
142
{0x55, 0x00},
143
{0x56, 0xe4},
144
{0x57, 0x0d},
145
{0x58, 0x00},
146
{0x59, 0xe4},
147
{0x5a, 0x8a},
148
{0x5b, 0x00},
149
{0x5c, 0x34},
150
{0x1e, 0x4f},
151
{0x51, 0x00},
152
};
153
154
return regmap_multi_reg_write(lt->regmap[I2C_CEC_DSI], seq, ARRAY_SIZE(seq));
155
}
156
157
static int lt8912_write_rxlogicres_config(struct lt8912 *lt)
158
{
159
int ret;
160
161
ret = regmap_write(lt->regmap[I2C_MAIN], 0x03, 0x7f);
162
usleep_range(10000, 20000);
163
ret |= regmap_write(lt->regmap[I2C_MAIN], 0x03, 0xff);
164
165
return ret;
166
};
167
168
/* enable LVDS output with some hardcoded configuration, not required for the HDMI output */
169
static int lt8912_write_lvds_config(struct lt8912 *lt)
170
{
171
const struct reg_sequence seq[] = {
172
// lvds power up
173
{0x44, 0x30},
174
{0x51, 0x05},
175
176
// core pll bypass
177
{0x50, 0x24}, // cp=50uA
178
{0x51, 0x2d}, // Pix_clk as reference, second order passive LPF PLL
179
{0x52, 0x04}, // loopdiv=0, use second-order PLL
180
{0x69, 0x0e}, // CP_PRESET_DIV_RATIO
181
{0x69, 0x8e},
182
{0x6a, 0x00},
183
{0x6c, 0xb8}, // RGD_CP_SOFT_K_EN,RGD_CP_SOFT_K[13:8]
184
{0x6b, 0x51},
185
186
{0x04, 0xfb}, // core pll reset
187
{0x04, 0xff},
188
189
// scaler bypass
190
{0x7f, 0x00}, // disable scaler
191
{0xa8, 0x13}, // 0x13: JEIDA, 0x33: VESA
192
193
{0x02, 0xf7}, // lvds pll reset
194
{0x02, 0xff},
195
{0x03, 0xcf},
196
{0x03, 0xff},
197
};
198
199
return regmap_multi_reg_write(lt->regmap[I2C_MAIN], seq, ARRAY_SIZE(seq));
200
};
201
202
static inline struct lt8912 *bridge_to_lt8912(struct drm_bridge *b)
203
{
204
return container_of(b, struct lt8912, bridge);
205
}
206
207
static inline struct lt8912 *connector_to_lt8912(struct drm_connector *c)
208
{
209
return container_of(c, struct lt8912, connector);
210
}
211
212
static const struct regmap_config lt8912_regmap_config = {
213
.reg_bits = 8,
214
.val_bits = 8,
215
.max_register = 0xff,
216
};
217
218
static int lt8912_init_i2c(struct lt8912 *lt, struct i2c_client *client)
219
{
220
unsigned int i;
221
/*
222
* At this time we only initialize 2 chips, but the lt8912 provides
223
* a third interface for the audio over HDMI configuration.
224
*/
225
struct i2c_board_info info[] = {
226
{ I2C_BOARD_INFO("lt8912p0", I2C_ADDR_MAIN), },
227
{ I2C_BOARD_INFO("lt8912p1", I2C_ADDR_CEC_DSI), },
228
};
229
230
if (!lt)
231
return -ENODEV;
232
233
for (i = 0; i < ARRAY_SIZE(info); i++) {
234
if (i > 0) {
235
lt->i2c_client[i] = i2c_new_dummy_device(client->adapter,
236
info[i].addr);
237
if (IS_ERR(lt->i2c_client[i]))
238
return PTR_ERR(lt->i2c_client[i]);
239
}
240
241
lt->regmap[i] = devm_regmap_init_i2c(lt->i2c_client[i],
242
&lt8912_regmap_config);
243
if (IS_ERR(lt->regmap[i]))
244
return PTR_ERR(lt->regmap[i]);
245
}
246
return 0;
247
}
248
249
static int lt8912_free_i2c(struct lt8912 *lt)
250
{
251
unsigned int i;
252
253
for (i = 1; i < I2C_MAX_IDX; i++)
254
i2c_unregister_device(lt->i2c_client[i]);
255
256
return 0;
257
}
258
259
static int lt8912_hard_power_on(struct lt8912 *lt)
260
{
261
int ret;
262
263
ret = regulator_bulk_enable(ARRAY_SIZE(lt->supplies), lt->supplies);
264
if (ret)
265
return ret;
266
267
gpiod_set_value_cansleep(lt->gp_reset, 0);
268
msleep(20);
269
270
return 0;
271
}
272
273
static void lt8912_hard_power_off(struct lt8912 *lt)
274
{
275
gpiod_set_value_cansleep(lt->gp_reset, 1);
276
msleep(20);
277
278
regulator_bulk_disable(ARRAY_SIZE(lt->supplies), lt->supplies);
279
280
lt->is_power_on = false;
281
}
282
283
static int lt8912_video_setup(struct lt8912 *lt)
284
{
285
u32 hactive, h_total, hpw, hfp, hbp;
286
u32 vactive, v_total, vpw, vfp, vbp;
287
u8 settle = 0x08;
288
int ret, hsync_activehigh, vsync_activehigh;
289
290
if (!lt)
291
return -EINVAL;
292
293
hactive = lt->mode.hactive;
294
hfp = lt->mode.hfront_porch;
295
hpw = lt->mode.hsync_len;
296
hbp = lt->mode.hback_porch;
297
h_total = hactive + hfp + hpw + hbp;
298
hsync_activehigh = lt->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH;
299
300
vactive = lt->mode.vactive;
301
vfp = lt->mode.vfront_porch;
302
vpw = lt->mode.vsync_len;
303
vbp = lt->mode.vback_porch;
304
v_total = vactive + vfp + vpw + vbp;
305
vsync_activehigh = lt->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH;
306
307
if (vactive <= 600)
308
settle = 0x04;
309
else if (vactive == 1080)
310
settle = 0x0a;
311
312
ret = regmap_write(lt->regmap[I2C_CEC_DSI], 0x10, 0x01);
313
ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x11, settle);
314
ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x18, hpw);
315
ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x19, vpw);
316
ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x1c, hactive & 0xff);
317
ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x1d, hactive >> 8);
318
319
ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x2f, 0x0c);
320
321
ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x34, h_total & 0xff);
322
ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x35, h_total >> 8);
323
324
ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x36, v_total & 0xff);
325
ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x37, v_total >> 8);
326
327
ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x38, vbp & 0xff);
328
ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x39, vbp >> 8);
329
330
ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x3a, vfp & 0xff);
331
ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x3b, vfp >> 8);
332
333
ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x3c, hbp & 0xff);
334
ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x3d, hbp >> 8);
335
336
ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x3e, hfp & 0xff);
337
ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x3f, hfp >> 8);
338
339
ret |= regmap_update_bits(lt->regmap[I2C_MAIN], 0xab, BIT(0),
340
vsync_activehigh ? BIT(0) : 0);
341
ret |= regmap_update_bits(lt->regmap[I2C_MAIN], 0xab, BIT(1),
342
hsync_activehigh ? BIT(1) : 0);
343
ret |= regmap_update_bits(lt->regmap[I2C_MAIN], 0xb2, BIT(0),
344
lt->connector.display_info.is_hdmi ? BIT(0) : 0);
345
346
return ret;
347
}
348
349
static int lt8912_soft_power_on(struct lt8912 *lt)
350
{
351
if (!lt->is_power_on) {
352
u32 lanes = lt->data_lanes;
353
354
lt8912_write_init_config(lt);
355
regmap_write(lt->regmap[I2C_CEC_DSI], 0x13, lanes & 3);
356
357
lt8912_write_mipi_basic_config(lt);
358
359
lt->is_power_on = true;
360
}
361
362
return 0;
363
}
364
365
static int lt8912_video_on(struct lt8912 *lt)
366
{
367
int ret;
368
369
ret = lt8912_video_setup(lt);
370
if (ret < 0)
371
goto end;
372
373
ret = lt8912_write_dds_config(lt);
374
if (ret < 0)
375
goto end;
376
377
ret = lt8912_write_rxlogicres_config(lt);
378
if (ret < 0)
379
goto end;
380
381
ret = lt8912_write_lvds_config(lt);
382
if (ret < 0)
383
goto end;
384
385
end:
386
return ret;
387
}
388
389
static enum drm_connector_status lt8912_check_cable_status(struct lt8912 *lt)
390
{
391
int ret;
392
unsigned int reg_val;
393
394
ret = regmap_read(lt->regmap[I2C_MAIN], 0xC1, &reg_val);
395
if (ret)
396
return connector_status_unknown;
397
398
if (reg_val & BIT(7))
399
return connector_status_connected;
400
401
return connector_status_disconnected;
402
}
403
404
static enum drm_connector_status
405
lt8912_connector_detect(struct drm_connector *connector, bool force)
406
{
407
struct lt8912 *lt = connector_to_lt8912(connector);
408
409
if (lt->bridge.next_bridge->ops & DRM_BRIDGE_OP_DETECT)
410
return drm_bridge_detect(lt->bridge.next_bridge, connector);
411
412
return lt8912_check_cable_status(lt);
413
}
414
415
static const struct drm_connector_funcs lt8912_connector_funcs = {
416
.detect = lt8912_connector_detect,
417
.fill_modes = drm_helper_probe_single_connector_modes,
418
.destroy = drm_connector_cleanup,
419
.reset = drm_atomic_helper_connector_reset,
420
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
421
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
422
};
423
424
static int lt8912_connector_get_modes(struct drm_connector *connector)
425
{
426
const struct drm_edid *drm_edid;
427
struct lt8912 *lt = connector_to_lt8912(connector);
428
u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
429
int ret, num;
430
431
drm_edid = drm_bridge_edid_read(lt->bridge.next_bridge, connector);
432
drm_edid_connector_update(connector, drm_edid);
433
if (!drm_edid)
434
return 0;
435
436
num = drm_edid_connector_add_modes(connector);
437
438
ret = drm_display_info_set_bus_formats(&connector->display_info,
439
&bus_format, 1);
440
if (ret < 0)
441
num = 0;
442
443
drm_edid_free(drm_edid);
444
return num;
445
}
446
447
static const struct drm_connector_helper_funcs lt8912_connector_helper_funcs = {
448
.get_modes = lt8912_connector_get_modes,
449
};
450
451
static void lt8912_bridge_mode_set(struct drm_bridge *bridge,
452
const struct drm_display_mode *mode,
453
const struct drm_display_mode *adj)
454
{
455
struct lt8912 *lt = bridge_to_lt8912(bridge);
456
457
drm_display_mode_to_videomode(adj, &lt->mode);
458
}
459
460
static void lt8912_bridge_enable(struct drm_bridge *bridge)
461
{
462
struct lt8912 *lt = bridge_to_lt8912(bridge);
463
464
lt8912_video_on(lt);
465
}
466
467
static int lt8912_attach_dsi(struct lt8912 *lt)
468
{
469
struct device *dev = lt->dev;
470
struct mipi_dsi_host *host;
471
struct mipi_dsi_device *dsi;
472
int ret = -1;
473
const struct mipi_dsi_device_info info = { .type = "lt8912",
474
.channel = 0,
475
.node = NULL,
476
};
477
478
host = of_find_mipi_dsi_host_by_node(lt->host_node);
479
if (!host)
480
return dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n");
481
482
dsi = devm_mipi_dsi_device_register_full(dev, host, &info);
483
if (IS_ERR(dsi)) {
484
ret = PTR_ERR(dsi);
485
dev_err(dev, "failed to create dsi device (%d)\n", ret);
486
return ret;
487
}
488
489
lt->dsi = dsi;
490
491
dsi->lanes = lt->data_lanes;
492
dsi->format = MIPI_DSI_FMT_RGB888;
493
494
dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
495
MIPI_DSI_MODE_LPM |
496
MIPI_DSI_MODE_NO_EOT_PACKET;
497
498
ret = devm_mipi_dsi_attach(dev, dsi);
499
if (ret < 0) {
500
dev_err(dev, "failed to attach dsi to host\n");
501
return ret;
502
}
503
504
return 0;
505
}
506
507
static void lt8912_bridge_hpd_cb(void *data, enum drm_connector_status status)
508
{
509
struct lt8912 *lt = data;
510
511
if (lt->bridge.dev)
512
drm_helper_hpd_irq_event(lt->bridge.dev);
513
}
514
515
static int lt8912_bridge_connector_init(struct drm_bridge *bridge)
516
{
517
int ret;
518
struct lt8912 *lt = bridge_to_lt8912(bridge);
519
struct drm_connector *connector = &lt->connector;
520
521
if (lt->bridge.next_bridge->ops & DRM_BRIDGE_OP_HPD) {
522
drm_bridge_hpd_enable(lt->bridge.next_bridge, lt8912_bridge_hpd_cb, lt);
523
connector->polled = DRM_CONNECTOR_POLL_HPD;
524
} else {
525
connector->polled = DRM_CONNECTOR_POLL_CONNECT |
526
DRM_CONNECTOR_POLL_DISCONNECT;
527
}
528
529
ret = drm_connector_init(bridge->dev, connector,
530
&lt8912_connector_funcs,
531
lt->bridge.next_bridge->type);
532
if (ret)
533
goto exit;
534
535
drm_connector_helper_add(connector, &lt8912_connector_helper_funcs);
536
537
connector->dpms = DRM_MODE_DPMS_OFF;
538
drm_connector_attach_encoder(connector, bridge->encoder);
539
540
exit:
541
return ret;
542
}
543
544
static int lt8912_bridge_attach(struct drm_bridge *bridge,
545
struct drm_encoder *encoder,
546
enum drm_bridge_attach_flags flags)
547
{
548
struct lt8912 *lt = bridge_to_lt8912(bridge);
549
int ret;
550
551
ret = drm_bridge_attach(encoder, lt->bridge.next_bridge, bridge,
552
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
553
if (ret < 0) {
554
dev_err(lt->dev, "Failed to attach next bridge (%d)\n", ret);
555
return ret;
556
}
557
558
if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) {
559
ret = lt8912_bridge_connector_init(bridge);
560
if (ret) {
561
dev_err(lt->dev, "Failed to init bridge ! (%d)\n", ret);
562
return ret;
563
}
564
}
565
566
ret = lt8912_hard_power_on(lt);
567
if (ret)
568
return ret;
569
570
ret = lt8912_soft_power_on(lt);
571
if (ret)
572
goto error;
573
574
return 0;
575
576
error:
577
lt8912_hard_power_off(lt);
578
return ret;
579
}
580
581
static void lt8912_bridge_detach(struct drm_bridge *bridge)
582
{
583
struct lt8912 *lt = bridge_to_lt8912(bridge);
584
585
lt8912_hard_power_off(lt);
586
587
if (lt->connector.dev && lt->bridge.next_bridge->ops & DRM_BRIDGE_OP_HPD)
588
drm_bridge_hpd_disable(lt->bridge.next_bridge);
589
}
590
591
static enum drm_mode_status
592
lt8912_bridge_mode_valid(struct drm_bridge *bridge,
593
const struct drm_display_info *info,
594
const struct drm_display_mode *mode)
595
{
596
if (mode->clock > 150000)
597
return MODE_CLOCK_HIGH;
598
599
if (mode->hdisplay > 1920)
600
return MODE_BAD_HVALUE;
601
602
if (mode->vdisplay > 1080)
603
return MODE_BAD_VVALUE;
604
605
return MODE_OK;
606
}
607
608
static enum drm_connector_status
609
lt8912_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector)
610
{
611
struct lt8912 *lt = bridge_to_lt8912(bridge);
612
613
if (lt->bridge.next_bridge->ops & DRM_BRIDGE_OP_DETECT)
614
return drm_bridge_detect(lt->bridge.next_bridge, connector);
615
616
return lt8912_check_cable_status(lt);
617
}
618
619
static const struct drm_edid *lt8912_bridge_edid_read(struct drm_bridge *bridge,
620
struct drm_connector *connector)
621
{
622
struct lt8912 *lt = bridge_to_lt8912(bridge);
623
624
/*
625
* edid must be read through the ddc bus but it must be
626
* given to the hdmi connector node.
627
*/
628
if (lt->bridge.next_bridge->ops & DRM_BRIDGE_OP_EDID)
629
return drm_bridge_edid_read(lt->bridge.next_bridge, connector);
630
631
dev_warn(lt->dev, "The connected bridge does not supports DRM_BRIDGE_OP_EDID\n");
632
return NULL;
633
}
634
635
static const struct drm_bridge_funcs lt8912_bridge_funcs = {
636
.attach = lt8912_bridge_attach,
637
.detach = lt8912_bridge_detach,
638
.mode_valid = lt8912_bridge_mode_valid,
639
.mode_set = lt8912_bridge_mode_set,
640
.enable = lt8912_bridge_enable,
641
.detect = lt8912_bridge_detect,
642
.edid_read = lt8912_bridge_edid_read,
643
};
644
645
static int lt8912_bridge_resume(struct device *dev)
646
{
647
struct lt8912 *lt = dev_get_drvdata(dev);
648
int ret;
649
650
ret = lt8912_hard_power_on(lt);
651
if (ret)
652
return ret;
653
654
ret = lt8912_soft_power_on(lt);
655
if (ret)
656
return ret;
657
658
return lt8912_video_on(lt);
659
}
660
661
static int lt8912_bridge_suspend(struct device *dev)
662
{
663
struct lt8912 *lt = dev_get_drvdata(dev);
664
665
lt8912_hard_power_off(lt);
666
667
return 0;
668
}
669
670
static DEFINE_SIMPLE_DEV_PM_OPS(lt8912_bridge_pm_ops, lt8912_bridge_suspend, lt8912_bridge_resume);
671
672
static int lt8912_get_regulators(struct lt8912 *lt)
673
{
674
unsigned int i;
675
const char * const supply_names[] = {
676
"vdd", "vccmipirx", "vccsysclk", "vcclvdstx",
677
"vcchdmitx", "vcclvdspll", "vcchdmipll"
678
};
679
680
for (i = 0; i < ARRAY_SIZE(lt->supplies); i++)
681
lt->supplies[i].supply = supply_names[i];
682
683
return devm_regulator_bulk_get(lt->dev, ARRAY_SIZE(lt->supplies),
684
lt->supplies);
685
}
686
687
static int lt8912_parse_dt(struct lt8912 *lt)
688
{
689
struct gpio_desc *gp_reset;
690
struct device *dev = lt->dev;
691
int ret;
692
int data_lanes;
693
struct device_node *port_node;
694
695
gp_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
696
if (IS_ERR(gp_reset)) {
697
ret = PTR_ERR(gp_reset);
698
if (ret != -EPROBE_DEFER)
699
dev_err(dev, "Failed to get reset gpio: %d\n", ret);
700
return ret;
701
}
702
lt->gp_reset = gp_reset;
703
704
data_lanes = drm_of_get_data_lanes_count_ep(dev->of_node, 0, -1, 1, 4);
705
if (data_lanes < 0) {
706
dev_err(lt->dev, "%s: Bad data-lanes property\n", __func__);
707
return data_lanes;
708
}
709
710
lt->data_lanes = data_lanes;
711
712
lt->host_node = of_graph_get_remote_node(dev->of_node, 0, -1);
713
if (!lt->host_node) {
714
dev_err(lt->dev, "%s: Failed to get remote port\n", __func__);
715
return -ENODEV;
716
}
717
718
port_node = of_graph_get_remote_node(dev->of_node, 1, -1);
719
if (!port_node) {
720
dev_err(lt->dev, "%s: Failed to get connector port\n", __func__);
721
ret = -ENODEV;
722
goto err_free_host_node;
723
}
724
725
lt->bridge.next_bridge = of_drm_find_and_get_bridge(port_node);
726
if (!lt->bridge.next_bridge) {
727
ret = -EPROBE_DEFER;
728
dev_err_probe(lt->dev, ret, "%s: Failed to get hdmi port\n", __func__);
729
goto err_free_host_node;
730
}
731
732
if (!of_device_is_compatible(port_node, "hdmi-connector")) {
733
dev_err(lt->dev, "%s: Failed to get hdmi port\n", __func__);
734
ret = -EINVAL;
735
goto err_free_host_node;
736
}
737
738
ret = lt8912_get_regulators(lt);
739
if (ret)
740
goto err_free_host_node;
741
742
of_node_put(port_node);
743
return 0;
744
745
err_free_host_node:
746
of_node_put(port_node);
747
of_node_put(lt->host_node);
748
return ret;
749
}
750
751
static int lt8912_put_dt(struct lt8912 *lt)
752
{
753
of_node_put(lt->host_node);
754
return 0;
755
}
756
757
static int lt8912_probe(struct i2c_client *client)
758
{
759
static struct lt8912 *lt;
760
int ret = 0;
761
struct device *dev = &client->dev;
762
763
lt = devm_drm_bridge_alloc(dev, struct lt8912, bridge,
764
&lt8912_bridge_funcs);
765
if (IS_ERR(lt))
766
return PTR_ERR(lt);
767
768
lt->dev = dev;
769
lt->i2c_client[0] = client;
770
771
ret = lt8912_parse_dt(lt);
772
if (ret)
773
goto err_dt_parse;
774
775
ret = lt8912_init_i2c(lt, client);
776
if (ret)
777
goto err_i2c;
778
779
i2c_set_clientdata(client, lt);
780
781
lt->bridge.of_node = dev->of_node;
782
lt->bridge.ops = (DRM_BRIDGE_OP_EDID |
783
DRM_BRIDGE_OP_DETECT);
784
785
drm_bridge_add(&lt->bridge);
786
787
ret = lt8912_attach_dsi(lt);
788
if (ret)
789
goto err_attach;
790
791
return 0;
792
793
err_attach:
794
drm_bridge_remove(&lt->bridge);
795
lt8912_free_i2c(lt);
796
err_i2c:
797
lt8912_put_dt(lt);
798
err_dt_parse:
799
return ret;
800
}
801
802
static void lt8912_remove(struct i2c_client *client)
803
{
804
struct lt8912 *lt = i2c_get_clientdata(client);
805
806
drm_bridge_remove(&lt->bridge);
807
lt8912_free_i2c(lt);
808
lt8912_put_dt(lt);
809
}
810
811
static const struct of_device_id lt8912_dt_match[] = {
812
{.compatible = "lontium,lt8912b"},
813
{}
814
};
815
MODULE_DEVICE_TABLE(of, lt8912_dt_match);
816
817
static const struct i2c_device_id lt8912_id[] = {
818
{ "lt8912" },
819
{}
820
};
821
MODULE_DEVICE_TABLE(i2c, lt8912_id);
822
823
static struct i2c_driver lt8912_i2c_driver = {
824
.driver = {
825
.name = "lt8912",
826
.of_match_table = lt8912_dt_match,
827
.pm = pm_sleep_ptr(&lt8912_bridge_pm_ops),
828
},
829
.probe = lt8912_probe,
830
.remove = lt8912_remove,
831
.id_table = lt8912_id,
832
};
833
module_i2c_driver(lt8912_i2c_driver);
834
835
MODULE_AUTHOR("Adrien Grassein <[email protected]>");
836
MODULE_DESCRIPTION("lt8912 drm driver");
837
MODULE_LICENSE("GPL v2");
838
839