1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2014 The Linux Foundation. All rights reserved.
4 * Copyright (C) 2013 Red Hat
5 * Author: Rob Clark <robdclark@gmail.com>
8 #include <linux/of_irq.h>
9 #include <linux/of_gpio.h>
11 #include <sound/hdmi-codec.h>
14 void msm_hdmi_set_mode(struct hdmi
*hdmi
, bool power_on
)
19 spin_lock_irqsave(&hdmi
->reg_lock
, flags
);
21 ctrl
|= HDMI_CTRL_ENABLE
;
22 if (!hdmi
->hdmi_mode
) {
23 ctrl
|= HDMI_CTRL_HDMI
;
24 hdmi_write(hdmi
, REG_HDMI_CTRL
, ctrl
);
25 ctrl
&= ~HDMI_CTRL_HDMI
;
27 ctrl
|= HDMI_CTRL_HDMI
;
30 ctrl
= HDMI_CTRL_HDMI
;
33 hdmi_write(hdmi
, REG_HDMI_CTRL
, ctrl
);
34 spin_unlock_irqrestore(&hdmi
->reg_lock
, flags
);
35 DBG("HDMI Core: %s, HDMI_CTRL=0x%08x",
36 power_on
? "Enable" : "Disable", ctrl
);
39 static irqreturn_t
msm_hdmi_irq(int irq
, void *dev_id
)
41 struct hdmi
*hdmi
= dev_id
;
44 msm_hdmi_connector_irq(hdmi
->connector
);
47 msm_hdmi_i2c_irq(hdmi
->i2c
);
51 msm_hdmi_hdcp_irq(hdmi
->hdcp_ctrl
);
58 static void msm_hdmi_destroy(struct hdmi
*hdmi
)
61 * at this point, hpd has been disabled,
62 * after flush workq, it's safe to deinit hdcp
65 flush_workqueue(hdmi
->workq
);
66 destroy_workqueue(hdmi
->workq
);
68 msm_hdmi_hdcp_destroy(hdmi
);
71 put_device(hdmi
->phy_dev
);
77 msm_hdmi_i2c_destroy(hdmi
->i2c
);
79 platform_set_drvdata(hdmi
->pdev
, NULL
);
82 static int msm_hdmi_get_phy(struct hdmi
*hdmi
)
84 struct platform_device
*pdev
= hdmi
->pdev
;
85 struct platform_device
*phy_pdev
;
86 struct device_node
*phy_node
;
88 phy_node
= of_parse_phandle(pdev
->dev
.of_node
, "phys", 0);
90 DRM_DEV_ERROR(&pdev
->dev
, "cannot find phy device\n");
94 phy_pdev
= of_find_device_by_node(phy_node
);
96 hdmi
->phy
= platform_get_drvdata(phy_pdev
);
98 of_node_put(phy_node
);
100 if (!phy_pdev
|| !hdmi
->phy
) {
101 DRM_DEV_ERROR(&pdev
->dev
, "phy driver is not ready\n");
102 return -EPROBE_DEFER
;
105 hdmi
->phy_dev
= get_device(&phy_pdev
->dev
);
110 /* construct hdmi at bind/probe time, grab all the resources. If
111 * we are to EPROBE_DEFER we want to do it here, rather than later
112 * at modeset_init() time
114 static struct hdmi
*msm_hdmi_init(struct platform_device
*pdev
)
116 struct hdmi_platform_config
*config
= pdev
->dev
.platform_data
;
117 struct hdmi
*hdmi
= NULL
;
118 struct resource
*res
;
121 hdmi
= devm_kzalloc(&pdev
->dev
, sizeof(*hdmi
), GFP_KERNEL
);
128 hdmi
->config
= config
;
129 spin_lock_init(&hdmi
->reg_lock
);
131 hdmi
->mmio
= msm_ioremap(pdev
, config
->mmio_name
, "HDMI");
132 if (IS_ERR(hdmi
->mmio
)) {
133 ret
= PTR_ERR(hdmi
->mmio
);
137 /* HDCP needs physical address of hdmi register */
138 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
,
140 hdmi
->mmio_phy_addr
= res
->start
;
142 hdmi
->qfprom_mmio
= msm_ioremap(pdev
,
143 config
->qfprom_mmio_name
, "HDMI_QFPROM");
144 if (IS_ERR(hdmi
->qfprom_mmio
)) {
145 DRM_DEV_INFO(&pdev
->dev
, "can't find qfprom resource\n");
146 hdmi
->qfprom_mmio
= NULL
;
149 hdmi
->hpd_regs
= devm_kcalloc(&pdev
->dev
,
151 sizeof(hdmi
->hpd_regs
[0]),
153 if (!hdmi
->hpd_regs
) {
157 for (i
= 0; i
< config
->hpd_reg_cnt
; i
++) {
158 struct regulator
*reg
;
160 reg
= devm_regulator_get(&pdev
->dev
,
161 config
->hpd_reg_names
[i
]);
164 DRM_DEV_ERROR(&pdev
->dev
, "failed to get hpd regulator: %s (%d)\n",
165 config
->hpd_reg_names
[i
], ret
);
169 hdmi
->hpd_regs
[i
] = reg
;
172 hdmi
->pwr_regs
= devm_kcalloc(&pdev
->dev
,
174 sizeof(hdmi
->pwr_regs
[0]),
176 if (!hdmi
->pwr_regs
) {
180 for (i
= 0; i
< config
->pwr_reg_cnt
; i
++) {
181 struct regulator
*reg
;
183 reg
= devm_regulator_get(&pdev
->dev
,
184 config
->pwr_reg_names
[i
]);
187 DRM_DEV_ERROR(&pdev
->dev
, "failed to get pwr regulator: %s (%d)\n",
188 config
->pwr_reg_names
[i
], ret
);
192 hdmi
->pwr_regs
[i
] = reg
;
195 hdmi
->hpd_clks
= devm_kcalloc(&pdev
->dev
,
197 sizeof(hdmi
->hpd_clks
[0]),
199 if (!hdmi
->hpd_clks
) {
203 for (i
= 0; i
< config
->hpd_clk_cnt
; i
++) {
206 clk
= msm_clk_get(pdev
, config
->hpd_clk_names
[i
]);
209 DRM_DEV_ERROR(&pdev
->dev
, "failed to get hpd clk: %s (%d)\n",
210 config
->hpd_clk_names
[i
], ret
);
214 hdmi
->hpd_clks
[i
] = clk
;
217 hdmi
->pwr_clks
= devm_kcalloc(&pdev
->dev
,
219 sizeof(hdmi
->pwr_clks
[0]),
221 if (!hdmi
->pwr_clks
) {
225 for (i
= 0; i
< config
->pwr_clk_cnt
; i
++) {
228 clk
= msm_clk_get(pdev
, config
->pwr_clk_names
[i
]);
231 DRM_DEV_ERROR(&pdev
->dev
, "failed to get pwr clk: %s (%d)\n",
232 config
->pwr_clk_names
[i
], ret
);
236 hdmi
->pwr_clks
[i
] = clk
;
239 pm_runtime_enable(&pdev
->dev
);
241 hdmi
->workq
= alloc_ordered_workqueue("msm_hdmi", 0);
243 hdmi
->i2c
= msm_hdmi_i2c_init(hdmi
);
244 if (IS_ERR(hdmi
->i2c
)) {
245 ret
= PTR_ERR(hdmi
->i2c
);
246 DRM_DEV_ERROR(&pdev
->dev
, "failed to get i2c: %d\n", ret
);
251 ret
= msm_hdmi_get_phy(hdmi
);
253 DRM_DEV_ERROR(&pdev
->dev
, "failed to get phy\n");
257 hdmi
->hdcp_ctrl
= msm_hdmi_hdcp_init(hdmi
);
258 if (IS_ERR(hdmi
->hdcp_ctrl
)) {
259 dev_warn(&pdev
->dev
, "failed to init hdcp: disabled\n");
260 hdmi
->hdcp_ctrl
= NULL
;
267 msm_hdmi_destroy(hdmi
);
272 /* Second part of initialization, the drm/kms level modeset_init,
273 * constructs/initializes mode objects, etc, is called from master
274 * driver (not hdmi sub-device's probe/bind!)
276 * Any resource (regulator/clk/etc) which could be missing at boot
277 * should be handled in msm_hdmi_init() so that failure happens from
278 * hdmi sub-device's probe.
280 int msm_hdmi_modeset_init(struct hdmi
*hdmi
,
281 struct drm_device
*dev
, struct drm_encoder
*encoder
)
283 struct msm_drm_private
*priv
= dev
->dev_private
;
284 struct platform_device
*pdev
= hdmi
->pdev
;
288 hdmi
->encoder
= encoder
;
290 hdmi_audio_infoframe_init(&hdmi
->audio
.infoframe
);
292 hdmi
->bridge
= msm_hdmi_bridge_init(hdmi
);
293 if (IS_ERR(hdmi
->bridge
)) {
294 ret
= PTR_ERR(hdmi
->bridge
);
295 DRM_DEV_ERROR(dev
->dev
, "failed to create HDMI bridge: %d\n", ret
);
300 hdmi
->connector
= msm_hdmi_connector_init(hdmi
);
301 if (IS_ERR(hdmi
->connector
)) {
302 ret
= PTR_ERR(hdmi
->connector
);
303 DRM_DEV_ERROR(dev
->dev
, "failed to create HDMI connector: %d\n", ret
);
304 hdmi
->connector
= NULL
;
308 hdmi
->irq
= irq_of_parse_and_map(pdev
->dev
.of_node
, 0);
311 DRM_DEV_ERROR(dev
->dev
, "failed to get irq: %d\n", ret
);
315 ret
= devm_request_irq(&pdev
->dev
, hdmi
->irq
,
316 msm_hdmi_irq
, IRQF_TRIGGER_HIGH
| IRQF_ONESHOT
,
319 DRM_DEV_ERROR(dev
->dev
, "failed to request IRQ%u: %d\n",
324 ret
= msm_hdmi_hpd_enable(hdmi
->connector
);
326 DRM_DEV_ERROR(&hdmi
->pdev
->dev
, "failed to enable HPD: %d\n", ret
);
330 ret
= drm_bridge_attach(encoder
, hdmi
->bridge
, NULL
);
334 priv
->bridges
[priv
->num_bridges
++] = hdmi
->bridge
;
335 priv
->connectors
[priv
->num_connectors
++] = hdmi
->connector
;
337 platform_set_drvdata(pdev
, hdmi
);
342 /* bridge is normally destroyed by drm: */
344 msm_hdmi_bridge_destroy(hdmi
->bridge
);
347 if (hdmi
->connector
) {
348 hdmi
->connector
->funcs
->destroy(hdmi
->connector
);
349 hdmi
->connector
= NULL
;
359 #define HDMI_CFG(item, entry) \
360 .item ## _names = item ##_names_ ## entry, \
361 .item ## _cnt = ARRAY_SIZE(item ## _names_ ## entry)
363 static const char *pwr_reg_names_none
[] = {};
364 static const char *hpd_reg_names_none
[] = {};
366 static struct hdmi_platform_config hdmi_tx_8660_config
;
368 static const char *hpd_reg_names_8960
[] = {"core-vdda", "hdmi-mux"};
369 static const char *hpd_clk_names_8960
[] = {"core", "master_iface", "slave_iface"};
371 static struct hdmi_platform_config hdmi_tx_8960_config
= {
372 HDMI_CFG(hpd_reg
, 8960),
373 HDMI_CFG(hpd_clk
, 8960),
376 static const char *pwr_reg_names_8x74
[] = {"core-vdda", "core-vcc"};
377 static const char *hpd_reg_names_8x74
[] = {"hpd-gdsc", "hpd-5v"};
378 static const char *pwr_clk_names_8x74
[] = {"extp", "alt_iface"};
379 static const char *hpd_clk_names_8x74
[] = {"iface", "core", "mdp_core"};
380 static unsigned long hpd_clk_freq_8x74
[] = {0, 19200000, 0};
382 static struct hdmi_platform_config hdmi_tx_8974_config
= {
383 HDMI_CFG(pwr_reg
, 8x74
),
384 HDMI_CFG(hpd_reg
, 8x74
),
385 HDMI_CFG(pwr_clk
, 8x74
),
386 HDMI_CFG(hpd_clk
, 8x74
),
387 .hpd_freq
= hpd_clk_freq_8x74
,
390 static const char *hpd_reg_names_8084
[] = {"hpd-gdsc", "hpd-5v", "hpd-5v-en"};
392 static struct hdmi_platform_config hdmi_tx_8084_config
= {
393 HDMI_CFG(pwr_reg
, 8x74
),
394 HDMI_CFG(hpd_reg
, 8084),
395 HDMI_CFG(pwr_clk
, 8x74
),
396 HDMI_CFG(hpd_clk
, 8x74
),
397 .hpd_freq
= hpd_clk_freq_8x74
,
400 static struct hdmi_platform_config hdmi_tx_8994_config
= {
401 HDMI_CFG(pwr_reg
, 8x74
),
402 HDMI_CFG(hpd_reg
, none
),
403 HDMI_CFG(pwr_clk
, 8x74
),
404 HDMI_CFG(hpd_clk
, 8x74
),
405 .hpd_freq
= hpd_clk_freq_8x74
,
408 static struct hdmi_platform_config hdmi_tx_8996_config
= {
409 HDMI_CFG(pwr_reg
, none
),
410 HDMI_CFG(hpd_reg
, none
),
411 HDMI_CFG(pwr_clk
, 8x74
),
412 HDMI_CFG(hpd_clk
, 8x74
),
413 .hpd_freq
= hpd_clk_freq_8x74
,
416 static const struct {
421 } msm_hdmi_gpio_pdata
[] = {
422 { "qcom,hdmi-tx-ddc-clk", true, 1, "HDMI_DDC_CLK" },
423 { "qcom,hdmi-tx-ddc-data", true, 1, "HDMI_DDC_DATA" },
424 { "qcom,hdmi-tx-hpd", false, 1, "HDMI_HPD" },
425 { "qcom,hdmi-tx-mux-en", true, 1, "HDMI_MUX_EN" },
426 { "qcom,hdmi-tx-mux-sel", true, 0, "HDMI_MUX_SEL" },
427 { "qcom,hdmi-tx-mux-lpm", true, 1, "HDMI_MUX_LPM" },
431 * HDMI audio codec callbacks
433 static int msm_hdmi_audio_hw_params(struct device
*dev
, void *data
,
434 struct hdmi_codec_daifmt
*daifmt
,
435 struct hdmi_codec_params
*params
)
437 struct hdmi
*hdmi
= dev_get_drvdata(dev
);
439 unsigned int channel_allocation
= 0;
441 unsigned int level_shift
= 0; /* 0dB */
442 bool down_mix
= false;
444 DRM_DEV_DEBUG(dev
, "%u Hz, %d bit, %d channels\n", params
->sample_rate
,
445 params
->sample_width
, params
->cea
.channels
);
447 switch (params
->cea
.channels
) {
449 /* FR and FL speakers */
450 channel_allocation
= 0;
451 chan
= MSM_HDMI_AUDIO_CHANNEL_2
;
454 /* FC, LFE, FR and FL speakers */
455 channel_allocation
= 0x3;
456 chan
= MSM_HDMI_AUDIO_CHANNEL_4
;
459 /* RR, RL, FC, LFE, FR and FL speakers */
460 channel_allocation
= 0x0B;
461 chan
= MSM_HDMI_AUDIO_CHANNEL_6
;
464 /* FRC, FLC, RR, RL, FC, LFE, FR and FL speakers */
465 channel_allocation
= 0x1F;
466 chan
= MSM_HDMI_AUDIO_CHANNEL_8
;
472 switch (params
->sample_rate
) {
474 rate
= HDMI_SAMPLE_RATE_32KHZ
;
477 rate
= HDMI_SAMPLE_RATE_44_1KHZ
;
480 rate
= HDMI_SAMPLE_RATE_48KHZ
;
483 rate
= HDMI_SAMPLE_RATE_88_2KHZ
;
486 rate
= HDMI_SAMPLE_RATE_96KHZ
;
489 rate
= HDMI_SAMPLE_RATE_176_4KHZ
;
492 rate
= HDMI_SAMPLE_RATE_192KHZ
;
495 DRM_DEV_ERROR(dev
, "rate[%d] not supported!\n",
496 params
->sample_rate
);
500 msm_hdmi_audio_set_sample_rate(hdmi
, rate
);
501 msm_hdmi_audio_info_setup(hdmi
, 1, chan
, channel_allocation
,
502 level_shift
, down_mix
);
507 static void msm_hdmi_audio_shutdown(struct device
*dev
, void *data
)
509 struct hdmi
*hdmi
= dev_get_drvdata(dev
);
511 msm_hdmi_audio_info_setup(hdmi
, 0, 0, 0, 0, 0);
514 static const struct hdmi_codec_ops msm_hdmi_audio_codec_ops
= {
515 .hw_params
= msm_hdmi_audio_hw_params
,
516 .audio_shutdown
= msm_hdmi_audio_shutdown
,
519 static struct hdmi_codec_pdata codec_data
= {
520 .ops
= &msm_hdmi_audio_codec_ops
,
521 .max_i2s_channels
= 8,
525 static int msm_hdmi_register_audio_driver(struct hdmi
*hdmi
, struct device
*dev
)
527 hdmi
->audio_pdev
= platform_device_register_data(dev
,
532 return PTR_ERR_OR_ZERO(hdmi
->audio_pdev
);
535 static int msm_hdmi_bind(struct device
*dev
, struct device
*master
, void *data
)
537 struct drm_device
*drm
= dev_get_drvdata(master
);
538 struct msm_drm_private
*priv
= drm
->dev_private
;
539 struct hdmi_platform_config
*hdmi_cfg
;
541 struct device_node
*of_node
= dev
->of_node
;
544 hdmi_cfg
= (struct hdmi_platform_config
*)
545 of_device_get_match_data(dev
);
547 DRM_DEV_ERROR(dev
, "unknown hdmi_cfg: %pOFn\n", of_node
);
551 hdmi_cfg
->mmio_name
= "core_physical";
552 hdmi_cfg
->qfprom_mmio_name
= "qfprom_physical";
554 for (i
= 0; i
< HDMI_MAX_NUM_GPIO
; i
++) {
555 const char *name
= msm_hdmi_gpio_pdata
[i
].name
;
556 struct gpio_desc
*gpiod
;
559 * We are fetching the GPIO lines "as is" since the connector
560 * code is enabling and disabling the lines. Until that point
561 * the power-on default value will be kept.
563 gpiod
= devm_gpiod_get_optional(dev
, name
, GPIOD_ASIS
);
564 /* This will catch e.g. -PROBE_DEFER */
566 return PTR_ERR(gpiod
);
568 /* Try a second time, stripping down the name */
572 * Try again after stripping out the "qcom,hdmi-tx"
573 * prefix. This is mainly to match "hpd-gpios" used
574 * in the upstream bindings.
576 if (sscanf(name
, "qcom,hdmi-tx-%s", name3
))
577 gpiod
= devm_gpiod_get_optional(dev
, name3
, GPIOD_ASIS
);
579 return PTR_ERR(gpiod
);
581 DBG("failed to get gpio: %s", name
);
583 hdmi_cfg
->gpios
[i
].gpiod
= gpiod
;
585 gpiod_set_consumer_name(gpiod
, msm_hdmi_gpio_pdata
[i
].label
);
586 hdmi_cfg
->gpios
[i
].output
= msm_hdmi_gpio_pdata
[i
].output
;
587 hdmi_cfg
->gpios
[i
].value
= msm_hdmi_gpio_pdata
[i
].value
;
590 dev
->platform_data
= hdmi_cfg
;
592 hdmi
= msm_hdmi_init(to_platform_device(dev
));
594 return PTR_ERR(hdmi
);
597 err
= msm_hdmi_register_audio_driver(hdmi
, dev
);
599 DRM_ERROR("Failed to attach an audio codec %d\n", err
);
600 hdmi
->audio_pdev
= NULL
;
606 static void msm_hdmi_unbind(struct device
*dev
, struct device
*master
,
609 struct drm_device
*drm
= dev_get_drvdata(master
);
610 struct msm_drm_private
*priv
= drm
->dev_private
;
612 if (priv
->hdmi
->audio_pdev
)
613 platform_device_unregister(priv
->hdmi
->audio_pdev
);
615 msm_hdmi_destroy(priv
->hdmi
);
620 static const struct component_ops msm_hdmi_ops
= {
621 .bind
= msm_hdmi_bind
,
622 .unbind
= msm_hdmi_unbind
,
625 static int msm_hdmi_dev_probe(struct platform_device
*pdev
)
627 return component_add(&pdev
->dev
, &msm_hdmi_ops
);
630 static int msm_hdmi_dev_remove(struct platform_device
*pdev
)
632 component_del(&pdev
->dev
, &msm_hdmi_ops
);
636 static const struct of_device_id msm_hdmi_dt_match
[] = {
637 { .compatible
= "qcom,hdmi-tx-8996", .data
= &hdmi_tx_8996_config
},
638 { .compatible
= "qcom,hdmi-tx-8994", .data
= &hdmi_tx_8994_config
},
639 { .compatible
= "qcom,hdmi-tx-8084", .data
= &hdmi_tx_8084_config
},
640 { .compatible
= "qcom,hdmi-tx-8974", .data
= &hdmi_tx_8974_config
},
641 { .compatible
= "qcom,hdmi-tx-8960", .data
= &hdmi_tx_8960_config
},
642 { .compatible
= "qcom,hdmi-tx-8660", .data
= &hdmi_tx_8660_config
},
646 static struct platform_driver msm_hdmi_driver
= {
647 .probe
= msm_hdmi_dev_probe
,
648 .remove
= msm_hdmi_dev_remove
,
651 .of_match_table
= msm_hdmi_dt_match
,
655 void __init
msm_hdmi_register(void)
657 msm_hdmi_phy_driver_register();
658 platform_driver_register(&msm_hdmi_driver
);
661 void __exit
msm_hdmi_unregister(void)
663 platform_driver_unregister(&msm_hdmi_driver
);
664 msm_hdmi_phy_driver_unregister();