Lines Matching +full:hdmi +full:- +full:bridge
1 // SPDX-License-Identifier: GPL-2.0-only
11 #include <sound/hdmi-codec.h>
12 #include "hdmi.h"
14 void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on) in msm_hdmi_set_mode() argument
19 spin_lock_irqsave(&hdmi->reg_lock, flags); in msm_hdmi_set_mode()
22 if (!hdmi->hdmi_mode) { in msm_hdmi_set_mode()
24 hdmi_write(hdmi, REG_HDMI_CTRL, ctrl); in msm_hdmi_set_mode()
33 hdmi_write(hdmi, REG_HDMI_CTRL, ctrl); in msm_hdmi_set_mode()
34 spin_unlock_irqrestore(&hdmi->reg_lock, flags); in msm_hdmi_set_mode()
35 DBG("HDMI Core: %s, HDMI_CTRL=0x%08x", in msm_hdmi_set_mode()
41 struct hdmi *hdmi = dev_id; in msm_hdmi_irq() local
44 msm_hdmi_connector_irq(hdmi->connector); in msm_hdmi_irq()
47 msm_hdmi_i2c_irq(hdmi->i2c); in msm_hdmi_irq()
50 if (hdmi->hdcp_ctrl) in msm_hdmi_irq()
51 msm_hdmi_hdcp_irq(hdmi->hdcp_ctrl); in msm_hdmi_irq()
58 static void msm_hdmi_destroy(struct hdmi *hdmi) in msm_hdmi_destroy() argument
64 if (hdmi->workq) { in msm_hdmi_destroy()
65 flush_workqueue(hdmi->workq); in msm_hdmi_destroy()
66 destroy_workqueue(hdmi->workq); in msm_hdmi_destroy()
68 msm_hdmi_hdcp_destroy(hdmi); in msm_hdmi_destroy()
70 if (hdmi->phy_dev) { in msm_hdmi_destroy()
71 put_device(hdmi->phy_dev); in msm_hdmi_destroy()
72 hdmi->phy = NULL; in msm_hdmi_destroy()
73 hdmi->phy_dev = NULL; in msm_hdmi_destroy()
76 if (hdmi->i2c) in msm_hdmi_destroy()
77 msm_hdmi_i2c_destroy(hdmi->i2c); in msm_hdmi_destroy()
79 platform_set_drvdata(hdmi->pdev, NULL); in msm_hdmi_destroy()
82 static int msm_hdmi_get_phy(struct hdmi *hdmi) in msm_hdmi_get_phy() argument
84 struct platform_device *pdev = hdmi->pdev; in msm_hdmi_get_phy()
88 phy_node = of_parse_phandle(pdev->dev.of_node, "phys", 0); in msm_hdmi_get_phy()
90 DRM_DEV_ERROR(&pdev->dev, "cannot find phy device\n"); in msm_hdmi_get_phy()
91 return -ENXIO; in msm_hdmi_get_phy()
96 hdmi->phy = platform_get_drvdata(phy_pdev); in msm_hdmi_get_phy()
100 if (!phy_pdev || !hdmi->phy) { in msm_hdmi_get_phy()
101 DRM_DEV_ERROR(&pdev->dev, "phy driver is not ready\n"); in msm_hdmi_get_phy()
102 return -EPROBE_DEFER; in msm_hdmi_get_phy()
105 hdmi->phy_dev = get_device(&phy_pdev->dev); in msm_hdmi_get_phy()
110 /* construct hdmi at bind/probe time, grab all the resources. If
114 static struct hdmi *msm_hdmi_init(struct platform_device *pdev) in msm_hdmi_init()
116 struct hdmi_platform_config *config = pdev->dev.platform_data; in msm_hdmi_init()
117 struct hdmi *hdmi = NULL; in msm_hdmi_init() local
121 hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); in msm_hdmi_init()
122 if (!hdmi) { in msm_hdmi_init()
123 ret = -ENOMEM; in msm_hdmi_init()
127 hdmi->pdev = pdev; in msm_hdmi_init()
128 hdmi->config = config; in msm_hdmi_init()
129 spin_lock_init(&hdmi->reg_lock); in msm_hdmi_init()
131 hdmi->mmio = msm_ioremap(pdev, config->mmio_name, "HDMI"); in msm_hdmi_init()
132 if (IS_ERR(hdmi->mmio)) { in msm_hdmi_init()
133 ret = PTR_ERR(hdmi->mmio); in msm_hdmi_init()
137 /* HDCP needs physical address of hdmi register */ in msm_hdmi_init()
139 config->mmio_name); in msm_hdmi_init()
140 hdmi->mmio_phy_addr = res->start; in msm_hdmi_init()
142 hdmi->qfprom_mmio = msm_ioremap(pdev, in msm_hdmi_init()
143 config->qfprom_mmio_name, "HDMI_QFPROM"); in msm_hdmi_init()
144 if (IS_ERR(hdmi->qfprom_mmio)) { in msm_hdmi_init()
145 DRM_DEV_INFO(&pdev->dev, "can't find qfprom resource\n"); in msm_hdmi_init()
146 hdmi->qfprom_mmio = NULL; in msm_hdmi_init()
149 hdmi->hpd_regs = devm_kcalloc(&pdev->dev, in msm_hdmi_init()
150 config->hpd_reg_cnt, in msm_hdmi_init()
151 sizeof(hdmi->hpd_regs[0]), in msm_hdmi_init()
153 if (!hdmi->hpd_regs) { in msm_hdmi_init()
154 ret = -ENOMEM; in msm_hdmi_init()
157 for (i = 0; i < config->hpd_reg_cnt; i++) { in msm_hdmi_init()
160 reg = devm_regulator_get(&pdev->dev, in msm_hdmi_init()
161 config->hpd_reg_names[i]); in msm_hdmi_init()
164 DRM_DEV_ERROR(&pdev->dev, "failed to get hpd regulator: %s (%d)\n", in msm_hdmi_init()
165 config->hpd_reg_names[i], ret); in msm_hdmi_init()
169 hdmi->hpd_regs[i] = reg; in msm_hdmi_init()
172 hdmi->pwr_regs = devm_kcalloc(&pdev->dev, in msm_hdmi_init()
173 config->pwr_reg_cnt, in msm_hdmi_init()
174 sizeof(hdmi->pwr_regs[0]), in msm_hdmi_init()
176 if (!hdmi->pwr_regs) { in msm_hdmi_init()
177 ret = -ENOMEM; in msm_hdmi_init()
180 for (i = 0; i < config->pwr_reg_cnt; i++) { in msm_hdmi_init()
183 reg = devm_regulator_get(&pdev->dev, in msm_hdmi_init()
184 config->pwr_reg_names[i]); in msm_hdmi_init()
187 DRM_DEV_ERROR(&pdev->dev, "failed to get pwr regulator: %s (%d)\n", in msm_hdmi_init()
188 config->pwr_reg_names[i], ret); in msm_hdmi_init()
192 hdmi->pwr_regs[i] = reg; in msm_hdmi_init()
195 hdmi->hpd_clks = devm_kcalloc(&pdev->dev, in msm_hdmi_init()
196 config->hpd_clk_cnt, in msm_hdmi_init()
197 sizeof(hdmi->hpd_clks[0]), in msm_hdmi_init()
199 if (!hdmi->hpd_clks) { in msm_hdmi_init()
200 ret = -ENOMEM; in msm_hdmi_init()
203 for (i = 0; i < config->hpd_clk_cnt; i++) { in msm_hdmi_init()
206 clk = msm_clk_get(pdev, config->hpd_clk_names[i]); in msm_hdmi_init()
209 DRM_DEV_ERROR(&pdev->dev, "failed to get hpd clk: %s (%d)\n", in msm_hdmi_init()
210 config->hpd_clk_names[i], ret); in msm_hdmi_init()
214 hdmi->hpd_clks[i] = clk; in msm_hdmi_init()
217 hdmi->pwr_clks = devm_kcalloc(&pdev->dev, in msm_hdmi_init()
218 config->pwr_clk_cnt, in msm_hdmi_init()
219 sizeof(hdmi->pwr_clks[0]), in msm_hdmi_init()
221 if (!hdmi->pwr_clks) { in msm_hdmi_init()
222 ret = -ENOMEM; in msm_hdmi_init()
225 for (i = 0; i < config->pwr_clk_cnt; i++) { in msm_hdmi_init()
228 clk = msm_clk_get(pdev, config->pwr_clk_names[i]); in msm_hdmi_init()
231 DRM_DEV_ERROR(&pdev->dev, "failed to get pwr clk: %s (%d)\n", in msm_hdmi_init()
232 config->pwr_clk_names[i], ret); in msm_hdmi_init()
236 hdmi->pwr_clks[i] = clk; in msm_hdmi_init()
239 pm_runtime_enable(&pdev->dev); in msm_hdmi_init()
241 hdmi->workq = alloc_ordered_workqueue("msm_hdmi", 0); in msm_hdmi_init()
243 hdmi->i2c = msm_hdmi_i2c_init(hdmi); in msm_hdmi_init()
244 if (IS_ERR(hdmi->i2c)) { in msm_hdmi_init()
245 ret = PTR_ERR(hdmi->i2c); in msm_hdmi_init()
246 DRM_DEV_ERROR(&pdev->dev, "failed to get i2c: %d\n", ret); in msm_hdmi_init()
247 hdmi->i2c = NULL; in msm_hdmi_init()
251 ret = msm_hdmi_get_phy(hdmi); in msm_hdmi_init()
253 DRM_DEV_ERROR(&pdev->dev, "failed to get phy\n"); in msm_hdmi_init()
257 hdmi->hdcp_ctrl = msm_hdmi_hdcp_init(hdmi); in msm_hdmi_init()
258 if (IS_ERR(hdmi->hdcp_ctrl)) { in msm_hdmi_init()
259 dev_warn(&pdev->dev, "failed to init hdcp: disabled\n"); in msm_hdmi_init()
260 hdmi->hdcp_ctrl = NULL; in msm_hdmi_init()
263 return hdmi; in msm_hdmi_init()
266 if (hdmi) in msm_hdmi_init()
267 msm_hdmi_destroy(hdmi); in msm_hdmi_init()
274 * driver (not hdmi sub-device's probe/bind!)
278 * hdmi sub-device's probe.
280 int msm_hdmi_modeset_init(struct hdmi *hdmi, in msm_hdmi_modeset_init() argument
283 struct msm_drm_private *priv = dev->dev_private; in msm_hdmi_modeset_init()
284 struct platform_device *pdev = hdmi->pdev; in msm_hdmi_modeset_init()
287 hdmi->dev = dev; in msm_hdmi_modeset_init()
288 hdmi->encoder = encoder; in msm_hdmi_modeset_init()
290 hdmi_audio_infoframe_init(&hdmi->audio.infoframe); in msm_hdmi_modeset_init()
292 hdmi->bridge = msm_hdmi_bridge_init(hdmi); in msm_hdmi_modeset_init()
293 if (IS_ERR(hdmi->bridge)) { in msm_hdmi_modeset_init()
294 ret = PTR_ERR(hdmi->bridge); in msm_hdmi_modeset_init()
295 DRM_DEV_ERROR(dev->dev, "failed to create HDMI bridge: %d\n", ret); in msm_hdmi_modeset_init()
296 hdmi->bridge = NULL; in msm_hdmi_modeset_init()
300 hdmi->connector = msm_hdmi_connector_init(hdmi); in msm_hdmi_modeset_init()
301 if (IS_ERR(hdmi->connector)) { in msm_hdmi_modeset_init()
302 ret = PTR_ERR(hdmi->connector); in msm_hdmi_modeset_init()
303 DRM_DEV_ERROR(dev->dev, "failed to create HDMI connector: %d\n", ret); in msm_hdmi_modeset_init()
304 hdmi->connector = NULL; in msm_hdmi_modeset_init()
308 hdmi->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); in msm_hdmi_modeset_init()
309 if (hdmi->irq < 0) { in msm_hdmi_modeset_init()
310 ret = hdmi->irq; in msm_hdmi_modeset_init()
311 DRM_DEV_ERROR(dev->dev, "failed to get irq: %d\n", ret); in msm_hdmi_modeset_init()
315 ret = devm_request_irq(&pdev->dev, hdmi->irq, in msm_hdmi_modeset_init()
317 "hdmi_isr", hdmi); in msm_hdmi_modeset_init()
319 DRM_DEV_ERROR(dev->dev, "failed to request IRQ%u: %d\n", in msm_hdmi_modeset_init()
320 hdmi->irq, ret); in msm_hdmi_modeset_init()
324 ret = msm_hdmi_hpd_enable(hdmi->connector); in msm_hdmi_modeset_init()
326 DRM_DEV_ERROR(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret); in msm_hdmi_modeset_init()
330 priv->bridges[priv->num_bridges++] = hdmi->bridge; in msm_hdmi_modeset_init()
331 priv->connectors[priv->num_connectors++] = hdmi->connector; in msm_hdmi_modeset_init()
333 platform_set_drvdata(pdev, hdmi); in msm_hdmi_modeset_init()
338 /* bridge is normally destroyed by drm: */ in msm_hdmi_modeset_init()
339 if (hdmi->bridge) { in msm_hdmi_modeset_init()
340 msm_hdmi_bridge_destroy(hdmi->bridge); in msm_hdmi_modeset_init()
341 hdmi->bridge = NULL; in msm_hdmi_modeset_init()
343 if (hdmi->connector) { in msm_hdmi_modeset_init()
344 hdmi->connector->funcs->destroy(hdmi->connector); in msm_hdmi_modeset_init()
345 hdmi->connector = NULL; in msm_hdmi_modeset_init()
352 * The hdmi device:
364 static const char *hpd_reg_names_8960[] = {"core-vdda", "hdmi-mux"};
372 static const char *pwr_reg_names_8x74[] = {"core-vdda", "core-vcc"};
373 static const char *hpd_reg_names_8x74[] = {"hpd-gdsc", "hpd-5v"};
386 static const char *hpd_reg_names_8084[] = {"hpd-gdsc", "hpd-5v", "hpd-5v-en"};
418 { "qcom,hdmi-tx-ddc-clk", true, 1, "HDMI_DDC_CLK" },
419 { "qcom,hdmi-tx-ddc-data", true, 1, "HDMI_DDC_DATA" },
420 { "qcom,hdmi-tx-hpd", false, 1, "HDMI_HPD" },
421 { "qcom,hdmi-tx-mux-en", true, 1, "HDMI_MUX_EN" },
422 { "qcom,hdmi-tx-mux-sel", true, 0, "HDMI_MUX_SEL" },
423 { "qcom,hdmi-tx-mux-lpm", true, 1, "HDMI_MUX_LPM" },
427 * HDMI audio codec callbacks
433 struct hdmi *hdmi = dev_get_drvdata(dev); in msm_hdmi_audio_hw_params() local
440 DRM_DEV_DEBUG(dev, "%u Hz, %d bit, %d channels\n", params->sample_rate, in msm_hdmi_audio_hw_params()
441 params->sample_width, params->cea.channels); in msm_hdmi_audio_hw_params()
443 switch (params->cea.channels) { in msm_hdmi_audio_hw_params()
465 return -EINVAL; in msm_hdmi_audio_hw_params()
468 switch (params->sample_rate) { in msm_hdmi_audio_hw_params()
492 params->sample_rate); in msm_hdmi_audio_hw_params()
493 return -EINVAL; in msm_hdmi_audio_hw_params()
496 msm_hdmi_audio_set_sample_rate(hdmi, rate); in msm_hdmi_audio_hw_params()
497 msm_hdmi_audio_info_setup(hdmi, 1, chan, channel_allocation, in msm_hdmi_audio_hw_params()
505 struct hdmi *hdmi = dev_get_drvdata(dev); in msm_hdmi_audio_shutdown() local
507 msm_hdmi_audio_info_setup(hdmi, 0, 0, 0, 0, 0); in msm_hdmi_audio_shutdown()
521 static int msm_hdmi_register_audio_driver(struct hdmi *hdmi, struct device *dev) in msm_hdmi_register_audio_driver() argument
523 hdmi->audio_pdev = platform_device_register_data(dev, in msm_hdmi_register_audio_driver()
528 return PTR_ERR_OR_ZERO(hdmi->audio_pdev); in msm_hdmi_register_audio_driver()
534 struct msm_drm_private *priv = drm->dev_private; in msm_hdmi_bind()
536 struct hdmi *hdmi; in msm_hdmi_bind() local
537 struct device_node *of_node = dev->of_node; in msm_hdmi_bind()
544 return -ENXIO; in msm_hdmi_bind()
547 hdmi_cfg->mmio_name = "core_physical"; in msm_hdmi_bind()
548 hdmi_cfg->qfprom_mmio_name = "qfprom_physical"; in msm_hdmi_bind()
557 * the power-on default value will be kept. in msm_hdmi_bind()
560 /* This will catch e.g. -PROBE_DEFER */ in msm_hdmi_bind()
568 * Try again after stripping out the "qcom,hdmi-tx" in msm_hdmi_bind()
569 * prefix. This is mainly to match "hpd-gpios" used in msm_hdmi_bind()
572 if (sscanf(name, "qcom,hdmi-tx-%s", name3)) in msm_hdmi_bind()
579 hdmi_cfg->gpios[i].gpiod = gpiod; in msm_hdmi_bind()
582 hdmi_cfg->gpios[i].output = msm_hdmi_gpio_pdata[i].output; in msm_hdmi_bind()
583 hdmi_cfg->gpios[i].value = msm_hdmi_gpio_pdata[i].value; in msm_hdmi_bind()
586 dev->platform_data = hdmi_cfg; in msm_hdmi_bind()
588 hdmi = msm_hdmi_init(to_platform_device(dev)); in msm_hdmi_bind()
589 if (IS_ERR(hdmi)) in msm_hdmi_bind()
590 return PTR_ERR(hdmi); in msm_hdmi_bind()
591 priv->hdmi = hdmi; in msm_hdmi_bind()
593 err = msm_hdmi_register_audio_driver(hdmi, dev); in msm_hdmi_bind()
596 hdmi->audio_pdev = NULL; in msm_hdmi_bind()
606 struct msm_drm_private *priv = drm->dev_private; in msm_hdmi_unbind()
607 if (priv->hdmi) { in msm_hdmi_unbind()
608 if (priv->hdmi->audio_pdev) in msm_hdmi_unbind()
609 platform_device_unregister(priv->hdmi->audio_pdev); in msm_hdmi_unbind()
611 msm_hdmi_destroy(priv->hdmi); in msm_hdmi_unbind()
612 priv->hdmi = NULL; in msm_hdmi_unbind()
623 return component_add(&pdev->dev, &msm_hdmi_ops); in msm_hdmi_dev_probe()
628 component_del(&pdev->dev, &msm_hdmi_ops); in msm_hdmi_dev_remove()
633 { .compatible = "qcom,hdmi-tx-8996", .data = &hdmi_tx_8996_config },
634 { .compatible = "qcom,hdmi-tx-8994", .data = &hdmi_tx_8994_config },
635 { .compatible = "qcom,hdmi-tx-8084", .data = &hdmi_tx_8084_config },
636 { .compatible = "qcom,hdmi-tx-8974", .data = &hdmi_tx_8974_config },
637 { .compatible = "qcom,hdmi-tx-8960", .data = &hdmi_tx_8960_config },
638 { .compatible = "qcom,hdmi-tx-8660", .data = &hdmi_tx_8660_config },