1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2019 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
6 #include <linux/gpio/consumer.h>
8 #include <linux/interrupt.h>
9 #include <linux/media-bus-format.h>
10 #include <linux/module.h>
11 #include <linux/mutex.h>
13 #include <linux/platform_device.h>
14 #include <linux/regulator/consumer.h>
16 #include <drm/drm_atomic_helper.h>
17 #include <drm/drm_bridge.h>
18 #include <drm/drm_edid.h>
20 struct display_connector
{
21 struct drm_bridge bridge
;
23 struct gpio_desc
*hpd_gpio
;
26 struct regulator
*supply
;
27 struct gpio_desc
*ddc_en
;
30 static inline struct display_connector
*
31 to_display_connector(struct drm_bridge
*bridge
)
33 return container_of(bridge
, struct display_connector
, bridge
);
36 static int display_connector_attach(struct drm_bridge
*bridge
,
37 enum drm_bridge_attach_flags flags
)
39 return flags
& DRM_BRIDGE_ATTACH_NO_CONNECTOR
? 0 : -EINVAL
;
42 static enum drm_connector_status
43 display_connector_detect(struct drm_bridge
*bridge
)
45 struct display_connector
*conn
= to_display_connector(bridge
);
48 if (gpiod_get_value_cansleep(conn
->hpd_gpio
))
49 return connector_status_connected
;
51 return connector_status_disconnected
;
54 if (conn
->bridge
.ddc
&& drm_probe_ddc(conn
->bridge
.ddc
))
55 return connector_status_connected
;
57 switch (conn
->bridge
.type
) {
58 case DRM_MODE_CONNECTOR_DVIA
:
59 case DRM_MODE_CONNECTOR_DVID
:
60 case DRM_MODE_CONNECTOR_DVII
:
61 case DRM_MODE_CONNECTOR_HDMIA
:
62 case DRM_MODE_CONNECTOR_HDMIB
:
64 * For DVI and HDMI connectors a DDC probe failure indicates
65 * that no cable is connected.
67 return connector_status_disconnected
;
69 case DRM_MODE_CONNECTOR_Composite
:
70 case DRM_MODE_CONNECTOR_SVIDEO
:
71 case DRM_MODE_CONNECTOR_VGA
:
74 * Composite and S-Video connectors have no other detection
75 * mean than the HPD GPIO. For VGA connectors, even if we have
76 * an I2C bus, we can't assume that the cable is disconnected
77 * if drm_probe_ddc fails, as some cables don't wire the DDC
80 return connector_status_unknown
;
84 static const struct drm_edid
*display_connector_edid_read(struct drm_bridge
*bridge
,
85 struct drm_connector
*connector
)
87 struct display_connector
*conn
= to_display_connector(bridge
);
89 return drm_edid_read_ddc(connector
, conn
->bridge
.ddc
);
93 * Since this bridge is tied to the connector, it acts like a passthrough,
94 * so concerning the output bus formats, either pass the bus formats from the
95 * previous bridge or return fallback data like done in the bridge function:
96 * drm_atomic_bridge_chain_select_bus_fmts().
97 * This supports negotiation if the bridge chain has all bits in place.
99 static u32
*display_connector_get_output_bus_fmts(struct drm_bridge
*bridge
,
100 struct drm_bridge_state
*bridge_state
,
101 struct drm_crtc_state
*crtc_state
,
102 struct drm_connector_state
*conn_state
,
103 unsigned int *num_output_fmts
)
105 struct drm_bridge
*prev_bridge
= drm_bridge_get_prev_bridge(bridge
);
106 struct drm_bridge_state
*prev_bridge_state
;
108 if (!prev_bridge
|| !prev_bridge
->funcs
->atomic_get_output_bus_fmts
) {
109 struct drm_connector
*conn
= conn_state
->connector
;
112 *num_output_fmts
= 1;
113 out_bus_fmts
= kmalloc(sizeof(*out_bus_fmts
), GFP_KERNEL
);
117 if (conn
->display_info
.num_bus_formats
&&
118 conn
->display_info
.bus_formats
)
119 out_bus_fmts
[0] = conn
->display_info
.bus_formats
[0];
121 out_bus_fmts
[0] = MEDIA_BUS_FMT_FIXED
;
126 prev_bridge_state
= drm_atomic_get_new_bridge_state(crtc_state
->state
,
129 return prev_bridge
->funcs
->atomic_get_output_bus_fmts(prev_bridge
, prev_bridge_state
,
130 crtc_state
, conn_state
,
135 * Since this bridge is tied to the connector, it acts like a passthrough,
136 * so concerning the input bus formats, either pass the bus formats from the
137 * previous bridge or MEDIA_BUS_FMT_FIXED (like select_bus_fmt_recursive())
138 * when atomic_get_input_bus_fmts is not supported.
139 * This supports negotiation if the bridge chain has all bits in place.
141 static u32
*display_connector_get_input_bus_fmts(struct drm_bridge
*bridge
,
142 struct drm_bridge_state
*bridge_state
,
143 struct drm_crtc_state
*crtc_state
,
144 struct drm_connector_state
*conn_state
,
146 unsigned int *num_input_fmts
)
148 struct drm_bridge
*prev_bridge
= drm_bridge_get_prev_bridge(bridge
);
149 struct drm_bridge_state
*prev_bridge_state
;
151 if (!prev_bridge
|| !prev_bridge
->funcs
->atomic_get_input_bus_fmts
) {
155 in_bus_fmts
= kmalloc(sizeof(*in_bus_fmts
), GFP_KERNEL
);
159 in_bus_fmts
[0] = MEDIA_BUS_FMT_FIXED
;
164 prev_bridge_state
= drm_atomic_get_new_bridge_state(crtc_state
->state
,
167 return prev_bridge
->funcs
->atomic_get_input_bus_fmts(prev_bridge
, prev_bridge_state
,
168 crtc_state
, conn_state
, output_fmt
,
172 static const struct drm_bridge_funcs display_connector_bridge_funcs
= {
173 .attach
= display_connector_attach
,
174 .detect
= display_connector_detect
,
175 .edid_read
= display_connector_edid_read
,
176 .atomic_get_output_bus_fmts
= display_connector_get_output_bus_fmts
,
177 .atomic_get_input_bus_fmts
= display_connector_get_input_bus_fmts
,
178 .atomic_duplicate_state
= drm_atomic_helper_bridge_duplicate_state
,
179 .atomic_destroy_state
= drm_atomic_helper_bridge_destroy_state
,
180 .atomic_reset
= drm_atomic_helper_bridge_reset
,
183 static irqreturn_t
display_connector_hpd_irq(int irq
, void *arg
)
185 struct display_connector
*conn
= arg
;
186 struct drm_bridge
*bridge
= &conn
->bridge
;
188 drm_bridge_hpd_notify(bridge
, display_connector_detect(bridge
));
193 static int display_connector_get_supply(struct platform_device
*pdev
,
194 struct display_connector
*conn
,
197 conn
->supply
= devm_regulator_get_optional(&pdev
->dev
, name
);
199 if (conn
->supply
== ERR_PTR(-ENODEV
))
202 return PTR_ERR_OR_ZERO(conn
->supply
);
205 static int display_connector_probe(struct platform_device
*pdev
)
207 struct display_connector
*conn
;
209 const char *label
= NULL
;
212 conn
= devm_kzalloc(&pdev
->dev
, sizeof(*conn
), GFP_KERNEL
);
216 platform_set_drvdata(pdev
, conn
);
218 type
= (uintptr_t)of_device_get_match_data(&pdev
->dev
);
220 /* Get the exact connector type. */
222 case DRM_MODE_CONNECTOR_DVII
: {
223 bool analog
, digital
;
225 analog
= of_property_read_bool(pdev
->dev
.of_node
, "analog");
226 digital
= of_property_read_bool(pdev
->dev
.of_node
, "digital");
227 if (analog
&& !digital
) {
228 conn
->bridge
.type
= DRM_MODE_CONNECTOR_DVIA
;
229 } else if (!analog
&& digital
) {
230 conn
->bridge
.type
= DRM_MODE_CONNECTOR_DVID
;
231 } else if (analog
&& digital
) {
232 conn
->bridge
.type
= DRM_MODE_CONNECTOR_DVII
;
234 dev_err(&pdev
->dev
, "DVI connector with no type\n");
240 case DRM_MODE_CONNECTOR_HDMIA
: {
241 const char *hdmi_type
;
243 ret
= of_property_read_string(pdev
->dev
.of_node
, "type",
246 dev_err(&pdev
->dev
, "HDMI connector with no type\n");
250 if (!strcmp(hdmi_type
, "a") || !strcmp(hdmi_type
, "c") ||
251 !strcmp(hdmi_type
, "d") || !strcmp(hdmi_type
, "e")) {
252 conn
->bridge
.type
= DRM_MODE_CONNECTOR_HDMIA
;
253 } else if (!strcmp(hdmi_type
, "b")) {
254 conn
->bridge
.type
= DRM_MODE_CONNECTOR_HDMIB
;
257 "Unsupported HDMI connector type '%s'\n",
266 conn
->bridge
.type
= type
;
270 /* All the supported connector types support interlaced modes. */
271 conn
->bridge
.interlace_allowed
= true;
273 if (type
== DRM_MODE_CONNECTOR_HDMIA
||
274 type
== DRM_MODE_CONNECTOR_DisplayPort
)
275 conn
->bridge
.ycbcr_420_allowed
= true;
277 /* Get the optional connector label. */
278 of_property_read_string(pdev
->dev
.of_node
, "label", &label
);
281 * Get the HPD GPIO for DVI, HDMI and DP connectors. If the GPIO can provide
282 * edge interrupts, register an interrupt handler.
284 if (type
== DRM_MODE_CONNECTOR_DVII
||
285 type
== DRM_MODE_CONNECTOR_HDMIA
||
286 type
== DRM_MODE_CONNECTOR_DisplayPort
) {
287 conn
->hpd_gpio
= devm_gpiod_get_optional(&pdev
->dev
, "hpd",
289 if (IS_ERR(conn
->hpd_gpio
))
290 return dev_err_probe(&pdev
->dev
, PTR_ERR(conn
->hpd_gpio
),
291 "Unable to retrieve HPD GPIO\n");
293 conn
->hpd_irq
= gpiod_to_irq(conn
->hpd_gpio
);
295 conn
->hpd_irq
= -EINVAL
;
298 if (conn
->hpd_irq
>= 0) {
299 ret
= devm_request_threaded_irq(&pdev
->dev
, conn
->hpd_irq
,
300 NULL
, display_connector_hpd_irq
,
301 IRQF_TRIGGER_RISING
|
302 IRQF_TRIGGER_FALLING
|
307 "Failed to request HPD edge interrupt, falling back to polling\n");
308 conn
->hpd_irq
= -EINVAL
;
312 /* Retrieve the DDC I2C adapter for DVI, HDMI and VGA connectors. */
313 if (type
== DRM_MODE_CONNECTOR_DVII
||
314 type
== DRM_MODE_CONNECTOR_HDMIA
||
315 type
== DRM_MODE_CONNECTOR_VGA
) {
316 struct device_node
*phandle
;
318 phandle
= of_parse_phandle(pdev
->dev
.of_node
, "ddc-i2c-bus", 0);
320 conn
->bridge
.ddc
= of_get_i2c_adapter_by_node(phandle
);
321 of_node_put(phandle
);
322 if (!conn
->bridge
.ddc
)
323 return -EPROBE_DEFER
;
326 "No I2C bus specified, disabling EDID readout\n");
330 /* Get the DP PWR for DP connector. */
331 if (type
== DRM_MODE_CONNECTOR_DisplayPort
) {
334 ret
= display_connector_get_supply(pdev
, conn
, "dp-pwr");
336 return dev_err_probe(&pdev
->dev
, ret
, "failed to get DP PWR regulator\n");
340 if (type
== DRM_MODE_CONNECTOR_HDMIA
) {
343 conn
->ddc_en
= devm_gpiod_get_optional(&pdev
->dev
, "ddc-en",
346 if (IS_ERR(conn
->ddc_en
)) {
347 dev_err(&pdev
->dev
, "Couldn't get ddc-en gpio\n");
348 return PTR_ERR(conn
->ddc_en
);
351 ret
= display_connector_get_supply(pdev
, conn
, "hdmi-pwr");
353 return dev_err_probe(&pdev
->dev
, ret
, "failed to get HDMI +5V Power regulator\n");
357 ret
= regulator_enable(conn
->supply
);
359 dev_err(&pdev
->dev
, "failed to enable PWR regulator: %d\n", ret
);
364 conn
->bridge
.funcs
= &display_connector_bridge_funcs
;
365 conn
->bridge
.of_node
= pdev
->dev
.of_node
;
367 if (conn
->bridge
.ddc
)
368 conn
->bridge
.ops
|= DRM_BRIDGE_OP_EDID
369 | DRM_BRIDGE_OP_DETECT
;
371 conn
->bridge
.ops
|= DRM_BRIDGE_OP_DETECT
;
372 if (conn
->hpd_irq
>= 0)
373 conn
->bridge
.ops
|= DRM_BRIDGE_OP_HPD
;
376 "Found %s display connector '%s' %s DDC bus and %s HPD GPIO (ops 0x%x)\n",
377 drm_get_connector_type_name(conn
->bridge
.type
),
378 label
? label
: "<unlabelled>",
379 conn
->bridge
.ddc
? "with" : "without",
380 conn
->hpd_gpio
? "with" : "without",
383 drm_bridge_add(&conn
->bridge
);
388 static void display_connector_remove(struct platform_device
*pdev
)
390 struct display_connector
*conn
= platform_get_drvdata(pdev
);
393 gpiod_set_value(conn
->ddc_en
, 0);
396 regulator_disable(conn
->supply
);
398 drm_bridge_remove(&conn
->bridge
);
400 if (!IS_ERR(conn
->bridge
.ddc
))
401 i2c_put_adapter(conn
->bridge
.ddc
);
404 static const struct of_device_id display_connector_match
[] = {
406 .compatible
= "composite-video-connector",
407 .data
= (void *)DRM_MODE_CONNECTOR_Composite
,
409 .compatible
= "dvi-connector",
410 .data
= (void *)DRM_MODE_CONNECTOR_DVII
,
412 .compatible
= "hdmi-connector",
413 .data
= (void *)DRM_MODE_CONNECTOR_HDMIA
,
415 .compatible
= "svideo-connector",
416 .data
= (void *)DRM_MODE_CONNECTOR_SVIDEO
,
418 .compatible
= "vga-connector",
419 .data
= (void *)DRM_MODE_CONNECTOR_VGA
,
421 .compatible
= "dp-connector",
422 .data
= (void *)DRM_MODE_CONNECTOR_DisplayPort
,
426 MODULE_DEVICE_TABLE(of
, display_connector_match
);
428 static struct platform_driver display_connector_driver
= {
429 .probe
= display_connector_probe
,
430 .remove
= display_connector_remove
,
432 .name
= "display-connector",
433 .of_match_table
= display_connector_match
,
436 module_platform_driver(display_connector_driver
);
438 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
439 MODULE_DESCRIPTION("Display connector driver");
440 MODULE_LICENSE("GPL");