dt-bindings: mtd: ingenic: Use standard ecc-engine property
[linux/fpc-iii.git] / drivers / gpu / drm / omapdrm / displays / connector-hdmi.c
blobe602fa4a50a4a45d2ad58bec75b10eba70c3ba6b
1 /*
2 * HDMI Connector driver
4 * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
5 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
12 #include <linux/gpio/consumer.h>
13 #include <linux/module.h>
14 #include <linux/mutex.h>
15 #include <linux/platform_device.h>
16 #include <linux/slab.h>
18 #include "../dss/omapdss.h"
20 struct panel_drv_data {
21 struct omap_dss_device dssdev;
22 void (*hpd_cb)(void *cb_data, enum drm_connector_status status);
23 void *hpd_cb_data;
24 struct mutex hpd_lock;
26 struct device *dev;
28 struct gpio_desc *hpd_gpio;
31 #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
33 static int hdmic_connect(struct omap_dss_device *src,
34 struct omap_dss_device *dst)
36 return 0;
39 static void hdmic_disconnect(struct omap_dss_device *src,
40 struct omap_dss_device *dst)
44 static int hdmic_enable(struct omap_dss_device *dssdev)
46 struct panel_drv_data *ddata = to_panel_data(dssdev);
47 struct omap_dss_device *src = dssdev->src;
48 int r;
50 dev_dbg(ddata->dev, "enable\n");
52 if (!omapdss_device_is_connected(dssdev))
53 return -ENODEV;
55 if (omapdss_device_is_enabled(dssdev))
56 return 0;
58 r = src->ops->enable(src);
59 if (r)
60 return r;
62 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
64 return r;
67 static void hdmic_disable(struct omap_dss_device *dssdev)
69 struct panel_drv_data *ddata = to_panel_data(dssdev);
70 struct omap_dss_device *src = dssdev->src;
72 dev_dbg(ddata->dev, "disable\n");
74 if (!omapdss_device_is_enabled(dssdev))
75 return;
77 src->ops->disable(src);
79 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
82 static bool hdmic_detect(struct omap_dss_device *dssdev)
84 struct panel_drv_data *ddata = to_panel_data(dssdev);
86 return gpiod_get_value_cansleep(ddata->hpd_gpio);
89 static void hdmic_register_hpd_cb(struct omap_dss_device *dssdev,
90 void (*cb)(void *cb_data,
91 enum drm_connector_status status),
92 void *cb_data)
94 struct panel_drv_data *ddata = to_panel_data(dssdev);
96 mutex_lock(&ddata->hpd_lock);
97 ddata->hpd_cb = cb;
98 ddata->hpd_cb_data = cb_data;
99 mutex_unlock(&ddata->hpd_lock);
102 static void hdmic_unregister_hpd_cb(struct omap_dss_device *dssdev)
104 struct panel_drv_data *ddata = to_panel_data(dssdev);
106 mutex_lock(&ddata->hpd_lock);
107 ddata->hpd_cb = NULL;
108 ddata->hpd_cb_data = NULL;
109 mutex_unlock(&ddata->hpd_lock);
112 static const struct omap_dss_device_ops hdmic_ops = {
113 .connect = hdmic_connect,
114 .disconnect = hdmic_disconnect,
116 .enable = hdmic_enable,
117 .disable = hdmic_disable,
119 .detect = hdmic_detect,
120 .register_hpd_cb = hdmic_register_hpd_cb,
121 .unregister_hpd_cb = hdmic_unregister_hpd_cb,
124 static irqreturn_t hdmic_hpd_isr(int irq, void *data)
126 struct panel_drv_data *ddata = data;
128 mutex_lock(&ddata->hpd_lock);
129 if (ddata->hpd_cb) {
130 enum drm_connector_status status;
132 if (hdmic_detect(&ddata->dssdev))
133 status = connector_status_connected;
134 else
135 status = connector_status_disconnected;
137 ddata->hpd_cb(ddata->hpd_cb_data, status);
139 mutex_unlock(&ddata->hpd_lock);
141 return IRQ_HANDLED;
144 static int hdmic_probe(struct platform_device *pdev)
146 struct panel_drv_data *ddata;
147 struct omap_dss_device *dssdev;
148 struct gpio_desc *gpio;
149 int r;
151 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
152 if (!ddata)
153 return -ENOMEM;
155 platform_set_drvdata(pdev, ddata);
156 ddata->dev = &pdev->dev;
158 mutex_init(&ddata->hpd_lock);
160 /* HPD GPIO */
161 gpio = devm_gpiod_get_optional(&pdev->dev, "hpd", GPIOD_IN);
162 if (IS_ERR(gpio)) {
163 dev_err(&pdev->dev, "failed to parse HPD gpio\n");
164 return PTR_ERR(gpio);
167 ddata->hpd_gpio = gpio;
169 if (ddata->hpd_gpio) {
170 r = devm_request_threaded_irq(&pdev->dev,
171 gpiod_to_irq(ddata->hpd_gpio),
172 NULL, hdmic_hpd_isr,
173 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
174 IRQF_ONESHOT,
175 "hdmic hpd", ddata);
176 if (r)
177 return r;
180 dssdev = &ddata->dssdev;
181 dssdev->ops = &hdmic_ops;
182 dssdev->dev = &pdev->dev;
183 dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
184 dssdev->owner = THIS_MODULE;
185 dssdev->of_ports = BIT(0);
186 dssdev->ops_flags = ddata->hpd_gpio
187 ? OMAP_DSS_DEVICE_OP_DETECT | OMAP_DSS_DEVICE_OP_HPD
188 : 0;
190 omapdss_display_init(dssdev);
191 omapdss_device_register(dssdev);
193 return 0;
196 static int __exit hdmic_remove(struct platform_device *pdev)
198 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
199 struct omap_dss_device *dssdev = &ddata->dssdev;
201 omapdss_device_unregister(&ddata->dssdev);
203 hdmic_disable(dssdev);
205 return 0;
208 static const struct of_device_id hdmic_of_match[] = {
209 { .compatible = "omapdss,hdmi-connector", },
213 MODULE_DEVICE_TABLE(of, hdmic_of_match);
215 static struct platform_driver hdmi_connector_driver = {
216 .probe = hdmic_probe,
217 .remove = __exit_p(hdmic_remove),
218 .driver = {
219 .name = "connector-hdmi",
220 .of_match_table = hdmic_of_match,
221 .suppress_bind_attrs = true,
225 module_platform_driver(hdmi_connector_driver);
227 MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
228 MODULE_DESCRIPTION("HDMI Connector driver");
229 MODULE_LICENSE("GPL");