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