2 * Copyright (c) 2014 The Linux Foundation. All rights reserved.
3 * Copyright (C) 2013 Red Hat
4 * Author: Rob Clark <robdclark@gmail.com>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <linux/of_irq.h>
20 #include <linux/of_gpio.h>
24 void msm_hdmi_set_mode(struct hdmi
*hdmi
, bool power_on
)
29 spin_lock_irqsave(&hdmi
->reg_lock
, flags
);
31 ctrl
|= HDMI_CTRL_ENABLE
;
32 if (!hdmi
->hdmi_mode
) {
33 ctrl
|= HDMI_CTRL_HDMI
;
34 hdmi_write(hdmi
, REG_HDMI_CTRL
, ctrl
);
35 ctrl
&= ~HDMI_CTRL_HDMI
;
37 ctrl
|= HDMI_CTRL_HDMI
;
40 ctrl
= HDMI_CTRL_HDMI
;
43 hdmi_write(hdmi
, REG_HDMI_CTRL
, ctrl
);
44 spin_unlock_irqrestore(&hdmi
->reg_lock
, flags
);
45 DBG("HDMI Core: %s, HDMI_CTRL=0x%08x",
46 power_on
? "Enable" : "Disable", ctrl
);
49 static irqreturn_t
msm_hdmi_irq(int irq
, void *dev_id
)
51 struct hdmi
*hdmi
= dev_id
;
54 msm_hdmi_connector_irq(hdmi
->connector
);
57 msm_hdmi_i2c_irq(hdmi
->i2c
);
61 msm_hdmi_hdcp_irq(hdmi
->hdcp_ctrl
);
68 static void msm_hdmi_destroy(struct hdmi
*hdmi
)
71 * at this point, hpd has been disabled,
72 * after flush workq, it's safe to deinit hdcp
75 flush_workqueue(hdmi
->workq
);
76 destroy_workqueue(hdmi
->workq
);
78 msm_hdmi_hdcp_destroy(hdmi
);
81 put_device(hdmi
->phy_dev
);
87 msm_hdmi_i2c_destroy(hdmi
->i2c
);
89 platform_set_drvdata(hdmi
->pdev
, NULL
);
92 static int msm_hdmi_get_phy(struct hdmi
*hdmi
)
94 struct platform_device
*pdev
= hdmi
->pdev
;
95 struct platform_device
*phy_pdev
;
96 struct device_node
*phy_node
;
98 phy_node
= of_parse_phandle(pdev
->dev
.of_node
, "phys", 0);
100 dev_err(&pdev
->dev
, "cannot find phy device\n");
104 phy_pdev
= of_find_device_by_node(phy_node
);
106 hdmi
->phy
= platform_get_drvdata(phy_pdev
);
108 of_node_put(phy_node
);
110 if (!phy_pdev
|| !hdmi
->phy
) {
111 dev_err(&pdev
->dev
, "phy driver is not ready\n");
112 return -EPROBE_DEFER
;
115 hdmi
->phy_dev
= get_device(&phy_pdev
->dev
);
120 /* construct hdmi at bind/probe time, grab all the resources. If
121 * we are to EPROBE_DEFER we want to do it here, rather than later
122 * at modeset_init() time
124 static struct hdmi
*msm_hdmi_init(struct platform_device
*pdev
)
126 struct hdmi_platform_config
*config
= pdev
->dev
.platform_data
;
127 struct hdmi
*hdmi
= NULL
;
128 struct resource
*res
;
131 hdmi
= devm_kzalloc(&pdev
->dev
, sizeof(*hdmi
), GFP_KERNEL
);
138 hdmi
->config
= config
;
139 spin_lock_init(&hdmi
->reg_lock
);
141 hdmi
->mmio
= msm_ioremap(pdev
, config
->mmio_name
, "HDMI");
142 if (IS_ERR(hdmi
->mmio
)) {
143 ret
= PTR_ERR(hdmi
->mmio
);
147 /* HDCP needs physical address of hdmi register */
148 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
,
150 hdmi
->mmio_phy_addr
= res
->start
;
152 hdmi
->qfprom_mmio
= msm_ioremap(pdev
,
153 config
->qfprom_mmio_name
, "HDMI_QFPROM");
154 if (IS_ERR(hdmi
->qfprom_mmio
)) {
155 dev_info(&pdev
->dev
, "can't find qfprom resource\n");
156 hdmi
->qfprom_mmio
= NULL
;
159 hdmi
->hpd_regs
= devm_kzalloc(&pdev
->dev
, sizeof(hdmi
->hpd_regs
[0]) *
160 config
->hpd_reg_cnt
, GFP_KERNEL
);
161 if (!hdmi
->hpd_regs
) {
165 for (i
= 0; i
< config
->hpd_reg_cnt
; i
++) {
166 struct regulator
*reg
;
168 reg
= devm_regulator_get(&pdev
->dev
,
169 config
->hpd_reg_names
[i
]);
172 dev_err(&pdev
->dev
, "failed to get hpd regulator: %s (%d)\n",
173 config
->hpd_reg_names
[i
], ret
);
177 hdmi
->hpd_regs
[i
] = reg
;
180 hdmi
->pwr_regs
= devm_kzalloc(&pdev
->dev
, sizeof(hdmi
->pwr_regs
[0]) *
181 config
->pwr_reg_cnt
, GFP_KERNEL
);
182 if (!hdmi
->pwr_regs
) {
186 for (i
= 0; i
< config
->pwr_reg_cnt
; i
++) {
187 struct regulator
*reg
;
189 reg
= devm_regulator_get(&pdev
->dev
,
190 config
->pwr_reg_names
[i
]);
193 dev_err(&pdev
->dev
, "failed to get pwr regulator: %s (%d)\n",
194 config
->pwr_reg_names
[i
], ret
);
198 hdmi
->pwr_regs
[i
] = reg
;
201 hdmi
->hpd_clks
= devm_kzalloc(&pdev
->dev
, sizeof(hdmi
->hpd_clks
[0]) *
202 config
->hpd_clk_cnt
, GFP_KERNEL
);
203 if (!hdmi
->hpd_clks
) {
207 for (i
= 0; i
< config
->hpd_clk_cnt
; i
++) {
210 clk
= devm_clk_get(&pdev
->dev
, config
->hpd_clk_names
[i
]);
213 dev_err(&pdev
->dev
, "failed to get hpd clk: %s (%d)\n",
214 config
->hpd_clk_names
[i
], ret
);
218 hdmi
->hpd_clks
[i
] = clk
;
221 hdmi
->pwr_clks
= devm_kzalloc(&pdev
->dev
, sizeof(hdmi
->pwr_clks
[0]) *
222 config
->pwr_clk_cnt
, GFP_KERNEL
);
223 if (!hdmi
->pwr_clks
) {
227 for (i
= 0; i
< config
->pwr_clk_cnt
; i
++) {
230 clk
= devm_clk_get(&pdev
->dev
, config
->pwr_clk_names
[i
]);
233 dev_err(&pdev
->dev
, "failed to get pwr clk: %s (%d)\n",
234 config
->pwr_clk_names
[i
], ret
);
238 hdmi
->pwr_clks
[i
] = clk
;
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 dev_err(&pdev
->dev
, "failed to get i2c: %d\n", ret
);
251 ret
= msm_hdmi_get_phy(hdmi
);
253 dev_err(&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 dev_err(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 dev_err(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 dev_err(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 dev_err(dev
->dev
, "failed to request IRQ%u: %d\n",
324 encoder
->bridge
= hdmi
->bridge
;
326 priv
->bridges
[priv
->num_bridges
++] = hdmi
->bridge
;
327 priv
->connectors
[priv
->num_connectors
++] = hdmi
->connector
;
329 platform_set_drvdata(pdev
, hdmi
);
334 /* bridge is normally destroyed by drm: */
336 msm_hdmi_bridge_destroy(hdmi
->bridge
);
339 if (hdmi
->connector
) {
340 hdmi
->connector
->funcs
->destroy(hdmi
->connector
);
341 hdmi
->connector
= NULL
;
351 #define HDMI_CFG(item, entry) \
352 .item ## _names = item ##_names_ ## entry, \
353 .item ## _cnt = ARRAY_SIZE(item ## _names_ ## entry)
355 static const char *pwr_reg_names_none
[] = {};
356 static const char *hpd_reg_names_none
[] = {};
358 static struct hdmi_platform_config hdmi_tx_8660_config
;
360 static const char *hpd_reg_names_8960
[] = {"core-vdda", "hdmi-mux"};
361 static const char *hpd_clk_names_8960
[] = {"core_clk", "master_iface_clk", "slave_iface_clk"};
363 static struct hdmi_platform_config hdmi_tx_8960_config
= {
364 HDMI_CFG(hpd_reg
, 8960),
365 HDMI_CFG(hpd_clk
, 8960),
368 static const char *pwr_reg_names_8x74
[] = {"core-vdda", "core-vcc"};
369 static const char *hpd_reg_names_8x74
[] = {"hpd-gdsc", "hpd-5v"};
370 static const char *pwr_clk_names_8x74
[] = {"extp_clk", "alt_iface_clk"};
371 static const char *hpd_clk_names_8x74
[] = {"iface_clk", "core_clk", "mdp_core_clk"};
372 static unsigned long hpd_clk_freq_8x74
[] = {0, 19200000, 0};
374 static struct hdmi_platform_config hdmi_tx_8974_config
= {
375 HDMI_CFG(pwr_reg
, 8x74
),
376 HDMI_CFG(hpd_reg
, 8x74
),
377 HDMI_CFG(pwr_clk
, 8x74
),
378 HDMI_CFG(hpd_clk
, 8x74
),
379 .hpd_freq
= hpd_clk_freq_8x74
,
382 static const char *hpd_reg_names_8084
[] = {"hpd-gdsc", "hpd-5v", "hpd-5v-en"};
384 static struct hdmi_platform_config hdmi_tx_8084_config
= {
385 HDMI_CFG(pwr_reg
, 8x74
),
386 HDMI_CFG(hpd_reg
, 8084),
387 HDMI_CFG(pwr_clk
, 8x74
),
388 HDMI_CFG(hpd_clk
, 8x74
),
389 .hpd_freq
= hpd_clk_freq_8x74
,
392 static struct hdmi_platform_config hdmi_tx_8994_config
= {
393 HDMI_CFG(pwr_reg
, 8x74
),
394 HDMI_CFG(hpd_reg
, none
),
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_8996_config
= {
401 HDMI_CFG(pwr_reg
, none
),
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 const struct {
413 } msm_hdmi_gpio_pdata
[] = {
414 { "qcom,hdmi-tx-ddc-clk", true, 1, "HDMI_DDC_CLK" },
415 { "qcom,hdmi-tx-ddc-data", true, 1, "HDMI_DDC_DATA" },
416 { "qcom,hdmi-tx-hpd", false, 1, "HDMI_HPD" },
417 { "qcom,hdmi-tx-mux-en", true, 1, "HDMI_MUX_EN" },
418 { "qcom,hdmi-tx-mux-sel", true, 0, "HDMI_MUX_SEL" },
419 { "qcom,hdmi-tx-mux-lpm", true, 1, "HDMI_MUX_LPM" },
422 static int msm_hdmi_get_gpio(struct device_node
*of_node
, const char *name
)
424 int gpio
= of_get_named_gpio(of_node
, name
, 0);
427 snprintf(name2
, sizeof(name2
), "%s-gpio", name
);
428 gpio
= of_get_named_gpio(of_node
, name2
, 0);
430 DBG("failed to get gpio: %s (%d)", name
, gpio
);
437 static int msm_hdmi_bind(struct device
*dev
, struct device
*master
, void *data
)
439 struct drm_device
*drm
= dev_get_drvdata(master
);
440 struct msm_drm_private
*priv
= drm
->dev_private
;
441 static struct hdmi_platform_config
*hdmi_cfg
;
443 struct device_node
*of_node
= dev
->of_node
;
446 hdmi_cfg
= (struct hdmi_platform_config
*)
447 of_device_get_match_data(dev
);
449 dev_err(dev
, "unknown hdmi_cfg: %s\n", of_node
->name
);
453 hdmi_cfg
->mmio_name
= "core_physical";
454 hdmi_cfg
->qfprom_mmio_name
= "qfprom_physical";
456 for (i
= 0; i
< HDMI_MAX_NUM_GPIO
; i
++) {
457 hdmi_cfg
->gpios
[i
].num
= msm_hdmi_get_gpio(of_node
,
458 msm_hdmi_gpio_pdata
[i
].name
);
459 hdmi_cfg
->gpios
[i
].output
= msm_hdmi_gpio_pdata
[i
].output
;
460 hdmi_cfg
->gpios
[i
].value
= msm_hdmi_gpio_pdata
[i
].value
;
461 hdmi_cfg
->gpios
[i
].label
= msm_hdmi_gpio_pdata
[i
].label
;
464 dev
->platform_data
= hdmi_cfg
;
466 hdmi
= msm_hdmi_init(to_platform_device(dev
));
468 return PTR_ERR(hdmi
);
474 static void msm_hdmi_unbind(struct device
*dev
, struct device
*master
,
477 struct drm_device
*drm
= dev_get_drvdata(master
);
478 struct msm_drm_private
*priv
= drm
->dev_private
;
480 msm_hdmi_destroy(priv
->hdmi
);
485 static const struct component_ops msm_hdmi_ops
= {
486 .bind
= msm_hdmi_bind
,
487 .unbind
= msm_hdmi_unbind
,
490 static int msm_hdmi_dev_probe(struct platform_device
*pdev
)
492 return component_add(&pdev
->dev
, &msm_hdmi_ops
);
495 static int msm_hdmi_dev_remove(struct platform_device
*pdev
)
497 component_del(&pdev
->dev
, &msm_hdmi_ops
);
501 static const struct of_device_id msm_hdmi_dt_match
[] = {
502 { .compatible
= "qcom,hdmi-tx-8996", .data
= &hdmi_tx_8996_config
},
503 { .compatible
= "qcom,hdmi-tx-8994", .data
= &hdmi_tx_8994_config
},
504 { .compatible
= "qcom,hdmi-tx-8084", .data
= &hdmi_tx_8084_config
},
505 { .compatible
= "qcom,hdmi-tx-8974", .data
= &hdmi_tx_8974_config
},
506 { .compatible
= "qcom,hdmi-tx-8960", .data
= &hdmi_tx_8960_config
},
507 { .compatible
= "qcom,hdmi-tx-8660", .data
= &hdmi_tx_8660_config
},
511 static struct platform_driver msm_hdmi_driver
= {
512 .probe
= msm_hdmi_dev_probe
,
513 .remove
= msm_hdmi_dev_remove
,
516 .of_match_table
= msm_hdmi_dt_match
,
520 void __init
msm_hdmi_register(void)
522 msm_hdmi_phy_driver_register();
523 platform_driver_register(&msm_hdmi_driver
);
526 void __exit
msm_hdmi_unregister(void)
528 platform_driver_unregister(&msm_hdmi_driver
);
529 msm_hdmi_phy_driver_unregister();