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>
22 void hdmi_set_mode(struct hdmi
*hdmi
, bool power_on
)
27 ctrl
|= HDMI_CTRL_ENABLE
;
28 if (!hdmi
->hdmi_mode
) {
29 ctrl
|= HDMI_CTRL_HDMI
;
30 hdmi_write(hdmi
, REG_HDMI_CTRL
, ctrl
);
31 ctrl
&= ~HDMI_CTRL_HDMI
;
33 ctrl
|= HDMI_CTRL_HDMI
;
36 ctrl
= HDMI_CTRL_HDMI
;
39 hdmi_write(hdmi
, REG_HDMI_CTRL
, ctrl
);
40 DBG("HDMI Core: %s, HDMI_CTRL=0x%08x",
41 power_on
? "Enable" : "Disable", ctrl
);
44 static irqreturn_t
hdmi_irq(int irq
, void *dev_id
)
46 struct hdmi
*hdmi
= dev_id
;
49 hdmi_connector_irq(hdmi
->connector
);
52 hdmi_i2c_irq(hdmi
->i2c
);
59 static void hdmi_destroy(struct hdmi
*hdmi
)
61 struct hdmi_phy
*phy
= hdmi
->phy
;
64 phy
->funcs
->destroy(phy
);
67 hdmi_i2c_destroy(hdmi
->i2c
);
69 platform_set_drvdata(hdmi
->pdev
, NULL
);
72 /* construct hdmi at bind/probe time, grab all the resources. If
73 * we are to EPROBE_DEFER we want to do it here, rather than later
74 * at modeset_init() time
76 static struct hdmi
*hdmi_init(struct platform_device
*pdev
)
78 struct hdmi_platform_config
*config
= pdev
->dev
.platform_data
;
79 struct hdmi
*hdmi
= NULL
;
82 hdmi
= devm_kzalloc(&pdev
->dev
, sizeof(*hdmi
), GFP_KERNEL
);
89 hdmi
->config
= config
;
91 /* not sure about which phy maps to which msm.. probably I miss some */
93 hdmi
->phy
= config
->phy_init(hdmi
);
95 hdmi
->phy
= ERR_PTR(-ENXIO
);
97 if (IS_ERR(hdmi
->phy
)) {
98 ret
= PTR_ERR(hdmi
->phy
);
99 dev_err(&pdev
->dev
, "failed to load phy: %d\n", ret
);
104 hdmi
->mmio
= msm_ioremap(pdev
, config
->mmio_name
, "HDMI");
105 if (IS_ERR(hdmi
->mmio
)) {
106 ret
= PTR_ERR(hdmi
->mmio
);
110 hdmi
->hpd_regs
= devm_kzalloc(&pdev
->dev
, sizeof(hdmi
->hpd_regs
[0]) *
111 config
->hpd_reg_cnt
, GFP_KERNEL
);
112 if (!hdmi
->hpd_regs
) {
116 for (i
= 0; i
< config
->hpd_reg_cnt
; i
++) {
117 struct regulator
*reg
;
119 reg
= devm_regulator_get(&pdev
->dev
,
120 config
->hpd_reg_names
[i
]);
123 dev_err(&pdev
->dev
, "failed to get hpd regulator: %s (%d)\n",
124 config
->hpd_reg_names
[i
], ret
);
128 hdmi
->hpd_regs
[i
] = reg
;
131 hdmi
->pwr_regs
= devm_kzalloc(&pdev
->dev
, sizeof(hdmi
->pwr_regs
[0]) *
132 config
->pwr_reg_cnt
, GFP_KERNEL
);
133 if (!hdmi
->pwr_regs
) {
137 for (i
= 0; i
< config
->pwr_reg_cnt
; i
++) {
138 struct regulator
*reg
;
140 reg
= devm_regulator_get(&pdev
->dev
,
141 config
->pwr_reg_names
[i
]);
144 dev_err(&pdev
->dev
, "failed to get pwr regulator: %s (%d)\n",
145 config
->pwr_reg_names
[i
], ret
);
149 hdmi
->pwr_regs
[i
] = reg
;
152 hdmi
->hpd_clks
= devm_kzalloc(&pdev
->dev
, sizeof(hdmi
->hpd_clks
[0]) *
153 config
->hpd_clk_cnt
, GFP_KERNEL
);
154 if (!hdmi
->hpd_clks
) {
158 for (i
= 0; i
< config
->hpd_clk_cnt
; i
++) {
161 clk
= devm_clk_get(&pdev
->dev
, config
->hpd_clk_names
[i
]);
164 dev_err(&pdev
->dev
, "failed to get hpd clk: %s (%d)\n",
165 config
->hpd_clk_names
[i
], ret
);
169 hdmi
->hpd_clks
[i
] = clk
;
172 hdmi
->pwr_clks
= devm_kzalloc(&pdev
->dev
, sizeof(hdmi
->pwr_clks
[0]) *
173 config
->pwr_clk_cnt
, GFP_KERNEL
);
174 if (!hdmi
->pwr_clks
) {
178 for (i
= 0; i
< config
->pwr_clk_cnt
; i
++) {
181 clk
= devm_clk_get(&pdev
->dev
, config
->pwr_clk_names
[i
]);
184 dev_err(&pdev
->dev
, "failed to get pwr clk: %s (%d)\n",
185 config
->pwr_clk_names
[i
], ret
);
189 hdmi
->pwr_clks
[i
] = clk
;
192 hdmi
->i2c
= hdmi_i2c_init(hdmi
);
193 if (IS_ERR(hdmi
->i2c
)) {
194 ret
= PTR_ERR(hdmi
->i2c
);
195 dev_err(&pdev
->dev
, "failed to get i2c: %d\n", ret
);
209 /* Second part of initialization, the drm/kms level modeset_init,
210 * constructs/initializes mode objects, etc, is called from master
211 * driver (not hdmi sub-device's probe/bind!)
213 * Any resource (regulator/clk/etc) which could be missing at boot
214 * should be handled in hdmi_init() so that failure happens from
215 * hdmi sub-device's probe.
217 int hdmi_modeset_init(struct hdmi
*hdmi
,
218 struct drm_device
*dev
, struct drm_encoder
*encoder
)
220 struct msm_drm_private
*priv
= dev
->dev_private
;
221 struct platform_device
*pdev
= hdmi
->pdev
;
225 hdmi
->encoder
= encoder
;
227 hdmi_audio_infoframe_init(&hdmi
->audio
.infoframe
);
229 hdmi
->bridge
= hdmi_bridge_init(hdmi
);
230 if (IS_ERR(hdmi
->bridge
)) {
231 ret
= PTR_ERR(hdmi
->bridge
);
232 dev_err(dev
->dev
, "failed to create HDMI bridge: %d\n", ret
);
237 hdmi
->connector
= hdmi_connector_init(hdmi
);
238 if (IS_ERR(hdmi
->connector
)) {
239 ret
= PTR_ERR(hdmi
->connector
);
240 dev_err(dev
->dev
, "failed to create HDMI connector: %d\n", ret
);
241 hdmi
->connector
= NULL
;
245 hdmi
->irq
= irq_of_parse_and_map(pdev
->dev
.of_node
, 0);
248 dev_err(dev
->dev
, "failed to get irq: %d\n", ret
);
252 ret
= devm_request_irq(&pdev
->dev
, hdmi
->irq
,
253 hdmi_irq
, IRQF_TRIGGER_HIGH
| IRQF_ONESHOT
,
256 dev_err(dev
->dev
, "failed to request IRQ%u: %d\n",
261 encoder
->bridge
= hdmi
->bridge
;
263 priv
->bridges
[priv
->num_bridges
++] = hdmi
->bridge
;
264 priv
->connectors
[priv
->num_connectors
++] = hdmi
->connector
;
266 platform_set_drvdata(pdev
, hdmi
);
271 /* bridge is normally destroyed by drm: */
273 hdmi_bridge_destroy(hdmi
->bridge
);
276 if (hdmi
->connector
) {
277 hdmi
->connector
->funcs
->destroy(hdmi
->connector
);
278 hdmi
->connector
= NULL
;
288 #include <linux/of_gpio.h>
290 #define HDMI_CFG(item, entry) \
291 .item ## _names = item ##_names_ ## entry, \
292 .item ## _cnt = ARRAY_SIZE(item ## _names_ ## entry)
294 static struct hdmi_platform_config hdmi_tx_8660_config
= {
295 .phy_init
= hdmi_phy_8x60_init
,
298 static const char *hpd_reg_names_8960
[] = {"core-vdda", "hdmi-mux"};
299 static const char *hpd_clk_names_8960
[] = {"core_clk", "master_iface_clk", "slave_iface_clk"};
301 static struct hdmi_platform_config hdmi_tx_8960_config
= {
302 .phy_init
= hdmi_phy_8960_init
,
303 HDMI_CFG(hpd_reg
, 8960),
304 HDMI_CFG(hpd_clk
, 8960),
307 static const char *pwr_reg_names_8x74
[] = {"core-vdda", "core-vcc"};
308 static const char *hpd_reg_names_8x74
[] = {"hpd-gdsc", "hpd-5v"};
309 static const char *pwr_clk_names_8x74
[] = {"extp_clk", "alt_iface_clk"};
310 static const char *hpd_clk_names_8x74
[] = {"iface_clk", "core_clk", "mdp_core_clk"};
311 static unsigned long hpd_clk_freq_8x74
[] = {0, 19200000, 0};
313 static struct hdmi_platform_config hdmi_tx_8074_config
= {
314 .phy_init
= hdmi_phy_8x74_init
,
315 HDMI_CFG(pwr_reg
, 8x74
),
316 HDMI_CFG(hpd_reg
, 8x74
),
317 HDMI_CFG(pwr_clk
, 8x74
),
318 HDMI_CFG(hpd_clk
, 8x74
),
319 .hpd_freq
= hpd_clk_freq_8x74
,
322 static const char *hpd_reg_names_8084
[] = {"hpd-gdsc", "hpd-5v", "hpd-5v-en"};
324 static struct hdmi_platform_config hdmi_tx_8084_config
= {
325 .phy_init
= hdmi_phy_8x74_init
,
326 HDMI_CFG(pwr_reg
, 8x74
),
327 HDMI_CFG(hpd_reg
, 8084),
328 HDMI_CFG(pwr_clk
, 8x74
),
329 HDMI_CFG(hpd_clk
, 8x74
),
330 .hpd_freq
= hpd_clk_freq_8x74
,
333 static const struct of_device_id dt_match
[] = {
334 { .compatible
= "qcom,hdmi-tx-8084", .data
= &hdmi_tx_8084_config
},
335 { .compatible
= "qcom,hdmi-tx-8074", .data
= &hdmi_tx_8074_config
},
336 { .compatible
= "qcom,hdmi-tx-8960", .data
= &hdmi_tx_8960_config
},
337 { .compatible
= "qcom,hdmi-tx-8660", .data
= &hdmi_tx_8660_config
},
342 static int get_gpio(struct device
*dev
, struct device_node
*of_node
, const char *name
)
344 int gpio
= of_get_named_gpio(of_node
, name
, 0);
347 snprintf(name2
, sizeof(name2
), "%s-gpio", name
);
348 gpio
= of_get_named_gpio(of_node
, name2
, 0);
350 dev_err(dev
, "failed to get gpio: %s (%d)\n",
359 static int hdmi_bind(struct device
*dev
, struct device
*master
, void *data
)
361 struct drm_device
*drm
= dev_get_drvdata(master
);
362 struct msm_drm_private
*priv
= drm
->dev_private
;
363 static struct hdmi_platform_config
*hdmi_cfg
;
366 struct device_node
*of_node
= dev
->of_node
;
367 const struct of_device_id
*match
;
369 match
= of_match_node(dt_match
, of_node
);
370 if (match
&& match
->data
) {
371 hdmi_cfg
= (struct hdmi_platform_config
*)match
->data
;
372 DBG("hdmi phy: %s", match
->compatible
);
374 dev_err(dev
, "unknown phy: %s\n", of_node
->name
);
378 hdmi_cfg
->mmio_name
= "core_physical";
379 hdmi_cfg
->ddc_clk_gpio
= get_gpio(dev
, of_node
, "qcom,hdmi-tx-ddc-clk");
380 hdmi_cfg
->ddc_data_gpio
= get_gpio(dev
, of_node
, "qcom,hdmi-tx-ddc-data");
381 hdmi_cfg
->hpd_gpio
= get_gpio(dev
, of_node
, "qcom,hdmi-tx-hpd");
382 hdmi_cfg
->mux_en_gpio
= get_gpio(dev
, of_node
, "qcom,hdmi-tx-mux-en");
383 hdmi_cfg
->mux_sel_gpio
= get_gpio(dev
, of_node
, "qcom,hdmi-tx-mux-sel");
384 hdmi_cfg
->mux_lpm_gpio
= get_gpio(dev
, of_node
, "qcom,hdmi-tx-mux-lpm");
387 static struct hdmi_platform_config config
= {};
388 static const char *hpd_clk_names
[] = {
389 "core_clk", "master_iface_clk", "slave_iface_clk",
391 if (cpu_is_apq8064()) {
392 static const char *hpd_reg_names
[] = {"8921_hdmi_mvs"};
393 config
.phy_init
= hdmi_phy_8960_init
;
394 config
.mmio_name
= "hdmi_msm_hdmi_addr";
395 config
.hpd_reg_names
= hpd_reg_names
;
396 config
.hpd_reg_cnt
= ARRAY_SIZE(hpd_reg_names
);
397 config
.hpd_clk_names
= hpd_clk_names
;
398 config
.hpd_clk_cnt
= ARRAY_SIZE(hpd_clk_names
);
399 config
.ddc_clk_gpio
= 70;
400 config
.ddc_data_gpio
= 71;
401 config
.hpd_gpio
= 72;
402 config
.mux_en_gpio
= -1;
403 config
.mux_sel_gpio
= -1;
404 } else if (cpu_is_msm8960() || cpu_is_msm8960ab()) {
405 static const char *hpd_reg_names
[] = {"8921_hdmi_mvs"};
406 config
.phy_init
= hdmi_phy_8960_init
;
407 config
.mmio_name
= "hdmi_msm_hdmi_addr";
408 config
.hpd_reg_names
= hpd_reg_names
;
409 config
.hpd_reg_cnt
= ARRAY_SIZE(hpd_reg_names
);
410 config
.hpd_clk_names
= hpd_clk_names
;
411 config
.hpd_clk_cnt
= ARRAY_SIZE(hpd_clk_names
);
412 config
.ddc_clk_gpio
= 100;
413 config
.ddc_data_gpio
= 101;
414 config
.hpd_gpio
= 102;
415 config
.mux_en_gpio
= -1;
416 config
.mux_sel_gpio
= -1;
417 } else if (cpu_is_msm8x60()) {
418 static const char *hpd_reg_names
[] = {
419 "8901_hdmi_mvs", "8901_mpp0"
421 config
.phy_init
= hdmi_phy_8x60_init
;
422 config
.mmio_name
= "hdmi_msm_hdmi_addr";
423 config
.hpd_reg_names
= hpd_reg_names
;
424 config
.hpd_reg_cnt
= ARRAY_SIZE(hpd_reg_names
);
425 config
.hpd_clk_names
= hpd_clk_names
;
426 config
.hpd_clk_cnt
= ARRAY_SIZE(hpd_clk_names
);
427 config
.ddc_clk_gpio
= 170;
428 config
.ddc_data_gpio
= 171;
429 config
.hpd_gpio
= 172;
430 config
.mux_en_gpio
= -1;
431 config
.mux_sel_gpio
= -1;
435 dev
->platform_data
= hdmi_cfg
;
437 hdmi
= hdmi_init(to_platform_device(dev
));
439 return PTR_ERR(hdmi
);
445 static void hdmi_unbind(struct device
*dev
, struct device
*master
,
448 struct drm_device
*drm
= dev_get_drvdata(master
);
449 struct msm_drm_private
*priv
= drm
->dev_private
;
451 hdmi_destroy(priv
->hdmi
);
456 static const struct component_ops hdmi_ops
= {
458 .unbind
= hdmi_unbind
,
461 static int hdmi_dev_probe(struct platform_device
*pdev
)
463 return component_add(&pdev
->dev
, &hdmi_ops
);
466 static int hdmi_dev_remove(struct platform_device
*pdev
)
468 component_del(&pdev
->dev
, &hdmi_ops
);
472 static struct platform_driver hdmi_driver
= {
473 .probe
= hdmi_dev_probe
,
474 .remove
= hdmi_dev_remove
,
477 .of_match_table
= dt_match
,
481 void __init
hdmi_register(void)
483 platform_driver_register(&hdmi_driver
);
486 void __exit
hdmi_unregister(void)
488 platform_driver_unregister(&hdmi_driver
);