Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/gpu/drm/bridge/ti-tfp410.c
50903 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* Copyright (C) 2016 Texas Instruments
4
* Author: Jyri Sarha <[email protected]>
5
*/
6
7
#include <linux/gpio/consumer.h>
8
#include <linux/i2c.h>
9
#include <linux/media-bus-format.h>
10
#include <linux/module.h>
11
#include <linux/of_graph.h>
12
#include <linux/platform_device.h>
13
#include <linux/workqueue.h>
14
15
#include <drm/drm_atomic_helper.h>
16
#include <drm/drm_bridge.h>
17
#include <drm/drm_crtc.h>
18
#include <drm/drm_edid.h>
19
#include <drm/drm_print.h>
20
#include <drm/drm_probe_helper.h>
21
22
#define HOTPLUG_DEBOUNCE_MS 1100
23
24
struct tfp410 {
25
struct drm_bridge bridge;
26
struct drm_connector connector;
27
28
u32 bus_format;
29
struct delayed_work hpd_work;
30
struct gpio_desc *powerdown;
31
32
struct drm_bridge_timings timings;
33
34
struct device *dev;
35
};
36
37
static inline struct tfp410 *
38
drm_bridge_to_tfp410(struct drm_bridge *bridge)
39
{
40
return container_of(bridge, struct tfp410, bridge);
41
}
42
43
static inline struct tfp410 *
44
drm_connector_to_tfp410(struct drm_connector *connector)
45
{
46
return container_of(connector, struct tfp410, connector);
47
}
48
49
static int tfp410_get_modes(struct drm_connector *connector)
50
{
51
struct tfp410 *dvi = drm_connector_to_tfp410(connector);
52
const struct drm_edid *drm_edid;
53
int ret;
54
55
if (dvi->bridge.next_bridge->ops & DRM_BRIDGE_OP_EDID) {
56
drm_edid = drm_bridge_edid_read(dvi->bridge.next_bridge, connector);
57
if (!drm_edid)
58
DRM_INFO("EDID read failed. Fallback to standard modes\n");
59
} else {
60
drm_edid = NULL;
61
}
62
63
drm_edid_connector_update(connector, drm_edid);
64
65
if (!drm_edid) {
66
/*
67
* No EDID, fallback on the XGA standard modes and prefer a mode
68
* pretty much anything can handle.
69
*/
70
ret = drm_add_modes_noedid(connector, 1920, 1200);
71
drm_set_preferred_mode(connector, 1024, 768);
72
return ret;
73
}
74
75
ret = drm_edid_connector_add_modes(connector);
76
77
drm_edid_free(drm_edid);
78
79
return ret;
80
}
81
82
static const struct drm_connector_helper_funcs tfp410_con_helper_funcs = {
83
.get_modes = tfp410_get_modes,
84
};
85
86
static enum drm_connector_status
87
tfp410_connector_detect(struct drm_connector *connector, bool force)
88
{
89
struct tfp410 *dvi = drm_connector_to_tfp410(connector);
90
91
return drm_bridge_detect(dvi->bridge.next_bridge, connector);
92
}
93
94
static const struct drm_connector_funcs tfp410_con_funcs = {
95
.detect = tfp410_connector_detect,
96
.fill_modes = drm_helper_probe_single_connector_modes,
97
.destroy = drm_connector_cleanup,
98
.reset = drm_atomic_helper_connector_reset,
99
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
100
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
101
};
102
103
static void tfp410_hpd_work_func(struct work_struct *work)
104
{
105
struct tfp410 *dvi;
106
107
dvi = container_of(work, struct tfp410, hpd_work.work);
108
109
if (dvi->bridge.dev)
110
drm_helper_hpd_irq_event(dvi->bridge.dev);
111
}
112
113
static void tfp410_hpd_callback(void *arg, enum drm_connector_status status)
114
{
115
struct tfp410 *dvi = arg;
116
117
mod_delayed_work(system_wq, &dvi->hpd_work,
118
msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));
119
}
120
121
static int tfp410_attach(struct drm_bridge *bridge,
122
struct drm_encoder *encoder,
123
enum drm_bridge_attach_flags flags)
124
{
125
struct tfp410 *dvi = drm_bridge_to_tfp410(bridge);
126
int ret;
127
128
ret = drm_bridge_attach(encoder, dvi->bridge.next_bridge, bridge,
129
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
130
if (ret < 0)
131
return ret;
132
133
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
134
return 0;
135
136
if (dvi->bridge.next_bridge->ops & DRM_BRIDGE_OP_DETECT)
137
dvi->connector.polled = DRM_CONNECTOR_POLL_HPD;
138
else
139
dvi->connector.polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
140
141
if (dvi->bridge.next_bridge->ops & DRM_BRIDGE_OP_HPD) {
142
INIT_DELAYED_WORK(&dvi->hpd_work, tfp410_hpd_work_func);
143
drm_bridge_hpd_enable(dvi->bridge.next_bridge, tfp410_hpd_callback,
144
dvi);
145
}
146
147
drm_connector_helper_add(&dvi->connector,
148
&tfp410_con_helper_funcs);
149
ret = drm_connector_init_with_ddc(bridge->dev, &dvi->connector,
150
&tfp410_con_funcs,
151
dvi->bridge.next_bridge->type,
152
dvi->bridge.next_bridge->ddc);
153
if (ret) {
154
dev_err(dvi->dev, "drm_connector_init_with_ddc() failed: %d\n",
155
ret);
156
return ret;
157
}
158
159
drm_display_info_set_bus_formats(&dvi->connector.display_info,
160
&dvi->bus_format, 1);
161
162
drm_connector_attach_encoder(&dvi->connector, encoder);
163
164
return 0;
165
}
166
167
static void tfp410_detach(struct drm_bridge *bridge)
168
{
169
struct tfp410 *dvi = drm_bridge_to_tfp410(bridge);
170
171
if (dvi->connector.dev && dvi->bridge.next_bridge->ops & DRM_BRIDGE_OP_HPD) {
172
drm_bridge_hpd_disable(dvi->bridge.next_bridge);
173
cancel_delayed_work_sync(&dvi->hpd_work);
174
}
175
}
176
177
static void tfp410_enable(struct drm_bridge *bridge)
178
{
179
struct tfp410 *dvi = drm_bridge_to_tfp410(bridge);
180
181
gpiod_set_value_cansleep(dvi->powerdown, 0);
182
}
183
184
static void tfp410_disable(struct drm_bridge *bridge)
185
{
186
struct tfp410 *dvi = drm_bridge_to_tfp410(bridge);
187
188
gpiod_set_value_cansleep(dvi->powerdown, 1);
189
}
190
191
static enum drm_mode_status tfp410_mode_valid(struct drm_bridge *bridge,
192
const struct drm_display_info *info,
193
const struct drm_display_mode *mode)
194
{
195
if (mode->clock < 25000)
196
return MODE_CLOCK_LOW;
197
198
if (mode->clock > 165000)
199
return MODE_CLOCK_HIGH;
200
201
return MODE_OK;
202
}
203
204
static u32 *tfp410_get_input_bus_fmts(struct drm_bridge *bridge,
205
struct drm_bridge_state *bridge_state,
206
struct drm_crtc_state *crtc_state,
207
struct drm_connector_state *conn_state,
208
u32 output_fmt,
209
unsigned int *num_input_fmts)
210
{
211
struct tfp410 *dvi = drm_bridge_to_tfp410(bridge);
212
u32 *input_fmts;
213
214
*num_input_fmts = 0;
215
216
input_fmts = kzalloc(sizeof(*input_fmts), GFP_KERNEL);
217
if (!input_fmts)
218
return NULL;
219
220
*num_input_fmts = 1;
221
input_fmts[0] = dvi->bus_format;
222
223
return input_fmts;
224
}
225
226
static int tfp410_atomic_check(struct drm_bridge *bridge,
227
struct drm_bridge_state *bridge_state,
228
struct drm_crtc_state *crtc_state,
229
struct drm_connector_state *conn_state)
230
{
231
struct tfp410 *dvi = drm_bridge_to_tfp410(bridge);
232
233
/*
234
* There might be flags negotiation supported in future.
235
* Set the bus flags in atomic_check statically for now.
236
*/
237
bridge_state->input_bus_cfg.flags = dvi->timings.input_bus_flags;
238
239
return 0;
240
}
241
242
static const struct drm_bridge_funcs tfp410_bridge_funcs = {
243
.attach = tfp410_attach,
244
.detach = tfp410_detach,
245
.enable = tfp410_enable,
246
.disable = tfp410_disable,
247
.mode_valid = tfp410_mode_valid,
248
.atomic_reset = drm_atomic_helper_bridge_reset,
249
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
250
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
251
.atomic_get_input_bus_fmts = tfp410_get_input_bus_fmts,
252
.atomic_check = tfp410_atomic_check,
253
};
254
255
static const struct drm_bridge_timings tfp410_default_timings = {
256
.input_bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE
257
| DRM_BUS_FLAG_DE_HIGH,
258
.setup_time_ps = 1200,
259
.hold_time_ps = 1300,
260
};
261
262
static int tfp410_parse_timings(struct tfp410 *dvi, bool i2c)
263
{
264
struct drm_bridge_timings *timings = &dvi->timings;
265
struct device_node *ep;
266
u32 pclk_sample = 0;
267
u32 bus_width = 24;
268
u32 deskew = 0;
269
270
/* Start with defaults. */
271
*timings = tfp410_default_timings;
272
273
if (i2c)
274
/*
275
* In I2C mode timings are configured through the I2C interface.
276
* As the driver doesn't support I2C configuration yet, we just
277
* go with the defaults (BSEL=1, DSEL=1, DKEN=0, EDGE=1).
278
*/
279
return 0;
280
281
/*
282
* In non-I2C mode, timings are configured through the BSEL, DSEL, DKEN
283
* and EDGE pins. They are specified in DT through endpoint properties
284
* and vendor-specific properties.
285
*/
286
ep = of_graph_get_endpoint_by_regs(dvi->dev->of_node, 0, 0);
287
if (!ep)
288
return -EINVAL;
289
290
/* Get the sampling edge from the endpoint. */
291
of_property_read_u32(ep, "pclk-sample", &pclk_sample);
292
of_property_read_u32(ep, "bus-width", &bus_width);
293
of_node_put(ep);
294
295
timings->input_bus_flags = DRM_BUS_FLAG_DE_HIGH;
296
297
switch (pclk_sample) {
298
case 0:
299
timings->input_bus_flags |= DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE
300
| DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE;
301
break;
302
case 1:
303
timings->input_bus_flags |= DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE
304
| DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE;
305
break;
306
default:
307
return -EINVAL;
308
}
309
310
switch (bus_width) {
311
case 12:
312
dvi->bus_format = MEDIA_BUS_FMT_RGB888_2X12_LE;
313
break;
314
case 24:
315
dvi->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
316
break;
317
default:
318
return -EINVAL;
319
}
320
321
/* Get the setup and hold time from vendor-specific properties. */
322
of_property_read_u32(dvi->dev->of_node, "ti,deskew", &deskew);
323
if (deskew > 7)
324
return -EINVAL;
325
326
timings->setup_time_ps = 1200 - 350 * ((s32)deskew - 4);
327
timings->hold_time_ps = max(0, 1300 + 350 * ((s32)deskew - 4));
328
329
return 0;
330
}
331
332
static int tfp410_init(struct device *dev, bool i2c)
333
{
334
struct device_node *node;
335
struct tfp410 *dvi;
336
int ret;
337
338
if (!dev->of_node) {
339
dev_err(dev, "device-tree data is missing\n");
340
return -ENXIO;
341
}
342
343
dvi = devm_drm_bridge_alloc(dev, struct tfp410, bridge,
344
&tfp410_bridge_funcs);
345
if (IS_ERR(dvi))
346
return PTR_ERR(dvi);
347
348
dvi->dev = dev;
349
dev_set_drvdata(dev, dvi);
350
351
dvi->bridge.of_node = dev->of_node;
352
dvi->bridge.timings = &dvi->timings;
353
dvi->bridge.type = DRM_MODE_CONNECTOR_DVID;
354
355
ret = tfp410_parse_timings(dvi, i2c);
356
if (ret)
357
return ret;
358
359
/* Get the next bridge, connected to port@1. */
360
node = of_graph_get_remote_node(dev->of_node, 1, -1);
361
if (!node)
362
return -ENODEV;
363
364
dvi->bridge.next_bridge = of_drm_find_and_get_bridge(node);
365
of_node_put(node);
366
367
if (!dvi->bridge.next_bridge)
368
return -EPROBE_DEFER;
369
370
/* Get the powerdown GPIO. */
371
dvi->powerdown = devm_gpiod_get_optional(dev, "powerdown",
372
GPIOD_OUT_HIGH);
373
if (IS_ERR(dvi->powerdown)) {
374
dev_err(dev, "failed to parse powerdown gpio\n");
375
return PTR_ERR(dvi->powerdown);
376
}
377
378
/* Register the DRM bridge. */
379
drm_bridge_add(&dvi->bridge);
380
381
return 0;
382
}
383
384
static void tfp410_fini(struct device *dev)
385
{
386
struct tfp410 *dvi = dev_get_drvdata(dev);
387
388
drm_bridge_remove(&dvi->bridge);
389
}
390
391
static int tfp410_probe(struct platform_device *pdev)
392
{
393
return tfp410_init(&pdev->dev, false);
394
}
395
396
static void tfp410_remove(struct platform_device *pdev)
397
{
398
tfp410_fini(&pdev->dev);
399
}
400
401
static const struct of_device_id tfp410_match[] = {
402
{ .compatible = "ti,tfp410" },
403
{},
404
};
405
MODULE_DEVICE_TABLE(of, tfp410_match);
406
407
static struct platform_driver tfp410_platform_driver = {
408
.probe = tfp410_probe,
409
.remove = tfp410_remove,
410
.driver = {
411
.name = "tfp410-bridge",
412
.of_match_table = tfp410_match,
413
},
414
};
415
416
#if IS_ENABLED(CONFIG_I2C)
417
/* There is currently no i2c functionality. */
418
static int tfp410_i2c_probe(struct i2c_client *client)
419
{
420
int reg;
421
422
if (!client->dev.of_node ||
423
of_property_read_u32(client->dev.of_node, "reg", &reg)) {
424
dev_err(&client->dev,
425
"Can't get i2c reg property from device-tree\n");
426
return -ENXIO;
427
}
428
429
return tfp410_init(&client->dev, true);
430
}
431
432
static void tfp410_i2c_remove(struct i2c_client *client)
433
{
434
tfp410_fini(&client->dev);
435
}
436
437
static const struct i2c_device_id tfp410_i2c_ids[] = {
438
{ "tfp410" },
439
{ }
440
};
441
MODULE_DEVICE_TABLE(i2c, tfp410_i2c_ids);
442
443
static struct i2c_driver tfp410_i2c_driver = {
444
.driver = {
445
.name = "tfp410",
446
.of_match_table = tfp410_match,
447
},
448
.id_table = tfp410_i2c_ids,
449
.probe = tfp410_i2c_probe,
450
.remove = tfp410_i2c_remove,
451
};
452
#endif /* IS_ENABLED(CONFIG_I2C) */
453
454
static struct {
455
uint i2c:1;
456
uint platform:1;
457
} tfp410_registered_driver;
458
459
static int __init tfp410_module_init(void)
460
{
461
int ret;
462
463
#if IS_ENABLED(CONFIG_I2C)
464
ret = i2c_add_driver(&tfp410_i2c_driver);
465
if (ret)
466
pr_err("%s: registering i2c driver failed: %d",
467
__func__, ret);
468
else
469
tfp410_registered_driver.i2c = 1;
470
#endif
471
472
ret = platform_driver_register(&tfp410_platform_driver);
473
if (ret)
474
pr_err("%s: registering platform driver failed: %d",
475
__func__, ret);
476
else
477
tfp410_registered_driver.platform = 1;
478
479
if (tfp410_registered_driver.i2c ||
480
tfp410_registered_driver.platform)
481
return 0;
482
483
return ret;
484
}
485
module_init(tfp410_module_init);
486
487
static void __exit tfp410_module_exit(void)
488
{
489
#if IS_ENABLED(CONFIG_I2C)
490
if (tfp410_registered_driver.i2c)
491
i2c_del_driver(&tfp410_i2c_driver);
492
#endif
493
if (tfp410_registered_driver.platform)
494
platform_driver_unregister(&tfp410_platform_driver);
495
}
496
module_exit(tfp410_module_exit);
497
498
MODULE_AUTHOR("Jyri Sarha <[email protected]>");
499
MODULE_DESCRIPTION("TI TFP410 DVI bridge driver");
500
MODULE_LICENSE("GPL");
501
502