2 * Copyright (C) 2013 Red Hat
3 * Author: Rob Clark <robdclark@gmail.com>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
20 static struct platform_device
*hdmi_pdev
;
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 void hdmi_destroy(struct kref
*kref
)
61 struct hdmi
*hdmi
= container_of(kref
, struct hdmi
, refcount
);
62 struct hdmi_phy
*phy
= hdmi
->phy
;
65 phy
->funcs
->destroy(phy
);
68 hdmi_i2c_destroy(hdmi
->i2c
);
70 put_device(&hdmi
->pdev
->dev
);
73 /* initialize connector */
74 int hdmi_init(struct drm_device
*dev
, struct drm_encoder
*encoder
)
76 struct hdmi
*hdmi
= NULL
;
77 struct msm_drm_private
*priv
= dev
->dev_private
;
78 struct platform_device
*pdev
= hdmi_pdev
;
79 struct hdmi_platform_config
*config
;
83 dev_err(dev
->dev
, "no hdmi device\n");
88 config
= pdev
->dev
.platform_data
;
90 hdmi
= kzalloc(sizeof(*hdmi
), GFP_KERNEL
);
96 kref_init(&hdmi
->refcount
);
98 get_device(&pdev
->dev
);
102 hdmi
->encoder
= encoder
;
104 /* not sure about which phy maps to which msm.. probably I miss some */
105 if (config
->phy_init
)
106 hdmi
->phy
= config
->phy_init(hdmi
);
108 hdmi
->phy
= ERR_PTR(-ENXIO
);
110 if (IS_ERR(hdmi
->phy
)) {
111 ret
= PTR_ERR(hdmi
->phy
);
112 dev_err(dev
->dev
, "failed to load phy: %d\n", ret
);
117 hdmi
->mmio
= msm_ioremap(pdev
, "hdmi_msm_hdmi_addr", "HDMI");
118 if (IS_ERR(hdmi
->mmio
)) {
119 ret
= PTR_ERR(hdmi
->mmio
);
123 hdmi
->mvs
= devm_regulator_get(&pdev
->dev
, "8901_hdmi_mvs");
124 if (IS_ERR(hdmi
->mvs
))
125 hdmi
->mvs
= devm_regulator_get(&pdev
->dev
, "hdmi_mvs");
126 if (IS_ERR(hdmi
->mvs
)) {
127 ret
= PTR_ERR(hdmi
->mvs
);
128 dev_err(dev
->dev
, "failed to get mvs regulator: %d\n", ret
);
132 hdmi
->mpp0
= devm_regulator_get(&pdev
->dev
, "8901_mpp0");
133 if (IS_ERR(hdmi
->mpp0
))
136 hdmi
->clk
= devm_clk_get(&pdev
->dev
, "core_clk");
137 if (IS_ERR(hdmi
->clk
)) {
138 ret
= PTR_ERR(hdmi
->clk
);
139 dev_err(dev
->dev
, "failed to get 'clk': %d\n", ret
);
143 hdmi
->m_pclk
= devm_clk_get(&pdev
->dev
, "master_iface_clk");
144 if (IS_ERR(hdmi
->m_pclk
)) {
145 ret
= PTR_ERR(hdmi
->m_pclk
);
146 dev_err(dev
->dev
, "failed to get 'm_pclk': %d\n", ret
);
150 hdmi
->s_pclk
= devm_clk_get(&pdev
->dev
, "slave_iface_clk");
151 if (IS_ERR(hdmi
->s_pclk
)) {
152 ret
= PTR_ERR(hdmi
->s_pclk
);
153 dev_err(dev
->dev
, "failed to get 's_pclk': %d\n", ret
);
157 hdmi
->i2c
= hdmi_i2c_init(hdmi
);
158 if (IS_ERR(hdmi
->i2c
)) {
159 ret
= PTR_ERR(hdmi
->i2c
);
160 dev_err(dev
->dev
, "failed to get i2c: %d\n", ret
);
165 hdmi
->bridge
= hdmi_bridge_init(hdmi
);
166 if (IS_ERR(hdmi
->bridge
)) {
167 ret
= PTR_ERR(hdmi
->bridge
);
168 dev_err(dev
->dev
, "failed to create HDMI bridge: %d\n", ret
);
173 hdmi
->connector
= hdmi_connector_init(hdmi
);
174 if (IS_ERR(hdmi
->connector
)) {
175 ret
= PTR_ERR(hdmi
->connector
);
176 dev_err(dev
->dev
, "failed to create HDMI connector: %d\n", ret
);
177 hdmi
->connector
= NULL
;
181 hdmi
->irq
= platform_get_irq(pdev
, 0);
184 dev_err(dev
->dev
, "failed to get irq: %d\n", ret
);
188 ret
= devm_request_threaded_irq(&pdev
->dev
, hdmi
->irq
,
189 NULL
, hdmi_irq
, IRQF_TRIGGER_HIGH
| IRQF_ONESHOT
,
192 dev_err(dev
->dev
, "failed to request IRQ%u: %d\n",
197 encoder
->bridge
= hdmi
->bridge
;
199 priv
->bridges
[priv
->num_bridges
++] = hdmi
->bridge
;
200 priv
->connectors
[priv
->num_connectors
++] = hdmi
->connector
;
206 /* bridge/connector are normally destroyed by drm: */
208 hdmi
->bridge
->funcs
->destroy(hdmi
->bridge
);
210 hdmi
->connector
->funcs
->destroy(hdmi
->connector
);
211 hdmi_destroy(&hdmi
->refcount
);
221 static int hdmi_dev_probe(struct platform_device
*pdev
)
223 static struct hdmi_platform_config config
= {};
227 if (cpu_is_apq8064()) {
228 config
.phy_init
= hdmi_phy_8960_init
;
229 config
.ddc_clk_gpio
= 70;
230 config
.ddc_data_gpio
= 71;
231 config
.hpd_gpio
= 72;
232 config
.pmic_gpio
= 13 + NR_GPIO_IRQS
;
233 } else if (cpu_is_msm8960()) {
234 config
.phy_init
= hdmi_phy_8960_init
;
235 config
.ddc_clk_gpio
= 100;
236 config
.ddc_data_gpio
= 101;
237 config
.hpd_gpio
= 102;
238 config
.pmic_gpio
= -1;
239 } else if (cpu_is_msm8x60()) {
240 config
.phy_init
= hdmi_phy_8x60_init
;
241 config
.ddc_clk_gpio
= 170;
242 config
.ddc_data_gpio
= 171;
243 config
.hpd_gpio
= 172;
244 config
.pmic_gpio
= -1;
247 pdev
->dev
.platform_data
= &config
;
252 static int hdmi_dev_remove(struct platform_device
*pdev
)
258 static struct platform_driver hdmi_driver
= {
259 .probe
= hdmi_dev_probe
,
260 .remove
= hdmi_dev_remove
,
261 .driver
.name
= "hdmi_msm",
264 void __init
hdmi_register(void)
266 platform_driver_register(&hdmi_driver
);
269 void __exit
hdmi_unregister(void)
271 platform_driver_unregister(&hdmi_driver
);