1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2019 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
4  */
5 
6 #include <linux/gpio/consumer.h>
7 #include <linux/i2c.h>
8 #include <linux/interrupt.h>
9 #include <linux/module.h>
10 #include <linux/mutex.h>
11 #include <linux/of.h>
12 #include <linux/of_device.h>
13 #include <linux/platform_device.h>
14 #include <linux/regulator/consumer.h>
15 
16 #include <drm/drm_atomic_helper.h>
17 #include <drm/drm_bridge.h>
18 #include <drm/drm_edid.h>
19 
20 struct display_connector {
21 	struct drm_bridge	bridge;
22 
23 	struct gpio_desc	*hpd_gpio;
24 	int			hpd_irq;
25 
26 	struct regulator	*dp_pwr;
27 };
28 
29 static inline struct display_connector *
30 to_display_connector(struct drm_bridge *bridge)
31 {
32 	return container_of(bridge, struct display_connector, bridge);
33 }
34 
35 static int display_connector_attach(struct drm_bridge *bridge,
36 				    enum drm_bridge_attach_flags flags)
37 {
38 	return flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR ? 0 : -EINVAL;
39 }
40 
41 static enum drm_connector_status
42 display_connector_detect(struct drm_bridge *bridge)
43 {
44 	struct display_connector *conn = to_display_connector(bridge);
45 
46 	if (conn->hpd_gpio) {
47 		if (gpiod_get_value_cansleep(conn->hpd_gpio))
48 			return connector_status_connected;
49 		else
50 			return connector_status_disconnected;
51 	}
52 
53 	if (conn->bridge.ddc && drm_probe_ddc(conn->bridge.ddc))
54 		return connector_status_connected;
55 
56 	switch (conn->bridge.type) {
57 	case DRM_MODE_CONNECTOR_DVIA:
58 	case DRM_MODE_CONNECTOR_DVID:
59 	case DRM_MODE_CONNECTOR_DVII:
60 	case DRM_MODE_CONNECTOR_HDMIA:
61 	case DRM_MODE_CONNECTOR_HDMIB:
62 		/*
63 		 * For DVI and HDMI connectors a DDC probe failure indicates
64 		 * that no cable is connected.
65 		 */
66 		return connector_status_disconnected;
67 
68 	case DRM_MODE_CONNECTOR_Composite:
69 	case DRM_MODE_CONNECTOR_SVIDEO:
70 	case DRM_MODE_CONNECTOR_VGA:
71 	default:
72 		/*
73 		 * Composite and S-Video connectors have no other detection
74 		 * mean than the HPD GPIO. For VGA connectors, even if we have
75 		 * an I2C bus, we can't assume that the cable is disconnected
76 		 * if drm_probe_ddc fails, as some cables don't wire the DDC
77 		 * pins.
78 		 */
79 		return connector_status_unknown;
80 	}
81 }
82 
83 static struct edid *display_connector_get_edid(struct drm_bridge *bridge,
84 					       struct drm_connector *connector)
85 {
86 	struct display_connector *conn = to_display_connector(bridge);
87 
88 	return drm_get_edid(connector, conn->bridge.ddc);
89 }
90 
91 /*
92  * Since this bridge is tied to the connector, it acts like a passthrough,
93  * so concerning the output bus formats, either pass the bus formats from the
94  * previous bridge or return fallback data like done in the bridge function:
95  * drm_atomic_bridge_chain_select_bus_fmts().
96  * This supports negotiation if the bridge chain has all bits in place.
97  */
98 static u32 *display_connector_get_output_bus_fmts(struct drm_bridge *bridge,
99 					struct drm_bridge_state *bridge_state,
100 					struct drm_crtc_state *crtc_state,
101 					struct drm_connector_state *conn_state,
102 					unsigned int *num_output_fmts)
103 {
104 	struct drm_bridge *prev_bridge = drm_bridge_get_prev_bridge(bridge);
105 	struct drm_bridge_state *prev_bridge_state;
106 
107 	if (!prev_bridge || !prev_bridge->funcs->atomic_get_output_bus_fmts) {
108 		struct drm_connector *conn = conn_state->connector;
109 		u32 *out_bus_fmts;
110 
111 		*num_output_fmts = 1;
112 		out_bus_fmts = kmalloc(sizeof(*out_bus_fmts), GFP_KERNEL);
113 		if (!out_bus_fmts)
114 			return NULL;
115 
116 		if (conn->display_info.num_bus_formats &&
117 		    conn->display_info.bus_formats)
118 			out_bus_fmts[0] = conn->display_info.bus_formats[0];
119 		else
120 			out_bus_fmts[0] = MEDIA_BUS_FMT_FIXED;
121 
122 		return out_bus_fmts;
123 	}
124 
125 	prev_bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state,
126 							    prev_bridge);
127 
128 	return prev_bridge->funcs->atomic_get_output_bus_fmts(prev_bridge, prev_bridge_state,
129 							      crtc_state, conn_state,
130 							      num_output_fmts);
131 }
132 
133 /*
134  * Since this bridge is tied to the connector, it acts like a passthrough,
135  * so concerning the input bus formats, either pass the bus formats from the
136  * previous bridge or MEDIA_BUS_FMT_FIXED (like select_bus_fmt_recursive())
137  * when atomic_get_input_bus_fmts is not supported.
138  * This supports negotiation if the bridge chain has all bits in place.
139  */
140 static u32 *display_connector_get_input_bus_fmts(struct drm_bridge *bridge,
141 					struct drm_bridge_state *bridge_state,
142 					struct drm_crtc_state *crtc_state,
143 					struct drm_connector_state *conn_state,
144 					u32 output_fmt,
145 					unsigned int *num_input_fmts)
146 {
147 	struct drm_bridge *prev_bridge = drm_bridge_get_prev_bridge(bridge);
148 	struct drm_bridge_state *prev_bridge_state;
149 
150 	if (!prev_bridge || !prev_bridge->funcs->atomic_get_input_bus_fmts) {
151 		u32 *in_bus_fmts;
152 
153 		*num_input_fmts = 1;
154 		in_bus_fmts = kmalloc(sizeof(*in_bus_fmts), GFP_KERNEL);
155 		if (!in_bus_fmts)
156 			return NULL;
157 
158 		in_bus_fmts[0] = MEDIA_BUS_FMT_FIXED;
159 
160 		return in_bus_fmts;
161 	}
162 
163 	prev_bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state,
164 							    prev_bridge);
165 
166 	return prev_bridge->funcs->atomic_get_input_bus_fmts(prev_bridge, prev_bridge_state,
167 							     crtc_state, conn_state, output_fmt,
168 							     num_input_fmts);
169 }
170 
171 static const struct drm_bridge_funcs display_connector_bridge_funcs = {
172 	.attach = display_connector_attach,
173 	.detect = display_connector_detect,
174 	.get_edid = display_connector_get_edid,
175 	.atomic_get_output_bus_fmts = display_connector_get_output_bus_fmts,
176 	.atomic_get_input_bus_fmts = display_connector_get_input_bus_fmts,
177 	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
178 	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
179 	.atomic_reset = drm_atomic_helper_bridge_reset,
180 };
181 
182 static irqreturn_t display_connector_hpd_irq(int irq, void *arg)
183 {
184 	struct display_connector *conn = arg;
185 	struct drm_bridge *bridge = &conn->bridge;
186 
187 	drm_bridge_hpd_notify(bridge, display_connector_detect(bridge));
188 
189 	return IRQ_HANDLED;
190 }
191 
192 static int display_connector_probe(struct platform_device *pdev)
193 {
194 	struct display_connector *conn;
195 	unsigned int type;
196 	const char *label = NULL;
197 	int ret;
198 
199 	conn = devm_kzalloc(&pdev->dev, sizeof(*conn), GFP_KERNEL);
200 	if (!conn)
201 		return -ENOMEM;
202 
203 	platform_set_drvdata(pdev, conn);
204 
205 	type = (uintptr_t)of_device_get_match_data(&pdev->dev);
206 
207 	/* Get the exact connector type. */
208 	switch (type) {
209 	case DRM_MODE_CONNECTOR_DVII: {
210 		bool analog, digital;
211 
212 		analog = of_property_read_bool(pdev->dev.of_node, "analog");
213 		digital = of_property_read_bool(pdev->dev.of_node, "digital");
214 		if (analog && !digital) {
215 			conn->bridge.type = DRM_MODE_CONNECTOR_DVIA;
216 		} else if (!analog && digital) {
217 			conn->bridge.type = DRM_MODE_CONNECTOR_DVID;
218 		} else if (analog && digital) {
219 			conn->bridge.type = DRM_MODE_CONNECTOR_DVII;
220 		} else {
221 			dev_err(&pdev->dev, "DVI connector with no type\n");
222 			return -EINVAL;
223 		}
224 		break;
225 	}
226 
227 	case DRM_MODE_CONNECTOR_HDMIA: {
228 		const char *hdmi_type;
229 
230 		ret = of_property_read_string(pdev->dev.of_node, "type",
231 					      &hdmi_type);
232 		if (ret < 0) {
233 			dev_err(&pdev->dev, "HDMI connector with no type\n");
234 			return -EINVAL;
235 		}
236 
237 		if (!strcmp(hdmi_type, "a") || !strcmp(hdmi_type, "c") ||
238 		    !strcmp(hdmi_type, "d") || !strcmp(hdmi_type, "e")) {
239 			conn->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
240 		} else if (!strcmp(hdmi_type, "b")) {
241 			conn->bridge.type = DRM_MODE_CONNECTOR_HDMIB;
242 		} else {
243 			dev_err(&pdev->dev,
244 				"Unsupported HDMI connector type '%s'\n",
245 				hdmi_type);
246 			return -EINVAL;
247 		}
248 
249 		break;
250 	}
251 
252 	default:
253 		conn->bridge.type = type;
254 		break;
255 	}
256 
257 	/* All the supported connector types support interlaced modes. */
258 	conn->bridge.interlace_allowed = true;
259 
260 	/* Get the optional connector label. */
261 	of_property_read_string(pdev->dev.of_node, "label", &label);
262 
263 	/*
264 	 * Get the HPD GPIO for DVI, HDMI and DP connectors. If the GPIO can provide
265 	 * edge interrupts, register an interrupt handler.
266 	 */
267 	if (type == DRM_MODE_CONNECTOR_DVII ||
268 	    type == DRM_MODE_CONNECTOR_HDMIA ||
269 	    type == DRM_MODE_CONNECTOR_DisplayPort) {
270 		conn->hpd_gpio = devm_gpiod_get_optional(&pdev->dev, "hpd",
271 							 GPIOD_IN);
272 		if (IS_ERR(conn->hpd_gpio)) {
273 			if (PTR_ERR(conn->hpd_gpio) != -EPROBE_DEFER)
274 				dev_err(&pdev->dev,
275 					"Unable to retrieve HPD GPIO\n");
276 			return PTR_ERR(conn->hpd_gpio);
277 		}
278 
279 		conn->hpd_irq = gpiod_to_irq(conn->hpd_gpio);
280 	} else {
281 		conn->hpd_irq = -EINVAL;
282 	}
283 
284 	if (conn->hpd_irq >= 0) {
285 		ret = devm_request_threaded_irq(&pdev->dev, conn->hpd_irq,
286 						NULL, display_connector_hpd_irq,
287 						IRQF_TRIGGER_RISING |
288 						IRQF_TRIGGER_FALLING |
289 						IRQF_ONESHOT,
290 						"HPD", conn);
291 		if (ret) {
292 			dev_info(&pdev->dev,
293 				 "Failed to request HPD edge interrupt, falling back to polling\n");
294 			conn->hpd_irq = -EINVAL;
295 		}
296 	}
297 
298 	/* Retrieve the DDC I2C adapter for DVI, HDMI and VGA connectors. */
299 	if (type == DRM_MODE_CONNECTOR_DVII ||
300 	    type == DRM_MODE_CONNECTOR_HDMIA ||
301 	    type == DRM_MODE_CONNECTOR_VGA) {
302 		struct device_node *phandle;
303 
304 		phandle = of_parse_phandle(pdev->dev.of_node, "ddc-i2c-bus", 0);
305 		if (phandle) {
306 			conn->bridge.ddc = of_get_i2c_adapter_by_node(phandle);
307 			of_node_put(phandle);
308 			if (!conn->bridge.ddc)
309 				return -EPROBE_DEFER;
310 		} else {
311 			dev_dbg(&pdev->dev,
312 				"No I2C bus specified, disabling EDID readout\n");
313 		}
314 	}
315 
316 	/* Get the DP PWR for DP connector. */
317 	if (type == DRM_MODE_CONNECTOR_DisplayPort) {
318 		int ret;
319 
320 		conn->dp_pwr = devm_regulator_get_optional(&pdev->dev, "dp-pwr");
321 
322 		if (IS_ERR(conn->dp_pwr)) {
323 			ret = PTR_ERR(conn->dp_pwr);
324 
325 			switch (ret) {
326 			case -ENODEV:
327 				conn->dp_pwr = NULL;
328 				break;
329 
330 			case -EPROBE_DEFER:
331 				return -EPROBE_DEFER;
332 
333 			default:
334 				dev_err(&pdev->dev, "failed to get DP PWR regulator: %d\n", ret);
335 				return ret;
336 			}
337 		}
338 
339 		if (conn->dp_pwr) {
340 			ret = regulator_enable(conn->dp_pwr);
341 			if (ret) {
342 				dev_err(&pdev->dev, "failed to enable DP PWR regulator: %d\n", ret);
343 				return ret;
344 			}
345 		}
346 	}
347 
348 	conn->bridge.funcs = &display_connector_bridge_funcs;
349 	conn->bridge.of_node = pdev->dev.of_node;
350 
351 	if (conn->bridge.ddc)
352 		conn->bridge.ops |= DRM_BRIDGE_OP_EDID
353 				 |  DRM_BRIDGE_OP_DETECT;
354 	if (conn->hpd_gpio)
355 		conn->bridge.ops |= DRM_BRIDGE_OP_DETECT;
356 	if (conn->hpd_irq >= 0)
357 		conn->bridge.ops |= DRM_BRIDGE_OP_HPD;
358 
359 	dev_dbg(&pdev->dev,
360 		"Found %s display connector '%s' %s DDC bus and %s HPD GPIO (ops 0x%x)\n",
361 		drm_get_connector_type_name(conn->bridge.type),
362 		label ? label : "<unlabelled>",
363 		conn->bridge.ddc ? "with" : "without",
364 		conn->hpd_gpio ? "with" : "without",
365 		conn->bridge.ops);
366 
367 	drm_bridge_add(&conn->bridge);
368 
369 	return 0;
370 }
371 
372 static int display_connector_remove(struct platform_device *pdev)
373 {
374 	struct display_connector *conn = platform_get_drvdata(pdev);
375 
376 	if (conn->dp_pwr)
377 		regulator_disable(conn->dp_pwr);
378 
379 	drm_bridge_remove(&conn->bridge);
380 
381 	if (!IS_ERR(conn->bridge.ddc))
382 		i2c_put_adapter(conn->bridge.ddc);
383 
384 	return 0;
385 }
386 
387 static const struct of_device_id display_connector_match[] = {
388 	{
389 		.compatible = "composite-video-connector",
390 		.data = (void *)DRM_MODE_CONNECTOR_Composite,
391 	}, {
392 		.compatible = "dvi-connector",
393 		.data = (void *)DRM_MODE_CONNECTOR_DVII,
394 	}, {
395 		.compatible = "hdmi-connector",
396 		.data = (void *)DRM_MODE_CONNECTOR_HDMIA,
397 	}, {
398 		.compatible = "svideo-connector",
399 		.data = (void *)DRM_MODE_CONNECTOR_SVIDEO,
400 	}, {
401 		.compatible = "vga-connector",
402 		.data = (void *)DRM_MODE_CONNECTOR_VGA,
403 	}, {
404 		.compatible = "dp-connector",
405 		.data = (void *)DRM_MODE_CONNECTOR_DisplayPort,
406 	},
407 	{},
408 };
409 MODULE_DEVICE_TABLE(of, display_connector_match);
410 
411 static struct platform_driver display_connector_driver = {
412 	.probe	= display_connector_probe,
413 	.remove	= display_connector_remove,
414 	.driver		= {
415 		.name		= "display-connector",
416 		.of_match_table	= display_connector_match,
417 	},
418 };
419 module_platform_driver(display_connector_driver);
420 
421 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
422 MODULE_DESCRIPTION("Display connector driver");
423 MODULE_LICENSE("GPL");
424