1 // SPDX-License-Identifier: GPL-2.0-only
3 * HDMI Connector driver
5 * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
6 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
9 #include <linux/gpio/consumer.h>
10 #include <linux/module.h>
11 #include <linux/mutex.h>
12 #include <linux/platform_device.h>
13 #include <linux/slab.h>
15 #include "../dss/omapdss.h"
17 struct panel_drv_data
{
18 struct omap_dss_device dssdev
;
19 void (*hpd_cb
)(void *cb_data
, enum drm_connector_status status
);
21 struct mutex hpd_lock
;
25 struct gpio_desc
*hpd_gpio
;
28 #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
30 static int hdmic_connect(struct omap_dss_device
*src
,
31 struct omap_dss_device
*dst
)
36 static void hdmic_disconnect(struct omap_dss_device
*src
,
37 struct omap_dss_device
*dst
)
41 static bool hdmic_detect(struct omap_dss_device
*dssdev
)
43 struct panel_drv_data
*ddata
= to_panel_data(dssdev
);
45 return gpiod_get_value_cansleep(ddata
->hpd_gpio
);
48 static void hdmic_register_hpd_cb(struct omap_dss_device
*dssdev
,
49 void (*cb
)(void *cb_data
,
50 enum drm_connector_status status
),
53 struct panel_drv_data
*ddata
= to_panel_data(dssdev
);
55 mutex_lock(&ddata
->hpd_lock
);
57 ddata
->hpd_cb_data
= cb_data
;
58 mutex_unlock(&ddata
->hpd_lock
);
61 static void hdmic_unregister_hpd_cb(struct omap_dss_device
*dssdev
)
63 struct panel_drv_data
*ddata
= to_panel_data(dssdev
);
65 mutex_lock(&ddata
->hpd_lock
);
67 ddata
->hpd_cb_data
= NULL
;
68 mutex_unlock(&ddata
->hpd_lock
);
71 static const struct omap_dss_device_ops hdmic_ops
= {
72 .connect
= hdmic_connect
,
73 .disconnect
= hdmic_disconnect
,
75 .detect
= hdmic_detect
,
76 .register_hpd_cb
= hdmic_register_hpd_cb
,
77 .unregister_hpd_cb
= hdmic_unregister_hpd_cb
,
80 static irqreturn_t
hdmic_hpd_isr(int irq
, void *data
)
82 struct panel_drv_data
*ddata
= data
;
84 mutex_lock(&ddata
->hpd_lock
);
86 enum drm_connector_status status
;
88 if (hdmic_detect(&ddata
->dssdev
))
89 status
= connector_status_connected
;
91 status
= connector_status_disconnected
;
93 ddata
->hpd_cb(ddata
->hpd_cb_data
, status
);
95 mutex_unlock(&ddata
->hpd_lock
);
100 static int hdmic_probe(struct platform_device
*pdev
)
102 struct panel_drv_data
*ddata
;
103 struct omap_dss_device
*dssdev
;
104 struct gpio_desc
*gpio
;
107 ddata
= devm_kzalloc(&pdev
->dev
, sizeof(*ddata
), GFP_KERNEL
);
111 platform_set_drvdata(pdev
, ddata
);
112 ddata
->dev
= &pdev
->dev
;
114 mutex_init(&ddata
->hpd_lock
);
117 gpio
= devm_gpiod_get_optional(&pdev
->dev
, "hpd", GPIOD_IN
);
119 dev_err(&pdev
->dev
, "failed to parse HPD gpio\n");
120 return PTR_ERR(gpio
);
123 ddata
->hpd_gpio
= gpio
;
125 if (ddata
->hpd_gpio
) {
126 r
= devm_request_threaded_irq(&pdev
->dev
,
127 gpiod_to_irq(ddata
->hpd_gpio
),
129 IRQF_TRIGGER_RISING
| IRQF_TRIGGER_FALLING
|
136 dssdev
= &ddata
->dssdev
;
137 dssdev
->ops
= &hdmic_ops
;
138 dssdev
->dev
= &pdev
->dev
;
139 dssdev
->type
= OMAP_DISPLAY_TYPE_HDMI
;
140 dssdev
->display
= true;
141 dssdev
->owner
= THIS_MODULE
;
142 dssdev
->of_ports
= BIT(0);
143 dssdev
->ops_flags
= ddata
->hpd_gpio
144 ? OMAP_DSS_DEVICE_OP_DETECT
| OMAP_DSS_DEVICE_OP_HPD
147 omapdss_display_init(dssdev
);
148 omapdss_device_register(dssdev
);
153 static int __exit
hdmic_remove(struct platform_device
*pdev
)
155 struct panel_drv_data
*ddata
= platform_get_drvdata(pdev
);
157 omapdss_device_unregister(&ddata
->dssdev
);
162 static const struct of_device_id hdmic_of_match
[] = {
163 { .compatible
= "omapdss,hdmi-connector", },
167 MODULE_DEVICE_TABLE(of
, hdmic_of_match
);
169 static struct platform_driver hdmi_connector_driver
= {
170 .probe
= hdmic_probe
,
171 .remove
= __exit_p(hdmic_remove
),
173 .name
= "connector-hdmi",
174 .of_match_table
= hdmic_of_match
,
175 .suppress_bind_attrs
= true,
179 module_platform_driver(hdmi_connector_driver
);
181 MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
182 MODULE_DESCRIPTION("HDMI Connector driver");
183 MODULE_LICENSE("GPL");