xref: /openbmc/linux/drivers/gpu/drm/msm/hdmi/hdmi.c (revision 3e87599b)
1c8afe684SRob Clark /*
2c8afe684SRob Clark  * Copyright (C) 2013 Red Hat
3c8afe684SRob Clark  * Author: Rob Clark <robdclark@gmail.com>
4c8afe684SRob Clark  *
5c8afe684SRob Clark  * This program is free software; you can redistribute it and/or modify it
6c8afe684SRob Clark  * under the terms of the GNU General Public License version 2 as published by
7c8afe684SRob Clark  * the Free Software Foundation.
8c8afe684SRob Clark  *
9c8afe684SRob Clark  * This program is distributed in the hope that it will be useful, but WITHOUT
10c8afe684SRob Clark  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11c8afe684SRob Clark  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12c8afe684SRob Clark  * more details.
13c8afe684SRob Clark  *
14c8afe684SRob Clark  * You should have received a copy of the GNU General Public License along with
15c8afe684SRob Clark  * this program.  If not, see <http://www.gnu.org/licenses/>.
16c8afe684SRob Clark  */
17c8afe684SRob Clark 
18c8afe684SRob Clark #include "hdmi.h"
19c8afe684SRob Clark 
20c8afe684SRob Clark void hdmi_set_mode(struct hdmi *hdmi, bool power_on)
21c8afe684SRob Clark {
22c8afe684SRob Clark 	uint32_t ctrl = 0;
23c8afe684SRob Clark 
24c8afe684SRob Clark 	if (power_on) {
25c8afe684SRob Clark 		ctrl |= HDMI_CTRL_ENABLE;
26c8afe684SRob Clark 		if (!hdmi->hdmi_mode) {
27c8afe684SRob Clark 			ctrl |= HDMI_CTRL_HDMI;
28c8afe684SRob Clark 			hdmi_write(hdmi, REG_HDMI_CTRL, ctrl);
29c8afe684SRob Clark 			ctrl &= ~HDMI_CTRL_HDMI;
30c8afe684SRob Clark 		} else {
31c8afe684SRob Clark 			ctrl |= HDMI_CTRL_HDMI;
32c8afe684SRob Clark 		}
33c8afe684SRob Clark 	} else {
34c8afe684SRob Clark 		ctrl = HDMI_CTRL_HDMI;
35c8afe684SRob Clark 	}
36c8afe684SRob Clark 
37c8afe684SRob Clark 	hdmi_write(hdmi, REG_HDMI_CTRL, ctrl);
38c8afe684SRob Clark 	DBG("HDMI Core: %s, HDMI_CTRL=0x%08x",
39c8afe684SRob Clark 			power_on ? "Enable" : "Disable", ctrl);
40c8afe684SRob Clark }
41c8afe684SRob Clark 
42dada25bdSRob Clark irqreturn_t hdmi_irq(int irq, void *dev_id)
43c8afe684SRob Clark {
44c8afe684SRob Clark 	struct hdmi *hdmi = dev_id;
45c8afe684SRob Clark 
46c8afe684SRob Clark 	/* Process HPD: */
47c8afe684SRob Clark 	hdmi_connector_irq(hdmi->connector);
48c8afe684SRob Clark 
49c8afe684SRob Clark 	/* Process DDC: */
50c8afe684SRob Clark 	hdmi_i2c_irq(hdmi->i2c);
51c8afe684SRob Clark 
52c8afe684SRob Clark 	/* TODO audio.. */
53c8afe684SRob Clark 
54c8afe684SRob Clark 	return IRQ_HANDLED;
55c8afe684SRob Clark }
56c8afe684SRob Clark 
57a3376e3eSRob Clark void hdmi_destroy(struct kref *kref)
58c8afe684SRob Clark {
59a3376e3eSRob Clark 	struct hdmi *hdmi = container_of(kref, struct hdmi, refcount);
60c8afe684SRob Clark 	struct hdmi_phy *phy = hdmi->phy;
61c8afe684SRob Clark 
62c8afe684SRob Clark 	if (phy)
63c8afe684SRob Clark 		phy->funcs->destroy(phy);
64c8afe684SRob Clark 
65c8afe684SRob Clark 	if (hdmi->i2c)
66c8afe684SRob Clark 		hdmi_i2c_destroy(hdmi->i2c);
67c8afe684SRob Clark 
68c0c0d9eeSRob Clark 	platform_set_drvdata(hdmi->pdev, NULL);
69c8afe684SRob Clark }
70c8afe684SRob Clark 
71c8afe684SRob Clark /* initialize connector */
72dada25bdSRob Clark struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
73c8afe684SRob Clark {
74a3376e3eSRob Clark 	struct hdmi *hdmi = NULL;
75a3376e3eSRob Clark 	struct msm_drm_private *priv = dev->dev_private;
76060530f1SRob Clark 	struct platform_device *pdev = priv->hdmi_pdev;
77c8afe684SRob Clark 	struct hdmi_platform_config *config;
78dada25bdSRob Clark 	int i, ret;
79c8afe684SRob Clark 
80c8afe684SRob Clark 	if (!pdev) {
81c8afe684SRob Clark 		dev_err(dev->dev, "no hdmi device\n");
82c8afe684SRob Clark 		ret = -ENXIO;
83c8afe684SRob Clark 		goto fail;
84c8afe684SRob Clark 	}
85c8afe684SRob Clark 
86c8afe684SRob Clark 	config = pdev->dev.platform_data;
87c8afe684SRob Clark 
88a3376e3eSRob Clark 	hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL);
89a3376e3eSRob Clark 	if (!hdmi) {
90a3376e3eSRob Clark 		ret = -ENOMEM;
91a3376e3eSRob Clark 		goto fail;
92a3376e3eSRob Clark 	}
93a3376e3eSRob Clark 
94a3376e3eSRob Clark 	kref_init(&hdmi->refcount);
95a3376e3eSRob Clark 
96c8afe684SRob Clark 	hdmi->dev = dev;
97c8afe684SRob Clark 	hdmi->pdev = pdev;
98dada25bdSRob Clark 	hdmi->config = config;
99a3376e3eSRob Clark 	hdmi->encoder = encoder;
100c8afe684SRob Clark 
101c0c0d9eeSRob Clark 	hdmi_audio_infoframe_init(&hdmi->audio.infoframe);
102c0c0d9eeSRob Clark 
103c8afe684SRob Clark 	/* not sure about which phy maps to which msm.. probably I miss some */
104c8afe684SRob Clark 	if (config->phy_init)
105c8afe684SRob Clark 		hdmi->phy = config->phy_init(hdmi);
106c8afe684SRob Clark 	else
107c8afe684SRob Clark 		hdmi->phy = ERR_PTR(-ENXIO);
108c8afe684SRob Clark 
109c8afe684SRob Clark 	if (IS_ERR(hdmi->phy)) {
110c8afe684SRob Clark 		ret = PTR_ERR(hdmi->phy);
111c8afe684SRob Clark 		dev_err(dev->dev, "failed to load phy: %d\n", ret);
112c8afe684SRob Clark 		hdmi->phy = NULL;
113c8afe684SRob Clark 		goto fail;
114c8afe684SRob Clark 	}
115c8afe684SRob Clark 
116dada25bdSRob Clark 	hdmi->mmio = msm_ioremap(pdev, config->mmio_name, "HDMI");
117c8afe684SRob Clark 	if (IS_ERR(hdmi->mmio)) {
118c8afe684SRob Clark 		ret = PTR_ERR(hdmi->mmio);
119c8afe684SRob Clark 		goto fail;
120c8afe684SRob Clark 	}
121c8afe684SRob Clark 
122dada25bdSRob Clark 	BUG_ON(config->hpd_reg_cnt > ARRAY_SIZE(hdmi->hpd_regs));
123dada25bdSRob Clark 	for (i = 0; i < config->hpd_reg_cnt; i++) {
124dada25bdSRob Clark 		struct regulator *reg;
125dada25bdSRob Clark 
1263e87599bSRob Clark 		reg = devm_regulator_get(&pdev->dev,
12741e69778SRob Clark 				config->hpd_reg_names[i]);
128dada25bdSRob Clark 		if (IS_ERR(reg)) {
129dada25bdSRob Clark 			ret = PTR_ERR(reg);
130dada25bdSRob Clark 			dev_err(dev->dev, "failed to get hpd regulator: %s (%d)\n",
131dada25bdSRob Clark 					config->hpd_reg_names[i], ret);
132c8afe684SRob Clark 			goto fail;
133c8afe684SRob Clark 		}
134c8afe684SRob Clark 
135dada25bdSRob Clark 		hdmi->hpd_regs[i] = reg;
136dada25bdSRob Clark 	}
137c8afe684SRob Clark 
138dada25bdSRob Clark 	BUG_ON(config->pwr_reg_cnt > ARRAY_SIZE(hdmi->pwr_regs));
139dada25bdSRob Clark 	for (i = 0; i < config->pwr_reg_cnt; i++) {
140dada25bdSRob Clark 		struct regulator *reg;
141dada25bdSRob Clark 
1423e87599bSRob Clark 		reg = devm_regulator_get(&pdev->dev,
14341e69778SRob Clark 				config->pwr_reg_names[i]);
144dada25bdSRob Clark 		if (IS_ERR(reg)) {
145dada25bdSRob Clark 			ret = PTR_ERR(reg);
146dada25bdSRob Clark 			dev_err(dev->dev, "failed to get pwr regulator: %s (%d)\n",
147dada25bdSRob Clark 					config->pwr_reg_names[i], ret);
148c8afe684SRob Clark 			goto fail;
149c8afe684SRob Clark 		}
150c8afe684SRob Clark 
151dada25bdSRob Clark 		hdmi->pwr_regs[i] = reg;
152dada25bdSRob Clark 	}
153dada25bdSRob Clark 
154dada25bdSRob Clark 	BUG_ON(config->hpd_clk_cnt > ARRAY_SIZE(hdmi->hpd_clks));
155dada25bdSRob Clark 	for (i = 0; i < config->hpd_clk_cnt; i++) {
156dada25bdSRob Clark 		struct clk *clk;
157dada25bdSRob Clark 
158dada25bdSRob Clark 		clk = devm_clk_get(&pdev->dev, config->hpd_clk_names[i]);
159dada25bdSRob Clark 		if (IS_ERR(clk)) {
160dada25bdSRob Clark 			ret = PTR_ERR(clk);
161dada25bdSRob Clark 			dev_err(dev->dev, "failed to get hpd clk: %s (%d)\n",
162dada25bdSRob Clark 					config->hpd_clk_names[i], ret);
163c8afe684SRob Clark 			goto fail;
164c8afe684SRob Clark 		}
165c8afe684SRob Clark 
166dada25bdSRob Clark 		hdmi->hpd_clks[i] = clk;
167dada25bdSRob Clark 	}
168dada25bdSRob Clark 
169dada25bdSRob Clark 	BUG_ON(config->pwr_clk_cnt > ARRAY_SIZE(hdmi->pwr_clks));
170dada25bdSRob Clark 	for (i = 0; i < config->pwr_clk_cnt; i++) {
171dada25bdSRob Clark 		struct clk *clk;
172dada25bdSRob Clark 
173dada25bdSRob Clark 		clk = devm_clk_get(&pdev->dev, config->pwr_clk_names[i]);
174dada25bdSRob Clark 		if (IS_ERR(clk)) {
175dada25bdSRob Clark 			ret = PTR_ERR(clk);
176dada25bdSRob Clark 			dev_err(dev->dev, "failed to get pwr clk: %s (%d)\n",
177dada25bdSRob Clark 					config->pwr_clk_names[i], ret);
178c8afe684SRob Clark 			goto fail;
179c8afe684SRob Clark 		}
180c8afe684SRob Clark 
181dada25bdSRob Clark 		hdmi->pwr_clks[i] = clk;
182dada25bdSRob Clark 	}
183dada25bdSRob Clark 
184c8afe684SRob Clark 	hdmi->i2c = hdmi_i2c_init(hdmi);
185c8afe684SRob Clark 	if (IS_ERR(hdmi->i2c)) {
186c8afe684SRob Clark 		ret = PTR_ERR(hdmi->i2c);
187c8afe684SRob Clark 		dev_err(dev->dev, "failed to get i2c: %d\n", ret);
188c8afe684SRob Clark 		hdmi->i2c = NULL;
189c8afe684SRob Clark 		goto fail;
190c8afe684SRob Clark 	}
191c8afe684SRob Clark 
192a3376e3eSRob Clark 	hdmi->bridge = hdmi_bridge_init(hdmi);
193a3376e3eSRob Clark 	if (IS_ERR(hdmi->bridge)) {
194a3376e3eSRob Clark 		ret = PTR_ERR(hdmi->bridge);
195a3376e3eSRob Clark 		dev_err(dev->dev, "failed to create HDMI bridge: %d\n", ret);
196a3376e3eSRob Clark 		hdmi->bridge = NULL;
197a3376e3eSRob Clark 		goto fail;
198a3376e3eSRob Clark 	}
199a3376e3eSRob Clark 
200a3376e3eSRob Clark 	hdmi->connector = hdmi_connector_init(hdmi);
201a3376e3eSRob Clark 	if (IS_ERR(hdmi->connector)) {
202a3376e3eSRob Clark 		ret = PTR_ERR(hdmi->connector);
203a3376e3eSRob Clark 		dev_err(dev->dev, "failed to create HDMI connector: %d\n", ret);
204a3376e3eSRob Clark 		hdmi->connector = NULL;
205a3376e3eSRob Clark 		goto fail;
206a3376e3eSRob Clark 	}
207a3376e3eSRob Clark 
208dada25bdSRob Clark 	if (!config->shared_irq) {
209c8afe684SRob Clark 		hdmi->irq = platform_get_irq(pdev, 0);
210c8afe684SRob Clark 		if (hdmi->irq < 0) {
211c8afe684SRob Clark 			ret = hdmi->irq;
212c8afe684SRob Clark 			dev_err(dev->dev, "failed to get irq: %d\n", ret);
213c8afe684SRob Clark 			goto fail;
214c8afe684SRob Clark 		}
215c8afe684SRob Clark 
216c8afe684SRob Clark 		ret = devm_request_threaded_irq(&pdev->dev, hdmi->irq,
217c8afe684SRob Clark 				NULL, hdmi_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
218c8afe684SRob Clark 				"hdmi_isr", hdmi);
219c8afe684SRob Clark 		if (ret < 0) {
220c8afe684SRob Clark 			dev_err(dev->dev, "failed to request IRQ%u: %d\n",
221c8afe684SRob Clark 					hdmi->irq, ret);
222c8afe684SRob Clark 			goto fail;
223c8afe684SRob Clark 		}
224dada25bdSRob Clark 	}
225c8afe684SRob Clark 
226a3376e3eSRob Clark 	encoder->bridge = hdmi->bridge;
227a3376e3eSRob Clark 
228a3376e3eSRob Clark 	priv->bridges[priv->num_bridges++]       = hdmi->bridge;
229a3376e3eSRob Clark 	priv->connectors[priv->num_connectors++] = hdmi->connector;
230a3376e3eSRob Clark 
231c0c0d9eeSRob Clark 	platform_set_drvdata(pdev, hdmi);
232c0c0d9eeSRob Clark 
233dada25bdSRob Clark 	return hdmi;
234c8afe684SRob Clark 
235c8afe684SRob Clark fail:
236a3376e3eSRob Clark 	if (hdmi) {
237a3376e3eSRob Clark 		/* bridge/connector are normally destroyed by drm: */
238a3376e3eSRob Clark 		if (hdmi->bridge)
239a3376e3eSRob Clark 			hdmi->bridge->funcs->destroy(hdmi->bridge);
240a3376e3eSRob Clark 		if (hdmi->connector)
241a3376e3eSRob Clark 			hdmi->connector->funcs->destroy(hdmi->connector);
242a3376e3eSRob Clark 		hdmi_destroy(&hdmi->refcount);
243a3376e3eSRob Clark 	}
244c8afe684SRob Clark 
245dada25bdSRob Clark 	return ERR_PTR(ret);
246c8afe684SRob Clark }
247c8afe684SRob Clark 
248c8afe684SRob Clark /*
249c8afe684SRob Clark  * The hdmi device:
250c8afe684SRob Clark  */
251c8afe684SRob Clark 
252dada25bdSRob Clark #include <linux/of_gpio.h>
253dada25bdSRob Clark 
254060530f1SRob Clark static void set_hdmi_pdev(struct drm_device *dev,
255060530f1SRob Clark 		struct platform_device *pdev)
256060530f1SRob Clark {
257060530f1SRob Clark 	struct msm_drm_private *priv = dev->dev_private;
258060530f1SRob Clark 	priv->hdmi_pdev = pdev;
259060530f1SRob Clark }
260060530f1SRob Clark 
261060530f1SRob Clark static int hdmi_bind(struct device *dev, struct device *master, void *data)
262c8afe684SRob Clark {
263c8afe684SRob Clark 	static struct hdmi_platform_config config = {};
264c8afe684SRob Clark #ifdef CONFIG_OF
265060530f1SRob Clark 	struct device_node *of_node = dev->of_node;
266dada25bdSRob Clark 
267dada25bdSRob Clark 	int get_gpio(const char *name)
268dada25bdSRob Clark 	{
269dada25bdSRob Clark 		int gpio = of_get_named_gpio(of_node, name, 0);
270dada25bdSRob Clark 		if (gpio < 0) {
27141e69778SRob Clark 			char name2[32];
27241e69778SRob Clark 			snprintf(name2, sizeof(name2), "%s-gpio", name);
27341e69778SRob Clark 			gpio = of_get_named_gpio(of_node, name2, 0);
27441e69778SRob Clark 			if (gpio < 0) {
275060530f1SRob Clark 				dev_err(dev, "failed to get gpio: %s (%d)\n",
276dada25bdSRob Clark 						name, gpio);
277dada25bdSRob Clark 				gpio = -1;
278dada25bdSRob Clark 			}
27941e69778SRob Clark 		}
280dada25bdSRob Clark 		return gpio;
281dada25bdSRob Clark 	}
282dada25bdSRob Clark 
28341e69778SRob Clark 	if (of_device_is_compatible(of_node, "qcom,hdmi-tx-8074")) {
284dada25bdSRob Clark 		static const char *hpd_reg_names[] = {"hpd-gdsc", "hpd-5v"};
285dada25bdSRob Clark 		static const char *pwr_reg_names[] = {"core-vdda", "core-vcc"};
286dada25bdSRob Clark 		static const char *hpd_clk_names[] = {"iface_clk", "core_clk", "mdp_core_clk"};
287b77f47e7SStephane Viau 		static unsigned long hpd_clk_freq[] = {0, 19200000, 0};
288dada25bdSRob Clark 		static const char *pwr_clk_names[] = {"extp_clk", "alt_iface_clk"};
289dada25bdSRob Clark 		config.phy_init      = hdmi_phy_8x74_init;
290dada25bdSRob Clark 		config.hpd_reg_names = hpd_reg_names;
291dada25bdSRob Clark 		config.hpd_reg_cnt   = ARRAY_SIZE(hpd_reg_names);
292dada25bdSRob Clark 		config.pwr_reg_names = pwr_reg_names;
293dada25bdSRob Clark 		config.pwr_reg_cnt   = ARRAY_SIZE(pwr_reg_names);
294dada25bdSRob Clark 		config.hpd_clk_names = hpd_clk_names;
295b77f47e7SStephane Viau 		config.hpd_freq      = hpd_clk_freq;
296dada25bdSRob Clark 		config.hpd_clk_cnt   = ARRAY_SIZE(hpd_clk_names);
297dada25bdSRob Clark 		config.pwr_clk_names = pwr_clk_names;
298dada25bdSRob Clark 		config.pwr_clk_cnt   = ARRAY_SIZE(pwr_clk_names);
29941e69778SRob Clark 		config.shared_irq    = true;
30041e69778SRob Clark 	} else if (of_device_is_compatible(of_node, "qcom,hdmi-tx-8960")) {
30141e69778SRob Clark 		static const char *hpd_clk_names[] = {"core_clk", "master_iface_clk", "slave_iface_clk"};
30241e69778SRob Clark 		static const char *hpd_reg_names[] = {"core-vdda", "hdmi-mux"};
30341e69778SRob Clark 		config.phy_init      = hdmi_phy_8960_init;
30441e69778SRob Clark 		config.hpd_reg_names = hpd_reg_names;
30541e69778SRob Clark 		config.hpd_reg_cnt   = ARRAY_SIZE(hpd_reg_names);
30641e69778SRob Clark 		config.hpd_clk_names = hpd_clk_names;
30741e69778SRob Clark 		config.hpd_clk_cnt   = ARRAY_SIZE(hpd_clk_names);
30841e69778SRob Clark 	} else if (of_device_is_compatible(of_node, "qcom,hdmi-tx-8660")) {
30941e69778SRob Clark 		config.phy_init      = hdmi_phy_8x60_init;
31041e69778SRob Clark 	} else {
31141e69778SRob Clark 		dev_err(dev, "unknown phy: %s\n", of_node->name);
31241e69778SRob Clark 	}
31341e69778SRob Clark 
31441e69778SRob Clark 	config.mmio_name     = "core_physical";
315dada25bdSRob Clark 	config.ddc_clk_gpio  = get_gpio("qcom,hdmi-tx-ddc-clk");
316dada25bdSRob Clark 	config.ddc_data_gpio = get_gpio("qcom,hdmi-tx-ddc-data");
317dada25bdSRob Clark 	config.hpd_gpio      = get_gpio("qcom,hdmi-tx-hpd");
318dada25bdSRob Clark 	config.mux_en_gpio   = get_gpio("qcom,hdmi-tx-mux-en");
319dada25bdSRob Clark 	config.mux_sel_gpio  = get_gpio("qcom,hdmi-tx-mux-sel");
3201930f38aSBeeresh Gopal 	config.mux_lpm_gpio  = get_gpio("qcom,hdmi-tx-mux-lpm");
321dada25bdSRob Clark 
322c8afe684SRob Clark #else
323dada25bdSRob Clark 	static const char *hpd_clk_names[] = {
324dada25bdSRob Clark 			"core_clk", "master_iface_clk", "slave_iface_clk",
325dada25bdSRob Clark 	};
326c8afe684SRob Clark 	if (cpu_is_apq8064()) {
327dada25bdSRob Clark 		static const char *hpd_reg_names[] = {"8921_hdmi_mvs"};
328c8afe684SRob Clark 		config.phy_init      = hdmi_phy_8960_init;
329dada25bdSRob Clark 		config.mmio_name     = "hdmi_msm_hdmi_addr";
330dada25bdSRob Clark 		config.hpd_reg_names = hpd_reg_names;
331dada25bdSRob Clark 		config.hpd_reg_cnt   = ARRAY_SIZE(hpd_reg_names);
332dada25bdSRob Clark 		config.hpd_clk_names = hpd_clk_names;
333dada25bdSRob Clark 		config.hpd_clk_cnt   = ARRAY_SIZE(hpd_clk_names);
334c8afe684SRob Clark 		config.ddc_clk_gpio  = 70;
335c8afe684SRob Clark 		config.ddc_data_gpio = 71;
336c8afe684SRob Clark 		config.hpd_gpio      = 72;
337dada25bdSRob Clark 		config.mux_en_gpio   = -1;
338c0c0d9eeSRob Clark 		config.mux_sel_gpio  = -1;
339e529c7e6SRob Clark 	} else if (cpu_is_msm8960() || cpu_is_msm8960ab()) {
340dada25bdSRob Clark 		static const char *hpd_reg_names[] = {"8921_hdmi_mvs"};
341c8afe684SRob Clark 		config.phy_init      = hdmi_phy_8960_init;
342dada25bdSRob Clark 		config.mmio_name     = "hdmi_msm_hdmi_addr";
343dada25bdSRob Clark 		config.hpd_reg_names = hpd_reg_names;
344dada25bdSRob Clark 		config.hpd_reg_cnt   = ARRAY_SIZE(hpd_reg_names);
345dada25bdSRob Clark 		config.hpd_clk_names = hpd_clk_names;
346dada25bdSRob Clark 		config.hpd_clk_cnt   = ARRAY_SIZE(hpd_clk_names);
347c8afe684SRob Clark 		config.ddc_clk_gpio  = 100;
348c8afe684SRob Clark 		config.ddc_data_gpio = 101;
349c8afe684SRob Clark 		config.hpd_gpio      = 102;
350dada25bdSRob Clark 		config.mux_en_gpio   = -1;
351dada25bdSRob Clark 		config.mux_sel_gpio  = -1;
352c8afe684SRob Clark 	} else if (cpu_is_msm8x60()) {
353dada25bdSRob Clark 		static const char *hpd_reg_names[] = {
354dada25bdSRob Clark 				"8901_hdmi_mvs", "8901_mpp0"
355dada25bdSRob Clark 		};
356c8afe684SRob Clark 		config.phy_init      = hdmi_phy_8x60_init;
357dada25bdSRob Clark 		config.mmio_name     = "hdmi_msm_hdmi_addr";
358dada25bdSRob Clark 		config.hpd_reg_names = hpd_reg_names;
359dada25bdSRob Clark 		config.hpd_reg_cnt   = ARRAY_SIZE(hpd_reg_names);
360dada25bdSRob Clark 		config.hpd_clk_names = hpd_clk_names;
361dada25bdSRob Clark 		config.hpd_clk_cnt   = ARRAY_SIZE(hpd_clk_names);
362c8afe684SRob Clark 		config.ddc_clk_gpio  = 170;
363c8afe684SRob Clark 		config.ddc_data_gpio = 171;
364c8afe684SRob Clark 		config.hpd_gpio      = 172;
365dada25bdSRob Clark 		config.mux_en_gpio   = -1;
366dada25bdSRob Clark 		config.mux_sel_gpio  = -1;
367c8afe684SRob Clark 	}
368c8afe684SRob Clark #endif
369060530f1SRob Clark 	dev->platform_data = &config;
370060530f1SRob Clark 	set_hdmi_pdev(dev_get_drvdata(master), to_platform_device(dev));
371c8afe684SRob Clark 	return 0;
372c8afe684SRob Clark }
373c8afe684SRob Clark 
374060530f1SRob Clark static void hdmi_unbind(struct device *dev, struct device *master,
375060530f1SRob Clark 		void *data)
376060530f1SRob Clark {
377060530f1SRob Clark 	set_hdmi_pdev(dev_get_drvdata(master), NULL);
378060530f1SRob Clark }
379060530f1SRob Clark 
380060530f1SRob Clark static const struct component_ops hdmi_ops = {
381060530f1SRob Clark 		.bind   = hdmi_bind,
382060530f1SRob Clark 		.unbind = hdmi_unbind,
383060530f1SRob Clark };
384060530f1SRob Clark 
385060530f1SRob Clark static int hdmi_dev_probe(struct platform_device *pdev)
386060530f1SRob Clark {
387060530f1SRob Clark 	return component_add(&pdev->dev, &hdmi_ops);
388060530f1SRob Clark }
389060530f1SRob Clark 
390c8afe684SRob Clark static int hdmi_dev_remove(struct platform_device *pdev)
391c8afe684SRob Clark {
392060530f1SRob Clark 	component_del(&pdev->dev, &hdmi_ops);
393c8afe684SRob Clark 	return 0;
394c8afe684SRob Clark }
395c8afe684SRob Clark 
396dada25bdSRob Clark static const struct of_device_id dt_match[] = {
39741e69778SRob Clark 	{ .compatible = "qcom,hdmi-tx-8074" },
39841e69778SRob Clark 	{ .compatible = "qcom,hdmi-tx-8960" },
39941e69778SRob Clark 	{ .compatible = "qcom,hdmi-tx-8660" },
400dada25bdSRob Clark 	{}
401dada25bdSRob Clark };
402dada25bdSRob Clark 
403c8afe684SRob Clark static struct platform_driver hdmi_driver = {
404c8afe684SRob Clark 	.probe = hdmi_dev_probe,
405c8afe684SRob Clark 	.remove = hdmi_dev_remove,
406dada25bdSRob Clark 	.driver = {
407dada25bdSRob Clark 		.name = "hdmi_msm",
408dada25bdSRob Clark 		.of_match_table = dt_match,
409dada25bdSRob Clark 	},
410c8afe684SRob Clark };
411c8afe684SRob Clark 
412c8afe684SRob Clark void __init hdmi_register(void)
413c8afe684SRob Clark {
414c8afe684SRob Clark 	platform_driver_register(&hdmi_driver);
415c8afe684SRob Clark }
416c8afe684SRob Clark 
417c8afe684SRob Clark void __exit hdmi_unregister(void)
418c8afe684SRob Clark {
419c8afe684SRob Clark 	platform_driver_unregister(&hdmi_driver);
420c8afe684SRob Clark }
421