]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - drivers/gpu/drm/msm/hdmi/hdmi.c
drm/msm/hdmi: Fix missing put_device() call in msm_hdmi_get_phy
[mirror_ubuntu-jammy-kernel.git] / drivers / gpu / drm / msm / hdmi / hdmi.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (c) 2014 The Linux Foundation. All rights reserved.
4 * Copyright (C) 2013 Red Hat
5 * Author: Rob Clark <robdclark@gmail.com>
6 */
7
8 #include <linux/of_irq.h>
9 #include <linux/of_gpio.h>
10
11 #include <sound/hdmi-codec.h>
12 #include "hdmi.h"
13
14 void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on)
15 {
16 uint32_t ctrl = 0;
17 unsigned long flags;
18
19 spin_lock_irqsave(&hdmi->reg_lock, flags);
20 if (power_on) {
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;
26 } else {
27 ctrl |= HDMI_CTRL_HDMI;
28 }
29 } else {
30 ctrl = HDMI_CTRL_HDMI;
31 }
32
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);
37 }
38
39 static irqreturn_t msm_hdmi_irq(int irq, void *dev_id)
40 {
41 struct hdmi *hdmi = dev_id;
42
43 /* Process HPD: */
44 msm_hdmi_connector_irq(hdmi->connector);
45
46 /* Process DDC: */
47 msm_hdmi_i2c_irq(hdmi->i2c);
48
49 /* Process HDCP: */
50 if (hdmi->hdcp_ctrl)
51 msm_hdmi_hdcp_irq(hdmi->hdcp_ctrl);
52
53 /* TODO audio.. */
54
55 return IRQ_HANDLED;
56 }
57
58 static void msm_hdmi_destroy(struct hdmi *hdmi)
59 {
60 /*
61 * at this point, hpd has been disabled,
62 * after flush workq, it's safe to deinit hdcp
63 */
64 if (hdmi->workq) {
65 flush_workqueue(hdmi->workq);
66 destroy_workqueue(hdmi->workq);
67 }
68 msm_hdmi_hdcp_destroy(hdmi);
69
70 if (hdmi->phy_dev) {
71 put_device(hdmi->phy_dev);
72 hdmi->phy = NULL;
73 hdmi->phy_dev = NULL;
74 }
75
76 if (hdmi->i2c)
77 msm_hdmi_i2c_destroy(hdmi->i2c);
78
79 platform_set_drvdata(hdmi->pdev, NULL);
80 }
81
82 static int msm_hdmi_get_phy(struct hdmi *hdmi)
83 {
84 struct platform_device *pdev = hdmi->pdev;
85 struct platform_device *phy_pdev;
86 struct device_node *phy_node;
87
88 phy_node = of_parse_phandle(pdev->dev.of_node, "phys", 0);
89 if (!phy_node) {
90 DRM_DEV_ERROR(&pdev->dev, "cannot find phy device\n");
91 return -ENXIO;
92 }
93
94 phy_pdev = of_find_device_by_node(phy_node);
95 if (phy_pdev)
96 hdmi->phy = platform_get_drvdata(phy_pdev);
97
98 of_node_put(phy_node);
99
100 if (!phy_pdev) {
101 DRM_DEV_ERROR(&pdev->dev, "phy driver is not ready\n");
102 return -EPROBE_DEFER;
103 }
104 if (!hdmi->phy) {
105 DRM_DEV_ERROR(&pdev->dev, "phy driver is not ready\n");
106 put_device(&phy_pdev->dev);
107 return -EPROBE_DEFER;
108 }
109
110 hdmi->phy_dev = get_device(&phy_pdev->dev);
111
112 return 0;
113 }
114
115 /* construct hdmi at bind/probe time, grab all the resources. If
116 * we are to EPROBE_DEFER we want to do it here, rather than later
117 * at modeset_init() time
118 */
119 static struct hdmi *msm_hdmi_init(struct platform_device *pdev)
120 {
121 struct hdmi_platform_config *config = pdev->dev.platform_data;
122 struct hdmi *hdmi = NULL;
123 struct resource *res;
124 int i, ret;
125
126 hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
127 if (!hdmi) {
128 ret = -ENOMEM;
129 goto fail;
130 }
131
132 hdmi->pdev = pdev;
133 hdmi->config = config;
134 spin_lock_init(&hdmi->reg_lock);
135
136 hdmi->mmio = msm_ioremap(pdev, config->mmio_name, "HDMI");
137 if (IS_ERR(hdmi->mmio)) {
138 ret = PTR_ERR(hdmi->mmio);
139 goto fail;
140 }
141
142 /* HDCP needs physical address of hdmi register */
143 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
144 config->mmio_name);
145 hdmi->mmio_phy_addr = res->start;
146
147 hdmi->qfprom_mmio = msm_ioremap(pdev,
148 config->qfprom_mmio_name, "HDMI_QFPROM");
149 if (IS_ERR(hdmi->qfprom_mmio)) {
150 DRM_DEV_INFO(&pdev->dev, "can't find qfprom resource\n");
151 hdmi->qfprom_mmio = NULL;
152 }
153
154 hdmi->hpd_regs = devm_kcalloc(&pdev->dev,
155 config->hpd_reg_cnt,
156 sizeof(hdmi->hpd_regs[0]),
157 GFP_KERNEL);
158 if (!hdmi->hpd_regs) {
159 ret = -ENOMEM;
160 goto fail;
161 }
162 for (i = 0; i < config->hpd_reg_cnt; i++) {
163 struct regulator *reg;
164
165 reg = devm_regulator_get(&pdev->dev,
166 config->hpd_reg_names[i]);
167 if (IS_ERR(reg)) {
168 ret = PTR_ERR(reg);
169 DRM_DEV_ERROR(&pdev->dev, "failed to get hpd regulator: %s (%d)\n",
170 config->hpd_reg_names[i], ret);
171 goto fail;
172 }
173
174 hdmi->hpd_regs[i] = reg;
175 }
176
177 hdmi->pwr_regs = devm_kcalloc(&pdev->dev,
178 config->pwr_reg_cnt,
179 sizeof(hdmi->pwr_regs[0]),
180 GFP_KERNEL);
181 if (!hdmi->pwr_regs) {
182 ret = -ENOMEM;
183 goto fail;
184 }
185 for (i = 0; i < config->pwr_reg_cnt; i++) {
186 struct regulator *reg;
187
188 reg = devm_regulator_get(&pdev->dev,
189 config->pwr_reg_names[i]);
190 if (IS_ERR(reg)) {
191 ret = PTR_ERR(reg);
192 DRM_DEV_ERROR(&pdev->dev, "failed to get pwr regulator: %s (%d)\n",
193 config->pwr_reg_names[i], ret);
194 goto fail;
195 }
196
197 hdmi->pwr_regs[i] = reg;
198 }
199
200 hdmi->hpd_clks = devm_kcalloc(&pdev->dev,
201 config->hpd_clk_cnt,
202 sizeof(hdmi->hpd_clks[0]),
203 GFP_KERNEL);
204 if (!hdmi->hpd_clks) {
205 ret = -ENOMEM;
206 goto fail;
207 }
208 for (i = 0; i < config->hpd_clk_cnt; i++) {
209 struct clk *clk;
210
211 clk = msm_clk_get(pdev, config->hpd_clk_names[i]);
212 if (IS_ERR(clk)) {
213 ret = PTR_ERR(clk);
214 DRM_DEV_ERROR(&pdev->dev, "failed to get hpd clk: %s (%d)\n",
215 config->hpd_clk_names[i], ret);
216 goto fail;
217 }
218
219 hdmi->hpd_clks[i] = clk;
220 }
221
222 hdmi->pwr_clks = devm_kcalloc(&pdev->dev,
223 config->pwr_clk_cnt,
224 sizeof(hdmi->pwr_clks[0]),
225 GFP_KERNEL);
226 if (!hdmi->pwr_clks) {
227 ret = -ENOMEM;
228 goto fail;
229 }
230 for (i = 0; i < config->pwr_clk_cnt; i++) {
231 struct clk *clk;
232
233 clk = msm_clk_get(pdev, config->pwr_clk_names[i]);
234 if (IS_ERR(clk)) {
235 ret = PTR_ERR(clk);
236 DRM_DEV_ERROR(&pdev->dev, "failed to get pwr clk: %s (%d)\n",
237 config->pwr_clk_names[i], ret);
238 goto fail;
239 }
240
241 hdmi->pwr_clks[i] = clk;
242 }
243
244 pm_runtime_enable(&pdev->dev);
245
246 hdmi->workq = alloc_ordered_workqueue("msm_hdmi", 0);
247
248 hdmi->i2c = msm_hdmi_i2c_init(hdmi);
249 if (IS_ERR(hdmi->i2c)) {
250 ret = PTR_ERR(hdmi->i2c);
251 DRM_DEV_ERROR(&pdev->dev, "failed to get i2c: %d\n", ret);
252 hdmi->i2c = NULL;
253 goto fail;
254 }
255
256 ret = msm_hdmi_get_phy(hdmi);
257 if (ret) {
258 DRM_DEV_ERROR(&pdev->dev, "failed to get phy\n");
259 goto fail;
260 }
261
262 hdmi->hdcp_ctrl = msm_hdmi_hdcp_init(hdmi);
263 if (IS_ERR(hdmi->hdcp_ctrl)) {
264 dev_warn(&pdev->dev, "failed to init hdcp: disabled\n");
265 hdmi->hdcp_ctrl = NULL;
266 }
267
268 return hdmi;
269
270 fail:
271 if (hdmi)
272 msm_hdmi_destroy(hdmi);
273
274 return ERR_PTR(ret);
275 }
276
277 /* Second part of initialization, the drm/kms level modeset_init,
278 * constructs/initializes mode objects, etc, is called from master
279 * driver (not hdmi sub-device's probe/bind!)
280 *
281 * Any resource (regulator/clk/etc) which could be missing at boot
282 * should be handled in msm_hdmi_init() so that failure happens from
283 * hdmi sub-device's probe.
284 */
285 int msm_hdmi_modeset_init(struct hdmi *hdmi,
286 struct drm_device *dev, struct drm_encoder *encoder)
287 {
288 struct msm_drm_private *priv = dev->dev_private;
289 struct platform_device *pdev = hdmi->pdev;
290 int ret;
291
292 hdmi->dev = dev;
293 hdmi->encoder = encoder;
294
295 hdmi_audio_infoframe_init(&hdmi->audio.infoframe);
296
297 hdmi->bridge = msm_hdmi_bridge_init(hdmi);
298 if (IS_ERR(hdmi->bridge)) {
299 ret = PTR_ERR(hdmi->bridge);
300 DRM_DEV_ERROR(dev->dev, "failed to create HDMI bridge: %d\n", ret);
301 hdmi->bridge = NULL;
302 goto fail;
303 }
304
305 hdmi->connector = msm_hdmi_connector_init(hdmi);
306 if (IS_ERR(hdmi->connector)) {
307 ret = PTR_ERR(hdmi->connector);
308 DRM_DEV_ERROR(dev->dev, "failed to create HDMI connector: %d\n", ret);
309 hdmi->connector = NULL;
310 goto fail;
311 }
312
313 hdmi->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
314 if (hdmi->irq < 0) {
315 ret = hdmi->irq;
316 DRM_DEV_ERROR(dev->dev, "failed to get irq: %d\n", ret);
317 goto fail;
318 }
319
320 ret = devm_request_irq(&pdev->dev, hdmi->irq,
321 msm_hdmi_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
322 "hdmi_isr", hdmi);
323 if (ret < 0) {
324 DRM_DEV_ERROR(dev->dev, "failed to request IRQ%u: %d\n",
325 hdmi->irq, ret);
326 goto fail;
327 }
328
329 ret = msm_hdmi_hpd_enable(hdmi->connector);
330 if (ret < 0) {
331 DRM_DEV_ERROR(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret);
332 goto fail;
333 }
334
335 priv->bridges[priv->num_bridges++] = hdmi->bridge;
336 priv->connectors[priv->num_connectors++] = hdmi->connector;
337
338 platform_set_drvdata(pdev, hdmi);
339
340 return 0;
341
342 fail:
343 /* bridge is normally destroyed by drm: */
344 if (hdmi->bridge) {
345 msm_hdmi_bridge_destroy(hdmi->bridge);
346 hdmi->bridge = NULL;
347 }
348 if (hdmi->connector) {
349 hdmi->connector->funcs->destroy(hdmi->connector);
350 hdmi->connector = NULL;
351 }
352
353 return ret;
354 }
355
356 /*
357 * The hdmi device:
358 */
359
360 #define HDMI_CFG(item, entry) \
361 .item ## _names = item ##_names_ ## entry, \
362 .item ## _cnt = ARRAY_SIZE(item ## _names_ ## entry)
363
364 static const char *pwr_reg_names_none[] = {};
365 static const char *hpd_reg_names_none[] = {};
366
367 static struct hdmi_platform_config hdmi_tx_8660_config;
368
369 static const char *hpd_reg_names_8960[] = {"core-vdda", "hdmi-mux"};
370 static const char *hpd_clk_names_8960[] = {"core", "master_iface", "slave_iface"};
371
372 static struct hdmi_platform_config hdmi_tx_8960_config = {
373 HDMI_CFG(hpd_reg, 8960),
374 HDMI_CFG(hpd_clk, 8960),
375 };
376
377 static const char *pwr_reg_names_8x74[] = {"core-vdda", "core-vcc"};
378 static const char *hpd_reg_names_8x74[] = {"hpd-gdsc", "hpd-5v"};
379 static const char *pwr_clk_names_8x74[] = {"extp", "alt_iface"};
380 static const char *hpd_clk_names_8x74[] = {"iface", "core", "mdp_core"};
381 static unsigned long hpd_clk_freq_8x74[] = {0, 19200000, 0};
382
383 static struct hdmi_platform_config hdmi_tx_8974_config = {
384 HDMI_CFG(pwr_reg, 8x74),
385 HDMI_CFG(hpd_reg, 8x74),
386 HDMI_CFG(pwr_clk, 8x74),
387 HDMI_CFG(hpd_clk, 8x74),
388 .hpd_freq = hpd_clk_freq_8x74,
389 };
390
391 static const char *hpd_reg_names_8084[] = {"hpd-gdsc", "hpd-5v", "hpd-5v-en"};
392
393 static struct hdmi_platform_config hdmi_tx_8084_config = {
394 HDMI_CFG(pwr_reg, 8x74),
395 HDMI_CFG(hpd_reg, 8084),
396 HDMI_CFG(pwr_clk, 8x74),
397 HDMI_CFG(hpd_clk, 8x74),
398 .hpd_freq = hpd_clk_freq_8x74,
399 };
400
401 static struct hdmi_platform_config hdmi_tx_8994_config = {
402 HDMI_CFG(pwr_reg, 8x74),
403 HDMI_CFG(hpd_reg, none),
404 HDMI_CFG(pwr_clk, 8x74),
405 HDMI_CFG(hpd_clk, 8x74),
406 .hpd_freq = hpd_clk_freq_8x74,
407 };
408
409 static struct hdmi_platform_config hdmi_tx_8996_config = {
410 HDMI_CFG(pwr_reg, none),
411 HDMI_CFG(hpd_reg, none),
412 HDMI_CFG(pwr_clk, 8x74),
413 HDMI_CFG(hpd_clk, 8x74),
414 .hpd_freq = hpd_clk_freq_8x74,
415 };
416
417 static const struct {
418 const char *name;
419 const bool output;
420 const int value;
421 const char *label;
422 } msm_hdmi_gpio_pdata[] = {
423 { "qcom,hdmi-tx-ddc-clk", true, 1, "HDMI_DDC_CLK" },
424 { "qcom,hdmi-tx-ddc-data", true, 1, "HDMI_DDC_DATA" },
425 { "qcom,hdmi-tx-hpd", false, 1, "HDMI_HPD" },
426 { "qcom,hdmi-tx-mux-en", true, 1, "HDMI_MUX_EN" },
427 { "qcom,hdmi-tx-mux-sel", true, 0, "HDMI_MUX_SEL" },
428 { "qcom,hdmi-tx-mux-lpm", true, 1, "HDMI_MUX_LPM" },
429 };
430
431 /*
432 * HDMI audio codec callbacks
433 */
434 static int msm_hdmi_audio_hw_params(struct device *dev, void *data,
435 struct hdmi_codec_daifmt *daifmt,
436 struct hdmi_codec_params *params)
437 {
438 struct hdmi *hdmi = dev_get_drvdata(dev);
439 unsigned int chan;
440 unsigned int channel_allocation = 0;
441 unsigned int rate;
442 unsigned int level_shift = 0; /* 0dB */
443 bool down_mix = false;
444
445 DRM_DEV_DEBUG(dev, "%u Hz, %d bit, %d channels\n", params->sample_rate,
446 params->sample_width, params->cea.channels);
447
448 switch (params->cea.channels) {
449 case 2:
450 /* FR and FL speakers */
451 channel_allocation = 0;
452 chan = MSM_HDMI_AUDIO_CHANNEL_2;
453 break;
454 case 4:
455 /* FC, LFE, FR and FL speakers */
456 channel_allocation = 0x3;
457 chan = MSM_HDMI_AUDIO_CHANNEL_4;
458 break;
459 case 6:
460 /* RR, RL, FC, LFE, FR and FL speakers */
461 channel_allocation = 0x0B;
462 chan = MSM_HDMI_AUDIO_CHANNEL_6;
463 break;
464 case 8:
465 /* FRC, FLC, RR, RL, FC, LFE, FR and FL speakers */
466 channel_allocation = 0x1F;
467 chan = MSM_HDMI_AUDIO_CHANNEL_8;
468 break;
469 default:
470 return -EINVAL;
471 }
472
473 switch (params->sample_rate) {
474 case 32000:
475 rate = HDMI_SAMPLE_RATE_32KHZ;
476 break;
477 case 44100:
478 rate = HDMI_SAMPLE_RATE_44_1KHZ;
479 break;
480 case 48000:
481 rate = HDMI_SAMPLE_RATE_48KHZ;
482 break;
483 case 88200:
484 rate = HDMI_SAMPLE_RATE_88_2KHZ;
485 break;
486 case 96000:
487 rate = HDMI_SAMPLE_RATE_96KHZ;
488 break;
489 case 176400:
490 rate = HDMI_SAMPLE_RATE_176_4KHZ;
491 break;
492 case 192000:
493 rate = HDMI_SAMPLE_RATE_192KHZ;
494 break;
495 default:
496 DRM_DEV_ERROR(dev, "rate[%d] not supported!\n",
497 params->sample_rate);
498 return -EINVAL;
499 }
500
501 msm_hdmi_audio_set_sample_rate(hdmi, rate);
502 msm_hdmi_audio_info_setup(hdmi, 1, chan, channel_allocation,
503 level_shift, down_mix);
504
505 return 0;
506 }
507
508 static void msm_hdmi_audio_shutdown(struct device *dev, void *data)
509 {
510 struct hdmi *hdmi = dev_get_drvdata(dev);
511
512 msm_hdmi_audio_info_setup(hdmi, 0, 0, 0, 0, 0);
513 }
514
515 static const struct hdmi_codec_ops msm_hdmi_audio_codec_ops = {
516 .hw_params = msm_hdmi_audio_hw_params,
517 .audio_shutdown = msm_hdmi_audio_shutdown,
518 };
519
520 static struct hdmi_codec_pdata codec_data = {
521 .ops = &msm_hdmi_audio_codec_ops,
522 .max_i2s_channels = 8,
523 .i2s = 1,
524 };
525
526 static int msm_hdmi_register_audio_driver(struct hdmi *hdmi, struct device *dev)
527 {
528 hdmi->audio_pdev = platform_device_register_data(dev,
529 HDMI_CODEC_DRV_NAME,
530 PLATFORM_DEVID_AUTO,
531 &codec_data,
532 sizeof(codec_data));
533 return PTR_ERR_OR_ZERO(hdmi->audio_pdev);
534 }
535
536 static int msm_hdmi_bind(struct device *dev, struct device *master, void *data)
537 {
538 struct drm_device *drm = dev_get_drvdata(master);
539 struct msm_drm_private *priv = drm->dev_private;
540 struct hdmi_platform_config *hdmi_cfg;
541 struct hdmi *hdmi;
542 struct device_node *of_node = dev->of_node;
543 int i, err;
544
545 hdmi_cfg = (struct hdmi_platform_config *)
546 of_device_get_match_data(dev);
547 if (!hdmi_cfg) {
548 DRM_DEV_ERROR(dev, "unknown hdmi_cfg: %pOFn\n", of_node);
549 return -ENXIO;
550 }
551
552 hdmi_cfg->mmio_name = "core_physical";
553 hdmi_cfg->qfprom_mmio_name = "qfprom_physical";
554
555 for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) {
556 const char *name = msm_hdmi_gpio_pdata[i].name;
557 struct gpio_desc *gpiod;
558
559 /*
560 * We are fetching the GPIO lines "as is" since the connector
561 * code is enabling and disabling the lines. Until that point
562 * the power-on default value will be kept.
563 */
564 gpiod = devm_gpiod_get_optional(dev, name, GPIOD_ASIS);
565 /* This will catch e.g. -PROBE_DEFER */
566 if (IS_ERR(gpiod))
567 return PTR_ERR(gpiod);
568 if (!gpiod) {
569 /* Try a second time, stripping down the name */
570 char name3[32];
571
572 /*
573 * Try again after stripping out the "qcom,hdmi-tx"
574 * prefix. This is mainly to match "hpd-gpios" used
575 * in the upstream bindings.
576 */
577 if (sscanf(name, "qcom,hdmi-tx-%s", name3))
578 gpiod = devm_gpiod_get_optional(dev, name3, GPIOD_ASIS);
579 if (IS_ERR(gpiod))
580 return PTR_ERR(gpiod);
581 if (!gpiod)
582 DBG("failed to get gpio: %s", name);
583 }
584 hdmi_cfg->gpios[i].gpiod = gpiod;
585 if (gpiod)
586 gpiod_set_consumer_name(gpiod, msm_hdmi_gpio_pdata[i].label);
587 hdmi_cfg->gpios[i].output = msm_hdmi_gpio_pdata[i].output;
588 hdmi_cfg->gpios[i].value = msm_hdmi_gpio_pdata[i].value;
589 }
590
591 dev->platform_data = hdmi_cfg;
592
593 hdmi = msm_hdmi_init(to_platform_device(dev));
594 if (IS_ERR(hdmi))
595 return PTR_ERR(hdmi);
596 priv->hdmi = hdmi;
597
598 err = msm_hdmi_register_audio_driver(hdmi, dev);
599 if (err) {
600 DRM_ERROR("Failed to attach an audio codec %d\n", err);
601 hdmi->audio_pdev = NULL;
602 }
603
604 return 0;
605 }
606
607 static void msm_hdmi_unbind(struct device *dev, struct device *master,
608 void *data)
609 {
610 struct drm_device *drm = dev_get_drvdata(master);
611 struct msm_drm_private *priv = drm->dev_private;
612 if (priv->hdmi) {
613 if (priv->hdmi->audio_pdev)
614 platform_device_unregister(priv->hdmi->audio_pdev);
615
616 msm_hdmi_destroy(priv->hdmi);
617 priv->hdmi = NULL;
618 }
619 }
620
621 static const struct component_ops msm_hdmi_ops = {
622 .bind = msm_hdmi_bind,
623 .unbind = msm_hdmi_unbind,
624 };
625
626 static int msm_hdmi_dev_probe(struct platform_device *pdev)
627 {
628 return component_add(&pdev->dev, &msm_hdmi_ops);
629 }
630
631 static int msm_hdmi_dev_remove(struct platform_device *pdev)
632 {
633 component_del(&pdev->dev, &msm_hdmi_ops);
634 return 0;
635 }
636
637 static const struct of_device_id msm_hdmi_dt_match[] = {
638 { .compatible = "qcom,hdmi-tx-8996", .data = &hdmi_tx_8996_config },
639 { .compatible = "qcom,hdmi-tx-8994", .data = &hdmi_tx_8994_config },
640 { .compatible = "qcom,hdmi-tx-8084", .data = &hdmi_tx_8084_config },
641 { .compatible = "qcom,hdmi-tx-8974", .data = &hdmi_tx_8974_config },
642 { .compatible = "qcom,hdmi-tx-8960", .data = &hdmi_tx_8960_config },
643 { .compatible = "qcom,hdmi-tx-8660", .data = &hdmi_tx_8660_config },
644 {}
645 };
646
647 static struct platform_driver msm_hdmi_driver = {
648 .probe = msm_hdmi_dev_probe,
649 .remove = msm_hdmi_dev_remove,
650 .driver = {
651 .name = "hdmi_msm",
652 .of_match_table = msm_hdmi_dt_match,
653 },
654 };
655
656 void __init msm_hdmi_register(void)
657 {
658 msm_hdmi_phy_driver_register();
659 platform_driver_register(&msm_hdmi_driver);
660 }
661
662 void __exit msm_hdmi_unregister(void)
663 {
664 platform_driver_unregister(&msm_hdmi_driver);
665 msm_hdmi_phy_driver_unregister();
666 }