xref: /linux/drivers/gpu/drm/msm/hdmi/hdmi.c (revision 25489a4f556414445d342951615178368ee45cde)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2014 The Linux Foundation. All rights reserved.
4  * Copyright (C) 2013 Red Hat
5  * Author: Rob Clark <robdclark@gmail.com>
6  */
7 
8 #include <linux/gpio/consumer.h>
9 #include <linux/of_irq.h>
10 #include <linux/of_platform.h>
11 #include <linux/pinctrl/consumer.h>
12 #include <linux/platform_device.h>
13 
14 #include <drm/drm_bridge_connector.h>
15 #include <drm/drm_of.h>
16 #include <drm/display/drm_hdmi_state_helper.h>
17 
18 #include "hdmi.h"
19 
20 void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on)
21 {
22 	uint32_t ctrl = 0;
23 	unsigned long flags;
24 
25 	spin_lock_irqsave(&hdmi->reg_lock, flags);
26 	if (power_on) {
27 		ctrl |= HDMI_CTRL_ENABLE;
28 		if (!hdmi->connector->display_info.is_hdmi) {
29 			ctrl |= HDMI_CTRL_HDMI;
30 			hdmi_write(hdmi, REG_HDMI_CTRL, ctrl);
31 			ctrl &= ~HDMI_CTRL_HDMI;
32 		} else {
33 			ctrl |= HDMI_CTRL_HDMI;
34 		}
35 	} else {
36 		ctrl = HDMI_CTRL_HDMI;
37 	}
38 
39 	hdmi_write(hdmi, REG_HDMI_CTRL, ctrl);
40 	spin_unlock_irqrestore(&hdmi->reg_lock, flags);
41 	DBG("HDMI Core: %s, HDMI_CTRL=0x%08x",
42 			power_on ? "Enable" : "Disable", ctrl);
43 }
44 
45 static irqreturn_t msm_hdmi_irq(int irq, void *dev_id)
46 {
47 	struct hdmi *hdmi = dev_id;
48 
49 	/* Process HPD: */
50 	msm_hdmi_hpd_irq(hdmi->bridge);
51 
52 	/* Process DDC: */
53 	msm_hdmi_i2c_irq(hdmi->i2c);
54 
55 	/* Process HDCP: */
56 	if (hdmi->hdcp_ctrl)
57 		msm_hdmi_hdcp_irq(hdmi->hdcp_ctrl);
58 
59 	/* TODO audio.. */
60 
61 	return IRQ_HANDLED;
62 }
63 
64 static void msm_hdmi_destroy(struct hdmi *hdmi)
65 {
66 	/*
67 	 * at this point, hpd has been disabled,
68 	 * after flush workq, it's safe to deinit hdcp
69 	 */
70 	if (hdmi->workq)
71 		destroy_workqueue(hdmi->workq);
72 	msm_hdmi_hdcp_destroy(hdmi);
73 
74 	if (hdmi->i2c)
75 		msm_hdmi_i2c_destroy(hdmi->i2c);
76 }
77 
78 static void msm_hdmi_put_phy(struct hdmi *hdmi)
79 {
80 	if (hdmi->phy_dev) {
81 		put_device(hdmi->phy_dev);
82 		hdmi->phy = NULL;
83 		hdmi->phy_dev = NULL;
84 	}
85 }
86 
87 static int msm_hdmi_get_phy(struct hdmi *hdmi)
88 {
89 	struct platform_device *pdev = hdmi->pdev;
90 	struct platform_device *phy_pdev;
91 	struct device_node *phy_node;
92 
93 	phy_node = of_parse_phandle(pdev->dev.of_node, "phys", 0);
94 	if (!phy_node) {
95 		DRM_DEV_ERROR(&pdev->dev, "cannot find phy device\n");
96 		return -ENXIO;
97 	}
98 
99 	phy_pdev = of_find_device_by_node(phy_node);
100 	of_node_put(phy_node);
101 
102 	if (!phy_pdev)
103 		return dev_err_probe(&pdev->dev, -EPROBE_DEFER, "phy driver is not ready\n");
104 
105 	hdmi->phy = platform_get_drvdata(phy_pdev);
106 	if (!hdmi->phy) {
107 		put_device(&phy_pdev->dev);
108 		return dev_err_probe(&pdev->dev, -EPROBE_DEFER, "phy driver is not ready\n");
109 	}
110 
111 	hdmi->phy_dev = &phy_pdev->dev;
112 
113 	return 0;
114 }
115 
116 /* construct hdmi at bind/probe time, grab all the resources.  If
117  * we are to EPROBE_DEFER we want to do it here, rather than later
118  * at modeset_init() time
119  */
120 static int msm_hdmi_init(struct hdmi *hdmi)
121 {
122 	struct platform_device *pdev = hdmi->pdev;
123 	int ret;
124 
125 	hdmi->workq = alloc_ordered_workqueue("msm_hdmi", 0);
126 	if (!hdmi->workq) {
127 		ret = -ENOMEM;
128 		goto fail;
129 	}
130 
131 	hdmi->i2c = msm_hdmi_i2c_init(hdmi);
132 	if (IS_ERR(hdmi->i2c)) {
133 		ret = PTR_ERR(hdmi->i2c);
134 		DRM_DEV_ERROR(&pdev->dev, "failed to get i2c: %d\n", ret);
135 		hdmi->i2c = NULL;
136 		goto fail;
137 	}
138 
139 	hdmi->hdcp_ctrl = msm_hdmi_hdcp_init(hdmi);
140 	if (IS_ERR(hdmi->hdcp_ctrl)) {
141 		dev_warn(&pdev->dev, "failed to init hdcp: disabled\n");
142 		hdmi->hdcp_ctrl = NULL;
143 	}
144 
145 	return 0;
146 
147 fail:
148 	msm_hdmi_destroy(hdmi);
149 
150 	return ret;
151 }
152 
153 /* Second part of initialization, the drm/kms level modeset_init,
154  * constructs/initializes mode objects, etc, is called from master
155  * driver (not hdmi sub-device's probe/bind!)
156  *
157  * Any resource (regulator/clk/etc) which could be missing at boot
158  * should be handled in msm_hdmi_init() so that failure happens from
159  * hdmi sub-device's probe.
160  */
161 int msm_hdmi_modeset_init(struct hdmi *hdmi,
162 		struct drm_device *dev, struct drm_encoder *encoder)
163 {
164 	int ret;
165 
166 	hdmi->dev = dev;
167 	hdmi->encoder = encoder;
168 
169 	ret = msm_hdmi_bridge_init(hdmi);
170 	if (ret) {
171 		DRM_DEV_ERROR(dev->dev, "failed to create HDMI bridge: %d\n", ret);
172 		goto fail;
173 	}
174 
175 	if (hdmi->next_bridge) {
176 		ret = drm_bridge_attach(hdmi->encoder, hdmi->next_bridge, hdmi->bridge,
177 					DRM_BRIDGE_ATTACH_NO_CONNECTOR);
178 		if (ret) {
179 			DRM_DEV_ERROR(dev->dev, "failed to attach next HDMI bridge: %d\n", ret);
180 			goto fail;
181 		}
182 	}
183 
184 	hdmi->connector = drm_bridge_connector_init(hdmi->dev, encoder);
185 	if (IS_ERR(hdmi->connector)) {
186 		ret = PTR_ERR(hdmi->connector);
187 		DRM_DEV_ERROR(dev->dev, "failed to create HDMI connector: %d\n", ret);
188 		hdmi->connector = NULL;
189 		goto fail;
190 	}
191 
192 	drm_connector_attach_encoder(hdmi->connector, hdmi->encoder);
193 
194 	ret = devm_request_irq(dev->dev, hdmi->irq,
195 			msm_hdmi_irq, IRQF_TRIGGER_HIGH,
196 			"hdmi_isr", hdmi);
197 	if (ret < 0) {
198 		DRM_DEV_ERROR(dev->dev, "failed to request IRQ%u: %d\n",
199 				hdmi->irq, ret);
200 		goto fail;
201 	}
202 
203 	return 0;
204 
205 fail:
206 	if (hdmi->connector) {
207 		hdmi->connector->funcs->destroy(hdmi->connector);
208 		hdmi->connector = NULL;
209 	}
210 
211 	return ret;
212 }
213 
214 /*
215  * The hdmi device:
216  */
217 
218 static const char * const pwr_reg_names_8960[] = {"core-vdda"};
219 static const char * const pwr_clk_names_8960[] = {"core", "master_iface", "slave_iface"};
220 
221 static const struct hdmi_platform_config hdmi_tx_8960_config = {
222 	.pwr_reg_names = pwr_reg_names_8960,
223 	.pwr_reg_cnt = ARRAY_SIZE(pwr_reg_names_8960),
224 	.pwr_clk_names = pwr_clk_names_8960,
225 	.pwr_clk_cnt = ARRAY_SIZE(pwr_clk_names_8960),
226 };
227 
228 static const char * const pwr_reg_names_8x74[] = {"core-vdda", "core-vcc"};
229 static const char * const pwr_clk_names_8x74[] = {"iface", "core", "mdp_core", "alt_iface"};
230 
231 static const struct hdmi_platform_config hdmi_tx_8974_config = {
232 	.pwr_reg_names = pwr_reg_names_8x74,
233 	.pwr_reg_cnt = ARRAY_SIZE(pwr_reg_names_8x74),
234 	.pwr_clk_names = pwr_clk_names_8x74,
235 	.pwr_clk_cnt = ARRAY_SIZE(pwr_clk_names_8x74),
236 };
237 
238 static int msm_hdmi_bind(struct device *dev, struct device *master, void *data)
239 {
240 	struct msm_drm_private *priv = dev_get_drvdata(master);
241 	struct hdmi *hdmi = dev_get_drvdata(dev);
242 	int err;
243 
244 	err = msm_hdmi_init(hdmi);
245 	if (err)
246 		return err;
247 	priv->hdmi = hdmi;
248 
249 	return 0;
250 }
251 
252 static void msm_hdmi_unbind(struct device *dev, struct device *master,
253 		void *data)
254 {
255 	struct msm_drm_private *priv = dev_get_drvdata(master);
256 
257 	if (priv->hdmi) {
258 		msm_hdmi_destroy(priv->hdmi);
259 		priv->hdmi = NULL;
260 	}
261 }
262 
263 static const struct component_ops msm_hdmi_ops = {
264 		.bind   = msm_hdmi_bind,
265 		.unbind = msm_hdmi_unbind,
266 };
267 
268 static int msm_hdmi_dev_probe(struct platform_device *pdev)
269 {
270 	const struct hdmi_platform_config *config;
271 	struct device *dev = &pdev->dev;
272 	struct hdmi *hdmi;
273 	struct resource *res;
274 	int i, ret;
275 
276 	config = of_device_get_match_data(dev);
277 	if (!config)
278 		return -EINVAL;
279 
280 	hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
281 	if (!hdmi)
282 		return -ENOMEM;
283 
284 	hdmi->pdev = pdev;
285 	hdmi->config = config;
286 	spin_lock_init(&hdmi->reg_lock);
287 	mutex_init(&hdmi->state_mutex);
288 
289 	ret = drm_of_find_panel_or_bridge(pdev->dev.of_node, 1, 0, NULL, &hdmi->next_bridge);
290 	if (ret && ret != -ENODEV)
291 		return ret;
292 
293 	hdmi->mmio = msm_ioremap(pdev, "core_physical");
294 	if (IS_ERR(hdmi->mmio))
295 		return PTR_ERR(hdmi->mmio);
296 
297 	/* HDCP needs physical address of hdmi register */
298 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
299 		"core_physical");
300 	if (!res)
301 		return -EINVAL;
302 	hdmi->mmio_phy_addr = res->start;
303 
304 	hdmi->qfprom_mmio = msm_ioremap(pdev, "qfprom_physical");
305 	if (IS_ERR(hdmi->qfprom_mmio)) {
306 		DRM_DEV_INFO(&pdev->dev, "can't find qfprom resource\n");
307 		hdmi->qfprom_mmio = NULL;
308 	}
309 
310 	hdmi->irq = platform_get_irq(pdev, 0);
311 	if (hdmi->irq < 0)
312 		return hdmi->irq;
313 
314 	hdmi->pwr_regs = devm_kcalloc(&pdev->dev,
315 				      config->pwr_reg_cnt,
316 				      sizeof(hdmi->pwr_regs[0]),
317 				      GFP_KERNEL);
318 	if (!hdmi->pwr_regs)
319 		return -ENOMEM;
320 
321 	for (i = 0; i < config->pwr_reg_cnt; i++)
322 		hdmi->pwr_regs[i].supply = config->pwr_reg_names[i];
323 
324 	ret = devm_regulator_bulk_get(&pdev->dev, config->pwr_reg_cnt, hdmi->pwr_regs);
325 	if (ret)
326 		return dev_err_probe(dev, ret, "failed to get pwr regulators\n");
327 
328 	hdmi->pwr_clks = devm_kcalloc(&pdev->dev,
329 				      config->pwr_clk_cnt,
330 				      sizeof(hdmi->pwr_clks[0]),
331 				      GFP_KERNEL);
332 	if (!hdmi->pwr_clks)
333 		return -ENOMEM;
334 
335 	for (i = 0; i < config->pwr_clk_cnt; i++)
336 		hdmi->pwr_clks[i].id = config->pwr_clk_names[i];
337 
338 	ret = devm_clk_bulk_get(&pdev->dev, config->pwr_clk_cnt, hdmi->pwr_clks);
339 	if (ret)
340 		return ret;
341 
342 	hdmi->extp_clk = devm_clk_get_optional(&pdev->dev, "extp");
343 	if (IS_ERR(hdmi->extp_clk))
344 		return dev_err_probe(dev, PTR_ERR(hdmi->extp_clk),
345 				     "failed to get extp clock\n");
346 
347 	hdmi->hpd_gpiod = devm_gpiod_get_optional(&pdev->dev, "hpd", GPIOD_IN);
348 	/* This will catch e.g. -EPROBE_DEFER */
349 	if (IS_ERR(hdmi->hpd_gpiod))
350 		return dev_err_probe(dev, PTR_ERR(hdmi->hpd_gpiod),
351 				     "failed to get hpd gpio\n");
352 
353 	if (!hdmi->hpd_gpiod)
354 		DBG("failed to get HPD gpio");
355 
356 	if (hdmi->hpd_gpiod)
357 		gpiod_set_consumer_name(hdmi->hpd_gpiod, "HDMI_HPD");
358 
359 	ret = msm_hdmi_get_phy(hdmi);
360 	if (ret) {
361 		DRM_DEV_ERROR(&pdev->dev, "failed to get phy\n");
362 		return ret;
363 	}
364 
365 	ret = devm_pm_runtime_enable(&pdev->dev);
366 	if (ret)
367 		goto err_put_phy;
368 
369 	platform_set_drvdata(pdev, hdmi);
370 
371 	ret = component_add(&pdev->dev, &msm_hdmi_ops);
372 	if (ret)
373 		goto err_put_phy;
374 
375 	return 0;
376 
377 err_put_phy:
378 	msm_hdmi_put_phy(hdmi);
379 	return ret;
380 }
381 
382 static void msm_hdmi_dev_remove(struct platform_device *pdev)
383 {
384 	struct hdmi *hdmi = dev_get_drvdata(&pdev->dev);
385 
386 	component_del(&pdev->dev, &msm_hdmi_ops);
387 
388 	msm_hdmi_put_phy(hdmi);
389 }
390 
391 static int msm_hdmi_runtime_suspend(struct device *dev)
392 {
393 	struct hdmi *hdmi = dev_get_drvdata(dev);
394 	const struct hdmi_platform_config *config = hdmi->config;
395 
396 	clk_bulk_disable_unprepare(config->pwr_clk_cnt, hdmi->pwr_clks);
397 
398 	pinctrl_pm_select_sleep_state(dev);
399 
400 	regulator_bulk_disable(config->pwr_reg_cnt, hdmi->pwr_regs);
401 
402 	return 0;
403 }
404 
405 static int msm_hdmi_runtime_resume(struct device *dev)
406 {
407 	struct hdmi *hdmi = dev_get_drvdata(dev);
408 	const struct hdmi_platform_config *config = hdmi->config;
409 	int ret;
410 
411 	ret = regulator_bulk_enable(config->pwr_reg_cnt, hdmi->pwr_regs);
412 	if (ret)
413 		return ret;
414 
415 	ret = pinctrl_pm_select_default_state(dev);
416 	if (ret)
417 		goto fail;
418 
419 	ret = clk_bulk_prepare_enable(config->pwr_clk_cnt, hdmi->pwr_clks);
420 	if (ret)
421 		goto fail;
422 
423 	return 0;
424 
425 fail:
426 	pinctrl_pm_select_sleep_state(dev);
427 
428 	return ret;
429 }
430 
431 DEFINE_RUNTIME_DEV_PM_OPS(msm_hdmi_pm_ops, msm_hdmi_runtime_suspend, msm_hdmi_runtime_resume, NULL);
432 
433 static const struct of_device_id msm_hdmi_dt_match[] = {
434 	{ .compatible = "qcom,hdmi-tx-8998", .data = &hdmi_tx_8974_config },
435 	{ .compatible = "qcom,hdmi-tx-8996", .data = &hdmi_tx_8974_config },
436 	{ .compatible = "qcom,hdmi-tx-8994", .data = &hdmi_tx_8974_config },
437 	{ .compatible = "qcom,hdmi-tx-8084", .data = &hdmi_tx_8974_config },
438 	{ .compatible = "qcom,hdmi-tx-8974", .data = &hdmi_tx_8974_config },
439 	{ .compatible = "qcom,hdmi-tx-8960", .data = &hdmi_tx_8960_config },
440 	{ .compatible = "qcom,hdmi-tx-8660", .data = &hdmi_tx_8960_config },
441 	{}
442 };
443 
444 static struct platform_driver msm_hdmi_driver = {
445 	.probe = msm_hdmi_dev_probe,
446 	.remove = msm_hdmi_dev_remove,
447 	.driver = {
448 		.name = "hdmi_msm",
449 		.of_match_table = msm_hdmi_dt_match,
450 		.pm = &msm_hdmi_pm_ops,
451 	},
452 };
453 
454 void __init msm_hdmi_register(void)
455 {
456 	msm_hdmi_phy_driver_register();
457 	platform_driver_register(&msm_hdmi_driver);
458 }
459 
460 void __exit msm_hdmi_unregister(void)
461 {
462 	platform_driver_unregister(&msm_hdmi_driver);
463 	msm_hdmi_phy_driver_unregister();
464 }
465