4 * Copyright (C) 2011 Texas Instruments Inc
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.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <linux/module.h>
21 #include <linux/slab.h>
22 #include <video/omapdss.h>
23 #include <linux/i2c.h>
24 #include <linux/gpio.h>
25 #include <drm/drm_edid.h>
27 #include <video/omap-panel-dvi.h>
29 static const struct omap_video_timings panel_dvi_default_timings = {
44 struct panel_drv_data {
45 struct omap_dss_device *dssdev;
52 static inline struct panel_dvi_platform_data
53 *get_pdata(const struct omap_dss_device *dssdev)
58 static int panel_dvi_power_on(struct omap_dss_device *dssdev)
60 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
61 struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
64 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
67 r = omapdss_dpi_display_enable(dssdev);
71 if (pdata->platform_enable) {
72 r = pdata->platform_enable(dssdev);
77 if (gpio_is_valid(ddata->pd_gpio))
78 gpio_set_value(ddata->pd_gpio, 1);
82 omapdss_dpi_display_disable(dssdev);
87 static void panel_dvi_power_off(struct omap_dss_device *dssdev)
89 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
90 struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
92 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
95 if (gpio_is_valid(ddata->pd_gpio))
96 gpio_set_value(ddata->pd_gpio, 0);
98 if (pdata->platform_disable)
99 pdata->platform_disable(dssdev);
101 omapdss_dpi_display_disable(dssdev);
104 static int panel_dvi_probe(struct omap_dss_device *dssdev)
106 struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
107 struct panel_drv_data *ddata;
110 ddata = kzalloc(sizeof(*ddata), GFP_KERNEL);
114 dssdev->panel.timings = panel_dvi_default_timings;
115 dssdev->panel.config = OMAP_DSS_LCD_TFT;
117 ddata->dssdev = dssdev;
118 mutex_init(&ddata->lock);
121 ddata->pd_gpio = pdata->power_down_gpio;
125 if (gpio_is_valid(ddata->pd_gpio)) {
126 r = gpio_request_one(ddata->pd_gpio, GPIOF_OUT_INIT_LOW,
129 dev_err(&dssdev->dev, "Failed to request PD GPIO %d\n",
135 dev_set_drvdata(&dssdev->dev, ddata);
140 static void __exit panel_dvi_remove(struct omap_dss_device *dssdev)
142 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
144 mutex_lock(&ddata->lock);
146 if (gpio_is_valid(ddata->pd_gpio))
147 gpio_free(ddata->pd_gpio);
149 dev_set_drvdata(&dssdev->dev, NULL);
151 mutex_unlock(&ddata->lock);
156 static int panel_dvi_enable(struct omap_dss_device *dssdev)
158 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
161 mutex_lock(&ddata->lock);
163 r = panel_dvi_power_on(dssdev);
165 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
167 mutex_unlock(&ddata->lock);
172 static void panel_dvi_disable(struct omap_dss_device *dssdev)
174 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
176 mutex_lock(&ddata->lock);
178 panel_dvi_power_off(dssdev);
180 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
182 mutex_unlock(&ddata->lock);
185 static int panel_dvi_suspend(struct omap_dss_device *dssdev)
187 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
189 mutex_lock(&ddata->lock);
191 panel_dvi_power_off(dssdev);
193 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
195 mutex_unlock(&ddata->lock);
200 static int panel_dvi_resume(struct omap_dss_device *dssdev)
202 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
205 mutex_lock(&ddata->lock);
207 r = panel_dvi_power_on(dssdev);
209 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
211 mutex_unlock(&ddata->lock);
216 static void panel_dvi_set_timings(struct omap_dss_device *dssdev,
217 struct omap_video_timings *timings)
219 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
221 mutex_lock(&ddata->lock);
222 dpi_set_timings(dssdev, timings);
223 mutex_unlock(&ddata->lock);
226 static void panel_dvi_get_timings(struct omap_dss_device *dssdev,
227 struct omap_video_timings *timings)
229 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
231 mutex_lock(&ddata->lock);
232 *timings = dssdev->panel.timings;
233 mutex_unlock(&ddata->lock);
236 static int panel_dvi_check_timings(struct omap_dss_device *dssdev,
237 struct omap_video_timings *timings)
239 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
242 mutex_lock(&ddata->lock);
243 r = dpi_check_timings(dssdev, timings);
244 mutex_unlock(&ddata->lock);
250 static int panel_dvi_ddc_read(struct i2c_adapter *adapter,
251 unsigned char *buf, u16 count, u8 offset)
255 for (retries = 3; retries > 0; retries--) {
256 struct i2c_msg msgs[] = {
270 r = i2c_transfer(adapter, msgs, 2);
278 return r < 0 ? r : -EIO;
281 static int panel_dvi_read_edid(struct omap_dss_device *dssdev,
284 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
285 struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
286 struct i2c_adapter *adapter;
287 int r, l, bytes_read;
289 mutex_lock(&ddata->lock);
291 if (pdata->i2c_bus_num == 0) {
296 adapter = i2c_get_adapter(pdata->i2c_bus_num);
298 dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",
304 l = min(EDID_LENGTH, len);
305 r = panel_dvi_ddc_read(adapter, edid, l, 0);
311 /* if there are extensions, read second block */
312 if (len > EDID_LENGTH && edid[0x7e] > 0) {
313 l = min(EDID_LENGTH, len - EDID_LENGTH);
315 r = panel_dvi_ddc_read(adapter, edid + EDID_LENGTH,
323 mutex_unlock(&ddata->lock);
328 mutex_unlock(&ddata->lock);
332 static bool panel_dvi_detect(struct omap_dss_device *dssdev)
334 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
335 struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
336 struct i2c_adapter *adapter;
340 mutex_lock(&ddata->lock);
342 if (pdata->i2c_bus_num == 0)
345 adapter = i2c_get_adapter(pdata->i2c_bus_num);
349 r = panel_dvi_ddc_read(adapter, &out, 1, 0);
351 mutex_unlock(&ddata->lock);
356 mutex_unlock(&ddata->lock);
360 static struct omap_dss_driver panel_dvi_driver = {
361 .probe = panel_dvi_probe,
362 .remove = __exit_p(panel_dvi_remove),
364 .enable = panel_dvi_enable,
365 .disable = panel_dvi_disable,
366 .suspend = panel_dvi_suspend,
367 .resume = panel_dvi_resume,
369 .set_timings = panel_dvi_set_timings,
370 .get_timings = panel_dvi_get_timings,
371 .check_timings = panel_dvi_check_timings,
373 .read_edid = panel_dvi_read_edid,
374 .detect = panel_dvi_detect,
378 .owner = THIS_MODULE,
382 static int __init panel_dvi_init(void)
384 return omap_dss_register_driver(&panel_dvi_driver);
387 static void __exit panel_dvi_exit(void)
389 omap_dss_unregister_driver(&panel_dvi_driver);
392 module_init(panel_dvi_init);
393 module_exit(panel_dvi_exit);
394 MODULE_LICENSE("GPL");