aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c6
-rw-r--r--drivers/video/omap2/Kconfig1
-rw-r--r--drivers/video/omap2/Makefile1
-rw-r--r--drivers/video/omap2/displays-new/Kconfig73
-rw-r--r--drivers/video/omap2/displays-new/Makefile12
-rw-r--r--drivers/video/omap2/displays-new/connector-analog-tv.c265
-rw-r--r--drivers/video/omap2/displays-new/connector-dvi.c351
-rw-r--r--drivers/video/omap2/displays-new/connector-hdmi.c375
-rw-r--r--drivers/video/omap2/displays-new/encoder-tfp410.c267
-rw-r--r--drivers/video/omap2/displays-new/encoder-tpd12s015.c395
-rw-r--r--drivers/video/omap2/displays-new/panel-dpi.c270
-rw-r--r--drivers/video/omap2/displays-new/panel-dsi-cm.c1336
-rw-r--r--drivers/video/omap2/displays-new/panel-lgphilips-lb035q02.c358
-rw-r--r--drivers/video/omap2/displays-new/panel-nec-nl8048hl11.c394
-rw-r--r--drivers/video/omap2/displays-new/panel-sharp-ls037v7dw01.c324
-rw-r--r--drivers/video/omap2/displays-new/panel-sony-acx565akm.c865
-rw-r--r--drivers/video/omap2/displays-new/panel-tpo-td043mtea1.c646
-rw-r--r--drivers/video/omap2/displays/Kconfig2
-rw-r--r--drivers/video/omap2/dss/apply.c14
-rw-r--r--drivers/video/omap2/dss/display.c1
-rw-r--r--drivers/video/omap2/dss/dpi.c74
-rw-r--r--drivers/video/omap2/dss/dsi.c97
-rw-r--r--drivers/video/omap2/dss/dss.h4
-rw-r--r--drivers/video/omap2/dss/hdmi.c238
-rw-r--r--drivers/video/omap2/dss/output.c15
-rw-r--r--drivers/video/omap2/dss/rfbi.c4
-rw-r--r--drivers/video/omap2/dss/sdi.c82
-rw-r--r--drivers/video/omap2/dss/venc.c76
-rw-r--r--include/video/omap-panel-data.h209
-rw-r--r--include/video/omapdss.h192
30 files changed, 6911 insertions, 36 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 2c2316a59b6c..a3004f12b9a3 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -65,10 +65,8 @@ static int get_connector_type(struct omap_dss_device *dssdev)
65 switch (dssdev->type) { 65 switch (dssdev->type) {
66 case OMAP_DISPLAY_TYPE_HDMI: 66 case OMAP_DISPLAY_TYPE_HDMI:
67 return DRM_MODE_CONNECTOR_HDMIA; 67 return DRM_MODE_CONNECTOR_HDMIA;
68 case OMAP_DISPLAY_TYPE_DPI: 68 case OMAP_DISPLAY_TYPE_DVI:
69 if (!strcmp(dssdev->name, "dvi")) 69 return DRM_MODE_CONNECTOR_DVID;
70 return DRM_MODE_CONNECTOR_DVID;
71 /* fallthrough */
72 default: 70 default:
73 return DRM_MODE_CONNECTOR_Unknown; 71 return DRM_MODE_CONNECTOR_Unknown;
74 } 72 }
diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
index b07b2b042e7e..56cad0f5386c 100644
--- a/drivers/video/omap2/Kconfig
+++ b/drivers/video/omap2/Kconfig
@@ -6,5 +6,6 @@ if ARCH_OMAP2PLUS
6source "drivers/video/omap2/dss/Kconfig" 6source "drivers/video/omap2/dss/Kconfig"
7source "drivers/video/omap2/omapfb/Kconfig" 7source "drivers/video/omap2/omapfb/Kconfig"
8source "drivers/video/omap2/displays/Kconfig" 8source "drivers/video/omap2/displays/Kconfig"
9source "drivers/video/omap2/displays-new/Kconfig"
9 10
10endif 11endif
diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
index 296e5c5281c5..86873c2fbb27 100644
--- a/drivers/video/omap2/Makefile
+++ b/drivers/video/omap2/Makefile
@@ -2,4 +2,5 @@ obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
2 2
3obj-$(CONFIG_OMAP2_DSS) += dss/ 3obj-$(CONFIG_OMAP2_DSS) += dss/
4obj-y += displays/ 4obj-y += displays/
5obj-y += displays-new/
5obj-$(CONFIG_FB_OMAP2) += omapfb/ 6obj-$(CONFIG_FB_OMAP2) += omapfb/
diff --git a/drivers/video/omap2/displays-new/Kconfig b/drivers/video/omap2/displays-new/Kconfig
new file mode 100644
index 000000000000..6c90885b0940
--- /dev/null
+++ b/drivers/video/omap2/displays-new/Kconfig
@@ -0,0 +1,73 @@
1menu "OMAP Display Device Drivers (new device model)"
2 depends on OMAP2_DSS
3
4config DISPLAY_ENCODER_TFP410
5 tristate "TFP410 DPI to DVI Encoder"
6 help
7 Driver for TFP410 DPI to DVI encoder.
8
9config DISPLAY_ENCODER_TPD12S015
10 tristate "TPD12S015 HDMI ESD protection and level shifter"
11 help
12 Driver for TPD12S015, which offers HDMI ESD protection and level
13 shifting.
14
15config DISPLAY_CONNECTOR_DVI
16 tristate "DVI Connector"
17 depends on I2C
18 help
19 Driver for a generic DVI connector.
20
21config DISPLAY_CONNECTOR_HDMI
22 tristate "HDMI Connector"
23 help
24 Driver for a generic HDMI connector.
25
26config DISPLAY_CONNECTOR_ANALOG_TV
27 tristate "Analog TV Connector"
28 help
29 Driver for a generic analog TV connector.
30
31config DISPLAY_PANEL_DPI
32 tristate "Generic DPI panel"
33 help
34 Driver for generic DPI panels.
35
36config DISPLAY_PANEL_DSI_CM
37 tristate "Generic DSI Command Mode Panel"
38 help
39 Driver for generic DSI command mode panels.
40
41config DISPLAY_PANEL_SONY_ACX565AKM
42 tristate "ACX565AKM Panel"
43 depends on SPI && BACKLIGHT_CLASS_DEVICE
44 help
45 This is the LCD panel used on Nokia N900
46
47config DISPLAY_PANEL_LGPHILIPS_LB035Q02
48 tristate "LG.Philips LB035Q02 LCD Panel"
49 depends on SPI
50 help
51 LCD Panel used on the Gumstix Overo Palo35
52
53config DISPLAY_PANEL_SHARP_LS037V7DW01
54 tristate "Sharp LS037V7DW01 LCD Panel"
55 depends on BACKLIGHT_CLASS_DEVICE
56 help
57 LCD Panel used in TI's SDP3430 and EVM boards
58
59config DISPLAY_PANEL_TPO_TD043MTEA1
60 tristate "TPO TD043MTEA1 LCD Panel"
61 depends on SPI
62 help
63 LCD Panel used in OMAP3 Pandora
64
65config DISPLAY_PANEL_NEC_NL8048HL11
66 tristate "NEC NL8048HL11 Panel"
67 depends on SPI
68 depends on BACKLIGHT_CLASS_DEVICE
69 help
70 This NEC NL8048HL11 panel is TFT LCD used in the
71 Zoom2/3/3630 sdp boards.
72
73endmenu
diff --git a/drivers/video/omap2/displays-new/Makefile b/drivers/video/omap2/displays-new/Makefile
new file mode 100644
index 000000000000..5aeb11b8fcd5
--- /dev/null
+++ b/drivers/video/omap2/displays-new/Makefile
@@ -0,0 +1,12 @@
1obj-$(CONFIG_DISPLAY_ENCODER_TFP410) += encoder-tfp410.o
2obj-$(CONFIG_DISPLAY_ENCODER_TPD12S015) += encoder-tpd12s015.o
3obj-$(CONFIG_DISPLAY_CONNECTOR_DVI) += connector-dvi.o
4obj-$(CONFIG_DISPLAY_CONNECTOR_HDMI) += connector-hdmi.o
5obj-$(CONFIG_DISPLAY_CONNECTOR_ANALOG_TV) += connector-analog-tv.o
6obj-$(CONFIG_DISPLAY_PANEL_DPI) += panel-dpi.o
7obj-$(CONFIG_DISPLAY_PANEL_DSI_CM) += panel-dsi-cm.o
8obj-$(CONFIG_DISPLAY_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o
9obj-$(CONFIG_DISPLAY_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
10obj-$(CONFIG_DISPLAY_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
11obj-$(CONFIG_DISPLAY_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
12obj-$(CONFIG_DISPLAY_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o
diff --git a/drivers/video/omap2/displays-new/connector-analog-tv.c b/drivers/video/omap2/displays-new/connector-analog-tv.c
new file mode 100644
index 000000000000..5338f362293b
--- /dev/null
+++ b/drivers/video/omap2/displays-new/connector-analog-tv.c
@@ -0,0 +1,265 @@
1/*
2 * Analog TV Connector driver
3 *
4 * Copyright (C) 2013 Texas Instruments
5 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
6 *
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.
10 */
11
12#include <linux/slab.h>
13#include <linux/module.h>
14#include <linux/platform_device.h>
15
16#include <video/omapdss.h>
17#include <video/omap-panel-data.h>
18
19struct panel_drv_data {
20 struct omap_dss_device dssdev;
21 struct omap_dss_device *in;
22
23 struct device *dev;
24
25 struct omap_video_timings timings;
26
27 enum omap_dss_venc_type connector_type;
28 bool invert_polarity;
29};
30
31#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
32
33static int tvc_connect(struct omap_dss_device *dssdev)
34{
35 struct panel_drv_data *ddata = to_panel_data(dssdev);
36 struct omap_dss_device *in = ddata->in;
37 int r;
38
39 dev_dbg(ddata->dev, "connect\n");
40
41 if (omapdss_device_is_connected(dssdev))
42 return 0;
43
44 r = in->ops.atv->connect(in, dssdev);
45 if (r)
46 return r;
47
48 return 0;
49}
50
51static void tvc_disconnect(struct omap_dss_device *dssdev)
52{
53 struct panel_drv_data *ddata = to_panel_data(dssdev);
54 struct omap_dss_device *in = ddata->in;
55
56 dev_dbg(ddata->dev, "disconnect\n");
57
58 if (!omapdss_device_is_connected(dssdev))
59 return;
60
61 in->ops.atv->disconnect(in, dssdev);
62}
63
64static int tvc_enable(struct omap_dss_device *dssdev)
65{
66 struct panel_drv_data *ddata = to_panel_data(dssdev);
67 struct omap_dss_device *in = ddata->in;
68 int r;
69
70 dev_dbg(ddata->dev, "enable\n");
71
72 if (!omapdss_device_is_connected(dssdev))
73 return -ENODEV;
74
75 if (omapdss_device_is_enabled(dssdev))
76 return 0;
77
78 in->ops.atv->set_timings(in, &ddata->timings);
79
80 in->ops.atv->set_type(in, ddata->connector_type);
81 in->ops.atv->invert_vid_out_polarity(in, ddata->invert_polarity);
82
83 r = in->ops.atv->enable(in);
84 if (r)
85 return r;
86
87 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
88
89 return r;
90}
91
92static void tvc_disable(struct omap_dss_device *dssdev)
93{
94 struct panel_drv_data *ddata = to_panel_data(dssdev);
95 struct omap_dss_device *in = ddata->in;
96
97 dev_dbg(ddata->dev, "disable\n");
98
99 if (!omapdss_device_is_enabled(dssdev))
100 return;
101
102 in->ops.atv->disable(in);
103
104 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
105}
106
107static void tvc_set_timings(struct omap_dss_device *dssdev,
108 struct omap_video_timings *timings)
109{
110 struct panel_drv_data *ddata = to_panel_data(dssdev);
111 struct omap_dss_device *in = ddata->in;
112
113 ddata->timings = *timings;
114 dssdev->panel.timings = *timings;
115
116 in->ops.atv->set_timings(in, timings);
117}
118
119static void tvc_get_timings(struct omap_dss_device *dssdev,
120 struct omap_video_timings *timings)
121{
122 struct panel_drv_data *ddata = to_panel_data(dssdev);
123
124 *timings = ddata->timings;
125}
126
127static int tvc_check_timings(struct omap_dss_device *dssdev,
128 struct omap_video_timings *timings)
129{
130 struct panel_drv_data *ddata = to_panel_data(dssdev);
131 struct omap_dss_device *in = ddata->in;
132
133 return in->ops.atv->check_timings(in, timings);
134}
135
136static u32 tvc_get_wss(struct omap_dss_device *dssdev)
137{
138 struct panel_drv_data *ddata = to_panel_data(dssdev);
139 struct omap_dss_device *in = ddata->in;
140
141 return in->ops.atv->get_wss(in);
142}
143
144static int tvc_set_wss(struct omap_dss_device *dssdev, u32 wss)
145{
146 struct panel_drv_data *ddata = to_panel_data(dssdev);
147 struct omap_dss_device *in = ddata->in;
148
149 return in->ops.atv->set_wss(in, wss);
150}
151
152static struct omap_dss_driver tvc_driver = {
153 .connect = tvc_connect,
154 .disconnect = tvc_disconnect,
155
156 .enable = tvc_enable,
157 .disable = tvc_disable,
158
159 .set_timings = tvc_set_timings,
160 .get_timings = tvc_get_timings,
161 .check_timings = tvc_check_timings,
162
163 .get_resolution = omapdss_default_get_resolution,
164
165 .get_wss = tvc_get_wss,
166 .set_wss = tvc_set_wss,
167};
168
169static int tvc_probe_pdata(struct platform_device *pdev)
170{
171 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
172 struct connector_atv_platform_data *pdata;
173 struct omap_dss_device *in, *dssdev;
174
175 pdata = dev_get_platdata(&pdev->dev);
176
177 in = omap_dss_find_output(pdata->source);
178 if (in == NULL) {
179 dev_err(&pdev->dev, "Failed to find video source\n");
180 return -ENODEV;
181 }
182
183 ddata->in = in;
184
185 ddata->connector_type = pdata->connector_type;
186 ddata->invert_polarity = ddata->invert_polarity;
187
188 dssdev = &ddata->dssdev;
189 dssdev->name = pdata->name;
190
191 return 0;
192}
193
194static int tvc_probe(struct platform_device *pdev)
195{
196 struct panel_drv_data *ddata;
197 struct omap_dss_device *dssdev;
198 int r;
199
200 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
201 if (!ddata)
202 return -ENOMEM;
203
204 platform_set_drvdata(pdev, ddata);
205 ddata->dev = &pdev->dev;
206
207 if (dev_get_platdata(&pdev->dev)) {
208 r = tvc_probe_pdata(pdev);
209 if (r)
210 return r;
211 } else {
212 return -ENODEV;
213 }
214
215 ddata->timings = omap_dss_pal_timings;
216
217 dssdev = &ddata->dssdev;
218 dssdev->driver = &tvc_driver;
219 dssdev->dev = &pdev->dev;
220 dssdev->type = OMAP_DISPLAY_TYPE_VENC;
221 dssdev->owner = THIS_MODULE;
222 dssdev->panel.timings = omap_dss_pal_timings;
223
224 r = omapdss_register_display(dssdev);
225 if (r) {
226 dev_err(&pdev->dev, "Failed to register panel\n");
227 goto err_reg;
228 }
229
230 return 0;
231err_reg:
232 omap_dss_put_device(ddata->in);
233 return r;
234}
235
236static int __exit tvc_remove(struct platform_device *pdev)
237{
238 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
239 struct omap_dss_device *dssdev = &ddata->dssdev;
240 struct omap_dss_device *in = ddata->in;
241
242 omapdss_unregister_display(&ddata->dssdev);
243
244 tvc_disable(dssdev);
245 tvc_disconnect(dssdev);
246
247 omap_dss_put_device(in);
248
249 return 0;
250}
251
252static struct platform_driver tvc_connector_driver = {
253 .probe = tvc_probe,
254 .remove = __exit_p(tvc_remove),
255 .driver = {
256 .name = "connector-analog-tv",
257 .owner = THIS_MODULE,
258 },
259};
260
261module_platform_driver(tvc_connector_driver);
262
263MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
264MODULE_DESCRIPTION("Analog TV Connector driver");
265MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/connector-dvi.c b/drivers/video/omap2/displays-new/connector-dvi.c
new file mode 100644
index 000000000000..bc5f8ceda371
--- /dev/null
+++ b/drivers/video/omap2/displays-new/connector-dvi.c
@@ -0,0 +1,351 @@
1/*
2 * Generic DVI Connector driver
3 *
4 * Copyright (C) 2013 Texas Instruments
5 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
6 *
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.
10 */
11
12#include <linux/i2c.h>
13#include <linux/module.h>
14#include <linux/platform_device.h>
15#include <linux/slab.h>
16
17#include <drm/drm_edid.h>
18
19#include <video/omapdss.h>
20#include <video/omap-panel-data.h>
21
22static const struct omap_video_timings dvic_default_timings = {
23 .x_res = 640,
24 .y_res = 480,
25
26 .pixel_clock = 23500,
27
28 .hfp = 48,
29 .hsw = 32,
30 .hbp = 80,
31
32 .vfp = 3,
33 .vsw = 4,
34 .vbp = 7,
35
36 .vsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
37 .hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
38 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
39 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
40 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
41};
42
43struct panel_drv_data {
44 struct omap_dss_device dssdev;
45 struct omap_dss_device *in;
46
47 struct omap_video_timings timings;
48
49 struct i2c_adapter *i2c_adapter;
50};
51
52#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
53
54static int dvic_connect(struct omap_dss_device *dssdev)
55{
56 struct panel_drv_data *ddata = to_panel_data(dssdev);
57 struct omap_dss_device *in = ddata->in;
58 int r;
59
60 if (omapdss_device_is_connected(dssdev))
61 return 0;
62
63 r = in->ops.dvi->connect(in, dssdev);
64 if (r)
65 return r;
66
67 return 0;
68}
69
70static void dvic_disconnect(struct omap_dss_device *dssdev)
71{
72 struct panel_drv_data *ddata = to_panel_data(dssdev);
73 struct omap_dss_device *in = ddata->in;
74
75 if (!omapdss_device_is_connected(dssdev))
76 return;
77
78 in->ops.dvi->disconnect(in, dssdev);
79}
80
81static int dvic_enable(struct omap_dss_device *dssdev)
82{
83 struct panel_drv_data *ddata = to_panel_data(dssdev);
84 struct omap_dss_device *in = ddata->in;
85 int r;
86
87 if (!omapdss_device_is_connected(dssdev))
88 return -ENODEV;
89
90 if (omapdss_device_is_enabled(dssdev))
91 return 0;
92
93 in->ops.dvi->set_timings(in, &ddata->timings);
94
95 r = in->ops.dvi->enable(in);
96 if (r)
97 return r;
98
99 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
100
101 return 0;
102}
103
104static void dvic_disable(struct omap_dss_device *dssdev)
105{
106 struct panel_drv_data *ddata = to_panel_data(dssdev);
107 struct omap_dss_device *in = ddata->in;
108
109 if (!omapdss_device_is_enabled(dssdev))
110 return;
111
112 in->ops.dvi->disable(in);
113
114 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
115}
116
117static void dvic_set_timings(struct omap_dss_device *dssdev,
118 struct omap_video_timings *timings)
119{
120 struct panel_drv_data *ddata = to_panel_data(dssdev);
121 struct omap_dss_device *in = ddata->in;
122
123 ddata->timings = *timings;
124 dssdev->panel.timings = *timings;
125
126 in->ops.dvi->set_timings(in, timings);
127}
128
129static void dvic_get_timings(struct omap_dss_device *dssdev,
130 struct omap_video_timings *timings)
131{
132 struct panel_drv_data *ddata = to_panel_data(dssdev);
133
134 *timings = ddata->timings;
135}
136
137static int dvic_check_timings(struct omap_dss_device *dssdev,
138 struct omap_video_timings *timings)
139{
140 struct panel_drv_data *ddata = to_panel_data(dssdev);
141 struct omap_dss_device *in = ddata->in;
142
143 return in->ops.dvi->check_timings(in, timings);
144}
145
146static int dvic_ddc_read(struct i2c_adapter *adapter,
147 unsigned char *buf, u16 count, u8 offset)
148{
149 int r, retries;
150
151 for (retries = 3; retries > 0; retries--) {
152 struct i2c_msg msgs[] = {
153 {
154 .addr = DDC_ADDR,
155 .flags = 0,
156 .len = 1,
157 .buf = &offset,
158 }, {
159 .addr = DDC_ADDR,
160 .flags = I2C_M_RD,
161 .len = count,
162 .buf = buf,
163 }
164 };
165
166 r = i2c_transfer(adapter, msgs, 2);
167 if (r == 2)
168 return 0;
169
170 if (r != -EAGAIN)
171 break;
172 }
173
174 return r < 0 ? r : -EIO;
175}
176
177static int dvic_read_edid(struct omap_dss_device *dssdev,
178 u8 *edid, int len)
179{
180 struct panel_drv_data *ddata = to_panel_data(dssdev);
181 int r, l, bytes_read;
182
183 if (!ddata->i2c_adapter)
184 return -ENODEV;
185
186 l = min(EDID_LENGTH, len);
187 r = dvic_ddc_read(ddata->i2c_adapter, edid, l, 0);
188 if (r)
189 return r;
190
191 bytes_read = l;
192
193 /* if there are extensions, read second block */
194 if (len > EDID_LENGTH && edid[0x7e] > 0) {
195 l = min(EDID_LENGTH, len - EDID_LENGTH);
196
197 r = dvic_ddc_read(ddata->i2c_adapter, edid + EDID_LENGTH,
198 l, EDID_LENGTH);
199 if (r)
200 return r;
201
202 bytes_read += l;
203 }
204
205 return bytes_read;
206}
207
208static bool dvic_detect(struct omap_dss_device *dssdev)
209{
210 struct panel_drv_data *ddata = to_panel_data(dssdev);
211 unsigned char out;
212 int r;
213
214 if (!ddata->i2c_adapter)
215 return true;
216
217 r = dvic_ddc_read(ddata->i2c_adapter, &out, 1, 0);
218
219 return r == 0;
220}
221
222static struct omap_dss_driver dvic_driver = {
223 .connect = dvic_connect,
224 .disconnect = dvic_disconnect,
225
226 .enable = dvic_enable,
227 .disable = dvic_disable,
228
229 .set_timings = dvic_set_timings,
230 .get_timings = dvic_get_timings,
231 .check_timings = dvic_check_timings,
232
233 .get_resolution = omapdss_default_get_resolution,
234
235 .read_edid = dvic_read_edid,
236 .detect = dvic_detect,
237};
238
239static int dvic_probe_pdata(struct platform_device *pdev)
240{
241 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
242 struct connector_dvi_platform_data *pdata;
243 struct omap_dss_device *in, *dssdev;
244 int i2c_bus_num;
245
246 pdata = dev_get_platdata(&pdev->dev);
247 i2c_bus_num = pdata->i2c_bus_num;
248
249 if (i2c_bus_num != -1) {
250 struct i2c_adapter *adapter;
251
252 adapter = i2c_get_adapter(i2c_bus_num);
253 if (!adapter) {
254 dev_err(&pdev->dev,
255 "Failed to get I2C adapter, bus %d\n",
256 i2c_bus_num);
257 return -EPROBE_DEFER;
258 }
259
260 ddata->i2c_adapter = adapter;
261 }
262
263 in = omap_dss_find_output(pdata->source);
264 if (in == NULL) {
265 dev_err(&pdev->dev, "Failed to find video source\n");
266 return -ENODEV;
267 }
268
269 ddata->in = in;
270
271 dssdev = &ddata->dssdev;
272 dssdev->name = pdata->name;
273
274 return 0;
275}
276
277static int dvic_probe(struct platform_device *pdev)
278{
279 struct panel_drv_data *ddata;
280 struct omap_dss_device *dssdev;
281 int r;
282
283 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
284 if (!ddata)
285 return -ENOMEM;
286
287 platform_set_drvdata(pdev, ddata);
288
289 if (dev_get_platdata(&pdev->dev)) {
290 r = dvic_probe_pdata(pdev);
291 if (r)
292 return r;
293 } else {
294 return -ENODEV;
295 }
296
297 ddata->timings = dvic_default_timings;
298
299 dssdev = &ddata->dssdev;
300 dssdev->driver = &dvic_driver;
301 dssdev->dev = &pdev->dev;
302 dssdev->type = OMAP_DISPLAY_TYPE_DVI;
303 dssdev->owner = THIS_MODULE;
304 dssdev->panel.timings = dvic_default_timings;
305
306 r = omapdss_register_display(dssdev);
307 if (r) {
308 dev_err(&pdev->dev, "Failed to register panel\n");
309 goto err_reg;
310 }
311
312 return 0;
313
314err_reg:
315 omap_dss_put_device(ddata->in);
316 return r;
317}
318
319static int __exit dvic_remove(struct platform_device *pdev)
320{
321 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
322 struct omap_dss_device *dssdev = &ddata->dssdev;
323 struct omap_dss_device *in = ddata->in;
324
325 omapdss_unregister_display(&ddata->dssdev);
326
327 dvic_disable(dssdev);
328 dvic_disconnect(dssdev);
329
330 omap_dss_put_device(in);
331
332 if (ddata->i2c_adapter)
333 i2c_put_adapter(ddata->i2c_adapter);
334
335 return 0;
336}
337
338static struct platform_driver dvi_connector_driver = {
339 .probe = dvic_probe,
340 .remove = __exit_p(dvic_remove),
341 .driver = {
342 .name = "connector-dvi",
343 .owner = THIS_MODULE,
344 },
345};
346
347module_platform_driver(dvi_connector_driver);
348
349MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
350MODULE_DESCRIPTION("Generic DVI Connector driver");
351MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/connector-hdmi.c b/drivers/video/omap2/displays-new/connector-hdmi.c
new file mode 100644
index 000000000000..c5826716d6ab
--- /dev/null
+++ b/drivers/video/omap2/displays-new/connector-hdmi.c
@@ -0,0 +1,375 @@
1/*
2 * HDMI Connector driver
3 *
4 * Copyright (C) 2013 Texas Instruments
5 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
6 *
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.
10 */
11
12#include <linux/slab.h>
13#include <linux/module.h>
14#include <linux/platform_device.h>
15
16#include <drm/drm_edid.h>
17
18#include <video/omapdss.h>
19#include <video/omap-panel-data.h>
20
21static const struct omap_video_timings hdmic_default_timings = {
22 .x_res = 640,
23 .y_res = 480,
24 .pixel_clock = 25175,
25 .hsw = 96,
26 .hfp = 16,
27 .hbp = 48,
28 .vsw = 2,
29 .vfp = 11,
30 .vbp = 31,
31
32 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
33 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
34
35 .interlace = false,
36};
37
38struct panel_drv_data {
39 struct omap_dss_device dssdev;
40 struct omap_dss_device *in;
41
42 struct device *dev;
43
44 struct omap_video_timings timings;
45};
46
47#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
48
49static int hdmic_connect(struct omap_dss_device *dssdev)
50{
51 struct panel_drv_data *ddata = to_panel_data(dssdev);
52 struct omap_dss_device *in = ddata->in;
53 int r;
54
55 dev_dbg(ddata->dev, "connect\n");
56
57 if (omapdss_device_is_connected(dssdev))
58 return 0;
59
60 r = in->ops.hdmi->connect(in, dssdev);
61 if (r)
62 return r;
63
64 return 0;
65}
66
67static void hdmic_disconnect(struct omap_dss_device *dssdev)
68{
69 struct panel_drv_data *ddata = to_panel_data(dssdev);
70 struct omap_dss_device *in = ddata->in;
71
72 dev_dbg(ddata->dev, "disconnect\n");
73
74 if (!omapdss_device_is_connected(dssdev))
75 return;
76
77 in->ops.hdmi->disconnect(in, dssdev);
78}
79
80static int hdmic_enable(struct omap_dss_device *dssdev)
81{
82 struct panel_drv_data *ddata = to_panel_data(dssdev);
83 struct omap_dss_device *in = ddata->in;
84 int r;
85
86 dev_dbg(ddata->dev, "enable\n");
87
88 if (!omapdss_device_is_connected(dssdev))
89 return -ENODEV;
90
91 if (omapdss_device_is_enabled(dssdev))
92 return 0;
93
94 in->ops.hdmi->set_timings(in, &ddata->timings);
95
96 r = in->ops.hdmi->enable(in);
97 if (r)
98 return r;
99
100 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
101
102 return r;
103}
104
105static void hdmic_disable(struct omap_dss_device *dssdev)
106{
107 struct panel_drv_data *ddata = to_panel_data(dssdev);
108 struct omap_dss_device *in = ddata->in;
109
110 dev_dbg(ddata->dev, "disable\n");
111
112 if (!omapdss_device_is_enabled(dssdev))
113 return;
114
115 in->ops.hdmi->disable(in);
116
117 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
118}
119
120static void hdmic_set_timings(struct omap_dss_device *dssdev,
121 struct omap_video_timings *timings)
122{
123 struct panel_drv_data *ddata = to_panel_data(dssdev);
124 struct omap_dss_device *in = ddata->in;
125
126 ddata->timings = *timings;
127 dssdev->panel.timings = *timings;
128
129 in->ops.hdmi->set_timings(in, timings);
130}
131
132static void hdmic_get_timings(struct omap_dss_device *dssdev,
133 struct omap_video_timings *timings)
134{
135 struct panel_drv_data *ddata = to_panel_data(dssdev);
136
137 *timings = ddata->timings;
138}
139
140static int hdmic_check_timings(struct omap_dss_device *dssdev,
141 struct omap_video_timings *timings)
142{
143 struct panel_drv_data *ddata = to_panel_data(dssdev);
144 struct omap_dss_device *in = ddata->in;
145
146 return in->ops.hdmi->check_timings(in, timings);
147}
148
149static int hdmic_read_edid(struct omap_dss_device *dssdev,
150 u8 *edid, int len)
151{
152 struct panel_drv_data *ddata = to_panel_data(dssdev);
153 struct omap_dss_device *in = ddata->in;
154
155 return in->ops.hdmi->read_edid(in, edid, len);
156}
157
158static bool hdmic_detect(struct omap_dss_device *dssdev)
159{
160 struct panel_drv_data *ddata = to_panel_data(dssdev);
161 struct omap_dss_device *in = ddata->in;
162
163 return in->ops.hdmi->detect(in);
164}
165
166static int hdmic_audio_enable(struct omap_dss_device *dssdev)
167{
168 struct panel_drv_data *ddata = to_panel_data(dssdev);
169 struct omap_dss_device *in = ddata->in;
170 int r;
171
172 /* enable audio only if the display is active */
173 if (!omapdss_device_is_enabled(dssdev))
174 return -EPERM;
175
176 r = in->ops.hdmi->audio_enable(in);
177 if (r)
178 return r;
179
180 dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
181
182 return 0;
183}
184
185static void hdmic_audio_disable(struct omap_dss_device *dssdev)
186{
187 struct panel_drv_data *ddata = to_panel_data(dssdev);
188 struct omap_dss_device *in = ddata->in;
189
190 in->ops.hdmi->audio_disable(in);
191
192 dssdev->audio_state = OMAP_DSS_AUDIO_DISABLED;
193}
194
195static int hdmic_audio_start(struct omap_dss_device *dssdev)
196{
197 struct panel_drv_data *ddata = to_panel_data(dssdev);
198 struct omap_dss_device *in = ddata->in;
199 int r;
200
201 /*
202 * No need to check the panel state. It was checked when trasitioning
203 * to AUDIO_ENABLED.
204 */
205 if (dssdev->audio_state != OMAP_DSS_AUDIO_ENABLED)
206 return -EPERM;
207
208 r = in->ops.hdmi->audio_start(in);
209 if (r)
210 return r;
211
212 dssdev->audio_state = OMAP_DSS_AUDIO_PLAYING;
213
214 return 0;
215}
216
217static void hdmic_audio_stop(struct omap_dss_device *dssdev)
218{
219 struct panel_drv_data *ddata = to_panel_data(dssdev);
220 struct omap_dss_device *in = ddata->in;
221
222 in->ops.hdmi->audio_stop(in);
223
224 dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
225}
226
227static bool hdmic_audio_supported(struct omap_dss_device *dssdev)
228{
229 struct panel_drv_data *ddata = to_panel_data(dssdev);
230 struct omap_dss_device *in = ddata->in;
231
232 if (!omapdss_device_is_enabled(dssdev))
233 return false;
234
235 return in->ops.hdmi->audio_supported(in);
236}
237
238static int hdmic_audio_config(struct omap_dss_device *dssdev,
239 struct omap_dss_audio *audio)
240{
241 struct panel_drv_data *ddata = to_panel_data(dssdev);
242 struct omap_dss_device *in = ddata->in;
243 int r;
244
245 /* config audio only if the display is active */
246 if (!omapdss_device_is_enabled(dssdev))
247 return -EPERM;
248
249 r = in->ops.hdmi->audio_config(in, audio);
250 if (r)
251 return r;
252
253 dssdev->audio_state = OMAP_DSS_AUDIO_CONFIGURED;
254
255 return 0;
256}
257
258static struct omap_dss_driver hdmic_driver = {
259 .connect = hdmic_connect,
260 .disconnect = hdmic_disconnect,
261
262 .enable = hdmic_enable,
263 .disable = hdmic_disable,
264
265 .set_timings = hdmic_set_timings,
266 .get_timings = hdmic_get_timings,
267 .check_timings = hdmic_check_timings,
268
269 .get_resolution = omapdss_default_get_resolution,
270
271 .read_edid = hdmic_read_edid,
272 .detect = hdmic_detect,
273
274 .audio_enable = hdmic_audio_enable,
275 .audio_disable = hdmic_audio_disable,
276 .audio_start = hdmic_audio_start,
277 .audio_stop = hdmic_audio_stop,
278 .audio_supported = hdmic_audio_supported,
279 .audio_config = hdmic_audio_config,
280};
281
282static int hdmic_probe_pdata(struct platform_device *pdev)
283{
284 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
285 struct connector_hdmi_platform_data *pdata;
286 struct omap_dss_device *in, *dssdev;
287
288 pdata = dev_get_platdata(&pdev->dev);
289
290 in = omap_dss_find_output(pdata->source);
291 if (in == NULL) {
292 dev_err(&pdev->dev, "Failed to find video source\n");
293 return -ENODEV;
294 }
295
296 ddata->in = in;
297
298 dssdev = &ddata->dssdev;
299 dssdev->name = pdata->name;
300
301 return 0;
302}
303
304static int hdmic_probe(struct platform_device *pdev)
305{
306 struct panel_drv_data *ddata;
307 struct omap_dss_device *dssdev;
308 int r;
309
310 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
311 if (!ddata)
312 return -ENOMEM;
313
314 platform_set_drvdata(pdev, ddata);
315 ddata->dev = &pdev->dev;
316
317 if (dev_get_platdata(&pdev->dev)) {
318 r = hdmic_probe_pdata(pdev);
319 if (r)
320 return r;
321 } else {
322 return -ENODEV;
323 }
324
325 ddata->timings = hdmic_default_timings;
326
327 dssdev = &ddata->dssdev;
328 dssdev->driver = &hdmic_driver;
329 dssdev->dev = &pdev->dev;
330 dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
331 dssdev->owner = THIS_MODULE;
332 dssdev->panel.timings = hdmic_default_timings;
333
334 r = omapdss_register_display(dssdev);
335 if (r) {
336 dev_err(&pdev->dev, "Failed to register panel\n");
337 goto err_reg;
338 }
339
340 return 0;
341err_reg:
342 omap_dss_put_device(ddata->in);
343 return r;
344}
345
346static int __exit hdmic_remove(struct platform_device *pdev)
347{
348 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
349 struct omap_dss_device *dssdev = &ddata->dssdev;
350 struct omap_dss_device *in = ddata->in;
351
352 omapdss_unregister_display(&ddata->dssdev);
353
354 hdmic_disable(dssdev);
355 hdmic_disconnect(dssdev);
356
357 omap_dss_put_device(in);
358
359 return 0;
360}
361
362static struct platform_driver hdmi_connector_driver = {
363 .probe = hdmic_probe,
364 .remove = __exit_p(hdmic_remove),
365 .driver = {
366 .name = "connector-hdmi",
367 .owner = THIS_MODULE,
368 },
369};
370
371module_platform_driver(hdmi_connector_driver);
372
373MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
374MODULE_DESCRIPTION("HDMI Connector driver");
375MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/encoder-tfp410.c b/drivers/video/omap2/displays-new/encoder-tfp410.c
new file mode 100644
index 000000000000..a04f65856d6b
--- /dev/null
+++ b/drivers/video/omap2/displays-new/encoder-tfp410.c
@@ -0,0 +1,267 @@
1/*
2 * TFP410 DPI-to-DVI encoder driver
3 *
4 * Copyright (C) 2013 Texas Instruments
5 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
6 *
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.
10 */
11
12#include <linux/gpio.h>
13#include <linux/module.h>
14#include <linux/platform_device.h>
15#include <linux/slab.h>
16
17#include <video/omapdss.h>
18#include <video/omap-panel-data.h>
19
20struct panel_drv_data {
21 struct omap_dss_device dssdev;
22 struct omap_dss_device *in;
23
24 int pd_gpio;
25 int data_lines;
26
27 struct omap_video_timings timings;
28};
29
30#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
31
32static int tfp410_connect(struct omap_dss_device *dssdev,
33 struct omap_dss_device *dst)
34{
35 struct panel_drv_data *ddata = to_panel_data(dssdev);
36 struct omap_dss_device *in = ddata->in;
37 int r;
38
39 if (omapdss_device_is_connected(dssdev))
40 return -EBUSY;
41
42 r = in->ops.dpi->connect(in, dssdev);
43 if (r)
44 return r;
45
46 dst->output = dssdev;
47 dssdev->device = dst;
48
49 return 0;
50}
51
52static void tfp410_disconnect(struct omap_dss_device *dssdev,
53 struct omap_dss_device *dst)
54{
55 struct panel_drv_data *ddata = to_panel_data(dssdev);
56 struct omap_dss_device *in = ddata->in;
57
58 WARN_ON(!omapdss_device_is_connected(dssdev));
59 if (!omapdss_device_is_connected(dssdev))
60 return;
61
62 WARN_ON(dst != dssdev->device);
63 if (dst != dssdev->device)
64 return;
65
66 dst->output = NULL;
67 dssdev->device = NULL;
68
69 in->ops.dpi->disconnect(in, &ddata->dssdev);
70}
71
72static int tfp410_enable(struct omap_dss_device *dssdev)
73{
74 struct panel_drv_data *ddata = to_panel_data(dssdev);
75 struct omap_dss_device *in = ddata->in;
76 int r;
77
78 if (!omapdss_device_is_connected(dssdev))
79 return -ENODEV;
80
81 if (omapdss_device_is_enabled(dssdev))
82 return 0;
83
84 in->ops.dpi->set_timings(in, &ddata->timings);
85 in->ops.dpi->set_data_lines(in, ddata->data_lines);
86
87 r = in->ops.dpi->enable(in);
88 if (r)
89 return r;
90
91 if (gpio_is_valid(ddata->pd_gpio))
92 gpio_set_value_cansleep(ddata->pd_gpio, 1);
93
94 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
95
96 return 0;
97}
98
99static void tfp410_disable(struct omap_dss_device *dssdev)
100{
101 struct panel_drv_data *ddata = to_panel_data(dssdev);
102 struct omap_dss_device *in = ddata->in;
103
104 if (!omapdss_device_is_enabled(dssdev))
105 return;
106
107 if (gpio_is_valid(ddata->pd_gpio))
108 gpio_set_value_cansleep(ddata->pd_gpio, 0);
109
110 in->ops.dpi->disable(in);
111
112 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
113}
114
115static void tfp410_set_timings(struct omap_dss_device *dssdev,
116 struct omap_video_timings *timings)
117{
118 struct panel_drv_data *ddata = to_panel_data(dssdev);
119 struct omap_dss_device *in = ddata->in;
120
121 ddata->timings = *timings;
122 dssdev->panel.timings = *timings;
123
124 in->ops.dpi->set_timings(in, timings);
125}
126
127static void tfp410_get_timings(struct omap_dss_device *dssdev,
128 struct omap_video_timings *timings)
129{
130 struct panel_drv_data *ddata = to_panel_data(dssdev);
131
132 *timings = ddata->timings;
133}
134
135static int tfp410_check_timings(struct omap_dss_device *dssdev,
136 struct omap_video_timings *timings)
137{
138 struct panel_drv_data *ddata = to_panel_data(dssdev);
139 struct omap_dss_device *in = ddata->in;
140
141 return in->ops.dpi->check_timings(in, timings);
142}
143
144static const struct omapdss_dvi_ops tfp410_dvi_ops = {
145 .connect = tfp410_connect,
146 .disconnect = tfp410_disconnect,
147
148 .enable = tfp410_enable,
149 .disable = tfp410_disable,
150
151 .check_timings = tfp410_check_timings,
152 .set_timings = tfp410_set_timings,
153 .get_timings = tfp410_get_timings,
154};
155
156static int tfp410_probe_pdata(struct platform_device *pdev)
157{
158 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
159 struct encoder_tfp410_platform_data *pdata;
160 struct omap_dss_device *dssdev, *in;
161
162 pdata = dev_get_platdata(&pdev->dev);
163
164 ddata->pd_gpio = pdata->power_down_gpio;
165
166 ddata->data_lines = pdata->data_lines;
167
168 in = omap_dss_find_output(pdata->source);
169 if (in == NULL) {
170 dev_err(&pdev->dev, "Failed to find video source\n");
171 return -ENODEV;
172 }
173
174 ddata->in = in;
175
176 dssdev = &ddata->dssdev;
177 dssdev->name = pdata->name;
178
179 return 0;
180}
181
182static int tfp410_probe(struct platform_device *pdev)
183{
184 struct panel_drv_data *ddata;
185 struct omap_dss_device *dssdev;
186 int r;
187
188 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
189 if (!ddata)
190 return -ENOMEM;
191
192 platform_set_drvdata(pdev, ddata);
193
194 if (dev_get_platdata(&pdev->dev)) {
195 r = tfp410_probe_pdata(pdev);
196 if (r)
197 return r;
198 } else {
199 return -ENODEV;
200 }
201
202 if (gpio_is_valid(ddata->pd_gpio)) {
203 r = devm_gpio_request_one(&pdev->dev, ddata->pd_gpio,
204 GPIOF_OUT_INIT_LOW, "tfp410 PD");
205 if (r) {
206 dev_err(&pdev->dev, "Failed to request PD GPIO %d\n",
207 ddata->pd_gpio);
208 goto err_gpio;
209 }
210 }
211
212 dssdev = &ddata->dssdev;
213 dssdev->ops.dvi = &tfp410_dvi_ops;
214 dssdev->dev = &pdev->dev;
215 dssdev->type = OMAP_DISPLAY_TYPE_DPI;
216 dssdev->output_type = OMAP_DISPLAY_TYPE_DVI;
217 dssdev->owner = THIS_MODULE;
218 dssdev->phy.dpi.data_lines = ddata->data_lines;
219
220 r = omapdss_register_output(dssdev);
221 if (r) {
222 dev_err(&pdev->dev, "Failed to register output\n");
223 goto err_reg;
224 }
225
226 return 0;
227err_reg:
228err_gpio:
229 omap_dss_put_device(ddata->in);
230 return r;
231}
232
233static int __exit tfp410_remove(struct platform_device *pdev)
234{
235 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
236 struct omap_dss_device *dssdev = &ddata->dssdev;
237 struct omap_dss_device *in = ddata->in;
238
239 omapdss_unregister_output(&ddata->dssdev);
240
241 WARN_ON(omapdss_device_is_enabled(dssdev));
242 if (omapdss_device_is_enabled(dssdev))
243 tfp410_disable(dssdev);
244
245 WARN_ON(omapdss_device_is_connected(dssdev));
246 if (omapdss_device_is_connected(dssdev))
247 tfp410_disconnect(dssdev, dssdev->device);
248
249 omap_dss_put_device(in);
250
251 return 0;
252}
253
254static struct platform_driver tfp410_driver = {
255 .probe = tfp410_probe,
256 .remove = __exit_p(tfp410_remove),
257 .driver = {
258 .name = "tfp410",
259 .owner = THIS_MODULE,
260 },
261};
262
263module_platform_driver(tfp410_driver);
264
265MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
266MODULE_DESCRIPTION("TFP410 DPI to DVI encoder driver");
267MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/encoder-tpd12s015.c b/drivers/video/omap2/displays-new/encoder-tpd12s015.c
new file mode 100644
index 000000000000..ce0e010026cb
--- /dev/null
+++ b/drivers/video/omap2/displays-new/encoder-tpd12s015.c
@@ -0,0 +1,395 @@
1/*
2 * TPD12S015 HDMI ESD protection & level shifter chip driver
3 *
4 * Copyright (C) 2013 Texas Instruments
5 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
6 *
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.
10 */
11
12#include <linux/completion.h>
13#include <linux/delay.h>
14#include <linux/module.h>
15#include <linux/slab.h>
16#include <linux/gpio.h>
17#include <linux/platform_device.h>
18
19#include <video/omapdss.h>
20#include <video/omap-panel-data.h>
21
22struct panel_drv_data {
23 struct omap_dss_device dssdev;
24 struct omap_dss_device *in;
25
26 int ct_cp_hpd_gpio;
27 int ls_oe_gpio;
28 int hpd_gpio;
29
30 struct omap_video_timings timings;
31
32 struct completion hpd_completion;
33};
34
35#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
36
37static irqreturn_t tpd_hpd_irq_handler(int irq, void *data)
38{
39 struct panel_drv_data *ddata = data;
40 bool hpd;
41
42 hpd = gpio_get_value_cansleep(ddata->hpd_gpio);
43
44 dev_dbg(ddata->dssdev.dev, "hpd %d\n", hpd);
45
46 if (gpio_is_valid(ddata->ls_oe_gpio)) {
47 if (hpd)
48 gpio_set_value_cansleep(ddata->ls_oe_gpio, 1);
49 else
50 gpio_set_value_cansleep(ddata->ls_oe_gpio, 0);
51 }
52
53 complete_all(&ddata->hpd_completion);
54
55 return IRQ_HANDLED;
56}
57
58static int tpd_connect(struct omap_dss_device *dssdev,
59 struct omap_dss_device *dst)
60{
61 struct panel_drv_data *ddata = to_panel_data(dssdev);
62 struct omap_dss_device *in = ddata->in;
63 int r;
64
65 r = in->ops.hdmi->connect(in, dssdev);
66 if (r)
67 return r;
68
69 dst->output = dssdev;
70 dssdev->device = dst;
71
72 INIT_COMPLETION(ddata->hpd_completion);
73
74 gpio_set_value_cansleep(ddata->ct_cp_hpd_gpio, 1);
75 /* DC-DC converter needs at max 300us to get to 90% of 5V */
76 udelay(300);
77
78 /*
79 * If there's a cable connected, wait for the hpd irq to trigger,
80 * which turns on the level shifters.
81 */
82 if (gpio_get_value_cansleep(ddata->hpd_gpio)) {
83 unsigned long to;
84 to = wait_for_completion_timeout(&ddata->hpd_completion,
85 msecs_to_jiffies(250));
86 WARN_ON_ONCE(to == 0);
87 }
88
89 return 0;
90}
91
92static void tpd_disconnect(struct omap_dss_device *dssdev,
93 struct omap_dss_device *dst)
94{
95 struct panel_drv_data *ddata = to_panel_data(dssdev);
96 struct omap_dss_device *in = ddata->in;
97
98 WARN_ON(dst != dssdev->device);
99
100 if (dst != dssdev->device)
101 return;
102
103 gpio_set_value_cansleep(ddata->ct_cp_hpd_gpio, 0);
104
105 dst->output = NULL;
106 dssdev->device = NULL;
107
108 in->ops.hdmi->disconnect(in, &ddata->dssdev);
109}
110
111static int tpd_enable(struct omap_dss_device *dssdev)
112{
113 struct panel_drv_data *ddata = to_panel_data(dssdev);
114 struct omap_dss_device *in = ddata->in;
115 int r;
116
117 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
118 return 0;
119
120 in->ops.hdmi->set_timings(in, &ddata->timings);
121
122 r = in->ops.hdmi->enable(in);
123 if (r)
124 return r;
125
126 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
127
128 return r;
129}
130
131static void tpd_disable(struct omap_dss_device *dssdev)
132{
133 struct panel_drv_data *ddata = to_panel_data(dssdev);
134 struct omap_dss_device *in = ddata->in;
135
136 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
137 return;
138
139 in->ops.hdmi->disable(in);
140
141 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
142}
143
144static void tpd_set_timings(struct omap_dss_device *dssdev,
145 struct omap_video_timings *timings)
146{
147 struct panel_drv_data *ddata = to_panel_data(dssdev);
148 struct omap_dss_device *in = ddata->in;
149
150 ddata->timings = *timings;
151 dssdev->panel.timings = *timings;
152
153 in->ops.hdmi->set_timings(in, timings);
154}
155
156static void tpd_get_timings(struct omap_dss_device *dssdev,
157 struct omap_video_timings *timings)
158{
159 struct panel_drv_data *ddata = to_panel_data(dssdev);
160
161 *timings = ddata->timings;
162}
163
164static int tpd_check_timings(struct omap_dss_device *dssdev,
165 struct omap_video_timings *timings)
166{
167 struct panel_drv_data *ddata = to_panel_data(dssdev);
168 struct omap_dss_device *in = ddata->in;
169 int r;
170
171 r = in->ops.hdmi->check_timings(in, timings);
172
173 return r;
174}
175
176static int tpd_read_edid(struct omap_dss_device *dssdev,
177 u8 *edid, int len)
178{
179 struct panel_drv_data *ddata = to_panel_data(dssdev);
180 struct omap_dss_device *in = ddata->in;
181
182 if (!gpio_get_value_cansleep(ddata->hpd_gpio))
183 return -ENODEV;
184
185 return in->ops.hdmi->read_edid(in, edid, len);
186}
187
188static bool tpd_detect(struct omap_dss_device *dssdev)
189{
190 struct panel_drv_data *ddata = to_panel_data(dssdev);
191
192 return gpio_get_value_cansleep(ddata->hpd_gpio);
193}
194
195static int tpd_audio_enable(struct omap_dss_device *dssdev)
196{
197 struct panel_drv_data *ddata = to_panel_data(dssdev);
198 struct omap_dss_device *in = ddata->in;
199
200 return in->ops.hdmi->audio_enable(in);
201}
202
203static void tpd_audio_disable(struct omap_dss_device *dssdev)
204{
205 struct panel_drv_data *ddata = to_panel_data(dssdev);
206 struct omap_dss_device *in = ddata->in;
207
208 in->ops.hdmi->audio_disable(in);
209}
210
211static int tpd_audio_start(struct omap_dss_device *dssdev)
212{
213 struct panel_drv_data *ddata = to_panel_data(dssdev);
214 struct omap_dss_device *in = ddata->in;
215
216 return in->ops.hdmi->audio_start(in);
217}
218
219static void tpd_audio_stop(struct omap_dss_device *dssdev)
220{
221 struct panel_drv_data *ddata = to_panel_data(dssdev);
222 struct omap_dss_device *in = ddata->in;
223
224 in->ops.hdmi->audio_stop(in);
225}
226
227static bool tpd_audio_supported(struct omap_dss_device *dssdev)
228{
229 struct panel_drv_data *ddata = to_panel_data(dssdev);
230 struct omap_dss_device *in = ddata->in;
231
232 return in->ops.hdmi->audio_supported(in);
233}
234
235static int tpd_audio_config(struct omap_dss_device *dssdev,
236 struct omap_dss_audio *audio)
237{
238 struct panel_drv_data *ddata = to_panel_data(dssdev);
239 struct omap_dss_device *in = ddata->in;
240
241 return in->ops.hdmi->audio_config(in, audio);
242}
243
244static const struct omapdss_hdmi_ops tpd_hdmi_ops = {
245 .connect = tpd_connect,
246 .disconnect = tpd_disconnect,
247
248 .enable = tpd_enable,
249 .disable = tpd_disable,
250
251 .check_timings = tpd_check_timings,
252 .set_timings = tpd_set_timings,
253 .get_timings = tpd_get_timings,
254
255 .read_edid = tpd_read_edid,
256 .detect = tpd_detect,
257
258 .audio_enable = tpd_audio_enable,
259 .audio_disable = tpd_audio_disable,
260 .audio_start = tpd_audio_start,
261 .audio_stop = tpd_audio_stop,
262 .audio_supported = tpd_audio_supported,
263 .audio_config = tpd_audio_config,
264};
265
266static int tpd_probe_pdata(struct platform_device *pdev)
267{
268 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
269 struct encoder_tpd12s015_platform_data *pdata;
270 struct omap_dss_device *dssdev, *in;
271
272 pdata = dev_get_platdata(&pdev->dev);
273
274 ddata->ct_cp_hpd_gpio = pdata->ct_cp_hpd_gpio;
275 ddata->ls_oe_gpio = pdata->ls_oe_gpio;
276 ddata->hpd_gpio = pdata->hpd_gpio;
277
278 in = omap_dss_find_output(pdata->source);
279 if (in == NULL) {
280 dev_err(&pdev->dev, "Failed to find video source\n");
281 return -ENODEV;
282 }
283
284 ddata->in = in;
285
286 dssdev = &ddata->dssdev;
287 dssdev->name = pdata->name;
288
289 return 0;
290}
291
292static int tpd_probe(struct platform_device *pdev)
293{
294 struct omap_dss_device *in, *dssdev;
295 struct panel_drv_data *ddata;
296 int r;
297
298 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
299 if (!ddata)
300 return -ENOMEM;
301
302 platform_set_drvdata(pdev, ddata);
303
304 init_completion(&ddata->hpd_completion);
305
306 if (dev_get_platdata(&pdev->dev)) {
307 r = tpd_probe_pdata(pdev);
308 if (r)
309 return r;
310 } else {
311 return -ENODEV;
312 }
313
314 r = devm_gpio_request_one(&pdev->dev, ddata->ct_cp_hpd_gpio,
315 GPIOF_OUT_INIT_LOW, "hdmi_ct_cp_hpd");
316 if (r)
317 goto err_gpio;
318
319 if (gpio_is_valid(ddata->ls_oe_gpio)) {
320 r = devm_gpio_request_one(&pdev->dev, ddata->ls_oe_gpio,
321 GPIOF_OUT_INIT_LOW, "hdmi_ls_oe");
322 if (r)
323 goto err_gpio;
324 }
325
326 r = devm_gpio_request_one(&pdev->dev, ddata->hpd_gpio,
327 GPIOF_DIR_IN, "hdmi_hpd");
328 if (r)
329 goto err_gpio;
330
331 r = devm_request_threaded_irq(&pdev->dev, gpio_to_irq(ddata->hpd_gpio),
332 NULL, tpd_hpd_irq_handler,
333 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
334 IRQF_ONESHOT, "hpd", ddata);
335 if (r)
336 goto err_irq;
337
338 dssdev = &ddata->dssdev;
339 dssdev->ops.hdmi = &tpd_hdmi_ops;
340 dssdev->dev = &pdev->dev;
341 dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
342 dssdev->output_type = OMAP_DISPLAY_TYPE_HDMI;
343 dssdev->owner = THIS_MODULE;
344
345 in = ddata->in;
346
347 r = omapdss_register_output(dssdev);
348 if (r) {
349 dev_err(&pdev->dev, "Failed to register output\n");
350 goto err_reg;
351 }
352
353 return 0;
354err_reg:
355err_irq:
356err_gpio:
357 omap_dss_put_device(ddata->in);
358 return r;
359}
360
361static int __exit tpd_remove(struct platform_device *pdev)
362{
363 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
364 struct omap_dss_device *dssdev = &ddata->dssdev;
365 struct omap_dss_device *in = ddata->in;
366
367 omapdss_unregister_output(&ddata->dssdev);
368
369 WARN_ON(omapdss_device_is_enabled(dssdev));
370 if (omapdss_device_is_enabled(dssdev))
371 tpd_disable(dssdev);
372
373 WARN_ON(omapdss_device_is_connected(dssdev));
374 if (omapdss_device_is_connected(dssdev))
375 tpd_disconnect(dssdev, dssdev->device);
376
377 omap_dss_put_device(in);
378
379 return 0;
380}
381
382static struct platform_driver tpd_driver = {
383 .probe = tpd_probe,
384 .remove = __exit_p(tpd_remove),
385 .driver = {
386 .name = "tpd12s015",
387 .owner = THIS_MODULE,
388 },
389};
390
391module_platform_driver(tpd_driver);
392
393MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
394MODULE_DESCRIPTION("TPD12S015 driver");
395MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/panel-dpi.c b/drivers/video/omap2/displays-new/panel-dpi.c
new file mode 100644
index 000000000000..5f8f7e7c81ef
--- /dev/null
+++ b/drivers/video/omap2/displays-new/panel-dpi.c
@@ -0,0 +1,270 @@
1/*
2 * Generic MIPI DPI Panel Driver
3 *
4 * Copyright (C) 2013 Texas Instruments
5 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
6 *
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.
10 */
11
12#include <linux/gpio.h>
13#include <linux/module.h>
14#include <linux/platform_device.h>
15#include <linux/slab.h>
16
17#include <video/omapdss.h>
18#include <video/omap-panel-data.h>
19
20struct panel_drv_data {
21 struct omap_dss_device dssdev;
22 struct omap_dss_device *in;
23
24 int data_lines;
25
26 struct omap_video_timings videomode;
27
28 int backlight_gpio;
29 int enable_gpio;
30};
31
32#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
33
34static int panel_dpi_connect(struct omap_dss_device *dssdev)
35{
36 struct panel_drv_data *ddata = to_panel_data(dssdev);
37 struct omap_dss_device *in = ddata->in;
38 int r;
39
40 if (omapdss_device_is_connected(dssdev))
41 return 0;
42
43 r = in->ops.dpi->connect(in, dssdev);
44 if (r)
45 return r;
46
47 return 0;
48}
49
50static void panel_dpi_disconnect(struct omap_dss_device *dssdev)
51{
52 struct panel_drv_data *ddata = to_panel_data(dssdev);
53 struct omap_dss_device *in = ddata->in;
54
55 if (!omapdss_device_is_connected(dssdev))
56 return;
57
58 in->ops.dpi->disconnect(in, dssdev);
59}
60
61static int panel_dpi_enable(struct omap_dss_device *dssdev)
62{
63 struct panel_drv_data *ddata = to_panel_data(dssdev);
64 struct omap_dss_device *in = ddata->in;
65 int r;
66
67 if (!omapdss_device_is_connected(dssdev))
68 return -ENODEV;
69
70 if (omapdss_device_is_enabled(dssdev))
71 return 0;
72
73 in->ops.dpi->set_data_lines(in, ddata->data_lines);
74 in->ops.dpi->set_timings(in, &ddata->videomode);
75
76 r = in->ops.dpi->enable(in);
77 if (r)
78 return r;
79
80 if (gpio_is_valid(ddata->enable_gpio))
81 gpio_set_value_cansleep(ddata->enable_gpio, 1);
82
83 if (gpio_is_valid(ddata->backlight_gpio))
84 gpio_set_value_cansleep(ddata->backlight_gpio, 1);
85
86 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
87
88 return 0;
89}
90
91static void panel_dpi_disable(struct omap_dss_device *dssdev)
92{
93 struct panel_drv_data *ddata = to_panel_data(dssdev);
94 struct omap_dss_device *in = ddata->in;
95
96 if (!omapdss_device_is_enabled(dssdev))
97 return;
98
99 if (gpio_is_valid(ddata->enable_gpio))
100 gpio_set_value_cansleep(ddata->enable_gpio, 0);
101
102 if (gpio_is_valid(ddata->backlight_gpio))
103 gpio_set_value_cansleep(ddata->backlight_gpio, 0);
104
105 in->ops.dpi->disable(in);
106
107 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
108}
109
110static void panel_dpi_set_timings(struct omap_dss_device *dssdev,
111 struct omap_video_timings *timings)
112{
113 struct panel_drv_data *ddata = to_panel_data(dssdev);
114 struct omap_dss_device *in = ddata->in;
115
116 ddata->videomode = *timings;
117 dssdev->panel.timings = *timings;
118
119 in->ops.dpi->set_timings(in, timings);
120}
121
122static void panel_dpi_get_timings(struct omap_dss_device *dssdev,
123 struct omap_video_timings *timings)
124{
125 struct panel_drv_data *ddata = to_panel_data(dssdev);
126
127 *timings = ddata->videomode;
128}
129
130static int panel_dpi_check_timings(struct omap_dss_device *dssdev,
131 struct omap_video_timings *timings)
132{
133 struct panel_drv_data *ddata = to_panel_data(dssdev);
134 struct omap_dss_device *in = ddata->in;
135
136 return in->ops.dpi->check_timings(in, timings);
137}
138
139static struct omap_dss_driver panel_dpi_ops = {
140 .connect = panel_dpi_connect,
141 .disconnect = panel_dpi_disconnect,
142
143 .enable = panel_dpi_enable,
144 .disable = panel_dpi_disable,
145
146 .set_timings = panel_dpi_set_timings,
147 .get_timings = panel_dpi_get_timings,
148 .check_timings = panel_dpi_check_timings,
149
150 .get_resolution = omapdss_default_get_resolution,
151};
152
153static int panel_dpi_probe_pdata(struct platform_device *pdev)
154{
155 const struct panel_dpi_platform_data *pdata;
156 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
157 struct omap_dss_device *dssdev, *in;
158 struct videomode vm;
159
160 pdata = dev_get_platdata(&pdev->dev);
161
162 in = omap_dss_find_output(pdata->source);
163 if (in == NULL) {
164 dev_err(&pdev->dev, "failed to find video source '%s'\n",
165 pdata->source);
166 return -EPROBE_DEFER;
167 }
168
169 ddata->in = in;
170
171 ddata->data_lines = pdata->data_lines;
172
173 videomode_from_timing(pdata->display_timing, &vm);
174 videomode_to_omap_video_timings(&vm, &ddata->videomode);
175
176 dssdev = &ddata->dssdev;
177 dssdev->name = pdata->name;
178
179 ddata->enable_gpio = pdata->enable_gpio;
180 ddata->backlight_gpio = pdata->backlight_gpio;
181
182 return 0;
183}
184
185static int panel_dpi_probe(struct platform_device *pdev)
186{
187 struct panel_drv_data *ddata;
188 struct omap_dss_device *dssdev;
189 int r;
190
191 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
192 if (ddata == NULL)
193 return -ENOMEM;
194
195 platform_set_drvdata(pdev, ddata);
196
197 if (dev_get_platdata(&pdev->dev)) {
198 r = panel_dpi_probe_pdata(pdev);
199 if (r)
200 return r;
201 } else {
202 return -ENODEV;
203 }
204
205 if (gpio_is_valid(ddata->enable_gpio)) {
206 r = devm_gpio_request_one(&pdev->dev, ddata->enable_gpio,
207 GPIOF_OUT_INIT_LOW, "panel enable");
208 if (r)
209 goto err_gpio;
210 }
211
212 if (gpio_is_valid(ddata->backlight_gpio)) {
213 r = devm_gpio_request_one(&pdev->dev, ddata->backlight_gpio,
214 GPIOF_OUT_INIT_LOW, "panel backlight");
215 if (r)
216 goto err_gpio;
217 }
218
219 dssdev = &ddata->dssdev;
220 dssdev->dev = &pdev->dev;
221 dssdev->driver = &panel_dpi_ops;
222 dssdev->type = OMAP_DISPLAY_TYPE_DPI;
223 dssdev->owner = THIS_MODULE;
224 dssdev->panel.timings = ddata->videomode;
225 dssdev->phy.dpi.data_lines = ddata->data_lines;
226
227 r = omapdss_register_display(dssdev);
228 if (r) {
229 dev_err(&pdev->dev, "Failed to register panel\n");
230 goto err_reg;
231 }
232
233 return 0;
234
235err_reg:
236err_gpio:
237 omap_dss_put_device(ddata->in);
238 return r;
239}
240
241static int __exit panel_dpi_remove(struct platform_device *pdev)
242{
243 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
244 struct omap_dss_device *dssdev = &ddata->dssdev;
245 struct omap_dss_device *in = ddata->in;
246
247 omapdss_unregister_display(dssdev);
248
249 panel_dpi_disable(dssdev);
250 panel_dpi_disconnect(dssdev);
251
252 omap_dss_put_device(in);
253
254 return 0;
255}
256
257static struct platform_driver panel_dpi_driver = {
258 .probe = panel_dpi_probe,
259 .remove = __exit_p(panel_dpi_remove),
260 .driver = {
261 .name = "panel-dpi",
262 .owner = THIS_MODULE,
263 },
264};
265
266module_platform_driver(panel_dpi_driver);
267
268MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
269MODULE_DESCRIPTION("Generic MIPI DPI Panel Driver");
270MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/panel-dsi-cm.c b/drivers/video/omap2/displays-new/panel-dsi-cm.c
new file mode 100644
index 000000000000..aaaea6469cd9
--- /dev/null
+++ b/drivers/video/omap2/displays-new/panel-dsi-cm.c
@@ -0,0 +1,1336 @@
1/*
2 * Generic DSI Command Mode panel driver
3 *
4 * Copyright (C) 2013 Texas Instruments
5 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
6 *
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.
10 */
11
12/* #define DEBUG */
13
14#include <linux/backlight.h>
15#include <linux/delay.h>
16#include <linux/fb.h>
17#include <linux/gpio.h>
18#include <linux/interrupt.h>
19#include <linux/jiffies.h>
20#include <linux/module.h>
21#include <linux/platform_device.h>
22#include <linux/sched.h>
23#include <linux/slab.h>
24#include <linux/workqueue.h>
25
26#include <video/omapdss.h>
27#include <video/omap-panel-data.h>
28#include <video/mipi_display.h>
29
30/* DSI Virtual channel. Hardcoded for now. */
31#define TCH 0
32
33#define DCS_READ_NUM_ERRORS 0x05
34#define DCS_BRIGHTNESS 0x51
35#define DCS_CTRL_DISPLAY 0x53
36#define DCS_GET_ID1 0xda
37#define DCS_GET_ID2 0xdb
38#define DCS_GET_ID3 0xdc
39
40struct panel_drv_data {
41 struct omap_dss_device dssdev;
42 struct omap_dss_device *in;
43
44 struct omap_video_timings timings;
45
46 struct platform_device *pdev;
47
48 struct mutex lock;
49
50 struct backlight_device *bldev;
51
52 unsigned long hw_guard_end; /* next value of jiffies when we can
53 * issue the next sleep in/out command
54 */
55 unsigned long hw_guard_wait; /* max guard time in jiffies */
56
57 /* panel HW configuration from DT or platform data */
58 int reset_gpio;
59 int ext_te_gpio;
60
61 bool use_dsi_backlight;
62
63 struct omap_dsi_pin_config pin_config;
64
65 /* runtime variables */
66 bool enabled;
67
68 bool te_enabled;
69
70 atomic_t do_update;
71 int channel;
72
73 struct delayed_work te_timeout_work;
74
75 bool intro_printed;
76
77 struct workqueue_struct *workqueue;
78
79 bool ulps_enabled;
80 unsigned ulps_timeout;
81 struct delayed_work ulps_work;
82};
83
84#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
85
86static irqreturn_t dsicm_te_isr(int irq, void *data);
87static void dsicm_te_timeout_work_callback(struct work_struct *work);
88static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable);
89
90static int dsicm_panel_reset(struct panel_drv_data *ddata);
91
92static void dsicm_ulps_work(struct work_struct *work);
93
94static void hw_guard_start(struct panel_drv_data *ddata, int guard_msec)
95{
96 ddata->hw_guard_wait = msecs_to_jiffies(guard_msec);
97 ddata->hw_guard_end = jiffies + ddata->hw_guard_wait;
98}
99
100static void hw_guard_wait(struct panel_drv_data *ddata)
101{
102 unsigned long wait = ddata->hw_guard_end - jiffies;
103
104 if ((long)wait > 0 && wait <= ddata->hw_guard_wait) {
105 set_current_state(TASK_UNINTERRUPTIBLE);
106 schedule_timeout(wait);
107 }
108}
109
110static int dsicm_dcs_read_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 *data)
111{
112 struct omap_dss_device *in = ddata->in;
113 int r;
114 u8 buf[1];
115
116 r = in->ops.dsi->dcs_read(in, ddata->channel, dcs_cmd, buf, 1);
117
118 if (r < 0)
119 return r;
120
121 *data = buf[0];
122
123 return 0;
124}
125
126static int dsicm_dcs_write_0(struct panel_drv_data *ddata, u8 dcs_cmd)
127{
128 struct omap_dss_device *in = ddata->in;
129 return in->ops.dsi->dcs_write(in, ddata->channel, &dcs_cmd, 1);
130}
131
132static int dsicm_dcs_write_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 param)
133{
134 struct omap_dss_device *in = ddata->in;
135 u8 buf[2] = { dcs_cmd, param };
136
137 return in->ops.dsi->dcs_write(in, ddata->channel, buf, 2);
138}
139
140static int dsicm_sleep_in(struct panel_drv_data *ddata)
141
142{
143 struct omap_dss_device *in = ddata->in;
144 u8 cmd;
145 int r;
146
147 hw_guard_wait(ddata);
148
149 cmd = MIPI_DCS_ENTER_SLEEP_MODE;
150 r = in->ops.dsi->dcs_write_nosync(in, ddata->channel, &cmd, 1);
151 if (r)
152 return r;
153
154 hw_guard_start(ddata, 120);
155
156 usleep_range(5000, 10000);
157
158 return 0;
159}
160
161static int dsicm_sleep_out(struct panel_drv_data *ddata)
162{
163 int r;
164
165 hw_guard_wait(ddata);
166
167 r = dsicm_dcs_write_0(ddata, MIPI_DCS_EXIT_SLEEP_MODE);
168 if (r)
169 return r;
170
171 hw_guard_start(ddata, 120);
172
173 usleep_range(5000, 10000);
174
175 return 0;
176}
177
178static int dsicm_get_id(struct panel_drv_data *ddata, u8 *id1, u8 *id2, u8 *id3)
179{
180 int r;
181
182 r = dsicm_dcs_read_1(ddata, DCS_GET_ID1, id1);
183 if (r)
184 return r;
185 r = dsicm_dcs_read_1(ddata, DCS_GET_ID2, id2);
186 if (r)
187 return r;
188 r = dsicm_dcs_read_1(ddata, DCS_GET_ID3, id3);
189 if (r)
190 return r;
191
192 return 0;
193}
194
195static int dsicm_set_update_window(struct panel_drv_data *ddata,
196 u16 x, u16 y, u16 w, u16 h)
197{
198 struct omap_dss_device *in = ddata->in;
199 int r;
200 u16 x1 = x;
201 u16 x2 = x + w - 1;
202 u16 y1 = y;
203 u16 y2 = y + h - 1;
204
205 u8 buf[5];
206 buf[0] = MIPI_DCS_SET_COLUMN_ADDRESS;
207 buf[1] = (x1 >> 8) & 0xff;
208 buf[2] = (x1 >> 0) & 0xff;
209 buf[3] = (x2 >> 8) & 0xff;
210 buf[4] = (x2 >> 0) & 0xff;
211
212 r = in->ops.dsi->dcs_write_nosync(in, ddata->channel, buf, sizeof(buf));
213 if (r)
214 return r;
215
216 buf[0] = MIPI_DCS_SET_PAGE_ADDRESS;
217 buf[1] = (y1 >> 8) & 0xff;
218 buf[2] = (y1 >> 0) & 0xff;
219 buf[3] = (y2 >> 8) & 0xff;
220 buf[4] = (y2 >> 0) & 0xff;
221
222 r = in->ops.dsi->dcs_write_nosync(in, ddata->channel, buf, sizeof(buf));
223 if (r)
224 return r;
225
226 in->ops.dsi->bta_sync(in, ddata->channel);
227
228 return r;
229}
230
231static void dsicm_queue_ulps_work(struct panel_drv_data *ddata)
232{
233 if (ddata->ulps_timeout > 0)
234 queue_delayed_work(ddata->workqueue, &ddata->ulps_work,
235 msecs_to_jiffies(ddata->ulps_timeout));
236}
237
238static void dsicm_cancel_ulps_work(struct panel_drv_data *ddata)
239{
240 cancel_delayed_work(&ddata->ulps_work);
241}
242
243static int dsicm_enter_ulps(struct panel_drv_data *ddata)
244{
245 struct omap_dss_device *in = ddata->in;
246 int r;
247
248 if (ddata->ulps_enabled)
249 return 0;
250
251 dsicm_cancel_ulps_work(ddata);
252
253 r = _dsicm_enable_te(ddata, false);
254 if (r)
255 goto err;
256
257 if (gpio_is_valid(ddata->ext_te_gpio))
258 disable_irq(gpio_to_irq(ddata->ext_te_gpio));
259
260 in->ops.dsi->disable(in, false, true);
261
262 ddata->ulps_enabled = true;
263
264 return 0;
265
266err:
267 dev_err(&ddata->pdev->dev, "enter ULPS failed");
268 dsicm_panel_reset(ddata);
269
270 ddata->ulps_enabled = false;
271
272 dsicm_queue_ulps_work(ddata);
273
274 return r;
275}
276
277static int dsicm_exit_ulps(struct panel_drv_data *ddata)
278{
279 struct omap_dss_device *in = ddata->in;
280 int r;
281
282 if (!ddata->ulps_enabled)
283 return 0;
284
285 r = in->ops.dsi->enable(in);
286 if (r) {
287 dev_err(&ddata->pdev->dev, "failed to enable DSI\n");
288 goto err1;
289 }
290
291 in->ops.dsi->enable_hs(in, ddata->channel, true);
292
293 r = _dsicm_enable_te(ddata, true);
294 if (r) {
295 dev_err(&ddata->pdev->dev, "failed to re-enable TE");
296 goto err2;
297 }
298
299 if (gpio_is_valid(ddata->ext_te_gpio))
300 enable_irq(gpio_to_irq(ddata->ext_te_gpio));
301
302 dsicm_queue_ulps_work(ddata);
303
304 ddata->ulps_enabled = false;
305
306 return 0;
307
308err2:
309 dev_err(&ddata->pdev->dev, "failed to exit ULPS");
310
311 r = dsicm_panel_reset(ddata);
312 if (!r) {
313 if (gpio_is_valid(ddata->ext_te_gpio))
314 enable_irq(gpio_to_irq(ddata->ext_te_gpio));
315 ddata->ulps_enabled = false;
316 }
317err1:
318 dsicm_queue_ulps_work(ddata);
319
320 return r;
321}
322
323static int dsicm_wake_up(struct panel_drv_data *ddata)
324{
325 if (ddata->ulps_enabled)
326 return dsicm_exit_ulps(ddata);
327
328 dsicm_cancel_ulps_work(ddata);
329 dsicm_queue_ulps_work(ddata);
330 return 0;
331}
332
333static int dsicm_bl_update_status(struct backlight_device *dev)
334{
335 struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
336 struct omap_dss_device *in = ddata->in;
337 int r;
338 int level;
339
340 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
341 dev->props.power == FB_BLANK_UNBLANK)
342 level = dev->props.brightness;
343 else
344 level = 0;
345
346 dev_dbg(&ddata->pdev->dev, "update brightness to %d\n", level);
347
348 mutex_lock(&ddata->lock);
349
350 if (ddata->enabled) {
351 in->ops.dsi->bus_lock(in);
352
353 r = dsicm_wake_up(ddata);
354 if (!r)
355 r = dsicm_dcs_write_1(ddata, DCS_BRIGHTNESS, level);
356
357 in->ops.dsi->bus_unlock(in);
358 } else {
359 r = 0;
360 }
361
362 mutex_unlock(&ddata->lock);
363
364 return r;
365}
366
367static int dsicm_bl_get_intensity(struct backlight_device *dev)
368{
369 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
370 dev->props.power == FB_BLANK_UNBLANK)
371 return dev->props.brightness;
372
373 return 0;
374}
375
376static const struct backlight_ops dsicm_bl_ops = {
377 .get_brightness = dsicm_bl_get_intensity,
378 .update_status = dsicm_bl_update_status,
379};
380
381static void dsicm_get_resolution(struct omap_dss_device *dssdev,
382 u16 *xres, u16 *yres)
383{
384 *xres = dssdev->panel.timings.x_res;
385 *yres = dssdev->panel.timings.y_res;
386}
387
388static ssize_t dsicm_num_errors_show(struct device *dev,
389 struct device_attribute *attr, char *buf)
390{
391 struct platform_device *pdev = to_platform_device(dev);
392 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
393 struct omap_dss_device *in = ddata->in;
394 u8 errors = 0;
395 int r;
396
397 mutex_lock(&ddata->lock);
398
399 if (ddata->enabled) {
400 in->ops.dsi->bus_lock(in);
401
402 r = dsicm_wake_up(ddata);
403 if (!r)
404 r = dsicm_dcs_read_1(ddata, DCS_READ_NUM_ERRORS,
405 &errors);
406
407 in->ops.dsi->bus_unlock(in);
408 } else {
409 r = -ENODEV;
410 }
411
412 mutex_unlock(&ddata->lock);
413
414 if (r)
415 return r;
416
417 return snprintf(buf, PAGE_SIZE, "%d\n", errors);
418}
419
420static ssize_t dsicm_hw_revision_show(struct device *dev,
421 struct device_attribute *attr, char *buf)
422{
423 struct platform_device *pdev = to_platform_device(dev);
424 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
425 struct omap_dss_device *in = ddata->in;
426 u8 id1, id2, id3;
427 int r;
428
429 mutex_lock(&ddata->lock);
430
431 if (ddata->enabled) {
432 in->ops.dsi->bus_lock(in);
433
434 r = dsicm_wake_up(ddata);
435 if (!r)
436 r = dsicm_get_id(ddata, &id1, &id2, &id3);
437
438 in->ops.dsi->bus_unlock(in);
439 } else {
440 r = -ENODEV;
441 }
442
443 mutex_unlock(&ddata->lock);
444
445 if (r)
446 return r;
447
448 return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x\n", id1, id2, id3);
449}
450
451static ssize_t dsicm_store_ulps(struct device *dev,
452 struct device_attribute *attr,
453 const char *buf, size_t count)
454{
455 struct platform_device *pdev = to_platform_device(dev);
456 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
457 struct omap_dss_device *in = ddata->in;
458 unsigned long t;
459 int r;
460
461 r = kstrtoul(buf, 0, &t);
462 if (r)
463 return r;
464
465 mutex_lock(&ddata->lock);
466
467 if (ddata->enabled) {
468 in->ops.dsi->bus_lock(in);
469
470 if (t)
471 r = dsicm_enter_ulps(ddata);
472 else
473 r = dsicm_wake_up(ddata);
474
475 in->ops.dsi->bus_unlock(in);
476 }
477
478 mutex_unlock(&ddata->lock);
479
480 if (r)
481 return r;
482
483 return count;
484}
485
486static ssize_t dsicm_show_ulps(struct device *dev,
487 struct device_attribute *attr,
488 char *buf)
489{
490 struct platform_device *pdev = to_platform_device(dev);
491 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
492 unsigned t;
493
494 mutex_lock(&ddata->lock);
495 t = ddata->ulps_enabled;
496 mutex_unlock(&ddata->lock);
497
498 return snprintf(buf, PAGE_SIZE, "%u\n", t);
499}
500
501static ssize_t dsicm_store_ulps_timeout(struct device *dev,
502 struct device_attribute *attr,
503 const char *buf, size_t count)
504{
505 struct platform_device *pdev = to_platform_device(dev);
506 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
507 struct omap_dss_device *in = ddata->in;
508 unsigned long t;
509 int r;
510
511 r = kstrtoul(buf, 0, &t);
512 if (r)
513 return r;
514
515 mutex_lock(&ddata->lock);
516 ddata->ulps_timeout = t;
517
518 if (ddata->enabled) {
519 /* dsicm_wake_up will restart the timer */
520 in->ops.dsi->bus_lock(in);
521 r = dsicm_wake_up(ddata);
522 in->ops.dsi->bus_unlock(in);
523 }
524
525 mutex_unlock(&ddata->lock);
526
527 if (r)
528 return r;
529
530 return count;
531}
532
533static ssize_t dsicm_show_ulps_timeout(struct device *dev,
534 struct device_attribute *attr,
535 char *buf)
536{
537 struct platform_device *pdev = to_platform_device(dev);
538 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
539 unsigned t;
540
541 mutex_lock(&ddata->lock);
542 t = ddata->ulps_timeout;
543 mutex_unlock(&ddata->lock);
544
545 return snprintf(buf, PAGE_SIZE, "%u\n", t);
546}
547
548static DEVICE_ATTR(num_dsi_errors, S_IRUGO, dsicm_num_errors_show, NULL);
549static DEVICE_ATTR(hw_revision, S_IRUGO, dsicm_hw_revision_show, NULL);
550static DEVICE_ATTR(ulps, S_IRUGO | S_IWUSR,
551 dsicm_show_ulps, dsicm_store_ulps);
552static DEVICE_ATTR(ulps_timeout, S_IRUGO | S_IWUSR,
553 dsicm_show_ulps_timeout, dsicm_store_ulps_timeout);
554
555static struct attribute *dsicm_attrs[] = {
556 &dev_attr_num_dsi_errors.attr,
557 &dev_attr_hw_revision.attr,
558 &dev_attr_ulps.attr,
559 &dev_attr_ulps_timeout.attr,
560 NULL,
561};
562
563static struct attribute_group dsicm_attr_group = {
564 .attrs = dsicm_attrs,
565};
566
567static void dsicm_hw_reset(struct panel_drv_data *ddata)
568{
569 if (!gpio_is_valid(ddata->reset_gpio))
570 return;
571
572 gpio_set_value(ddata->reset_gpio, 1);
573 udelay(10);
574 /* reset the panel */
575 gpio_set_value(ddata->reset_gpio, 0);
576 /* assert reset */
577 udelay(10);
578 gpio_set_value(ddata->reset_gpio, 1);
579 /* wait after releasing reset */
580 usleep_range(5000, 10000);
581}
582
583static int dsicm_power_on(struct panel_drv_data *ddata)
584{
585 struct omap_dss_device *in = ddata->in;
586 u8 id1, id2, id3;
587 int r;
588 struct omap_dss_dsi_config dsi_config = {
589 .mode = OMAP_DSS_DSI_CMD_MODE,
590 .pixel_format = OMAP_DSS_DSI_FMT_RGB888,
591 .timings = &ddata->timings,
592 .hs_clk_min = 150000000,
593 .hs_clk_max = 300000000,
594 .lp_clk_min = 7000000,
595 .lp_clk_max = 10000000,
596 };
597
598 r = in->ops.dsi->configure_pins(in, &ddata->pin_config);
599 if (r) {
600 dev_err(&ddata->pdev->dev, "failed to configure DSI pins\n");
601 goto err0;
602 };
603
604 r = in->ops.dsi->set_config(in, &dsi_config);
605 if (r) {
606 dev_err(&ddata->pdev->dev, "failed to configure DSI\n");
607 goto err0;
608 }
609
610 r = in->ops.dsi->enable(in);
611 if (r) {
612 dev_err(&ddata->pdev->dev, "failed to enable DSI\n");
613 goto err0;
614 }
615
616 dsicm_hw_reset(ddata);
617
618 in->ops.dsi->enable_hs(in, ddata->channel, false);
619
620 r = dsicm_sleep_out(ddata);
621 if (r)
622 goto err;
623
624 r = dsicm_get_id(ddata, &id1, &id2, &id3);
625 if (r)
626 goto err;
627
628 r = dsicm_dcs_write_1(ddata, DCS_BRIGHTNESS, 0xff);
629 if (r)
630 goto err;
631
632 r = dsicm_dcs_write_1(ddata, DCS_CTRL_DISPLAY,
633 (1<<2) | (1<<5)); /* BL | BCTRL */
634 if (r)
635 goto err;
636
637 r = dsicm_dcs_write_1(ddata, MIPI_DCS_SET_PIXEL_FORMAT,
638 MIPI_DCS_PIXEL_FMT_24BIT);
639 if (r)
640 goto err;
641
642 r = dsicm_dcs_write_0(ddata, MIPI_DCS_SET_DISPLAY_ON);
643 if (r)
644 goto err;
645
646 r = _dsicm_enable_te(ddata, ddata->te_enabled);
647 if (r)
648 goto err;
649
650 r = in->ops.dsi->enable_video_output(in, ddata->channel);
651 if (r)
652 goto err;
653
654 ddata->enabled = 1;
655
656 if (!ddata->intro_printed) {
657 dev_info(&ddata->pdev->dev, "panel revision %02x.%02x.%02x\n",
658 id1, id2, id3);
659 ddata->intro_printed = true;
660 }
661
662 in->ops.dsi->enable_hs(in, ddata->channel, true);
663
664 return 0;
665err:
666 dev_err(&ddata->pdev->dev, "error while enabling panel, issuing HW reset\n");
667
668 dsicm_hw_reset(ddata);
669
670 in->ops.dsi->disable(in, true, false);
671err0:
672 return r;
673}
674
675static void dsicm_power_off(struct panel_drv_data *ddata)
676{
677 struct omap_dss_device *in = ddata->in;
678 int r;
679
680 in->ops.dsi->disable_video_output(in, ddata->channel);
681
682 r = dsicm_dcs_write_0(ddata, MIPI_DCS_SET_DISPLAY_OFF);
683 if (!r)
684 r = dsicm_sleep_in(ddata);
685
686 if (r) {
687 dev_err(&ddata->pdev->dev,
688 "error disabling panel, issuing HW reset\n");
689 dsicm_hw_reset(ddata);
690 }
691
692 in->ops.dsi->disable(in, true, false);
693
694 ddata->enabled = 0;
695}
696
697static int dsicm_panel_reset(struct panel_drv_data *ddata)
698{
699 dev_err(&ddata->pdev->dev, "performing LCD reset\n");
700
701 dsicm_power_off(ddata);
702 dsicm_hw_reset(ddata);
703 return dsicm_power_on(ddata);
704}
705
706static int dsicm_connect(struct omap_dss_device *dssdev)
707{
708 struct panel_drv_data *ddata = to_panel_data(dssdev);
709 struct omap_dss_device *in = ddata->in;
710 struct device *dev = &ddata->pdev->dev;
711 int r;
712
713 if (omapdss_device_is_connected(dssdev))
714 return 0;
715
716 r = in->ops.dsi->connect(in, dssdev);
717 if (r) {
718 dev_err(dev, "Failed to connect to video source\n");
719 return r;
720 }
721
722 r = in->ops.dsi->request_vc(ddata->in, &ddata->channel);
723 if (r) {
724 dev_err(dev, "failed to get virtual channel\n");
725 goto err_req_vc;
726 }
727
728 r = in->ops.dsi->set_vc_id(ddata->in, ddata->channel, TCH);
729 if (r) {
730 dev_err(dev, "failed to set VC_ID\n");
731 goto err_vc_id;
732 }
733
734 return 0;
735
736err_vc_id:
737 in->ops.dsi->release_vc(ddata->in, ddata->channel);
738err_req_vc:
739 in->ops.dsi->disconnect(in, dssdev);
740 return r;
741}
742
743static void dsicm_disconnect(struct omap_dss_device *dssdev)
744{
745 struct panel_drv_data *ddata = to_panel_data(dssdev);
746 struct omap_dss_device *in = ddata->in;
747
748 if (!omapdss_device_is_connected(dssdev))
749 return;
750
751 in->ops.dsi->release_vc(in, ddata->channel);
752 in->ops.dsi->disconnect(in, dssdev);
753}
754
755static int dsicm_enable(struct omap_dss_device *dssdev)
756{
757 struct panel_drv_data *ddata = to_panel_data(dssdev);
758 struct omap_dss_device *in = ddata->in;
759 int r;
760
761 dev_dbg(&ddata->pdev->dev, "enable\n");
762
763 mutex_lock(&ddata->lock);
764
765 if (!omapdss_device_is_connected(dssdev)) {
766 r = -ENODEV;
767 goto err;
768 }
769
770 if (omapdss_device_is_enabled(dssdev)) {
771 r = 0;
772 goto err;
773 }
774
775 in->ops.dsi->bus_lock(in);
776
777 r = dsicm_power_on(ddata);
778
779 in->ops.dsi->bus_unlock(in);
780
781 if (r)
782 goto err;
783
784 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
785
786 mutex_unlock(&ddata->lock);
787
788 return 0;
789err:
790 dev_dbg(&ddata->pdev->dev, "enable failed\n");
791 mutex_unlock(&ddata->lock);
792 return r;
793}
794
795static void dsicm_disable(struct omap_dss_device *dssdev)
796{
797 struct panel_drv_data *ddata = to_panel_data(dssdev);
798 struct omap_dss_device *in = ddata->in;
799 int r;
800
801 dev_dbg(&ddata->pdev->dev, "disable\n");
802
803 mutex_lock(&ddata->lock);
804
805 dsicm_cancel_ulps_work(ddata);
806
807 in->ops.dsi->bus_lock(in);
808
809 if (omapdss_device_is_enabled(dssdev)) {
810 r = dsicm_wake_up(ddata);
811 if (!r)
812 dsicm_power_off(ddata);
813 }
814
815 in->ops.dsi->bus_unlock(in);
816
817 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
818
819 mutex_unlock(&ddata->lock);
820}
821
822static void dsicm_framedone_cb(int err, void *data)
823{
824 struct panel_drv_data *ddata = data;
825 struct omap_dss_device *in = ddata->in;
826
827 dev_dbg(&ddata->pdev->dev, "framedone, err %d\n", err);
828 in->ops.dsi->bus_unlock(ddata->in);
829}
830
831static irqreturn_t dsicm_te_isr(int irq, void *data)
832{
833 struct panel_drv_data *ddata = data;
834 struct omap_dss_device *in = ddata->in;
835 int old;
836 int r;
837
838 old = atomic_cmpxchg(&ddata->do_update, 1, 0);
839
840 if (old) {
841 cancel_delayed_work(&ddata->te_timeout_work);
842
843 r = in->ops.dsi->update(in, ddata->channel, dsicm_framedone_cb,
844 ddata);
845 if (r)
846 goto err;
847 }
848
849 return IRQ_HANDLED;
850err:
851 dev_err(&ddata->pdev->dev, "start update failed\n");
852 in->ops.dsi->bus_unlock(in);
853 return IRQ_HANDLED;
854}
855
856static void dsicm_te_timeout_work_callback(struct work_struct *work)
857{
858 struct panel_drv_data *ddata = container_of(work, struct panel_drv_data,
859 te_timeout_work.work);
860 struct omap_dss_device *in = ddata->in;
861
862 dev_err(&ddata->pdev->dev, "TE not received for 250ms!\n");
863
864 atomic_set(&ddata->do_update, 0);
865 in->ops.dsi->bus_unlock(in);
866}
867
868static int dsicm_update(struct omap_dss_device *dssdev,
869 u16 x, u16 y, u16 w, u16 h)
870{
871 struct panel_drv_data *ddata = to_panel_data(dssdev);
872 struct omap_dss_device *in = ddata->in;
873 int r;
874
875 dev_dbg(&ddata->pdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
876
877 mutex_lock(&ddata->lock);
878 in->ops.dsi->bus_lock(in);
879
880 r = dsicm_wake_up(ddata);
881 if (r)
882 goto err;
883
884 if (!ddata->enabled) {
885 r = 0;
886 goto err;
887 }
888
889 /* XXX no need to send this every frame, but dsi break if not done */
890 r = dsicm_set_update_window(ddata, 0, 0,
891 dssdev->panel.timings.x_res,
892 dssdev->panel.timings.y_res);
893 if (r)
894 goto err;
895
896 if (ddata->te_enabled && gpio_is_valid(ddata->ext_te_gpio)) {
897 schedule_delayed_work(&ddata->te_timeout_work,
898 msecs_to_jiffies(250));
899 atomic_set(&ddata->do_update, 1);
900 } else {
901 r = in->ops.dsi->update(in, ddata->channel, dsicm_framedone_cb,
902 ddata);
903 if (r)
904 goto err;
905 }
906
907 /* note: no bus_unlock here. unlock is in framedone_cb */
908 mutex_unlock(&ddata->lock);
909 return 0;
910err:
911 in->ops.dsi->bus_unlock(in);
912 mutex_unlock(&ddata->lock);
913 return r;
914}
915
916static int dsicm_sync(struct omap_dss_device *dssdev)
917{
918 struct panel_drv_data *ddata = to_panel_data(dssdev);
919 struct omap_dss_device *in = ddata->in;
920
921 dev_dbg(&ddata->pdev->dev, "sync\n");
922
923 mutex_lock(&ddata->lock);
924 in->ops.dsi->bus_lock(in);
925 in->ops.dsi->bus_unlock(in);
926 mutex_unlock(&ddata->lock);
927
928 dev_dbg(&ddata->pdev->dev, "sync done\n");
929
930 return 0;
931}
932
933static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable)
934{
935 struct omap_dss_device *in = ddata->in;
936 int r;
937
938 if (enable)
939 r = dsicm_dcs_write_1(ddata, MIPI_DCS_SET_TEAR_ON, 0);
940 else
941 r = dsicm_dcs_write_0(ddata, MIPI_DCS_SET_TEAR_OFF);
942
943 if (!gpio_is_valid(ddata->ext_te_gpio))
944 in->ops.dsi->enable_te(in, enable);
945
946 /* possible panel bug */
947 msleep(100);
948
949 return r;
950}
951
952static int dsicm_enable_te(struct omap_dss_device *dssdev, bool enable)
953{
954 struct panel_drv_data *ddata = to_panel_data(dssdev);
955 struct omap_dss_device *in = ddata->in;
956 int r;
957
958 mutex_lock(&ddata->lock);
959
960 if (ddata->te_enabled == enable)
961 goto end;
962
963 in->ops.dsi->bus_lock(in);
964
965 if (ddata->enabled) {
966 r = dsicm_wake_up(ddata);
967 if (r)
968 goto err;
969
970 r = _dsicm_enable_te(ddata, enable);
971 if (r)
972 goto err;
973 }
974
975 ddata->te_enabled = enable;
976
977 in->ops.dsi->bus_unlock(in);
978end:
979 mutex_unlock(&ddata->lock);
980
981 return 0;
982err:
983 in->ops.dsi->bus_unlock(in);
984 mutex_unlock(&ddata->lock);
985
986 return r;
987}
988
989static int dsicm_get_te(struct omap_dss_device *dssdev)
990{
991 struct panel_drv_data *ddata = to_panel_data(dssdev);
992 int r;
993
994 mutex_lock(&ddata->lock);
995 r = ddata->te_enabled;
996 mutex_unlock(&ddata->lock);
997
998 return r;
999}
1000
1001static int dsicm_memory_read(struct omap_dss_device *dssdev,
1002 void *buf, size_t size,
1003 u16 x, u16 y, u16 w, u16 h)
1004{
1005 struct panel_drv_data *ddata = to_panel_data(dssdev);
1006 struct omap_dss_device *in = ddata->in;
1007 int r;
1008 int first = 1;
1009 int plen;
1010 unsigned buf_used = 0;
1011
1012 if (size < w * h * 3)
1013 return -ENOMEM;
1014
1015 mutex_lock(&ddata->lock);
1016
1017 if (!ddata->enabled) {
1018 r = -ENODEV;
1019 goto err1;
1020 }
1021
1022 size = min(w * h * 3,
1023 dssdev->panel.timings.x_res *
1024 dssdev->panel.timings.y_res * 3);
1025
1026 in->ops.dsi->bus_lock(in);
1027
1028 r = dsicm_wake_up(ddata);
1029 if (r)
1030 goto err2;
1031
1032 /* plen 1 or 2 goes into short packet. until checksum error is fixed,
1033 * use short packets. plen 32 works, but bigger packets seem to cause
1034 * an error. */
1035 if (size % 2)
1036 plen = 1;
1037 else
1038 plen = 2;
1039
1040 dsicm_set_update_window(ddata, x, y, w, h);
1041
1042 r = in->ops.dsi->set_max_rx_packet_size(in, ddata->channel, plen);
1043 if (r)
1044 goto err2;
1045
1046 while (buf_used < size) {
1047 u8 dcs_cmd = first ? 0x2e : 0x3e;
1048 first = 0;
1049
1050 r = in->ops.dsi->dcs_read(in, ddata->channel, dcs_cmd,
1051 buf + buf_used, size - buf_used);
1052
1053 if (r < 0) {
1054 dev_err(dssdev->dev, "read error\n");
1055 goto err3;
1056 }
1057
1058 buf_used += r;
1059
1060 if (r < plen) {
1061 dev_err(&ddata->pdev->dev, "short read\n");
1062 break;
1063 }
1064
1065 if (signal_pending(current)) {
1066 dev_err(&ddata->pdev->dev, "signal pending, "
1067 "aborting memory read\n");
1068 r = -ERESTARTSYS;
1069 goto err3;
1070 }
1071 }
1072
1073 r = buf_used;
1074
1075err3:
1076 in->ops.dsi->set_max_rx_packet_size(in, ddata->channel, 1);
1077err2:
1078 in->ops.dsi->bus_unlock(in);
1079err1:
1080 mutex_unlock(&ddata->lock);
1081 return r;
1082}
1083
1084static void dsicm_ulps_work(struct work_struct *work)
1085{
1086 struct panel_drv_data *ddata = container_of(work, struct panel_drv_data,
1087 ulps_work.work);
1088 struct omap_dss_device *dssdev = &ddata->dssdev;
1089 struct omap_dss_device *in = ddata->in;
1090
1091 mutex_lock(&ddata->lock);
1092
1093 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE || !ddata->enabled) {
1094 mutex_unlock(&ddata->lock);
1095 return;
1096 }
1097
1098 in->ops.dsi->bus_lock(in);
1099
1100 dsicm_enter_ulps(ddata);
1101
1102 in->ops.dsi->bus_unlock(in);
1103 mutex_unlock(&ddata->lock);
1104}
1105
1106static struct omap_dss_driver dsicm_ops = {
1107 .connect = dsicm_connect,
1108 .disconnect = dsicm_disconnect,
1109
1110 .enable = dsicm_enable,
1111 .disable = dsicm_disable,
1112
1113 .update = dsicm_update,
1114 .sync = dsicm_sync,
1115
1116 .get_resolution = dsicm_get_resolution,
1117 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
1118
1119 .enable_te = dsicm_enable_te,
1120 .get_te = dsicm_get_te,
1121
1122 .memory_read = dsicm_memory_read,
1123};
1124
1125static int dsicm_probe_pdata(struct platform_device *pdev)
1126{
1127 const struct panel_dsicm_platform_data *pdata;
1128 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
1129 struct omap_dss_device *dssdev, *in;
1130
1131 pdata = dev_get_platdata(&pdev->dev);
1132
1133 in = omap_dss_find_output(pdata->source);
1134 if (in == NULL) {
1135 dev_err(&pdev->dev, "failed to find video source\n");
1136 return -EPROBE_DEFER;
1137 }
1138 ddata->in = in;
1139
1140 ddata->reset_gpio = pdata->reset_gpio;
1141
1142 if (pdata->use_ext_te)
1143 ddata->ext_te_gpio = pdata->ext_te_gpio;
1144 else
1145 ddata->ext_te_gpio = -1;
1146
1147 ddata->ulps_timeout = pdata->ulps_timeout;
1148
1149 ddata->use_dsi_backlight = pdata->use_dsi_backlight;
1150
1151 ddata->pin_config = pdata->pin_config;
1152
1153 dssdev = &ddata->dssdev;
1154 dssdev->name = pdata->name;
1155
1156 return 0;
1157}
1158
1159static int dsicm_probe(struct platform_device *pdev)
1160{
1161 struct backlight_properties props;
1162 struct panel_drv_data *ddata;
1163 struct backlight_device *bldev = NULL;
1164 struct device *dev = &pdev->dev;
1165 struct omap_dss_device *dssdev;
1166 int r;
1167
1168 dev_dbg(dev, "probe\n");
1169
1170 ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
1171 if (!ddata)
1172 return -ENOMEM;
1173
1174 platform_set_drvdata(pdev, ddata);
1175 ddata->pdev = pdev;
1176
1177 if (dev_get_platdata(dev)) {
1178 r = dsicm_probe_pdata(pdev);
1179 if (r)
1180 return r;
1181 } else {
1182 return -ENODEV;
1183 }
1184
1185 ddata->timings.x_res = 864;
1186 ddata->timings.y_res = 480;
1187 ddata->timings.pixel_clock = DIV_ROUND_UP(864 * 480 * 60, 1000);
1188
1189 dssdev = &ddata->dssdev;
1190 dssdev->dev = dev;
1191 dssdev->driver = &dsicm_ops;
1192 dssdev->panel.timings = ddata->timings;
1193 dssdev->type = OMAP_DISPLAY_TYPE_DSI;
1194 dssdev->owner = THIS_MODULE;
1195
1196 dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
1197 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
1198 OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
1199
1200 r = omapdss_register_display(dssdev);
1201 if (r) {
1202 dev_err(dev, "Failed to register panel\n");
1203 goto err_reg;
1204 }
1205
1206 mutex_init(&ddata->lock);
1207
1208 atomic_set(&ddata->do_update, 0);
1209
1210 if (gpio_is_valid(ddata->reset_gpio)) {
1211 r = devm_gpio_request_one(dev, ddata->reset_gpio,
1212 GPIOF_OUT_INIT_LOW, "taal rst");
1213 if (r) {
1214 dev_err(dev, "failed to request reset gpio\n");
1215 return r;
1216 }
1217 }
1218
1219 if (gpio_is_valid(ddata->ext_te_gpio)) {
1220 r = devm_gpio_request_one(dev, ddata->ext_te_gpio,
1221 GPIOF_IN, "taal irq");
1222 if (r) {
1223 dev_err(dev, "GPIO request failed\n");
1224 return r;
1225 }
1226
1227 r = devm_request_irq(dev, gpio_to_irq(ddata->ext_te_gpio),
1228 dsicm_te_isr,
1229 IRQF_TRIGGER_RISING,
1230 "taal vsync", ddata);
1231
1232 if (r) {
1233 dev_err(dev, "IRQ request failed\n");
1234 return r;
1235 }
1236
1237 INIT_DEFERRABLE_WORK(&ddata->te_timeout_work,
1238 dsicm_te_timeout_work_callback);
1239
1240 dev_dbg(dev, "Using GPIO TE\n");
1241 }
1242
1243 ddata->workqueue = create_singlethread_workqueue("dsicm_wq");
1244 if (ddata->workqueue == NULL) {
1245 dev_err(dev, "can't create workqueue\n");
1246 return -ENOMEM;
1247 }
1248 INIT_DELAYED_WORK(&ddata->ulps_work, dsicm_ulps_work);
1249
1250 dsicm_hw_reset(ddata);
1251
1252 if (ddata->use_dsi_backlight) {
1253 memset(&props, 0, sizeof(struct backlight_properties));
1254 props.max_brightness = 255;
1255
1256 props.type = BACKLIGHT_RAW;
1257 bldev = backlight_device_register(dev_name(dev),
1258 dev, ddata, &dsicm_bl_ops, &props);
1259 if (IS_ERR(bldev)) {
1260 r = PTR_ERR(bldev);
1261 goto err_bl;
1262 }
1263
1264 ddata->bldev = bldev;
1265
1266 bldev->props.fb_blank = FB_BLANK_UNBLANK;
1267 bldev->props.power = FB_BLANK_UNBLANK;
1268 bldev->props.brightness = 255;
1269
1270 dsicm_bl_update_status(bldev);
1271 }
1272
1273 r = sysfs_create_group(&dev->kobj, &dsicm_attr_group);
1274 if (r) {
1275 dev_err(dev, "failed to create sysfs files\n");
1276 goto err_sysfs_create;
1277 }
1278
1279 return 0;
1280
1281err_sysfs_create:
1282 if (bldev != NULL)
1283 backlight_device_unregister(bldev);
1284err_bl:
1285 destroy_workqueue(ddata->workqueue);
1286err_reg:
1287 return r;
1288}
1289
1290static int __exit dsicm_remove(struct platform_device *pdev)
1291{
1292 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
1293 struct omap_dss_device *dssdev = &ddata->dssdev;
1294 struct backlight_device *bldev;
1295
1296 dev_dbg(&pdev->dev, "remove\n");
1297
1298 omapdss_unregister_display(dssdev);
1299
1300 dsicm_disable(dssdev);
1301 dsicm_disconnect(dssdev);
1302
1303 sysfs_remove_group(&pdev->dev.kobj, &dsicm_attr_group);
1304
1305 bldev = ddata->bldev;
1306 if (bldev != NULL) {
1307 bldev->props.power = FB_BLANK_POWERDOWN;
1308 dsicm_bl_update_status(bldev);
1309 backlight_device_unregister(bldev);
1310 }
1311
1312 omap_dss_put_device(ddata->in);
1313
1314 dsicm_cancel_ulps_work(ddata);
1315 destroy_workqueue(ddata->workqueue);
1316
1317 /* reset, to be sure that the panel is in a valid state */
1318 dsicm_hw_reset(ddata);
1319
1320 return 0;
1321}
1322
1323static struct platform_driver dsicm_driver = {
1324 .probe = dsicm_probe,
1325 .remove = __exit_p(dsicm_remove),
1326 .driver = {
1327 .name = "panel-dsi-cm",
1328 .owner = THIS_MODULE,
1329 },
1330};
1331
1332module_platform_driver(dsicm_driver);
1333
1334MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
1335MODULE_DESCRIPTION("Generic DSI Command Mode Panel Driver");
1336MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays-new/panel-lgphilips-lb035q02.c
new file mode 100644
index 000000000000..6e8977b18950
--- /dev/null
+++ b/drivers/video/omap2/displays-new/panel-lgphilips-lb035q02.c
@@ -0,0 +1,358 @@
1/*
2 * LG.Philips LB035Q02 LCD Panel driver
3 *
4 * Copyright (C) 2013 Texas Instruments
5 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
6 * Based on a driver by: Steve Sakoman <steve@sakoman.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/delay.h>
15#include <linux/spi/spi.h>
16#include <linux/mutex.h>
17#include <linux/gpio.h>
18
19#include <video/omapdss.h>
20#include <video/omap-panel-data.h>
21
22static struct omap_video_timings lb035q02_timings = {
23 .x_res = 320,
24 .y_res = 240,
25
26 .pixel_clock = 6500,
27
28 .hsw = 2,
29 .hfp = 20,
30 .hbp = 68,
31
32 .vsw = 2,
33 .vfp = 4,
34 .vbp = 18,
35
36 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
37 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
38 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
39 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
40 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
41};
42
43struct panel_drv_data {
44 struct omap_dss_device dssdev;
45 struct omap_dss_device *in;
46
47 struct spi_device *spi;
48
49 int data_lines;
50
51 struct omap_video_timings videomode;
52
53 int reset_gpio;
54 int backlight_gpio;
55 int enable_gpio;
56};
57
58#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
59
60static int lb035q02_write_reg(struct spi_device *spi, u8 reg, u16 val)
61{
62 struct spi_message msg;
63 struct spi_transfer index_xfer = {
64 .len = 3,
65 .cs_change = 1,
66 };
67 struct spi_transfer value_xfer = {
68 .len = 3,
69 };
70 u8 buffer[16];
71
72 spi_message_init(&msg);
73
74 /* register index */
75 buffer[0] = 0x70;
76 buffer[1] = 0x00;
77 buffer[2] = reg & 0x7f;
78 index_xfer.tx_buf = buffer;
79 spi_message_add_tail(&index_xfer, &msg);
80
81 /* register value */
82 buffer[4] = 0x72;
83 buffer[5] = val >> 8;
84 buffer[6] = val;
85 value_xfer.tx_buf = buffer + 4;
86 spi_message_add_tail(&value_xfer, &msg);
87
88 return spi_sync(spi, &msg);
89}
90
91static void init_lb035q02_panel(struct spi_device *spi)
92{
93 /* Init sequence from page 28 of the lb035q02 spec */
94 lb035q02_write_reg(spi, 0x01, 0x6300);
95 lb035q02_write_reg(spi, 0x02, 0x0200);
96 lb035q02_write_reg(spi, 0x03, 0x0177);
97 lb035q02_write_reg(spi, 0x04, 0x04c7);
98 lb035q02_write_reg(spi, 0x05, 0xffc0);
99 lb035q02_write_reg(spi, 0x06, 0xe806);
100 lb035q02_write_reg(spi, 0x0a, 0x4008);
101 lb035q02_write_reg(spi, 0x0b, 0x0000);
102 lb035q02_write_reg(spi, 0x0d, 0x0030);
103 lb035q02_write_reg(spi, 0x0e, 0x2800);
104 lb035q02_write_reg(spi, 0x0f, 0x0000);
105 lb035q02_write_reg(spi, 0x16, 0x9f80);
106 lb035q02_write_reg(spi, 0x17, 0x0a0f);
107 lb035q02_write_reg(spi, 0x1e, 0x00c1);
108 lb035q02_write_reg(spi, 0x30, 0x0300);
109 lb035q02_write_reg(spi, 0x31, 0x0007);
110 lb035q02_write_reg(spi, 0x32, 0x0000);
111 lb035q02_write_reg(spi, 0x33, 0x0000);
112 lb035q02_write_reg(spi, 0x34, 0x0707);
113 lb035q02_write_reg(spi, 0x35, 0x0004);
114 lb035q02_write_reg(spi, 0x36, 0x0302);
115 lb035q02_write_reg(spi, 0x37, 0x0202);
116 lb035q02_write_reg(spi, 0x3a, 0x0a0d);
117 lb035q02_write_reg(spi, 0x3b, 0x0806);
118}
119
120static int lb035q02_connect(struct omap_dss_device *dssdev)
121{
122 struct panel_drv_data *ddata = to_panel_data(dssdev);
123 struct omap_dss_device *in = ddata->in;
124 int r;
125
126 if (omapdss_device_is_connected(dssdev))
127 return 0;
128
129 r = in->ops.dpi->connect(in, dssdev);
130 if (r)
131 return r;
132
133 init_lb035q02_panel(ddata->spi);
134
135 return 0;
136}
137
138static void lb035q02_disconnect(struct omap_dss_device *dssdev)
139{
140 struct panel_drv_data *ddata = to_panel_data(dssdev);
141 struct omap_dss_device *in = ddata->in;
142
143 if (!omapdss_device_is_connected(dssdev))
144 return;
145
146 in->ops.dpi->disconnect(in, dssdev);
147}
148
149static int lb035q02_enable(struct omap_dss_device *dssdev)
150{
151 struct panel_drv_data *ddata = to_panel_data(dssdev);
152 struct omap_dss_device *in = ddata->in;
153 int r;
154
155 if (!omapdss_device_is_connected(dssdev))
156 return -ENODEV;
157
158 if (omapdss_device_is_enabled(dssdev))
159 return 0;
160
161 in->ops.dpi->set_data_lines(in, ddata->data_lines);
162 in->ops.dpi->set_timings(in, &ddata->videomode);
163
164 r = in->ops.dpi->enable(in);
165 if (r)
166 return r;
167
168 if (gpio_is_valid(ddata->enable_gpio))
169 gpio_set_value_cansleep(ddata->enable_gpio, 1);
170
171 if (gpio_is_valid(ddata->backlight_gpio))
172 gpio_set_value_cansleep(ddata->backlight_gpio, 1);
173
174 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
175
176 return 0;
177}
178
179static void lb035q02_disable(struct omap_dss_device *dssdev)
180{
181 struct panel_drv_data *ddata = to_panel_data(dssdev);
182 struct omap_dss_device *in = ddata->in;
183
184 if (!omapdss_device_is_enabled(dssdev))
185 return;
186
187 if (gpio_is_valid(ddata->enable_gpio))
188 gpio_set_value_cansleep(ddata->enable_gpio, 0);
189
190 if (gpio_is_valid(ddata->backlight_gpio))
191 gpio_set_value_cansleep(ddata->backlight_gpio, 0);
192
193 in->ops.dpi->disable(in);
194
195 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
196}
197
198static void lb035q02_set_timings(struct omap_dss_device *dssdev,
199 struct omap_video_timings *timings)
200{
201 struct panel_drv_data *ddata = to_panel_data(dssdev);
202 struct omap_dss_device *in = ddata->in;
203
204 ddata->videomode = *timings;
205 dssdev->panel.timings = *timings;
206
207 in->ops.dpi->set_timings(in, timings);
208}
209
210static void lb035q02_get_timings(struct omap_dss_device *dssdev,
211 struct omap_video_timings *timings)
212{
213 struct panel_drv_data *ddata = to_panel_data(dssdev);
214
215 *timings = ddata->videomode;
216}
217
218static int lb035q02_check_timings(struct omap_dss_device *dssdev,
219 struct omap_video_timings *timings)
220{
221 struct panel_drv_data *ddata = to_panel_data(dssdev);
222 struct omap_dss_device *in = ddata->in;
223
224 return in->ops.dpi->check_timings(in, timings);
225}
226
227static struct omap_dss_driver lb035q02_ops = {
228 .connect = lb035q02_connect,
229 .disconnect = lb035q02_disconnect,
230
231 .enable = lb035q02_enable,
232 .disable = lb035q02_disable,
233
234 .set_timings = lb035q02_set_timings,
235 .get_timings = lb035q02_get_timings,
236 .check_timings = lb035q02_check_timings,
237
238 .get_resolution = omapdss_default_get_resolution,
239};
240
241static int lb035q02_probe_pdata(struct spi_device *spi)
242{
243 const struct panel_lb035q02_platform_data *pdata;
244 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
245 struct omap_dss_device *dssdev, *in;
246
247 pdata = dev_get_platdata(&spi->dev);
248
249 in = omap_dss_find_output(pdata->source);
250 if (in == NULL) {
251 dev_err(&spi->dev, "failed to find video source '%s'\n",
252 pdata->source);
253 return -EPROBE_DEFER;
254 }
255
256 ddata->in = in;
257
258 ddata->data_lines = pdata->data_lines;
259
260 dssdev = &ddata->dssdev;
261 dssdev->name = pdata->name;
262
263 ddata->enable_gpio = pdata->enable_gpio;
264 ddata->backlight_gpio = pdata->backlight_gpio;
265
266 return 0;
267}
268
269static int lb035q02_panel_spi_probe(struct spi_device *spi)
270{
271 struct panel_drv_data *ddata;
272 struct omap_dss_device *dssdev;
273 int r;
274
275 ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
276 if (ddata == NULL)
277 return -ENOMEM;
278
279 dev_set_drvdata(&spi->dev, ddata);
280
281 ddata->spi = spi;
282
283 if (dev_get_platdata(&spi->dev)) {
284 r = lb035q02_probe_pdata(spi);
285 if (r)
286 return r;
287 } else {
288 return -ENODEV;
289 }
290
291 if (gpio_is_valid(ddata->enable_gpio)) {
292 r = devm_gpio_request_one(&spi->dev, ddata->enable_gpio,
293 GPIOF_OUT_INIT_LOW, "panel enable");
294 if (r)
295 goto err_gpio;
296 }
297
298 if (gpio_is_valid(ddata->backlight_gpio)) {
299 r = devm_gpio_request_one(&spi->dev, ddata->backlight_gpio,
300 GPIOF_OUT_INIT_LOW, "panel backlight");
301 if (r)
302 goto err_gpio;
303 }
304
305 ddata->videomode = lb035q02_timings;
306
307 dssdev = &ddata->dssdev;
308 dssdev->dev = &spi->dev;
309 dssdev->driver = &lb035q02_ops;
310 dssdev->type = OMAP_DISPLAY_TYPE_DPI;
311 dssdev->owner = THIS_MODULE;
312 dssdev->panel.timings = ddata->videomode;
313 dssdev->phy.dpi.data_lines = ddata->data_lines;
314
315 r = omapdss_register_display(dssdev);
316 if (r) {
317 dev_err(&spi->dev, "Failed to register panel\n");
318 goto err_reg;
319 }
320
321 return 0;
322
323err_reg:
324err_gpio:
325 omap_dss_put_device(ddata->in);
326 return r;
327}
328
329static int lb035q02_panel_spi_remove(struct spi_device *spi)
330{
331 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
332 struct omap_dss_device *dssdev = &ddata->dssdev;
333 struct omap_dss_device *in = ddata->in;
334
335 omapdss_unregister_display(dssdev);
336
337 lb035q02_disable(dssdev);
338 lb035q02_disconnect(dssdev);
339
340 omap_dss_put_device(in);
341
342 return 0;
343}
344
345static struct spi_driver lb035q02_spi_driver = {
346 .probe = lb035q02_panel_spi_probe,
347 .remove = lb035q02_panel_spi_remove,
348 .driver = {
349 .name = "panel_lgphilips_lb035q02",
350 .owner = THIS_MODULE,
351 },
352};
353
354module_spi_driver(lb035q02_spi_driver);
355
356MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
357MODULE_DESCRIPTION("LG.Philips LB035Q02 LCD Panel driver");
358MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/panel-nec-nl8048hl11.c b/drivers/video/omap2/displays-new/panel-nec-nl8048hl11.c
new file mode 100644
index 000000000000..bb217da65c5f
--- /dev/null
+++ b/drivers/video/omap2/displays-new/panel-nec-nl8048hl11.c
@@ -0,0 +1,394 @@
1/*
2 * NEC NL8048HL11 Panel driver
3 *
4 * Copyright (C) 2010 Texas Instruments Inc.
5 * Author: Erik Gilling <konkers@android.com>
6 * Converted to new DSS device model: Tomi Valkeinen <tomi.valkeinen@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 */
13
14#include <linux/module.h>
15#include <linux/delay.h>
16#include <linux/spi/spi.h>
17#include <linux/fb.h>
18#include <linux/gpio.h>
19
20#include <video/omapdss.h>
21#include <video/omap-panel-data.h>
22
23struct panel_drv_data {
24 struct omap_dss_device dssdev;
25 struct omap_dss_device *in;
26
27 struct omap_video_timings videomode;
28
29 int data_lines;
30
31 int res_gpio;
32 int qvga_gpio;
33
34 struct spi_device *spi;
35};
36
37#define LCD_XRES 800
38#define LCD_YRES 480
39/*
40 * NEC PIX Clock Ratings
41 * MIN:21.8MHz TYP:23.8MHz MAX:25.7MHz
42 */
43#define LCD_PIXEL_CLOCK 23800
44
45static const struct {
46 unsigned char addr;
47 unsigned char dat;
48} nec_8048_init_seq[] = {
49 { 3, 0x01 }, { 0, 0x00 }, { 1, 0x01 }, { 4, 0x00 }, { 5, 0x14 },
50 { 6, 0x24 }, { 16, 0xD7 }, { 17, 0x00 }, { 18, 0x00 }, { 19, 0x55 },
51 { 20, 0x01 }, { 21, 0x70 }, { 22, 0x1E }, { 23, 0x25 }, { 24, 0x25 },
52 { 25, 0x02 }, { 26, 0x02 }, { 27, 0xA0 }, { 32, 0x2F }, { 33, 0x0F },
53 { 34, 0x0F }, { 35, 0x0F }, { 36, 0x0F }, { 37, 0x0F }, { 38, 0x0F },
54 { 39, 0x00 }, { 40, 0x02 }, { 41, 0x02 }, { 42, 0x02 }, { 43, 0x0F },
55 { 44, 0x0F }, { 45, 0x0F }, { 46, 0x0F }, { 47, 0x0F }, { 48, 0x0F },
56 { 49, 0x0F }, { 50, 0x00 }, { 51, 0x02 }, { 52, 0x02 }, { 53, 0x02 },
57 { 80, 0x0C }, { 83, 0x42 }, { 84, 0x42 }, { 85, 0x41 }, { 86, 0x14 },
58 { 89, 0x88 }, { 90, 0x01 }, { 91, 0x00 }, { 92, 0x02 }, { 93, 0x0C },
59 { 94, 0x1C }, { 95, 0x27 }, { 98, 0x49 }, { 99, 0x27 }, { 102, 0x76 },
60 { 103, 0x27 }, { 112, 0x01 }, { 113, 0x0E }, { 114, 0x02 },
61 { 115, 0x0C }, { 118, 0x0C }, { 121, 0x30 }, { 130, 0x00 },
62 { 131, 0x00 }, { 132, 0xFC }, { 134, 0x00 }, { 136, 0x00 },
63 { 138, 0x00 }, { 139, 0x00 }, { 140, 0x00 }, { 141, 0xFC },
64 { 143, 0x00 }, { 145, 0x00 }, { 147, 0x00 }, { 148, 0x00 },
65 { 149, 0x00 }, { 150, 0xFC }, { 152, 0x00 }, { 154, 0x00 },
66 { 156, 0x00 }, { 157, 0x00 }, { 2, 0x00 },
67};
68
69static const struct omap_video_timings nec_8048_panel_timings = {
70 .x_res = LCD_XRES,
71 .y_res = LCD_YRES,
72 .pixel_clock = LCD_PIXEL_CLOCK,
73 .hfp = 6,
74 .hsw = 1,
75 .hbp = 4,
76 .vfp = 3,
77 .vsw = 1,
78 .vbp = 4,
79
80 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
81 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
82 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
83 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
84 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
85};
86
87#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
88
89static int nec_8048_spi_send(struct spi_device *spi, unsigned char reg_addr,
90 unsigned char reg_data)
91{
92 int ret = 0;
93 unsigned int cmd = 0, data = 0;
94
95 cmd = 0x0000 | reg_addr; /* register address write */
96 data = 0x0100 | reg_data; /* register data write */
97 data = (cmd << 16) | data;
98
99 ret = spi_write(spi, (unsigned char *)&data, 4);
100 if (ret)
101 pr_err("error in spi_write %x\n", data);
102
103 return ret;
104}
105
106static int init_nec_8048_wvga_lcd(struct spi_device *spi)
107{
108 unsigned int i;
109 /* Initialization Sequence */
110 /* nec_8048_spi_send(spi, REG, VAL) */
111 for (i = 0; i < (ARRAY_SIZE(nec_8048_init_seq) - 1); i++)
112 nec_8048_spi_send(spi, nec_8048_init_seq[i].addr,
113 nec_8048_init_seq[i].dat);
114 udelay(20);
115 nec_8048_spi_send(spi, nec_8048_init_seq[i].addr,
116 nec_8048_init_seq[i].dat);
117 return 0;
118}
119
120static int nec_8048_connect(struct omap_dss_device *dssdev)
121{
122 struct panel_drv_data *ddata = to_panel_data(dssdev);
123 struct omap_dss_device *in = ddata->in;
124 int r;
125
126 if (omapdss_device_is_connected(dssdev))
127 return 0;
128
129 r = in->ops.dpi->connect(in, dssdev);
130 if (r)
131 return r;
132
133 return 0;
134}
135
136static void nec_8048_disconnect(struct omap_dss_device *dssdev)
137{
138 struct panel_drv_data *ddata = to_panel_data(dssdev);
139 struct omap_dss_device *in = ddata->in;
140
141 if (!omapdss_device_is_connected(dssdev))
142 return;
143
144 in->ops.dpi->disconnect(in, dssdev);
145}
146
147static int nec_8048_enable(struct omap_dss_device *dssdev)
148{
149 struct panel_drv_data *ddata = to_panel_data(dssdev);
150 struct omap_dss_device *in = ddata->in;
151 int r;
152
153 if (!omapdss_device_is_connected(dssdev))
154 return -ENODEV;
155
156 if (omapdss_device_is_enabled(dssdev))
157 return 0;
158
159 in->ops.dpi->set_data_lines(in, ddata->data_lines);
160 in->ops.dpi->set_timings(in, &ddata->videomode);
161
162 r = in->ops.dpi->enable(in);
163 if (r)
164 return r;
165
166 if (gpio_is_valid(ddata->res_gpio))
167 gpio_set_value_cansleep(ddata->res_gpio, 1);
168
169 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
170
171 return 0;
172}
173
174static void nec_8048_disable(struct omap_dss_device *dssdev)
175{
176 struct panel_drv_data *ddata = to_panel_data(dssdev);
177 struct omap_dss_device *in = ddata->in;
178
179 if (!omapdss_device_is_enabled(dssdev))
180 return;
181
182 if (gpio_is_valid(ddata->res_gpio))
183 gpio_set_value_cansleep(ddata->res_gpio, 0);
184
185 in->ops.dpi->disable(in);
186
187 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
188}
189
190static void nec_8048_set_timings(struct omap_dss_device *dssdev,
191 struct omap_video_timings *timings)
192{
193 struct panel_drv_data *ddata = to_panel_data(dssdev);
194 struct omap_dss_device *in = ddata->in;
195
196 ddata->videomode = *timings;
197 dssdev->panel.timings = *timings;
198
199 in->ops.dpi->set_timings(in, timings);
200}
201
202static void nec_8048_get_timings(struct omap_dss_device *dssdev,
203 struct omap_video_timings *timings)
204{
205 struct panel_drv_data *ddata = to_panel_data(dssdev);
206
207 *timings = ddata->videomode;
208}
209
210static int nec_8048_check_timings(struct omap_dss_device *dssdev,
211 struct omap_video_timings *timings)
212{
213 struct panel_drv_data *ddata = to_panel_data(dssdev);
214 struct omap_dss_device *in = ddata->in;
215
216 return in->ops.dpi->check_timings(in, timings);
217}
218
219static struct omap_dss_driver nec_8048_ops = {
220 .connect = nec_8048_connect,
221 .disconnect = nec_8048_disconnect,
222
223 .enable = nec_8048_enable,
224 .disable = nec_8048_disable,
225
226 .set_timings = nec_8048_set_timings,
227 .get_timings = nec_8048_get_timings,
228 .check_timings = nec_8048_check_timings,
229
230 .get_resolution = omapdss_default_get_resolution,
231};
232
233
234static int nec_8048_probe_pdata(struct spi_device *spi)
235{
236 const struct panel_nec_nl8048hl11_platform_data *pdata;
237 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
238 struct omap_dss_device *dssdev, *in;
239
240 pdata = dev_get_platdata(&spi->dev);
241
242 ddata->qvga_gpio = pdata->qvga_gpio;
243 ddata->res_gpio = pdata->res_gpio;
244
245 in = omap_dss_find_output(pdata->source);
246 if (in == NULL) {
247 dev_err(&spi->dev, "failed to find video source '%s'\n",
248 pdata->source);
249 return -EPROBE_DEFER;
250 }
251 ddata->in = in;
252
253 ddata->data_lines = pdata->data_lines;
254
255 dssdev = &ddata->dssdev;
256 dssdev->name = pdata->name;
257
258 return 0;
259}
260
261static int nec_8048_probe(struct spi_device *spi)
262{
263 struct panel_drv_data *ddata;
264 struct omap_dss_device *dssdev;
265 int r;
266
267 dev_dbg(&spi->dev, "%s\n", __func__);
268
269 spi->mode = SPI_MODE_0;
270 spi->bits_per_word = 32;
271
272 r = spi_setup(spi);
273 if (r < 0) {
274 dev_err(&spi->dev, "spi_setup failed: %d\n", r);
275 return r;
276 }
277
278 init_nec_8048_wvga_lcd(spi);
279
280 ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
281 if (ddata == NULL)
282 return -ENOMEM;
283
284 dev_set_drvdata(&spi->dev, ddata);
285
286 ddata->spi = spi;
287
288 if (dev_get_platdata(&spi->dev)) {
289 r = nec_8048_probe_pdata(spi);
290 if (r)
291 return r;
292 } else {
293 return -ENODEV;
294 }
295
296 if (gpio_is_valid(ddata->qvga_gpio)) {
297 r = devm_gpio_request_one(&spi->dev, ddata->qvga_gpio,
298 GPIOF_OUT_INIT_HIGH, "lcd QVGA");
299 if (r)
300 goto err_gpio;
301 }
302
303 if (gpio_is_valid(ddata->res_gpio)) {
304 r = devm_gpio_request_one(&spi->dev, ddata->res_gpio,
305 GPIOF_OUT_INIT_LOW, "lcd RES");
306 if (r)
307 goto err_gpio;
308 }
309
310 ddata->videomode = nec_8048_panel_timings;
311
312 dssdev = &ddata->dssdev;
313 dssdev->dev = &spi->dev;
314 dssdev->driver = &nec_8048_ops;
315 dssdev->type = OMAP_DISPLAY_TYPE_DPI;
316 dssdev->owner = THIS_MODULE;
317 dssdev->panel.timings = ddata->videomode;
318
319 r = omapdss_register_display(dssdev);
320 if (r) {
321 dev_err(&spi->dev, "Failed to register panel\n");
322 goto err_reg;
323 }
324
325 return 0;
326
327err_reg:
328err_gpio:
329 omap_dss_put_device(ddata->in);
330 return r;
331}
332
333static int nec_8048_remove(struct spi_device *spi)
334{
335 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
336 struct omap_dss_device *dssdev = &ddata->dssdev;
337 struct omap_dss_device *in = ddata->in;
338
339 dev_dbg(&ddata->spi->dev, "%s\n", __func__);
340
341 omapdss_unregister_display(dssdev);
342
343 nec_8048_disable(dssdev);
344 nec_8048_disconnect(dssdev);
345
346 omap_dss_put_device(in);
347
348 return 0;
349}
350
351#ifdef CONFIG_PM_SLEEP
352static int nec_8048_suspend(struct device *dev)
353{
354 struct spi_device *spi = to_spi_device(dev);
355
356 nec_8048_spi_send(spi, 2, 0x01);
357 mdelay(40);
358
359 return 0;
360}
361
362static int nec_8048_resume(struct device *dev)
363{
364 struct spi_device *spi = to_spi_device(dev);
365
366 /* reinitialize the panel */
367 spi_setup(spi);
368 nec_8048_spi_send(spi, 2, 0x00);
369 init_nec_8048_wvga_lcd(spi);
370
371 return 0;
372}
373static SIMPLE_DEV_PM_OPS(nec_8048_pm_ops, nec_8048_suspend,
374 nec_8048_resume);
375#define NEC_8048_PM_OPS (&nec_8048_pm_ops)
376#else
377#define NEC_8048_PM_OPS NULL
378#endif
379
380static struct spi_driver nec_8048_driver = {
381 .driver = {
382 .name = "panel-nec-nl8048hl11",
383 .owner = THIS_MODULE,
384 .pm = NEC_8048_PM_OPS,
385 },
386 .probe = nec_8048_probe,
387 .remove = nec_8048_remove,
388};
389
390module_spi_driver(nec_8048_driver);
391
392MODULE_AUTHOR("Erik Gilling <konkers@android.com>");
393MODULE_DESCRIPTION("NEC-NL8048HL11 Driver");
394MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays-new/panel-sharp-ls037v7dw01.c
new file mode 100644
index 000000000000..72a4fb5aa6b1
--- /dev/null
+++ b/drivers/video/omap2/displays-new/panel-sharp-ls037v7dw01.c
@@ -0,0 +1,324 @@
1/*
2 * LCD panel driver for Sharp LS037V7DW01
3 *
4 * Copyright (C) 2013 Texas Instruments
5 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
6 *
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.
10 */
11
12#include <linux/delay.h>
13#include <linux/gpio.h>
14#include <linux/module.h>
15#include <linux/platform_device.h>
16#include <linux/slab.h>
17
18#include <video/omapdss.h>
19#include <video/omap-panel-data.h>
20
21struct panel_drv_data {
22 struct omap_dss_device dssdev;
23 struct omap_dss_device *in;
24
25 int data_lines;
26
27 struct omap_video_timings videomode;
28
29 int resb_gpio;
30 int ini_gpio;
31 int mo_gpio;
32 int lr_gpio;
33 int ud_gpio;
34};
35
36static const struct omap_video_timings sharp_ls_timings = {
37 .x_res = 480,
38 .y_res = 640,
39
40 .pixel_clock = 19200,
41
42 .hsw = 2,
43 .hfp = 1,
44 .hbp = 28,
45
46 .vsw = 1,
47 .vfp = 1,
48 .vbp = 1,
49
50 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
51 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
52 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
53 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
54 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
55};
56
57#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
58
59static int sharp_ls_connect(struct omap_dss_device *dssdev)
60{
61 struct panel_drv_data *ddata = to_panel_data(dssdev);
62 struct omap_dss_device *in = ddata->in;
63 int r;
64
65 if (omapdss_device_is_connected(dssdev))
66 return 0;
67
68 r = in->ops.dpi->connect(in, dssdev);
69 if (r)
70 return r;
71
72 return 0;
73}
74
75static void sharp_ls_disconnect(struct omap_dss_device *dssdev)
76{
77 struct panel_drv_data *ddata = to_panel_data(dssdev);
78 struct omap_dss_device *in = ddata->in;
79
80 if (!omapdss_device_is_connected(dssdev))
81 return;
82
83 in->ops.dpi->disconnect(in, dssdev);
84}
85
86static int sharp_ls_enable(struct omap_dss_device *dssdev)
87{
88 struct panel_drv_data *ddata = to_panel_data(dssdev);
89 struct omap_dss_device *in = ddata->in;
90 int r;
91
92 if (!omapdss_device_is_connected(dssdev))
93 return -ENODEV;
94
95 if (omapdss_device_is_enabled(dssdev))
96 return 0;
97
98 in->ops.dpi->set_data_lines(in, ddata->data_lines);
99 in->ops.dpi->set_timings(in, &ddata->videomode);
100
101 r = in->ops.dpi->enable(in);
102 if (r)
103 return r;
104
105 /* wait couple of vsyncs until enabling the LCD */
106 msleep(50);
107
108 if (gpio_is_valid(ddata->resb_gpio))
109 gpio_set_value_cansleep(ddata->resb_gpio, 1);
110
111 if (gpio_is_valid(ddata->ini_gpio))
112 gpio_set_value_cansleep(ddata->ini_gpio, 1);
113
114 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
115
116 return 0;
117}
118
119static void sharp_ls_disable(struct omap_dss_device *dssdev)
120{
121 struct panel_drv_data *ddata = to_panel_data(dssdev);
122 struct omap_dss_device *in = ddata->in;
123
124 if (!omapdss_device_is_enabled(dssdev))
125 return;
126
127 if (gpio_is_valid(ddata->ini_gpio))
128 gpio_set_value_cansleep(ddata->ini_gpio, 0);
129
130 if (gpio_is_valid(ddata->resb_gpio))
131 gpio_set_value_cansleep(ddata->resb_gpio, 0);
132
133 /* wait at least 5 vsyncs after disabling the LCD */
134
135 msleep(100);
136
137 in->ops.dpi->disable(in);
138
139 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
140}
141
142static void sharp_ls_set_timings(struct omap_dss_device *dssdev,
143 struct omap_video_timings *timings)
144{
145 struct panel_drv_data *ddata = to_panel_data(dssdev);
146 struct omap_dss_device *in = ddata->in;
147
148 ddata->videomode = *timings;
149 dssdev->panel.timings = *timings;
150
151 in->ops.dpi->set_timings(in, timings);
152}
153
154static void sharp_ls_get_timings(struct omap_dss_device *dssdev,
155 struct omap_video_timings *timings)
156{
157 struct panel_drv_data *ddata = to_panel_data(dssdev);
158
159 *timings = ddata->videomode;
160}
161
162static int sharp_ls_check_timings(struct omap_dss_device *dssdev,
163 struct omap_video_timings *timings)
164{
165 struct panel_drv_data *ddata = to_panel_data(dssdev);
166 struct omap_dss_device *in = ddata->in;
167
168 return in->ops.dpi->check_timings(in, timings);
169}
170
171static struct omap_dss_driver sharp_ls_ops = {
172 .connect = sharp_ls_connect,
173 .disconnect = sharp_ls_disconnect,
174
175 .enable = sharp_ls_enable,
176 .disable = sharp_ls_disable,
177
178 .set_timings = sharp_ls_set_timings,
179 .get_timings = sharp_ls_get_timings,
180 .check_timings = sharp_ls_check_timings,
181
182 .get_resolution = omapdss_default_get_resolution,
183};
184
185static int sharp_ls_probe_pdata(struct platform_device *pdev)
186{
187 const struct panel_sharp_ls037v7dw01_platform_data *pdata;
188 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
189 struct omap_dss_device *dssdev, *in;
190
191 pdata = dev_get_platdata(&pdev->dev);
192
193 in = omap_dss_find_output(pdata->source);
194 if (in == NULL) {
195 dev_err(&pdev->dev, "failed to find video source '%s'\n",
196 pdata->source);
197 return -EPROBE_DEFER;
198 }
199
200 ddata->in = in;
201
202 ddata->data_lines = pdata->data_lines;
203
204 dssdev = &ddata->dssdev;
205 dssdev->name = pdata->name;
206
207 ddata->resb_gpio = pdata->resb_gpio;
208 ddata->ini_gpio = pdata->ini_gpio;
209 ddata->mo_gpio = pdata->mo_gpio;
210 ddata->lr_gpio = pdata->lr_gpio;
211 ddata->ud_gpio = pdata->ud_gpio;
212
213 return 0;
214}
215
216static int sharp_ls_probe(struct platform_device *pdev)
217{
218 struct panel_drv_data *ddata;
219 struct omap_dss_device *dssdev;
220 int r;
221
222 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
223 if (ddata == NULL)
224 return -ENOMEM;
225
226 platform_set_drvdata(pdev, ddata);
227
228 if (dev_get_platdata(&pdev->dev)) {
229 r = sharp_ls_probe_pdata(pdev);
230 if (r)
231 return r;
232 } else {
233 return -ENODEV;
234 }
235
236 if (gpio_is_valid(ddata->mo_gpio)) {
237 r = devm_gpio_request_one(&pdev->dev, ddata->mo_gpio,
238 GPIOF_OUT_INIT_LOW, "lcd MO");
239 if (r)
240 goto err_gpio;
241 }
242
243 if (gpio_is_valid(ddata->lr_gpio)) {
244 r = devm_gpio_request_one(&pdev->dev, ddata->lr_gpio,
245 GPIOF_OUT_INIT_HIGH, "lcd LR");
246 if (r)
247 goto err_gpio;
248 }
249
250 if (gpio_is_valid(ddata->ud_gpio)) {
251 r = devm_gpio_request_one(&pdev->dev, ddata->ud_gpio,
252 GPIOF_OUT_INIT_HIGH, "lcd UD");
253 if (r)
254 goto err_gpio;
255 }
256
257 if (gpio_is_valid(ddata->resb_gpio)) {
258 r = devm_gpio_request_one(&pdev->dev, ddata->resb_gpio,
259 GPIOF_OUT_INIT_LOW, "lcd RESB");
260 if (r)
261 goto err_gpio;
262 }
263
264 if (gpio_is_valid(ddata->ini_gpio)) {
265 r = devm_gpio_request_one(&pdev->dev, ddata->ini_gpio,
266 GPIOF_OUT_INIT_LOW, "lcd INI");
267 if (r)
268 goto err_gpio;
269 }
270
271 ddata->videomode = sharp_ls_timings;
272
273 dssdev = &ddata->dssdev;
274 dssdev->dev = &pdev->dev;
275 dssdev->driver = &sharp_ls_ops;
276 dssdev->type = OMAP_DISPLAY_TYPE_DPI;
277 dssdev->owner = THIS_MODULE;
278 dssdev->panel.timings = ddata->videomode;
279 dssdev->phy.dpi.data_lines = ddata->data_lines;
280
281 r = omapdss_register_display(dssdev);
282 if (r) {
283 dev_err(&pdev->dev, "Failed to register panel\n");
284 goto err_reg;
285 }
286
287 return 0;
288
289err_reg:
290err_gpio:
291 omap_dss_put_device(ddata->in);
292 return r;
293}
294
295static int __exit sharp_ls_remove(struct platform_device *pdev)
296{
297 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
298 struct omap_dss_device *dssdev = &ddata->dssdev;
299 struct omap_dss_device *in = ddata->in;
300
301 omapdss_unregister_display(dssdev);
302
303 sharp_ls_disable(dssdev);
304 sharp_ls_disconnect(dssdev);
305
306 omap_dss_put_device(in);
307
308 return 0;
309}
310
311static struct platform_driver sharp_ls_driver = {
312 .probe = sharp_ls_probe,
313 .remove = __exit_p(sharp_ls_remove),
314 .driver = {
315 .name = "panel-sharp-ls037v7dw01",
316 .owner = THIS_MODULE,
317 },
318};
319
320module_platform_driver(sharp_ls_driver);
321
322MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
323MODULE_DESCRIPTION("Sharp LS037V7DW01 Panel Driver");
324MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/panel-sony-acx565akm.c b/drivers/video/omap2/displays-new/panel-sony-acx565akm.c
new file mode 100644
index 000000000000..e6d56f714ae4
--- /dev/null
+++ b/drivers/video/omap2/displays-new/panel-sony-acx565akm.c
@@ -0,0 +1,865 @@
1/*
2 * Sony ACX565AKM LCD Panel driver
3 *
4 * Copyright (C) 2010 Nokia Corporation
5 *
6 * Original Driver Author: Imre Deak <imre.deak@nokia.com>
7 * Based on panel-generic.c by Tomi Valkeinen <tomi.valkeinen@nokia.com>
8 * Adapted to new DSS2 framework: Roger Quadros <roger.quadros@nokia.com>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/platform_device.h>
26#include <linux/delay.h>
27#include <linux/spi/spi.h>
28#include <linux/jiffies.h>
29#include <linux/sched.h>
30#include <linux/backlight.h>
31#include <linux/fb.h>
32#include <linux/gpio.h>
33
34#include <video/omapdss.h>
35#include <video/omap-panel-data.h>
36
37#define MIPID_CMD_READ_DISP_ID 0x04
38#define MIPID_CMD_READ_RED 0x06
39#define MIPID_CMD_READ_GREEN 0x07
40#define MIPID_CMD_READ_BLUE 0x08
41#define MIPID_CMD_READ_DISP_STATUS 0x09
42#define MIPID_CMD_RDDSDR 0x0F
43#define MIPID_CMD_SLEEP_IN 0x10
44#define MIPID_CMD_SLEEP_OUT 0x11
45#define MIPID_CMD_DISP_OFF 0x28
46#define MIPID_CMD_DISP_ON 0x29
47#define MIPID_CMD_WRITE_DISP_BRIGHTNESS 0x51
48#define MIPID_CMD_READ_DISP_BRIGHTNESS 0x52
49#define MIPID_CMD_WRITE_CTRL_DISP 0x53
50
51#define CTRL_DISP_BRIGHTNESS_CTRL_ON (1 << 5)
52#define CTRL_DISP_AMBIENT_LIGHT_CTRL_ON (1 << 4)
53#define CTRL_DISP_BACKLIGHT_ON (1 << 2)
54#define CTRL_DISP_AUTO_BRIGHTNESS_ON (1 << 1)
55
56#define MIPID_CMD_READ_CTRL_DISP 0x54
57#define MIPID_CMD_WRITE_CABC 0x55
58#define MIPID_CMD_READ_CABC 0x56
59
60#define MIPID_VER_LPH8923 3
61#define MIPID_VER_LS041Y3 4
62#define MIPID_VER_L4F00311 8
63#define MIPID_VER_ACX565AKM 9
64
65struct panel_drv_data {
66 struct omap_dss_device dssdev;
67 struct omap_dss_device *in;
68
69 int reset_gpio;
70 int datapairs;
71
72 struct omap_video_timings videomode;
73
74 char *name;
75 int enabled;
76 int model;
77 int revision;
78 u8 display_id[3];
79 unsigned has_bc:1;
80 unsigned has_cabc:1;
81 unsigned cabc_mode;
82 unsigned long hw_guard_end; /* next value of jiffies
83 when we can issue the
84 next sleep in/out command */
85 unsigned long hw_guard_wait; /* max guard time in jiffies */
86
87 struct spi_device *spi;
88 struct mutex mutex;
89
90 struct backlight_device *bl_dev;
91};
92
93static const struct omap_video_timings acx565akm_panel_timings = {
94 .x_res = 800,
95 .y_res = 480,
96 .pixel_clock = 24000,
97 .hfp = 28,
98 .hsw = 4,
99 .hbp = 24,
100 .vfp = 3,
101 .vsw = 3,
102 .vbp = 4,
103
104 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
105 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
106
107 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
108 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
109 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
110};
111
112#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
113
114static void acx565akm_transfer(struct panel_drv_data *ddata, int cmd,
115 const u8 *wbuf, int wlen, u8 *rbuf, int rlen)
116{
117 struct spi_message m;
118 struct spi_transfer *x, xfer[5];
119 int r;
120
121 BUG_ON(ddata->spi == NULL);
122
123 spi_message_init(&m);
124
125 memset(xfer, 0, sizeof(xfer));
126 x = &xfer[0];
127
128 cmd &= 0xff;
129 x->tx_buf = &cmd;
130 x->bits_per_word = 9;
131 x->len = 2;
132
133 if (rlen > 1 && wlen == 0) {
134 /*
135 * Between the command and the response data there is a
136 * dummy clock cycle. Add an extra bit after the command
137 * word to account for this.
138 */
139 x->bits_per_word = 10;
140 cmd <<= 1;
141 }
142 spi_message_add_tail(x, &m);
143
144 if (wlen) {
145 x++;
146 x->tx_buf = wbuf;
147 x->len = wlen;
148 x->bits_per_word = 9;
149 spi_message_add_tail(x, &m);
150 }
151
152 if (rlen) {
153 x++;
154 x->rx_buf = rbuf;
155 x->len = rlen;
156 spi_message_add_tail(x, &m);
157 }
158
159 r = spi_sync(ddata->spi, &m);
160 if (r < 0)
161 dev_dbg(&ddata->spi->dev, "spi_sync %d\n", r);
162}
163
164static inline void acx565akm_cmd(struct panel_drv_data *ddata, int cmd)
165{
166 acx565akm_transfer(ddata, cmd, NULL, 0, NULL, 0);
167}
168
169static inline void acx565akm_write(struct panel_drv_data *ddata,
170 int reg, const u8 *buf, int len)
171{
172 acx565akm_transfer(ddata, reg, buf, len, NULL, 0);
173}
174
175static inline void acx565akm_read(struct panel_drv_data *ddata,
176 int reg, u8 *buf, int len)
177{
178 acx565akm_transfer(ddata, reg, NULL, 0, buf, len);
179}
180
181static void hw_guard_start(struct panel_drv_data *ddata, int guard_msec)
182{
183 ddata->hw_guard_wait = msecs_to_jiffies(guard_msec);
184 ddata->hw_guard_end = jiffies + ddata->hw_guard_wait;
185}
186
187static void hw_guard_wait(struct panel_drv_data *ddata)
188{
189 unsigned long wait = ddata->hw_guard_end - jiffies;
190
191 if ((long)wait > 0 && wait <= ddata->hw_guard_wait) {
192 set_current_state(TASK_UNINTERRUPTIBLE);
193 schedule_timeout(wait);
194 }
195}
196
197static void set_sleep_mode(struct panel_drv_data *ddata, int on)
198{
199 int cmd;
200
201 if (on)
202 cmd = MIPID_CMD_SLEEP_IN;
203 else
204 cmd = MIPID_CMD_SLEEP_OUT;
205 /*
206 * We have to keep 120msec between sleep in/out commands.
207 * (8.2.15, 8.2.16).
208 */
209 hw_guard_wait(ddata);
210 acx565akm_cmd(ddata, cmd);
211 hw_guard_start(ddata, 120);
212}
213
214static void set_display_state(struct panel_drv_data *ddata, int enabled)
215{
216 int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
217
218 acx565akm_cmd(ddata, cmd);
219}
220
221static int panel_enabled(struct panel_drv_data *ddata)
222{
223 u32 disp_status;
224 int enabled;
225
226 acx565akm_read(ddata, MIPID_CMD_READ_DISP_STATUS,
227 (u8 *)&disp_status, 4);
228 disp_status = __be32_to_cpu(disp_status);
229 enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
230 dev_dbg(&ddata->spi->dev,
231 "LCD panel %senabled by bootloader (status 0x%04x)\n",
232 enabled ? "" : "not ", disp_status);
233 return enabled;
234}
235
236static int panel_detect(struct panel_drv_data *ddata)
237{
238 acx565akm_read(ddata, MIPID_CMD_READ_DISP_ID, ddata->display_id, 3);
239 dev_dbg(&ddata->spi->dev, "MIPI display ID: %02x%02x%02x\n",
240 ddata->display_id[0],
241 ddata->display_id[1],
242 ddata->display_id[2]);
243
244 switch (ddata->display_id[0]) {
245 case 0x10:
246 ddata->model = MIPID_VER_ACX565AKM;
247 ddata->name = "acx565akm";
248 ddata->has_bc = 1;
249 ddata->has_cabc = 1;
250 break;
251 case 0x29:
252 ddata->model = MIPID_VER_L4F00311;
253 ddata->name = "l4f00311";
254 break;
255 case 0x45:
256 ddata->model = MIPID_VER_LPH8923;
257 ddata->name = "lph8923";
258 break;
259 case 0x83:
260 ddata->model = MIPID_VER_LS041Y3;
261 ddata->name = "ls041y3";
262 break;
263 default:
264 ddata->name = "unknown";
265 dev_err(&ddata->spi->dev, "invalid display ID\n");
266 return -ENODEV;
267 }
268
269 ddata->revision = ddata->display_id[1];
270
271 dev_info(&ddata->spi->dev, "omapfb: %s rev %02x LCD detected\n",
272 ddata->name, ddata->revision);
273
274 return 0;
275}
276
277/*----------------------Backlight Control-------------------------*/
278
279static void enable_backlight_ctrl(struct panel_drv_data *ddata, int enable)
280{
281 u16 ctrl;
282
283 acx565akm_read(ddata, MIPID_CMD_READ_CTRL_DISP, (u8 *)&ctrl, 1);
284 if (enable) {
285 ctrl |= CTRL_DISP_BRIGHTNESS_CTRL_ON |
286 CTRL_DISP_BACKLIGHT_ON;
287 } else {
288 ctrl &= ~(CTRL_DISP_BRIGHTNESS_CTRL_ON |
289 CTRL_DISP_BACKLIGHT_ON);
290 }
291
292 ctrl |= 1 << 8;
293 acx565akm_write(ddata, MIPID_CMD_WRITE_CTRL_DISP, (u8 *)&ctrl, 2);
294}
295
296static void set_cabc_mode(struct panel_drv_data *ddata, unsigned mode)
297{
298 u16 cabc_ctrl;
299
300 ddata->cabc_mode = mode;
301 if (!ddata->enabled)
302 return;
303 cabc_ctrl = 0;
304 acx565akm_read(ddata, MIPID_CMD_READ_CABC, (u8 *)&cabc_ctrl, 1);
305 cabc_ctrl &= ~3;
306 cabc_ctrl |= (1 << 8) | (mode & 3);
307 acx565akm_write(ddata, MIPID_CMD_WRITE_CABC, (u8 *)&cabc_ctrl, 2);
308}
309
310static unsigned get_cabc_mode(struct panel_drv_data *ddata)
311{
312 return ddata->cabc_mode;
313}
314
315static unsigned get_hw_cabc_mode(struct panel_drv_data *ddata)
316{
317 u8 cabc_ctrl;
318
319 acx565akm_read(ddata, MIPID_CMD_READ_CABC, &cabc_ctrl, 1);
320 return cabc_ctrl & 3;
321}
322
323static void acx565akm_set_brightness(struct panel_drv_data *ddata, int level)
324{
325 int bv;
326
327 bv = level | (1 << 8);
328 acx565akm_write(ddata, MIPID_CMD_WRITE_DISP_BRIGHTNESS, (u8 *)&bv, 2);
329
330 if (level)
331 enable_backlight_ctrl(ddata, 1);
332 else
333 enable_backlight_ctrl(ddata, 0);
334}
335
336static int acx565akm_get_actual_brightness(struct panel_drv_data *ddata)
337{
338 u8 bv;
339
340 acx565akm_read(ddata, MIPID_CMD_READ_DISP_BRIGHTNESS, &bv, 1);
341
342 return bv;
343}
344
345
346static int acx565akm_bl_update_status(struct backlight_device *dev)
347{
348 struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
349 int r;
350 int level;
351
352 dev_dbg(&ddata->spi->dev, "%s\n", __func__);
353
354 mutex_lock(&ddata->mutex);
355
356 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
357 dev->props.power == FB_BLANK_UNBLANK)
358 level = dev->props.brightness;
359 else
360 level = 0;
361
362 r = 0;
363 if (ddata->has_bc)
364 acx565akm_set_brightness(ddata, level);
365 else
366 r = -ENODEV;
367
368 mutex_unlock(&ddata->mutex);
369
370 return r;
371}
372
373static int acx565akm_bl_get_intensity(struct backlight_device *dev)
374{
375 struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
376
377 dev_dbg(&dev->dev, "%s\n", __func__);
378
379 if (!ddata->has_bc)
380 return -ENODEV;
381
382 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
383 dev->props.power == FB_BLANK_UNBLANK) {
384 if (ddata->has_bc)
385 return acx565akm_get_actual_brightness(ddata);
386 else
387 return dev->props.brightness;
388 }
389
390 return 0;
391}
392
393static const struct backlight_ops acx565akm_bl_ops = {
394 .get_brightness = acx565akm_bl_get_intensity,
395 .update_status = acx565akm_bl_update_status,
396};
397
398/*--------------------Auto Brightness control via Sysfs---------------------*/
399
400static const char * const cabc_modes[] = {
401 "off", /* always used when CABC is not supported */
402 "ui",
403 "still-image",
404 "moving-image",
405};
406
407static ssize_t show_cabc_mode(struct device *dev,
408 struct device_attribute *attr,
409 char *buf)
410{
411 struct panel_drv_data *ddata = dev_get_drvdata(dev);
412 const char *mode_str;
413 int mode;
414 int len;
415
416 if (!ddata->has_cabc)
417 mode = 0;
418 else
419 mode = get_cabc_mode(ddata);
420 mode_str = "unknown";
421 if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes))
422 mode_str = cabc_modes[mode];
423 len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str);
424
425 return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1;
426}
427
428static ssize_t store_cabc_mode(struct device *dev,
429 struct device_attribute *attr,
430 const char *buf, size_t count)
431{
432 struct panel_drv_data *ddata = dev_get_drvdata(dev);
433 int i;
434
435 for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
436 const char *mode_str = cabc_modes[i];
437 int cmp_len = strlen(mode_str);
438
439 if (count > 0 && buf[count - 1] == '\n')
440 count--;
441 if (count != cmp_len)
442 continue;
443
444 if (strncmp(buf, mode_str, cmp_len) == 0)
445 break;
446 }
447
448 if (i == ARRAY_SIZE(cabc_modes))
449 return -EINVAL;
450
451 if (!ddata->has_cabc && i != 0)
452 return -EINVAL;
453
454 mutex_lock(&ddata->mutex);
455 set_cabc_mode(ddata, i);
456 mutex_unlock(&ddata->mutex);
457
458 return count;
459}
460
461static ssize_t show_cabc_available_modes(struct device *dev,
462 struct device_attribute *attr,
463 char *buf)
464{
465 struct panel_drv_data *ddata = dev_get_drvdata(dev);
466 int len;
467 int i;
468
469 if (!ddata->has_cabc)
470 return snprintf(buf, PAGE_SIZE, "%s\n", cabc_modes[0]);
471
472 for (i = 0, len = 0;
473 len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++)
474 len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s",
475 i ? " " : "", cabc_modes[i],
476 i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : "");
477
478 return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
479}
480
481static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
482 show_cabc_mode, store_cabc_mode);
483static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
484 show_cabc_available_modes, NULL);
485
486static struct attribute *bldev_attrs[] = {
487 &dev_attr_cabc_mode.attr,
488 &dev_attr_cabc_available_modes.attr,
489 NULL,
490};
491
492static struct attribute_group bldev_attr_group = {
493 .attrs = bldev_attrs,
494};
495
496static int acx565akm_connect(struct omap_dss_device *dssdev)
497{
498 struct panel_drv_data *ddata = to_panel_data(dssdev);
499 struct omap_dss_device *in = ddata->in;
500 int r;
501
502 if (omapdss_device_is_connected(dssdev))
503 return 0;
504
505 r = in->ops.sdi->connect(in, dssdev);
506 if (r)
507 return r;
508
509 return 0;
510}
511
512static void acx565akm_disconnect(struct omap_dss_device *dssdev)
513{
514 struct panel_drv_data *ddata = to_panel_data(dssdev);
515 struct omap_dss_device *in = ddata->in;
516
517 if (!omapdss_device_is_connected(dssdev))
518 return;
519
520 in->ops.sdi->disconnect(in, dssdev);
521}
522
523static int acx565akm_panel_power_on(struct omap_dss_device *dssdev)
524{
525 struct panel_drv_data *ddata = to_panel_data(dssdev);
526 struct omap_dss_device *in = ddata->in;
527 int r;
528
529 dev_dbg(&ddata->spi->dev, "%s\n", __func__);
530
531 in->ops.sdi->set_timings(in, &ddata->videomode);
532 in->ops.sdi->set_datapairs(in, ddata->datapairs);
533
534 r = in->ops.sdi->enable(in);
535 if (r) {
536 pr_err("%s sdi enable failed\n", __func__);
537 return r;
538 }
539
540 /*FIXME tweak me */
541 msleep(50);
542
543 if (gpio_is_valid(ddata->reset_gpio))
544 gpio_set_value(ddata->reset_gpio, 1);
545
546 if (ddata->enabled) {
547 dev_dbg(&ddata->spi->dev, "panel already enabled\n");
548 return 0;
549 }
550
551 /*
552 * We have to meet all the following delay requirements:
553 * 1. tRW: reset pulse width 10usec (7.12.1)
554 * 2. tRT: reset cancel time 5msec (7.12.1)
555 * 3. Providing PCLK,HS,VS signals for 2 frames = ~50msec worst
556 * case (7.6.2)
557 * 4. 120msec before the sleep out command (7.12.1)
558 */
559 msleep(120);
560
561 set_sleep_mode(ddata, 0);
562 ddata->enabled = 1;
563
564 /* 5msec between sleep out and the next command. (8.2.16) */
565 usleep_range(5000, 10000);
566 set_display_state(ddata, 1);
567 set_cabc_mode(ddata, ddata->cabc_mode);
568
569 mutex_unlock(&ddata->mutex);
570
571 return acx565akm_bl_update_status(ddata->bl_dev);
572}
573
574static void acx565akm_panel_power_off(struct omap_dss_device *dssdev)
575{
576 struct panel_drv_data *ddata = to_panel_data(dssdev);
577 struct omap_dss_device *in = ddata->in;
578
579 dev_dbg(dssdev->dev, "%s\n", __func__);
580
581 if (!ddata->enabled)
582 return;
583
584 set_display_state(ddata, 0);
585 set_sleep_mode(ddata, 1);
586 ddata->enabled = 0;
587 /*
588 * We have to provide PCLK,HS,VS signals for 2 frames (worst case
589 * ~50msec) after sending the sleep in command and asserting the
590 * reset signal. We probably could assert the reset w/o the delay
591 * but we still delay to avoid possible artifacts. (7.6.1)
592 */
593 msleep(50);
594
595 if (gpio_is_valid(ddata->reset_gpio))
596 gpio_set_value(ddata->reset_gpio, 0);
597
598 /* FIXME need to tweak this delay */
599 msleep(100);
600
601 in->ops.sdi->disable(in);
602}
603
604static int acx565akm_enable(struct omap_dss_device *dssdev)
605{
606 struct panel_drv_data *ddata = to_panel_data(dssdev);
607 int r;
608
609 dev_dbg(dssdev->dev, "%s\n", __func__);
610
611 if (!omapdss_device_is_connected(dssdev))
612 return -ENODEV;
613
614 if (omapdss_device_is_enabled(dssdev))
615 return 0;
616
617 mutex_lock(&ddata->mutex);
618 r = acx565akm_panel_power_on(dssdev);
619 mutex_unlock(&ddata->mutex);
620
621 if (r)
622 return r;
623
624 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
625
626 return 0;
627}
628
629static void acx565akm_disable(struct omap_dss_device *dssdev)
630{
631 struct panel_drv_data *ddata = to_panel_data(dssdev);
632
633 dev_dbg(dssdev->dev, "%s\n", __func__);
634
635 if (!omapdss_device_is_enabled(dssdev))
636 return;
637
638 mutex_lock(&ddata->mutex);
639 acx565akm_panel_power_off(dssdev);
640 mutex_unlock(&ddata->mutex);
641
642 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
643}
644
645static void acx565akm_set_timings(struct omap_dss_device *dssdev,
646 struct omap_video_timings *timings)
647{
648 struct panel_drv_data *ddata = to_panel_data(dssdev);
649 struct omap_dss_device *in = ddata->in;
650
651 ddata->videomode = *timings;
652 dssdev->panel.timings = *timings;
653
654 in->ops.sdi->set_timings(in, timings);
655}
656
657static void acx565akm_get_timings(struct omap_dss_device *dssdev,
658 struct omap_video_timings *timings)
659{
660 struct panel_drv_data *ddata = to_panel_data(dssdev);
661
662 *timings = ddata->videomode;
663}
664
665static int acx565akm_check_timings(struct omap_dss_device *dssdev,
666 struct omap_video_timings *timings)
667{
668 struct panel_drv_data *ddata = to_panel_data(dssdev);
669 struct omap_dss_device *in = ddata->in;
670
671 return in->ops.sdi->check_timings(in, timings);
672}
673
674static struct omap_dss_driver acx565akm_ops = {
675 .connect = acx565akm_connect,
676 .disconnect = acx565akm_disconnect,
677
678 .enable = acx565akm_enable,
679 .disable = acx565akm_disable,
680
681 .set_timings = acx565akm_set_timings,
682 .get_timings = acx565akm_get_timings,
683 .check_timings = acx565akm_check_timings,
684
685 .get_resolution = omapdss_default_get_resolution,
686};
687
688static int acx565akm_probe_pdata(struct spi_device *spi)
689{
690 const struct panel_acx565akm_platform_data *pdata;
691 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
692 struct omap_dss_device *dssdev, *in;
693
694 pdata = dev_get_platdata(&spi->dev);
695
696 ddata->reset_gpio = pdata->reset_gpio;
697
698 in = omap_dss_find_output(pdata->source);
699 if (in == NULL) {
700 dev_err(&spi->dev, "failed to find video source '%s'\n",
701 pdata->source);
702 return -EPROBE_DEFER;
703 }
704 ddata->in = in;
705
706 ddata->datapairs = pdata->datapairs;
707
708 dssdev = &ddata->dssdev;
709 dssdev->name = pdata->name;
710
711 return 0;
712}
713
714static int acx565akm_probe(struct spi_device *spi)
715{
716 struct panel_drv_data *ddata;
717 struct omap_dss_device *dssdev;
718 struct backlight_device *bldev;
719 int max_brightness, brightness;
720 struct backlight_properties props;
721 int r;
722
723 dev_dbg(&spi->dev, "%s\n", __func__);
724
725 spi->mode = SPI_MODE_3;
726
727 ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
728 if (ddata == NULL)
729 return -ENOMEM;
730
731 dev_set_drvdata(&spi->dev, ddata);
732
733 ddata->spi = spi;
734
735 mutex_init(&ddata->mutex);
736
737 if (dev_get_platdata(&spi->dev)) {
738 r = acx565akm_probe_pdata(spi);
739 if (r)
740 return r;
741 } else {
742 return -ENODEV;
743 }
744
745 if (gpio_is_valid(ddata->reset_gpio)) {
746 r = devm_gpio_request_one(&spi->dev, ddata->reset_gpio,
747 GPIOF_OUT_INIT_LOW, "lcd reset");
748 if (r)
749 goto err_gpio;
750 }
751
752 if (gpio_is_valid(ddata->reset_gpio))
753 gpio_set_value(ddata->reset_gpio, 1);
754
755 /*
756 * After reset we have to wait 5 msec before the first
757 * command can be sent.
758 */
759 usleep_range(5000, 10000);
760
761 ddata->enabled = panel_enabled(ddata);
762
763 r = panel_detect(ddata);
764
765 if (!ddata->enabled && gpio_is_valid(ddata->reset_gpio))
766 gpio_set_value(ddata->reset_gpio, 0);
767
768 if (r) {
769 dev_err(&spi->dev, "%s panel detect error\n", __func__);
770 goto err_detect;
771 }
772
773 memset(&props, 0, sizeof(props));
774 props.fb_blank = FB_BLANK_UNBLANK;
775 props.power = FB_BLANK_UNBLANK;
776 props.type = BACKLIGHT_RAW;
777
778 bldev = backlight_device_register("acx565akm", &ddata->spi->dev,
779 ddata, &acx565akm_bl_ops, &props);
780 ddata->bl_dev = bldev;
781 if (ddata->has_cabc) {
782 r = sysfs_create_group(&bldev->dev.kobj, &bldev_attr_group);
783 if (r) {
784 dev_err(&bldev->dev,
785 "%s failed to create sysfs files\n", __func__);
786 goto err_sysfs;
787 }
788 ddata->cabc_mode = get_hw_cabc_mode(ddata);
789 }
790
791 max_brightness = 255;
792
793 if (ddata->has_bc)
794 brightness = acx565akm_get_actual_brightness(ddata);
795 else
796 brightness = 0;
797
798 bldev->props.max_brightness = max_brightness;
799 bldev->props.brightness = brightness;
800
801 acx565akm_bl_update_status(bldev);
802
803
804 ddata->videomode = acx565akm_panel_timings;
805
806 dssdev = &ddata->dssdev;
807 dssdev->dev = &spi->dev;
808 dssdev->driver = &acx565akm_ops;
809 dssdev->type = OMAP_DISPLAY_TYPE_SDI;
810 dssdev->owner = THIS_MODULE;
811 dssdev->panel.timings = ddata->videomode;
812
813 r = omapdss_register_display(dssdev);
814 if (r) {
815 dev_err(&spi->dev, "Failed to register panel\n");
816 goto err_reg;
817 }
818
819 return 0;
820
821err_reg:
822 sysfs_remove_group(&bldev->dev.kobj, &bldev_attr_group);
823err_sysfs:
824 backlight_device_unregister(bldev);
825err_detect:
826err_gpio:
827 omap_dss_put_device(ddata->in);
828 return r;
829}
830
831static int acx565akm_remove(struct spi_device *spi)
832{
833 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
834 struct omap_dss_device *dssdev = &ddata->dssdev;
835 struct omap_dss_device *in = ddata->in;
836
837 dev_dbg(&ddata->spi->dev, "%s\n", __func__);
838
839 sysfs_remove_group(&ddata->bl_dev->dev.kobj, &bldev_attr_group);
840 backlight_device_unregister(ddata->bl_dev);
841
842 omapdss_unregister_display(dssdev);
843
844 acx565akm_disable(dssdev);
845 acx565akm_disconnect(dssdev);
846
847 omap_dss_put_device(in);
848
849 return 0;
850}
851
852static struct spi_driver acx565akm_driver = {
853 .driver = {
854 .name = "acx565akm",
855 .owner = THIS_MODULE,
856 },
857 .probe = acx565akm_probe,
858 .remove = acx565akm_remove,
859};
860
861module_spi_driver(acx565akm_driver);
862
863MODULE_AUTHOR("Nokia Corporation");
864MODULE_DESCRIPTION("acx565akm LCD Driver");
865MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays-new/panel-tpo-td043mtea1.c
new file mode 100644
index 000000000000..eadc6529fa3d
--- /dev/null
+++ b/drivers/video/omap2/displays-new/panel-tpo-td043mtea1.c
@@ -0,0 +1,646 @@
1/*
2 * TPO TD043MTEA1 Panel driver
3 *
4 * Author: Gražvydas Ignotas <notasas@gmail.com>
5 * Converted to new DSS device model: Tomi Valkeinen <tomi.valkeinen@ti.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <linux/module.h>
14#include <linux/delay.h>
15#include <linux/spi/spi.h>
16#include <linux/regulator/consumer.h>
17#include <linux/gpio.h>
18#include <linux/err.h>
19#include <linux/slab.h>
20
21#include <video/omapdss.h>
22#include <video/omap-panel-data.h>
23
24#define TPO_R02_MODE(x) ((x) & 7)
25#define TPO_R02_MODE_800x480 7
26#define TPO_R02_NCLK_RISING BIT(3)
27#define TPO_R02_HSYNC_HIGH BIT(4)
28#define TPO_R02_VSYNC_HIGH BIT(5)
29
30#define TPO_R03_NSTANDBY BIT(0)
31#define TPO_R03_EN_CP_CLK BIT(1)
32#define TPO_R03_EN_VGL_PUMP BIT(2)
33#define TPO_R03_EN_PWM BIT(3)
34#define TPO_R03_DRIVING_CAP_100 BIT(4)
35#define TPO_R03_EN_PRE_CHARGE BIT(6)
36#define TPO_R03_SOFTWARE_CTL BIT(7)
37
38#define TPO_R04_NFLIP_H BIT(0)
39#define TPO_R04_NFLIP_V BIT(1)
40#define TPO_R04_CP_CLK_FREQ_1H BIT(2)
41#define TPO_R04_VGL_FREQ_1H BIT(4)
42
43#define TPO_R03_VAL_NORMAL (TPO_R03_NSTANDBY | TPO_R03_EN_CP_CLK | \
44 TPO_R03_EN_VGL_PUMP | TPO_R03_EN_PWM | \
45 TPO_R03_DRIVING_CAP_100 | TPO_R03_EN_PRE_CHARGE | \
46 TPO_R03_SOFTWARE_CTL)
47
48#define TPO_R03_VAL_STANDBY (TPO_R03_DRIVING_CAP_100 | \
49 TPO_R03_EN_PRE_CHARGE | TPO_R03_SOFTWARE_CTL)
50
51static const u16 tpo_td043_def_gamma[12] = {
52 105, 315, 381, 431, 490, 537, 579, 686, 780, 837, 880, 1023
53};
54
55struct panel_drv_data {
56 struct omap_dss_device dssdev;
57 struct omap_dss_device *in;
58
59 struct omap_video_timings videomode;
60
61 int data_lines;
62
63 struct spi_device *spi;
64 struct regulator *vcc_reg;
65 int nreset_gpio;
66 u16 gamma[12];
67 u32 mode;
68 u32 hmirror:1;
69 u32 vmirror:1;
70 u32 powered_on:1;
71 u32 spi_suspended:1;
72 u32 power_on_resume:1;
73};
74
75static const struct omap_video_timings tpo_td043_timings = {
76 .x_res = 800,
77 .y_res = 480,
78
79 .pixel_clock = 36000,
80
81 .hsw = 1,
82 .hfp = 68,
83 .hbp = 214,
84
85 .vsw = 1,
86 .vfp = 39,
87 .vbp = 34,
88
89 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
90 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
91 .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
92 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
93 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
94};
95
96#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
97
98static int tpo_td043_write(struct spi_device *spi, u8 addr, u8 data)
99{
100 struct spi_message m;
101 struct spi_transfer xfer;
102 u16 w;
103 int r;
104
105 spi_message_init(&m);
106
107 memset(&xfer, 0, sizeof(xfer));
108
109 w = ((u16)addr << 10) | (1 << 8) | data;
110 xfer.tx_buf = &w;
111 xfer.bits_per_word = 16;
112 xfer.len = 2;
113 spi_message_add_tail(&xfer, &m);
114
115 r = spi_sync(spi, &m);
116 if (r < 0)
117 dev_warn(&spi->dev, "failed to write to LCD reg (%d)\n", r);
118 return r;
119}
120
121static void tpo_td043_write_gamma(struct spi_device *spi, u16 gamma[12])
122{
123 u8 i, val;
124
125 /* gamma bits [9:8] */
126 for (val = i = 0; i < 4; i++)
127 val |= (gamma[i] & 0x300) >> ((i + 1) * 2);
128 tpo_td043_write(spi, 0x11, val);
129
130 for (val = i = 0; i < 4; i++)
131 val |= (gamma[i+4] & 0x300) >> ((i + 1) * 2);
132 tpo_td043_write(spi, 0x12, val);
133
134 for (val = i = 0; i < 4; i++)
135 val |= (gamma[i+8] & 0x300) >> ((i + 1) * 2);
136 tpo_td043_write(spi, 0x13, val);
137
138 /* gamma bits [7:0] */
139 for (val = i = 0; i < 12; i++)
140 tpo_td043_write(spi, 0x14 + i, gamma[i] & 0xff);
141}
142
143static int tpo_td043_write_mirror(struct spi_device *spi, bool h, bool v)
144{
145 u8 reg4 = TPO_R04_NFLIP_H | TPO_R04_NFLIP_V |
146 TPO_R04_CP_CLK_FREQ_1H | TPO_R04_VGL_FREQ_1H;
147 if (h)
148 reg4 &= ~TPO_R04_NFLIP_H;
149 if (v)
150 reg4 &= ~TPO_R04_NFLIP_V;
151
152 return tpo_td043_write(spi, 4, reg4);
153}
154
155static int tpo_td043_set_hmirror(struct omap_dss_device *dssdev, bool enable)
156{
157 struct panel_drv_data *ddata = dev_get_drvdata(dssdev->dev);
158
159 ddata->hmirror = enable;
160 return tpo_td043_write_mirror(ddata->spi, ddata->hmirror,
161 ddata->vmirror);
162}
163
164static bool tpo_td043_get_hmirror(struct omap_dss_device *dssdev)
165{
166 struct panel_drv_data *ddata = dev_get_drvdata(dssdev->dev);
167
168 return ddata->hmirror;
169}
170
171static ssize_t tpo_td043_vmirror_show(struct device *dev,
172 struct device_attribute *attr, char *buf)
173{
174 struct panel_drv_data *ddata = dev_get_drvdata(dev);
175
176 return snprintf(buf, PAGE_SIZE, "%d\n", ddata->vmirror);
177}
178
179static ssize_t tpo_td043_vmirror_store(struct device *dev,
180 struct device_attribute *attr, const char *buf, size_t count)
181{
182 struct panel_drv_data *ddata = dev_get_drvdata(dev);
183 int val;
184 int ret;
185
186 ret = kstrtoint(buf, 0, &val);
187 if (ret < 0)
188 return ret;
189
190 val = !!val;
191
192 ret = tpo_td043_write_mirror(ddata->spi, ddata->hmirror, val);
193 if (ret < 0)
194 return ret;
195
196 ddata->vmirror = val;
197
198 return count;
199}
200
201static ssize_t tpo_td043_mode_show(struct device *dev,
202 struct device_attribute *attr, char *buf)
203{
204 struct panel_drv_data *ddata = dev_get_drvdata(dev);
205
206 return snprintf(buf, PAGE_SIZE, "%d\n", ddata->mode);
207}
208
209static ssize_t tpo_td043_mode_store(struct device *dev,
210 struct device_attribute *attr, const char *buf, size_t count)
211{
212 struct panel_drv_data *ddata = dev_get_drvdata(dev);
213 long val;
214 int ret;
215
216 ret = kstrtol(buf, 0, &val);
217 if (ret != 0 || val & ~7)
218 return -EINVAL;
219
220 ddata->mode = val;
221
222 val |= TPO_R02_NCLK_RISING;
223 tpo_td043_write(ddata->spi, 2, val);
224
225 return count;
226}
227
228static ssize_t tpo_td043_gamma_show(struct device *dev,
229 struct device_attribute *attr, char *buf)
230{
231 struct panel_drv_data *ddata = dev_get_drvdata(dev);
232 ssize_t len = 0;
233 int ret;
234 int i;
235
236 for (i = 0; i < ARRAY_SIZE(ddata->gamma); i++) {
237 ret = snprintf(buf + len, PAGE_SIZE - len, "%u ",
238 ddata->gamma[i]);
239 if (ret < 0)
240 return ret;
241 len += ret;
242 }
243 buf[len - 1] = '\n';
244
245 return len;
246}
247
248static ssize_t tpo_td043_gamma_store(struct device *dev,
249 struct device_attribute *attr, const char *buf, size_t count)
250{
251 struct panel_drv_data *ddata = dev_get_drvdata(dev);
252 unsigned int g[12];
253 int ret;
254 int i;
255
256 ret = sscanf(buf, "%u %u %u %u %u %u %u %u %u %u %u %u",
257 &g[0], &g[1], &g[2], &g[3], &g[4], &g[5],
258 &g[6], &g[7], &g[8], &g[9], &g[10], &g[11]);
259
260 if (ret != 12)
261 return -EINVAL;
262
263 for (i = 0; i < 12; i++)
264 ddata->gamma[i] = g[i];
265
266 tpo_td043_write_gamma(ddata->spi, ddata->gamma);
267
268 return count;
269}
270
271static DEVICE_ATTR(vmirror, S_IRUGO | S_IWUSR,
272 tpo_td043_vmirror_show, tpo_td043_vmirror_store);
273static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
274 tpo_td043_mode_show, tpo_td043_mode_store);
275static DEVICE_ATTR(gamma, S_IRUGO | S_IWUSR,
276 tpo_td043_gamma_show, tpo_td043_gamma_store);
277
278static struct attribute *tpo_td043_attrs[] = {
279 &dev_attr_vmirror.attr,
280 &dev_attr_mode.attr,
281 &dev_attr_gamma.attr,
282 NULL,
283};
284
285static struct attribute_group tpo_td043_attr_group = {
286 .attrs = tpo_td043_attrs,
287};
288
289static int tpo_td043_power_on(struct panel_drv_data *ddata)
290{
291 int r;
292
293 if (ddata->powered_on)
294 return 0;
295
296 r = regulator_enable(ddata->vcc_reg);
297 if (r != 0)
298 return r;
299
300 /* wait for panel to stabilize */
301 msleep(160);
302
303 if (gpio_is_valid(ddata->nreset_gpio))
304 gpio_set_value(ddata->nreset_gpio, 1);
305
306 tpo_td043_write(ddata->spi, 2,
307 TPO_R02_MODE(ddata->mode) | TPO_R02_NCLK_RISING);
308 tpo_td043_write(ddata->spi, 3, TPO_R03_VAL_NORMAL);
309 tpo_td043_write(ddata->spi, 0x20, 0xf0);
310 tpo_td043_write(ddata->spi, 0x21, 0xf0);
311 tpo_td043_write_mirror(ddata->spi, ddata->hmirror,
312 ddata->vmirror);
313 tpo_td043_write_gamma(ddata->spi, ddata->gamma);
314
315 ddata->powered_on = 1;
316 return 0;
317}
318
319static void tpo_td043_power_off(struct panel_drv_data *ddata)
320{
321 if (!ddata->powered_on)
322 return;
323
324 tpo_td043_write(ddata->spi, 3,
325 TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM);
326
327 if (gpio_is_valid(ddata->nreset_gpio))
328 gpio_set_value(ddata->nreset_gpio, 0);
329
330 /* wait for at least 2 vsyncs before cutting off power */
331 msleep(50);
332
333 tpo_td043_write(ddata->spi, 3, TPO_R03_VAL_STANDBY);
334
335 regulator_disable(ddata->vcc_reg);
336
337 ddata->powered_on = 0;
338}
339
340static int tpo_td043_connect(struct omap_dss_device *dssdev)
341{
342 struct panel_drv_data *ddata = to_panel_data(dssdev);
343 struct omap_dss_device *in = ddata->in;
344 int r;
345
346 if (omapdss_device_is_connected(dssdev))
347 return 0;
348
349 r = in->ops.dpi->connect(in, dssdev);
350 if (r)
351 return r;
352
353 return 0;
354}
355
356static void tpo_td043_disconnect(struct omap_dss_device *dssdev)
357{
358 struct panel_drv_data *ddata = to_panel_data(dssdev);
359 struct omap_dss_device *in = ddata->in;
360
361 if (!omapdss_device_is_connected(dssdev))
362 return;
363
364 in->ops.dpi->disconnect(in, dssdev);
365}
366
367static int tpo_td043_enable(struct omap_dss_device *dssdev)
368{
369 struct panel_drv_data *ddata = to_panel_data(dssdev);
370 struct omap_dss_device *in = ddata->in;
371 int r;
372
373 if (!omapdss_device_is_connected(dssdev))
374 return -ENODEV;
375
376 if (omapdss_device_is_enabled(dssdev))
377 return 0;
378
379 in->ops.dpi->set_data_lines(in, ddata->data_lines);
380 in->ops.dpi->set_timings(in, &ddata->videomode);
381
382 r = in->ops.dpi->enable(in);
383 if (r)
384 return r;
385
386 /*
387 * If we are resuming from system suspend, SPI clocks might not be
388 * enabled yet, so we'll program the LCD from SPI PM resume callback.
389 */
390 if (!ddata->spi_suspended) {
391 r = tpo_td043_power_on(ddata);
392 if (r) {
393 in->ops.dpi->disable(in);
394 return r;
395 }
396 }
397
398 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
399
400 return 0;
401}
402
403static void tpo_td043_disable(struct omap_dss_device *dssdev)
404{
405 struct panel_drv_data *ddata = to_panel_data(dssdev);
406 struct omap_dss_device *in = ddata->in;
407
408 if (!omapdss_device_is_enabled(dssdev))
409 return;
410
411 in->ops.dpi->disable(in);
412
413 if (!ddata->spi_suspended)
414 tpo_td043_power_off(ddata);
415
416 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
417}
418
419static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
420 struct omap_video_timings *timings)
421{
422 struct panel_drv_data *ddata = to_panel_data(dssdev);
423 struct omap_dss_device *in = ddata->in;
424
425 ddata->videomode = *timings;
426 dssdev->panel.timings = *timings;
427
428 in->ops.dpi->set_timings(in, timings);
429}
430
431static void tpo_td043_get_timings(struct omap_dss_device *dssdev,
432 struct omap_video_timings *timings)
433{
434 struct panel_drv_data *ddata = to_panel_data(dssdev);
435
436 *timings = ddata->videomode;
437}
438
439static int tpo_td043_check_timings(struct omap_dss_device *dssdev,
440 struct omap_video_timings *timings)
441{
442 struct panel_drv_data *ddata = to_panel_data(dssdev);
443 struct omap_dss_device *in = ddata->in;
444
445 return in->ops.dpi->check_timings(in, timings);
446}
447
448static struct omap_dss_driver tpo_td043_ops = {
449 .connect = tpo_td043_connect,
450 .disconnect = tpo_td043_disconnect,
451
452 .enable = tpo_td043_enable,
453 .disable = tpo_td043_disable,
454
455 .set_timings = tpo_td043_set_timings,
456 .get_timings = tpo_td043_get_timings,
457 .check_timings = tpo_td043_check_timings,
458
459 .set_mirror = tpo_td043_set_hmirror,
460 .get_mirror = tpo_td043_get_hmirror,
461
462 .get_resolution = omapdss_default_get_resolution,
463};
464
465
466static int tpo_td043_probe_pdata(struct spi_device *spi)
467{
468 const struct panel_tpo_td043mtea1_platform_data *pdata;
469 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
470 struct omap_dss_device *dssdev, *in;
471
472 pdata = dev_get_platdata(&spi->dev);
473
474 ddata->nreset_gpio = pdata->nreset_gpio;
475
476 in = omap_dss_find_output(pdata->source);
477 if (in == NULL) {
478 dev_err(&spi->dev, "failed to find video source '%s'\n",
479 pdata->source);
480 return -EPROBE_DEFER;
481 }
482 ddata->in = in;
483
484 ddata->data_lines = pdata->data_lines;
485
486 dssdev = &ddata->dssdev;
487 dssdev->name = pdata->name;
488
489 return 0;
490}
491
492static int tpo_td043_probe(struct spi_device *spi)
493{
494 struct panel_drv_data *ddata;
495 struct omap_dss_device *dssdev;
496 int r;
497
498 dev_dbg(&spi->dev, "%s\n", __func__);
499
500 spi->bits_per_word = 16;
501 spi->mode = SPI_MODE_0;
502
503 r = spi_setup(spi);
504 if (r < 0) {
505 dev_err(&spi->dev, "spi_setup failed: %d\n", r);
506 return r;
507 }
508
509 ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
510 if (ddata == NULL)
511 return -ENOMEM;
512
513 dev_set_drvdata(&spi->dev, ddata);
514
515 ddata->spi = spi;
516
517 if (dev_get_platdata(&spi->dev)) {
518 r = tpo_td043_probe_pdata(spi);
519 if (r)
520 return r;
521 } else {
522 return -ENODEV;
523 }
524
525 ddata->mode = TPO_R02_MODE_800x480;
526 memcpy(ddata->gamma, tpo_td043_def_gamma, sizeof(ddata->gamma));
527
528 ddata->vcc_reg = devm_regulator_get(&spi->dev, "vcc");
529 if (IS_ERR(ddata->vcc_reg)) {
530 dev_err(&spi->dev, "failed to get LCD VCC regulator\n");
531 r = PTR_ERR(ddata->vcc_reg);
532 goto err_regulator;
533 }
534
535 if (gpio_is_valid(ddata->nreset_gpio)) {
536 r = devm_gpio_request_one(&spi->dev,
537 ddata->nreset_gpio, GPIOF_OUT_INIT_LOW,
538 "lcd reset");
539 if (r < 0) {
540 dev_err(&spi->dev, "couldn't request reset GPIO\n");
541 goto err_gpio_req;
542 }
543 }
544
545 r = sysfs_create_group(&spi->dev.kobj, &tpo_td043_attr_group);
546 if (r) {
547 dev_err(&spi->dev, "failed to create sysfs files\n");
548 goto err_sysfs;
549 }
550
551 ddata->videomode = tpo_td043_timings;
552
553 dssdev = &ddata->dssdev;
554 dssdev->dev = &spi->dev;
555 dssdev->driver = &tpo_td043_ops;
556 dssdev->type = OMAP_DISPLAY_TYPE_DPI;
557 dssdev->owner = THIS_MODULE;
558 dssdev->panel.timings = ddata->videomode;
559
560 r = omapdss_register_display(dssdev);
561 if (r) {
562 dev_err(&spi->dev, "Failed to register panel\n");
563 goto err_reg;
564 }
565
566 return 0;
567
568err_reg:
569 sysfs_remove_group(&spi->dev.kobj, &tpo_td043_attr_group);
570err_sysfs:
571err_gpio_req:
572err_regulator:
573 omap_dss_put_device(ddata->in);
574 return r;
575}
576
577static int tpo_td043_remove(struct spi_device *spi)
578{
579 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
580 struct omap_dss_device *dssdev = &ddata->dssdev;
581 struct omap_dss_device *in = ddata->in;
582
583 dev_dbg(&ddata->spi->dev, "%s\n", __func__);
584
585 omapdss_unregister_display(dssdev);
586
587 tpo_td043_disable(dssdev);
588 tpo_td043_disconnect(dssdev);
589
590 omap_dss_put_device(in);
591
592 sysfs_remove_group(&spi->dev.kobj, &tpo_td043_attr_group);
593
594 return 0;
595}
596
597#ifdef CONFIG_PM_SLEEP
598static int tpo_td043_spi_suspend(struct device *dev)
599{
600 struct panel_drv_data *ddata = dev_get_drvdata(dev);
601
602 dev_dbg(dev, "tpo_td043_spi_suspend, tpo %p\n", ddata);
603
604 ddata->power_on_resume = ddata->powered_on;
605 tpo_td043_power_off(ddata);
606 ddata->spi_suspended = 1;
607
608 return 0;
609}
610
611static int tpo_td043_spi_resume(struct device *dev)
612{
613 struct panel_drv_data *ddata = dev_get_drvdata(dev);
614 int ret;
615
616 dev_dbg(dev, "tpo_td043_spi_resume\n");
617
618 if (ddata->power_on_resume) {
619 ret = tpo_td043_power_on(ddata);
620 if (ret)
621 return ret;
622 }
623 ddata->spi_suspended = 0;
624
625 return 0;
626}
627#endif
628
629static SIMPLE_DEV_PM_OPS(tpo_td043_spi_pm,
630 tpo_td043_spi_suspend, tpo_td043_spi_resume);
631
632static struct spi_driver tpo_td043_spi_driver = {
633 .driver = {
634 .name = "panel-tpo-td043mtea1",
635 .owner = THIS_MODULE,
636 .pm = &tpo_td043_spi_pm,
637 },
638 .probe = tpo_td043_probe,
639 .remove = tpo_td043_remove,
640};
641
642module_spi_driver(tpo_td043_spi_driver);
643
644MODULE_AUTHOR("Gražvydas Ignotas <notasas@gmail.com>");
645MODULE_DESCRIPTION("TPO TD043MTEA1 LCD Driver");
646MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index c3853c92279b..e80ac1c79561 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -1,4 +1,4 @@
1menu "OMAP2/3 Display Device Drivers" 1menu "OMAP2/3 Display Device Drivers (old device model)"
2 depends on OMAP2_DSS 2 depends on OMAP2_DSS
3 3
4config PANEL_GENERIC_DPI 4config PANEL_GENERIC_DPI
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 752b98592908..d6212d63cfb2 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -422,7 +422,19 @@ static void wait_pending_extra_info_updates(void)
422 422
423static struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr) 423static struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
424{ 424{
425 return mgr->output ? mgr->output->device : NULL; 425 struct omap_dss_device *dssdev;
426
427 dssdev = mgr->output;
428 if (dssdev == NULL)
429 return NULL;
430
431 while (dssdev->device)
432 dssdev = dssdev->device;
433
434 if (dssdev->driver)
435 return dssdev;
436 else
437 return NULL;
426} 438}
427 439
428static struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl) 440static struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index 0daf3e37d597..fafe7c941a60 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -61,6 +61,7 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
61 case OMAP_DISPLAY_TYPE_VENC: 61 case OMAP_DISPLAY_TYPE_VENC:
62 case OMAP_DISPLAY_TYPE_SDI: 62 case OMAP_DISPLAY_TYPE_SDI:
63 case OMAP_DISPLAY_TYPE_HDMI: 63 case OMAP_DISPLAY_TYPE_HDMI:
64 case OMAP_DISPLAY_TYPE_DVI:
64 return 24; 65 return 24;
65 default: 66 default:
66 BUG(); 67 BUG();
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 892a2b207ee4..6433eab6bcf2 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -461,6 +461,16 @@ void omapdss_dpi_set_timings(struct omap_dss_device *dssdev,
461} 461}
462EXPORT_SYMBOL(omapdss_dpi_set_timings); 462EXPORT_SYMBOL(omapdss_dpi_set_timings);
463 463
464static void dpi_get_timings(struct omap_dss_device *dssdev,
465 struct omap_video_timings *timings)
466{
467 mutex_lock(&dpi.lock);
468
469 *timings = dpi.timings;
470
471 mutex_unlock(&dpi.lock);
472}
473
464int dpi_check_timings(struct omap_dss_device *dssdev, 474int dpi_check_timings(struct omap_dss_device *dssdev,
465 struct omap_video_timings *timings) 475 struct omap_video_timings *timings)
466{ 476{
@@ -678,6 +688,65 @@ static int dpi_probe_pdata(struct platform_device *dpidev)
678 return 0; 688 return 0;
679} 689}
680 690
691static int dpi_connect(struct omap_dss_device *dssdev,
692 struct omap_dss_device *dst)
693{
694 struct omap_overlay_manager *mgr;
695 int r;
696
697 r = dpi_init_regulator();
698 if (r)
699 return r;
700
701 dpi_init_pll();
702
703 mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
704 if (!mgr)
705 return -ENODEV;
706
707 r = dss_mgr_connect(mgr, dssdev);
708 if (r)
709 return r;
710
711 r = omapdss_output_set_device(dssdev, dst);
712 if (r) {
713 DSSERR("failed to connect output to new device: %s\n",
714 dst->name);
715 dss_mgr_disconnect(mgr, dssdev);
716 return r;
717 }
718
719 return 0;
720}
721
722static void dpi_disconnect(struct omap_dss_device *dssdev,
723 struct omap_dss_device *dst)
724{
725 WARN_ON(dst != dssdev->device);
726
727 if (dst != dssdev->device)
728 return;
729
730 omapdss_output_unset_device(dssdev);
731
732 if (dssdev->manager)
733 dss_mgr_disconnect(dssdev->manager, dssdev);
734}
735
736static const struct omapdss_dpi_ops dpi_ops = {
737 .connect = dpi_connect,
738 .disconnect = dpi_disconnect,
739
740 .enable = omapdss_dpi_display_enable,
741 .disable = omapdss_dpi_display_disable,
742
743 .check_timings = dpi_check_timings,
744 .set_timings = omapdss_dpi_set_timings,
745 .get_timings = dpi_get_timings,
746
747 .set_data_lines = omapdss_dpi_set_data_lines,
748};
749
681static void dpi_init_output(struct platform_device *pdev) 750static void dpi_init_output(struct platform_device *pdev)
682{ 751{
683 struct omap_dss_device *out = &dpi.output; 752 struct omap_dss_device *out = &dpi.output;
@@ -687,16 +756,17 @@ static void dpi_init_output(struct platform_device *pdev)
687 out->output_type = OMAP_DISPLAY_TYPE_DPI; 756 out->output_type = OMAP_DISPLAY_TYPE_DPI;
688 out->name = "dpi.0"; 757 out->name = "dpi.0";
689 out->dispc_channel = dpi_get_channel(); 758 out->dispc_channel = dpi_get_channel();
759 out->ops.dpi = &dpi_ops;
690 out->owner = THIS_MODULE; 760 out->owner = THIS_MODULE;
691 761
692 dss_register_output(out); 762 omapdss_register_output(out);
693} 763}
694 764
695static void __exit dpi_uninit_output(struct platform_device *pdev) 765static void __exit dpi_uninit_output(struct platform_device *pdev)
696{ 766{
697 struct omap_dss_device *out = &dpi.output; 767 struct omap_dss_device *out = &dpi.output;
698 768
699 dss_unregister_output(out); 769 omapdss_unregister_output(out);
700} 770}
701 771
702static int omap_dpi_probe(struct platform_device *pdev) 772static int omap_dpi_probe(struct platform_device *pdev)
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index d6b019faed23..99a043b08f0d 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -383,6 +383,15 @@ static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dside
383 383
384static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev) 384static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev)
385{ 385{
386 /* HACK: dssdev can be either the panel device, when using old API, or
387 * the dsi device itself, when using the new API. So we solve this for
388 * now by checking the dssdev->id. This will be removed when the old API
389 * is removed.
390 */
391 if (dssdev->id == OMAP_DSS_OUTPUT_DSI1 ||
392 dssdev->id == OMAP_DSS_OUTPUT_DSI2)
393 return to_platform_device(dssdev->dev);
394
386 return to_platform_device(dssdev->output->dev); 395 return to_platform_device(dssdev->output->dev);
387} 396}
388 397
@@ -5412,6 +5421,89 @@ static int dsi_probe_pdata(struct platform_device *dsidev)
5412 return 0; 5421 return 0;
5413} 5422}
5414 5423
5424static int dsi_connect(struct omap_dss_device *dssdev,
5425 struct omap_dss_device *dst)
5426{
5427 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
5428 struct omap_overlay_manager *mgr;
5429 int r;
5430
5431 r = dsi_regulator_init(dsidev);
5432 if (r)
5433 return r;
5434
5435 mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
5436 if (!mgr)
5437 return -ENODEV;
5438
5439 r = dss_mgr_connect(mgr, dssdev);
5440 if (r)
5441 return r;
5442
5443 r = omapdss_output_set_device(dssdev, dst);
5444 if (r) {
5445 DSSERR("failed to connect output to new device: %s\n",
5446 dssdev->name);
5447 dss_mgr_disconnect(mgr, dssdev);
5448 return r;
5449 }
5450
5451 return 0;
5452}
5453
5454static void dsi_disconnect(struct omap_dss_device *dssdev,
5455 struct omap_dss_device *dst)
5456{
5457 WARN_ON(dst != dssdev->device);
5458
5459 if (dst != dssdev->device)
5460 return;
5461
5462 omapdss_output_unset_device(dssdev);
5463
5464 if (dssdev->manager)
5465 dss_mgr_disconnect(dssdev->manager, dssdev);
5466}
5467
5468static const struct omapdss_dsi_ops dsi_ops = {
5469 .connect = dsi_connect,
5470 .disconnect = dsi_disconnect,
5471
5472 .bus_lock = dsi_bus_lock,
5473 .bus_unlock = dsi_bus_unlock,
5474
5475 .enable = omapdss_dsi_display_enable,
5476 .disable = omapdss_dsi_display_disable,
5477
5478 .enable_hs = omapdss_dsi_vc_enable_hs,
5479
5480 .configure_pins = omapdss_dsi_configure_pins,
5481 .set_config = omapdss_dsi_set_config,
5482
5483 .enable_video_output = dsi_enable_video_output,
5484 .disable_video_output = dsi_disable_video_output,
5485
5486 .update = omap_dsi_update,
5487
5488 .enable_te = omapdss_dsi_enable_te,
5489
5490 .request_vc = omap_dsi_request_vc,
5491 .set_vc_id = omap_dsi_set_vc_id,
5492 .release_vc = omap_dsi_release_vc,
5493
5494 .dcs_write = dsi_vc_dcs_write,
5495 .dcs_write_nosync = dsi_vc_dcs_write_nosync,
5496 .dcs_read = dsi_vc_dcs_read,
5497
5498 .gen_write = dsi_vc_generic_write,
5499 .gen_write_nosync = dsi_vc_generic_write_nosync,
5500 .gen_read = dsi_vc_generic_read,
5501
5502 .bta_sync = dsi_vc_send_bta_sync,
5503
5504 .set_max_rx_packet_size = dsi_vc_set_max_rx_packet_size,
5505};
5506
5415static void dsi_init_output(struct platform_device *dsidev) 5507static void dsi_init_output(struct platform_device *dsidev)
5416{ 5508{
5417 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 5509 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -5424,9 +5516,10 @@ static void dsi_init_output(struct platform_device *dsidev)
5424 out->output_type = OMAP_DISPLAY_TYPE_DSI; 5516 out->output_type = OMAP_DISPLAY_TYPE_DSI;
5425 out->name = dsi->module_id == 0 ? "dsi.0" : "dsi.1"; 5517 out->name = dsi->module_id == 0 ? "dsi.0" : "dsi.1";
5426 out->dispc_channel = dsi_get_channel(dsi->module_id); 5518 out->dispc_channel = dsi_get_channel(dsi->module_id);
5519 out->ops.dsi = &dsi_ops;
5427 out->owner = THIS_MODULE; 5520 out->owner = THIS_MODULE;
5428 5521
5429 dss_register_output(out); 5522 omapdss_register_output(out);
5430} 5523}
5431 5524
5432static void dsi_uninit_output(struct platform_device *dsidev) 5525static void dsi_uninit_output(struct platform_device *dsidev)
@@ -5434,7 +5527,7 @@ static void dsi_uninit_output(struct platform_device *dsidev)
5434 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 5527 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5435 struct omap_dss_device *out = &dsi->output; 5528 struct omap_dss_device *out = &dsi->output;
5436 5529
5437 dss_unregister_output(out); 5530 omapdss_unregister_output(out);
5438} 5531}
5439 5532
5440/* DSI1 HW IP initialisation */ 5533/* DSI1 HW IP initialisation */
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index ed70fa01d192..50a2362ef8f8 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -179,10 +179,6 @@ void dss_put_device(struct omap_dss_device *dssdev);
179void dss_copy_device_pdata(struct omap_dss_device *dst, 179void dss_copy_device_pdata(struct omap_dss_device *dst,
180 const struct omap_dss_device *src); 180 const struct omap_dss_device *src);
181 181
182/* output */
183void dss_register_output(struct omap_dss_device *out);
184void dss_unregister_output(struct omap_dss_device *out);
185
186/* display */ 182/* display */
187int dss_suspend_all_devices(void); 183int dss_suspend_all_devices(void);
188int dss_resume_all_devices(void); 184int dss_resume_all_devices(void);
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index e1c0992b522b..44a885b92825 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -70,6 +70,8 @@ static struct {
70 int ls_oe_gpio; 70 int ls_oe_gpio;
71 int hpd_gpio; 71 int hpd_gpio;
72 72
73 bool core_enabled;
74
73 struct omap_dss_device output; 75 struct omap_dss_device output;
74} hdmi; 76} hdmi;
75 77
@@ -515,8 +517,10 @@ static int hdmi_power_on_core(struct omap_dss_device *dssdev)
515{ 517{
516 int r; 518 int r;
517 519
518 gpio_set_value(hdmi.ct_cp_hpd_gpio, 1); 520 if (gpio_is_valid(hdmi.ct_cp_hpd_gpio))
519 gpio_set_value(hdmi.ls_oe_gpio, 1); 521 gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
522 if (gpio_is_valid(hdmi.ls_oe_gpio))
523 gpio_set_value(hdmi.ls_oe_gpio, 1);
520 524
521 /* wait 300us after CT_CP_HPD for the 5V power output to reach 90% */ 525 /* wait 300us after CT_CP_HPD for the 5V power output to reach 90% */
522 udelay(300); 526 udelay(300);
@@ -532,22 +536,30 @@ static int hdmi_power_on_core(struct omap_dss_device *dssdev)
532 /* Make selection of HDMI in DSS */ 536 /* Make selection of HDMI in DSS */
533 dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); 537 dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
534 538
539 hdmi.core_enabled = true;
540
535 return 0; 541 return 0;
536 542
537err_runtime_get: 543err_runtime_get:
538 regulator_disable(hdmi.vdda_hdmi_dac_reg); 544 regulator_disable(hdmi.vdda_hdmi_dac_reg);
539err_vdac_enable: 545err_vdac_enable:
540 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0); 546 if (gpio_is_valid(hdmi.ct_cp_hpd_gpio))
541 gpio_set_value(hdmi.ls_oe_gpio, 0); 547 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
548 if (gpio_is_valid(hdmi.ls_oe_gpio))
549 gpio_set_value(hdmi.ls_oe_gpio, 0);
542 return r; 550 return r;
543} 551}
544 552
545static void hdmi_power_off_core(struct omap_dss_device *dssdev) 553static void hdmi_power_off_core(struct omap_dss_device *dssdev)
546{ 554{
555 hdmi.core_enabled = false;
556
547 hdmi_runtime_put(); 557 hdmi_runtime_put();
548 regulator_disable(hdmi.vdda_hdmi_dac_reg); 558 regulator_disable(hdmi.vdda_hdmi_dac_reg);
549 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0); 559 if (gpio_is_valid(hdmi.ct_cp_hpd_gpio))
550 gpio_set_value(hdmi.ls_oe_gpio, 0); 560 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
561 if (gpio_is_valid(hdmi.ls_oe_gpio))
562 gpio_set_value(hdmi.ls_oe_gpio, 0);
551} 563}
552 564
553static int hdmi_power_on_full(struct omap_dss_device *dssdev) 565static int hdmi_power_on_full(struct omap_dss_device *dssdev)
@@ -662,6 +674,18 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
662 mutex_unlock(&hdmi.lock); 674 mutex_unlock(&hdmi.lock);
663} 675}
664 676
677static void omapdss_hdmi_display_get_timings(struct omap_dss_device *dssdev,
678 struct omap_video_timings *timings)
679{
680 const struct hdmi_config *cfg;
681
682 cfg = hdmi_get_timings();
683 if (cfg == NULL)
684 cfg = &vesa_timings[0];
685
686 memcpy(timings, &cfg->timings, sizeof(cfg->timings));
687}
688
665static void hdmi_dump_regs(struct seq_file *s) 689static void hdmi_dump_regs(struct seq_file *s)
666{ 690{
667 mutex_lock(&hdmi.lock); 691 mutex_lock(&hdmi.lock);
@@ -1025,6 +1049,199 @@ static int hdmi_probe_pdata(struct platform_device *pdev)
1025 return 0; 1049 return 0;
1026} 1050}
1027 1051
1052static int hdmi_connect(struct omap_dss_device *dssdev,
1053 struct omap_dss_device *dst)
1054{
1055 struct omap_overlay_manager *mgr;
1056 int r;
1057
1058 dss_init_hdmi_ip_ops(&hdmi.ip_data, omapdss_get_version());
1059
1060 r = hdmi_init_regulator();
1061 if (r)
1062 return r;
1063
1064 mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
1065 if (!mgr)
1066 return -ENODEV;
1067
1068 r = dss_mgr_connect(mgr, dssdev);
1069 if (r)
1070 return r;
1071
1072 r = omapdss_output_set_device(dssdev, dst);
1073 if (r) {
1074 DSSERR("failed to connect output to new device: %s\n",
1075 dst->name);
1076 dss_mgr_disconnect(mgr, dssdev);
1077 return r;
1078 }
1079
1080 return 0;
1081}
1082
1083static void hdmi_disconnect(struct omap_dss_device *dssdev,
1084 struct omap_dss_device *dst)
1085{
1086 WARN_ON(dst != dssdev->device);
1087
1088 if (dst != dssdev->device)
1089 return;
1090
1091 omapdss_output_unset_device(dssdev);
1092
1093 if (dssdev->manager)
1094 dss_mgr_disconnect(dssdev->manager, dssdev);
1095}
1096
1097static int hdmi_read_edid(struct omap_dss_device *dssdev,
1098 u8 *edid, int len)
1099{
1100 bool need_enable;
1101 int r;
1102
1103 need_enable = hdmi.core_enabled == false;
1104
1105 if (need_enable) {
1106 r = omapdss_hdmi_core_enable(dssdev);
1107 if (r)
1108 return r;
1109 }
1110
1111 r = omapdss_hdmi_read_edid(edid, len);
1112
1113 if (need_enable)
1114 omapdss_hdmi_core_disable(dssdev);
1115
1116 return r;
1117}
1118
1119#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
1120static int omapdss_hdmi_audio_enable(struct omap_dss_device *dssdev)
1121{
1122 int r;
1123
1124 mutex_lock(&hdmi.lock);
1125
1126 if (!hdmi_mode_has_audio()) {
1127 r = -EPERM;
1128 goto err;
1129 }
1130
1131 r = hdmi_audio_enable();
1132 if (r)
1133 goto err;
1134
1135 mutex_unlock(&hdmi.lock);
1136 return 0;
1137
1138err:
1139 mutex_unlock(&hdmi.lock);
1140 return r;
1141}
1142
1143static void omapdss_hdmi_audio_disable(struct omap_dss_device *dssdev)
1144{
1145 hdmi_audio_disable();
1146}
1147
1148static int omapdss_hdmi_audio_start(struct omap_dss_device *dssdev)
1149{
1150 return hdmi_audio_start();
1151}
1152
1153static void omapdss_hdmi_audio_stop(struct omap_dss_device *dssdev)
1154{
1155 hdmi_audio_stop();
1156}
1157
1158static bool omapdss_hdmi_audio_supported(struct omap_dss_device *dssdev)
1159{
1160 bool r;
1161
1162 mutex_lock(&hdmi.lock);
1163
1164 r = hdmi_mode_has_audio();
1165
1166 mutex_unlock(&hdmi.lock);
1167 return r;
1168}
1169
1170static int omapdss_hdmi_audio_config(struct omap_dss_device *dssdev,
1171 struct omap_dss_audio *audio)
1172{
1173 int r;
1174
1175 mutex_lock(&hdmi.lock);
1176
1177 if (!hdmi_mode_has_audio()) {
1178 r = -EPERM;
1179 goto err;
1180 }
1181
1182 r = hdmi_audio_config(audio);
1183 if (r)
1184 goto err;
1185
1186 mutex_unlock(&hdmi.lock);
1187 return 0;
1188
1189err:
1190 mutex_unlock(&hdmi.lock);
1191 return r;
1192}
1193#else
1194static int omapdss_hdmi_audio_enable(struct omap_dss_device *dssdev)
1195{
1196 return -EPERM;
1197}
1198
1199static void omapdss_hdmi_audio_disable(struct omap_dss_device *dssdev)
1200{
1201}
1202
1203static int omapdss_hdmi_audio_start(struct omap_dss_device *dssdev)
1204{
1205 return -EPERM;
1206}
1207
1208static void omapdss_hdmi_audio_stop(struct omap_dss_device *dssdev)
1209{
1210}
1211
1212static bool omapdss_hdmi_audio_supported(struct omap_dss_device *dssdev)
1213{
1214 return false;
1215}
1216
1217static int omapdss_hdmi_audio_config(struct omap_dss_device *dssdev,
1218 struct omap_dss_audio *audio)
1219{
1220 return -EPERM;
1221}
1222#endif
1223
1224static const struct omapdss_hdmi_ops hdmi_ops = {
1225 .connect = hdmi_connect,
1226 .disconnect = hdmi_disconnect,
1227
1228 .enable = omapdss_hdmi_display_enable,
1229 .disable = omapdss_hdmi_display_disable,
1230
1231 .check_timings = omapdss_hdmi_display_check_timing,
1232 .set_timings = omapdss_hdmi_display_set_timing,
1233 .get_timings = omapdss_hdmi_display_get_timings,
1234
1235 .read_edid = hdmi_read_edid,
1236
1237 .audio_enable = omapdss_hdmi_audio_enable,
1238 .audio_disable = omapdss_hdmi_audio_disable,
1239 .audio_start = omapdss_hdmi_audio_start,
1240 .audio_stop = omapdss_hdmi_audio_stop,
1241 .audio_supported = omapdss_hdmi_audio_supported,
1242 .audio_config = omapdss_hdmi_audio_config,
1243};
1244
1028static void hdmi_init_output(struct platform_device *pdev) 1245static void hdmi_init_output(struct platform_device *pdev)
1029{ 1246{
1030 struct omap_dss_device *out = &hdmi.output; 1247 struct omap_dss_device *out = &hdmi.output;
@@ -1034,16 +1251,17 @@ static void hdmi_init_output(struct platform_device *pdev)
1034 out->output_type = OMAP_DISPLAY_TYPE_HDMI; 1251 out->output_type = OMAP_DISPLAY_TYPE_HDMI;
1035 out->name = "hdmi.0"; 1252 out->name = "hdmi.0";
1036 out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT; 1253 out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
1254 out->ops.hdmi = &hdmi_ops;
1037 out->owner = THIS_MODULE; 1255 out->owner = THIS_MODULE;
1038 1256
1039 dss_register_output(out); 1257 omapdss_register_output(out);
1040} 1258}
1041 1259
1042static void __exit hdmi_uninit_output(struct platform_device *pdev) 1260static void __exit hdmi_uninit_output(struct platform_device *pdev)
1043{ 1261{
1044 struct omap_dss_device *out = &hdmi.output; 1262 struct omap_dss_device *out = &hdmi.output;
1045 1263
1046 dss_unregister_output(out); 1264 omapdss_unregister_output(out);
1047} 1265}
1048 1266
1049/* HDMI HW IP initialisation */ 1267/* HDMI HW IP initialisation */
@@ -1083,6 +1301,10 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
1083 hdmi.ip_data.pll_offset = HDMI_PLLCTRL; 1301 hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
1084 hdmi.ip_data.phy_offset = HDMI_PHY; 1302 hdmi.ip_data.phy_offset = HDMI_PHY;
1085 1303
1304 hdmi.ct_cp_hpd_gpio = -1;
1305 hdmi.ls_oe_gpio = -1;
1306 hdmi.hpd_gpio = -1;
1307
1086 hdmi_init_output(pdev); 1308 hdmi_init_output(pdev);
1087 1309
1088 r = hdmi_panel_init(); 1310 r = hdmi_panel_init();
diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c
index 9ad7d2175a7b..3f5c0a758b32 100644
--- a/drivers/video/omap2/dss/output.c
+++ b/drivers/video/omap2/dss/output.c
@@ -92,15 +92,18 @@ err:
92} 92}
93EXPORT_SYMBOL(omapdss_output_unset_device); 93EXPORT_SYMBOL(omapdss_output_unset_device);
94 94
95void dss_register_output(struct omap_dss_device *out) 95int omapdss_register_output(struct omap_dss_device *out)
96{ 96{
97 list_add_tail(&out->list, &output_list); 97 list_add_tail(&out->list, &output_list);
98 return 0;
98} 99}
100EXPORT_SYMBOL(omapdss_register_output);
99 101
100void dss_unregister_output(struct omap_dss_device *out) 102void omapdss_unregister_output(struct omap_dss_device *out)
101{ 103{
102 list_del(&out->list); 104 list_del(&out->list);
103} 105}
106EXPORT_SYMBOL(omapdss_unregister_output);
104 107
105struct omap_dss_device *omap_dss_get_output(enum omap_dss_output_id id) 108struct omap_dss_device *omap_dss_get_output(enum omap_dss_output_id id)
106{ 109{
@@ -143,7 +146,13 @@ EXPORT_SYMBOL(omap_dss_find_output_by_node);
143 146
144struct omap_dss_device *omapdss_find_output_from_display(struct omap_dss_device *dssdev) 147struct omap_dss_device *omapdss_find_output_from_display(struct omap_dss_device *dssdev)
145{ 148{
146 return omap_dss_get_device(dssdev->output); 149 while (dssdev->output)
150 dssdev = dssdev->output;
151
152 if (dssdev->id != 0)
153 return omap_dss_get_device(dssdev);
154
155 return NULL;
147} 156}
148EXPORT_SYMBOL(omapdss_find_output_from_display); 157EXPORT_SYMBOL(omapdss_find_output_from_display);
149 158
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index f18c9466849b..fdfe6e6f25df 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -1022,14 +1022,14 @@ static void rfbi_init_output(struct platform_device *pdev)
1022 out->dispc_channel = OMAP_DSS_CHANNEL_LCD; 1022 out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
1023 out->owner = THIS_MODULE; 1023 out->owner = THIS_MODULE;
1024 1024
1025 dss_register_output(out); 1025 omapdss_register_output(out);
1026} 1026}
1027 1027
1028static void __exit rfbi_uninit_output(struct platform_device *pdev) 1028static void __exit rfbi_uninit_output(struct platform_device *pdev)
1029{ 1029{
1030 struct omap_dss_device *out = &rfbi.output; 1030 struct omap_dss_device *out = &rfbi.output;
1031 1031
1032 dss_unregister_output(out); 1032 omapdss_unregister_output(out);
1033} 1033}
1034 1034
1035/* RFBI HW IP initialisation */ 1035/* RFBI HW IP initialisation */
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index bcb75f5d5373..856af2e89760 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -234,6 +234,26 @@ void omapdss_sdi_set_timings(struct omap_dss_device *dssdev,
234} 234}
235EXPORT_SYMBOL(omapdss_sdi_set_timings); 235EXPORT_SYMBOL(omapdss_sdi_set_timings);
236 236
237static void sdi_get_timings(struct omap_dss_device *dssdev,
238 struct omap_video_timings *timings)
239{
240 *timings = sdi.timings;
241}
242
243static int sdi_check_timings(struct omap_dss_device *dssdev,
244 struct omap_video_timings *timings)
245{
246 struct omap_overlay_manager *mgr = sdi.output.manager;
247
248 if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
249 return -EINVAL;
250
251 if (timings->pixel_clock == 0)
252 return -EINVAL;
253
254 return 0;
255}
256
237void omapdss_sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs) 257void omapdss_sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs)
238{ 258{
239 sdi.datapairs = datapairs; 259 sdi.datapairs = datapairs;
@@ -333,6 +353,63 @@ static int sdi_probe_pdata(struct platform_device *sdidev)
333 return 0; 353 return 0;
334} 354}
335 355
356static int sdi_connect(struct omap_dss_device *dssdev,
357 struct omap_dss_device *dst)
358{
359 struct omap_overlay_manager *mgr;
360 int r;
361
362 r = sdi_init_regulator();
363 if (r)
364 return r;
365
366 mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
367 if (!mgr)
368 return -ENODEV;
369
370 r = dss_mgr_connect(mgr, dssdev);
371 if (r)
372 return r;
373
374 r = omapdss_output_set_device(dssdev, dst);
375 if (r) {
376 DSSERR("failed to connect output to new device: %s\n",
377 dst->name);
378 dss_mgr_disconnect(mgr, dssdev);
379 return r;
380 }
381
382 return 0;
383}
384
385static void sdi_disconnect(struct omap_dss_device *dssdev,
386 struct omap_dss_device *dst)
387{
388 WARN_ON(dst != dssdev->device);
389
390 if (dst != dssdev->device)
391 return;
392
393 omapdss_output_unset_device(dssdev);
394
395 if (dssdev->manager)
396 dss_mgr_disconnect(dssdev->manager, dssdev);
397}
398
399static const struct omapdss_sdi_ops sdi_ops = {
400 .connect = sdi_connect,
401 .disconnect = sdi_disconnect,
402
403 .enable = omapdss_sdi_display_enable,
404 .disable = omapdss_sdi_display_disable,
405
406 .check_timings = sdi_check_timings,
407 .set_timings = omapdss_sdi_set_timings,
408 .get_timings = sdi_get_timings,
409
410 .set_datapairs = omapdss_sdi_set_datapairs,
411};
412
336static void sdi_init_output(struct platform_device *pdev) 413static void sdi_init_output(struct platform_device *pdev)
337{ 414{
338 struct omap_dss_device *out = &sdi.output; 415 struct omap_dss_device *out = &sdi.output;
@@ -342,16 +419,17 @@ static void sdi_init_output(struct platform_device *pdev)
342 out->output_type = OMAP_DISPLAY_TYPE_SDI; 419 out->output_type = OMAP_DISPLAY_TYPE_SDI;
343 out->name = "sdi.0"; 420 out->name = "sdi.0";
344 out->dispc_channel = OMAP_DSS_CHANNEL_LCD; 421 out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
422 out->ops.sdi = &sdi_ops;
345 out->owner = THIS_MODULE; 423 out->owner = THIS_MODULE;
346 424
347 dss_register_output(out); 425 omapdss_register_output(out);
348} 426}
349 427
350static void __exit sdi_uninit_output(struct platform_device *pdev) 428static void __exit sdi_uninit_output(struct platform_device *pdev)
351{ 429{
352 struct omap_dss_device *out = &sdi.output; 430 struct omap_dss_device *out = &sdi.output;
353 431
354 dss_unregister_output(out); 432 omapdss_unregister_output(out);
355} 433}
356 434
357static int omap_sdi_probe(struct platform_device *pdev) 435static int omap_sdi_probe(struct platform_device *pdev)
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 8720f137d4f8..496a106fe823 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -564,6 +564,16 @@ int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
564 return -EINVAL; 564 return -EINVAL;
565} 565}
566 566
567static void venc_get_timings(struct omap_dss_device *dssdev,
568 struct omap_video_timings *timings)
569{
570 mutex_lock(&venc.venc_lock);
571
572 *timings = venc.timings;
573
574 mutex_unlock(&venc.venc_lock);
575}
576
567u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev) 577u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev)
568{ 578{
569 /* Invert due to VENC_L21_WC_CTL:INV=1 */ 579 /* Invert due to VENC_L21_WC_CTL:INV=1 */
@@ -779,6 +789,67 @@ static int venc_probe_pdata(struct platform_device *vencdev)
779 return 0; 789 return 0;
780} 790}
781 791
792static int venc_connect(struct omap_dss_device *dssdev,
793 struct omap_dss_device *dst)
794{
795 struct omap_overlay_manager *mgr;
796 int r;
797
798 r = venc_init_regulator();
799 if (r)
800 return r;
801
802 mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
803 if (!mgr)
804 return -ENODEV;
805
806 r = dss_mgr_connect(mgr, dssdev);
807 if (r)
808 return r;
809
810 r = omapdss_output_set_device(dssdev, dst);
811 if (r) {
812 DSSERR("failed to connect output to new device: %s\n",
813 dst->name);
814 dss_mgr_disconnect(mgr, dssdev);
815 return r;
816 }
817
818 return 0;
819}
820
821static void venc_disconnect(struct omap_dss_device *dssdev,
822 struct omap_dss_device *dst)
823{
824 WARN_ON(dst != dssdev->device);
825
826 if (dst != dssdev->device)
827 return;
828
829 omapdss_output_unset_device(dssdev);
830
831 if (dssdev->manager)
832 dss_mgr_disconnect(dssdev->manager, dssdev);
833}
834
835static const struct omapdss_atv_ops venc_ops = {
836 .connect = venc_connect,
837 .disconnect = venc_disconnect,
838
839 .enable = omapdss_venc_display_enable,
840 .disable = omapdss_venc_display_disable,
841
842 .check_timings = omapdss_venc_check_timings,
843 .set_timings = omapdss_venc_set_timings,
844 .get_timings = venc_get_timings,
845
846 .set_type = omapdss_venc_set_type,
847 .invert_vid_out_polarity = omapdss_venc_invert_vid_out_polarity,
848
849 .set_wss = omapdss_venc_set_wss,
850 .get_wss = omapdss_venc_get_wss,
851};
852
782static void venc_init_output(struct platform_device *pdev) 853static void venc_init_output(struct platform_device *pdev)
783{ 854{
784 struct omap_dss_device *out = &venc.output; 855 struct omap_dss_device *out = &venc.output;
@@ -788,16 +859,17 @@ static void venc_init_output(struct platform_device *pdev)
788 out->output_type = OMAP_DISPLAY_TYPE_VENC; 859 out->output_type = OMAP_DISPLAY_TYPE_VENC;
789 out->name = "venc.0"; 860 out->name = "venc.0";
790 out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT; 861 out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
862 out->ops.atv = &venc_ops;
791 out->owner = THIS_MODULE; 863 out->owner = THIS_MODULE;
792 864
793 dss_register_output(out); 865 omapdss_register_output(out);
794} 866}
795 867
796static void __exit venc_uninit_output(struct platform_device *pdev) 868static void __exit venc_uninit_output(struct platform_device *pdev)
797{ 869{
798 struct omap_dss_device *out = &venc.output; 870 struct omap_dss_device *out = &venc.output;
799 871
800 dss_unregister_output(out); 872 omapdss_unregister_output(out);
801} 873}
802 874
803/* VENC HW IP initialisation */ 875/* VENC HW IP initialisation */
diff --git a/include/video/omap-panel-data.h b/include/video/omap-panel-data.h
index 0c3b46d3daf3..6b2366fb6e53 100644
--- a/include/video/omap-panel-data.h
+++ b/include/video/omap-panel-data.h
@@ -27,6 +27,9 @@
27#ifndef __OMAP_PANEL_DATA_H 27#ifndef __OMAP_PANEL_DATA_H
28#define __OMAP_PANEL_DATA_H 28#define __OMAP_PANEL_DATA_H
29 29
30#include <video/omapdss.h>
31#include <video/display_timing.h>
32
30struct omap_dss_device; 33struct omap_dss_device;
31 34
32/** 35/**
@@ -147,4 +150,210 @@ struct panel_tpo_td043_data {
147 int nreset_gpio; 150 int nreset_gpio;
148}; 151};
149 152
153/**
154 * encoder_tfp410 platform data
155 * @name: name for this display entity
156 * @power_down_gpio: gpio number for PD pin (or -1 if not available)
157 * @data_lines: number of DPI datalines
158 */
159struct encoder_tfp410_platform_data {
160 const char *name;
161 const char *source;
162 int power_down_gpio;
163 int data_lines;
164};
165
166/**
167 * encoder_tpd12s015 platform data
168 * @name: name for this display entity
169 * @ct_cp_hpd_gpio: CT_CP_HPD gpio number
170 * @ls_oe_gpio: LS_OE gpio number
171 * @hpd_gpio: HPD gpio number
172 */
173struct encoder_tpd12s015_platform_data {
174 const char *name;
175 const char *source;
176
177 int ct_cp_hpd_gpio;
178 int ls_oe_gpio;
179 int hpd_gpio;
180};
181
182/**
183 * connector_dvi platform data
184 * @name: name for this display entity
185 * @source: name of the display entity used as a video source
186 * @i2c_bus_num: i2c bus number to be used for reading EDID
187 */
188struct connector_dvi_platform_data {
189 const char *name;
190 const char *source;
191 int i2c_bus_num;
192};
193
194/**
195 * connector_hdmi platform data
196 * @name: name for this display entity
197 * @source: name of the display entity used as a video source
198 */
199struct connector_hdmi_platform_data {
200 const char *name;
201 const char *source;
202};
203
204/**
205 * connector_atv platform data
206 * @name: name for this display entity
207 * @source: name of the display entity used as a video source
208 * @connector_type: composite/svideo
209 * @invert_polarity: invert signal polarity
210 */
211struct connector_atv_platform_data {
212 const char *name;
213 const char *source;
214
215 enum omap_dss_venc_type connector_type;
216 bool invert_polarity;
217};
218
219/**
220 * panel_dpi platform data
221 * @name: name for this display entity
222 * @source: name of the display entity used as a video source
223 * @data_lines: number of DPI datalines
224 * @display_timing: timings for this panel
225 * @backlight_gpio: gpio to enable/disable the backlight (or -1)
226 * @enable_gpio: gpio to enable/disable the panel (or -1)
227 */
228struct panel_dpi_platform_data {
229 const char *name;
230 const char *source;
231
232 int data_lines;
233
234 const struct display_timing *display_timing;
235
236 int backlight_gpio;
237 int enable_gpio;
238};
239
240/**
241 * panel_dsicm platform data
242 * @name: name for this display entity
243 * @source: name of the display entity used as a video source
244 * @reset_gpio: gpio to reset the panel (or -1)
245 * @use_ext_te: use external TE GPIO
246 * @ext_te_gpio: external TE GPIO
247 * @ulps_timeout: time to wait before entering ULPS, 0 = disabled (ms)
248 * @use_dsi_backlight: true if panel uses DSI command to control backlight
249 * @pin_config: DSI pin configuration
250 */
251struct panel_dsicm_platform_data {
252 const char *name;
253 const char *source;
254
255 int reset_gpio;
256
257 bool use_ext_te;
258 int ext_te_gpio;
259
260 unsigned ulps_timeout;
261
262 bool use_dsi_backlight;
263
264 struct omap_dsi_pin_config pin_config;
265};
266
267/**
268 * panel_acx565akm platform data
269 * @name: name for this display entity
270 * @source: name of the display entity used as a video source
271 * @reset_gpio: gpio to reset the panel (or -1)
272 * @datapairs: number of SDI datapairs
273 */
274struct panel_acx565akm_platform_data {
275 const char *name;
276 const char *source;
277
278 int reset_gpio;
279
280 int datapairs;
281};
282
283/**
284 * panel_lb035q02 platform data
285 * @name: name for this display entity
286 * @source: name of the display entity used as a video source
287 * @data_lines: number of DPI datalines
288 * @backlight_gpio: gpio to enable/disable the backlight (or -1)
289 * @enable_gpio: gpio to enable/disable the panel (or -1)
290 */
291struct panel_lb035q02_platform_data {
292 const char *name;
293 const char *source;
294
295 int data_lines;
296
297 int backlight_gpio;
298 int enable_gpio;
299};
300
301/**
302 * panel_sharp_ls037v7dw01 platform data
303 * @name: name for this display entity
304 * @source: name of the display entity used as a video source
305 * @data_lines: number of DPI datalines
306 * @resb_gpio: reset signal GPIO
307 * @ini_gpio: power on control GPIO
308 * @mo_gpio: selection for resolution(VGA/QVGA) GPIO
309 * @lr_gpio: selection for horizontal scanning direction GPIO
310 * @ud_gpio: selection for vertical scanning direction GPIO
311 */
312struct panel_sharp_ls037v7dw01_platform_data {
313 const char *name;
314 const char *source;
315
316 int data_lines;
317
318 int resb_gpio;
319 int ini_gpio;
320 int mo_gpio;
321 int lr_gpio;
322 int ud_gpio;
323};
324
325/**
326 * panel-tpo-td043mtea1 platform data
327 * @name: name for this display entity
328 * @source: name of the display entity used as a video source
329 * @data_lines: number of DPI datalines
330 * @nreset_gpio: reset signal
331 */
332struct panel_tpo_td043mtea1_platform_data {
333 const char *name;
334 const char *source;
335
336 int data_lines;
337
338 int nreset_gpio;
339};
340
341/**
342 * panel-nec-nl8048hl11 platform data
343 * @name: name for this display entity
344 * @source: name of the display entity used as a video source
345 * @data_lines: number of DPI datalines
346 * @res_gpio: reset signal
347 * @qvga_gpio: selection for resolution(QVGA/WVGA)
348 */
349struct panel_nec_nl8048hl11_platform_data {
350 const char *name;
351 const char *source;
352
353 int data_lines;
354
355 int res_gpio;
356 int qvga_gpio;
357};
358
150#endif /* __OMAP_PANEL_DATA_H */ 359#endif /* __OMAP_PANEL_DATA_H */
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index ef9db241b4a1..b39463553845 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -70,6 +70,7 @@ enum omap_display_type {
70 OMAP_DISPLAY_TYPE_DSI = 1 << 3, 70 OMAP_DISPLAY_TYPE_DSI = 1 << 3,
71 OMAP_DISPLAY_TYPE_VENC = 1 << 4, 71 OMAP_DISPLAY_TYPE_VENC = 1 << 4,
72 OMAP_DISPLAY_TYPE_HDMI = 1 << 5, 72 OMAP_DISPLAY_TYPE_HDMI = 1 << 5,
73 OMAP_DISPLAY_TYPE_DVI = 1 << 6,
73}; 74};
74 75
75enum omap_plane { 76enum omap_plane {
@@ -171,6 +172,11 @@ enum omap_dss_audio_state {
171 OMAP_DSS_AUDIO_PLAYING, 172 OMAP_DSS_AUDIO_PLAYING,
172}; 173};
173 174
175struct omap_dss_audio {
176 struct snd_aes_iec958 *iec;
177 struct snd_cea_861_aud_if *cea;
178};
179
174enum omap_dss_rotation_type { 180enum omap_dss_rotation_type {
175 OMAP_DSS_ROT_DMA = 1 << 0, 181 OMAP_DSS_ROT_DMA = 1 << 0,
176 OMAP_DSS_ROT_VRFB = 1 << 1, 182 OMAP_DSS_ROT_VRFB = 1 << 1,
@@ -572,6 +578,176 @@ struct omap_dss_writeback_info {
572 u8 pre_mult_alpha; 578 u8 pre_mult_alpha;
573}; 579};
574 580
581struct omapdss_dpi_ops {
582 int (*connect)(struct omap_dss_device *dssdev,
583 struct omap_dss_device *dst);
584 void (*disconnect)(struct omap_dss_device *dssdev,
585 struct omap_dss_device *dst);
586
587 int (*enable)(struct omap_dss_device *dssdev);
588 void (*disable)(struct omap_dss_device *dssdev);
589
590 int (*check_timings)(struct omap_dss_device *dssdev,
591 struct omap_video_timings *timings);
592 void (*set_timings)(struct omap_dss_device *dssdev,
593 struct omap_video_timings *timings);
594 void (*get_timings)(struct omap_dss_device *dssdev,
595 struct omap_video_timings *timings);
596
597 void (*set_data_lines)(struct omap_dss_device *dssdev, int data_lines);
598};
599
600struct omapdss_sdi_ops {
601 int (*connect)(struct omap_dss_device *dssdev,
602 struct omap_dss_device *dst);
603 void (*disconnect)(struct omap_dss_device *dssdev,
604 struct omap_dss_device *dst);
605
606 int (*enable)(struct omap_dss_device *dssdev);
607 void (*disable)(struct omap_dss_device *dssdev);
608
609 int (*check_timings)(struct omap_dss_device *dssdev,
610 struct omap_video_timings *timings);
611 void (*set_timings)(struct omap_dss_device *dssdev,
612 struct omap_video_timings *timings);
613 void (*get_timings)(struct omap_dss_device *dssdev,
614 struct omap_video_timings *timings);
615
616 void (*set_datapairs)(struct omap_dss_device *dssdev, int datapairs);
617};
618
619struct omapdss_dvi_ops {
620 int (*connect)(struct omap_dss_device *dssdev,
621 struct omap_dss_device *dst);
622 void (*disconnect)(struct omap_dss_device *dssdev,
623 struct omap_dss_device *dst);
624
625 int (*enable)(struct omap_dss_device *dssdev);
626 void (*disable)(struct omap_dss_device *dssdev);
627
628 int (*check_timings)(struct omap_dss_device *dssdev,
629 struct omap_video_timings *timings);
630 void (*set_timings)(struct omap_dss_device *dssdev,
631 struct omap_video_timings *timings);
632 void (*get_timings)(struct omap_dss_device *dssdev,
633 struct omap_video_timings *timings);
634};
635
636struct omapdss_atv_ops {
637 int (*connect)(struct omap_dss_device *dssdev,
638 struct omap_dss_device *dst);
639 void (*disconnect)(struct omap_dss_device *dssdev,
640 struct omap_dss_device *dst);
641
642 int (*enable)(struct omap_dss_device *dssdev);
643 void (*disable)(struct omap_dss_device *dssdev);
644
645 int (*check_timings)(struct omap_dss_device *dssdev,
646 struct omap_video_timings *timings);
647 void (*set_timings)(struct omap_dss_device *dssdev,
648 struct omap_video_timings *timings);
649 void (*get_timings)(struct omap_dss_device *dssdev,
650 struct omap_video_timings *timings);
651
652 void (*set_type)(struct omap_dss_device *dssdev,
653 enum omap_dss_venc_type type);
654 void (*invert_vid_out_polarity)(struct omap_dss_device *dssdev,
655 bool invert_polarity);
656
657 int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
658 u32 (*get_wss)(struct omap_dss_device *dssdev);
659};
660
661struct omapdss_hdmi_ops {
662 int (*connect)(struct omap_dss_device *dssdev,
663 struct omap_dss_device *dst);
664 void (*disconnect)(struct omap_dss_device *dssdev,
665 struct omap_dss_device *dst);
666
667 int (*enable)(struct omap_dss_device *dssdev);
668 void (*disable)(struct omap_dss_device *dssdev);
669
670 int (*check_timings)(struct omap_dss_device *dssdev,
671 struct omap_video_timings *timings);
672 void (*set_timings)(struct omap_dss_device *dssdev,
673 struct omap_video_timings *timings);
674 void (*get_timings)(struct omap_dss_device *dssdev,
675 struct omap_video_timings *timings);
676
677 int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
678 bool (*detect)(struct omap_dss_device *dssdev);
679
680 /*
681 * Note: These functions might sleep. Do not call while
682 * holding a spinlock/readlock.
683 */
684 int (*audio_enable)(struct omap_dss_device *dssdev);
685 void (*audio_disable)(struct omap_dss_device *dssdev);
686 bool (*audio_supported)(struct omap_dss_device *dssdev);
687 int (*audio_config)(struct omap_dss_device *dssdev,
688 struct omap_dss_audio *audio);
689 /* Note: These functions may not sleep */
690 int (*audio_start)(struct omap_dss_device *dssdev);
691 void (*audio_stop)(struct omap_dss_device *dssdev);
692};
693
694struct omapdss_dsi_ops {
695 int (*connect)(struct omap_dss_device *dssdev,
696 struct omap_dss_device *dst);
697 void (*disconnect)(struct omap_dss_device *dssdev,
698 struct omap_dss_device *dst);
699
700 int (*enable)(struct omap_dss_device *dssdev);
701 void (*disable)(struct omap_dss_device *dssdev, bool disconnect_lanes,
702 bool enter_ulps);
703
704 /* bus configuration */
705 int (*set_config)(struct omap_dss_device *dssdev,
706 const struct omap_dss_dsi_config *cfg);
707 int (*configure_pins)(struct omap_dss_device *dssdev,
708 const struct omap_dsi_pin_config *pin_cfg);
709
710 void (*enable_hs)(struct omap_dss_device *dssdev, int channel,
711 bool enable);
712 int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
713
714 int (*update)(struct omap_dss_device *dssdev, int channel,
715 void (*callback)(int, void *), void *data);
716
717 void (*bus_lock)(struct omap_dss_device *dssdev);
718 void (*bus_unlock)(struct omap_dss_device *dssdev);
719
720 int (*enable_video_output)(struct omap_dss_device *dssdev, int channel);
721 void (*disable_video_output)(struct omap_dss_device *dssdev,
722 int channel);
723
724 int (*request_vc)(struct omap_dss_device *dssdev, int *channel);
725 int (*set_vc_id)(struct omap_dss_device *dssdev, int channel,
726 int vc_id);
727 void (*release_vc)(struct omap_dss_device *dssdev, int channel);
728
729 /* data transfer */
730 int (*dcs_write)(struct omap_dss_device *dssdev, int channel,
731 u8 *data, int len);
732 int (*dcs_write_nosync)(struct omap_dss_device *dssdev, int channel,
733 u8 *data, int len);
734 int (*dcs_read)(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
735 u8 *data, int len);
736
737 int (*gen_write)(struct omap_dss_device *dssdev, int channel,
738 u8 *data, int len);
739 int (*gen_write_nosync)(struct omap_dss_device *dssdev, int channel,
740 u8 *data, int len);
741 int (*gen_read)(struct omap_dss_device *dssdev, int channel,
742 u8 *reqdata, int reqlen,
743 u8 *data, int len);
744
745 int (*bta_sync)(struct omap_dss_device *dssdev, int channel);
746
747 int (*set_max_rx_packet_size)(struct omap_dss_device *dssdev,
748 int channel, u16 plen);
749};
750
575struct omap_dss_device { 751struct omap_dss_device {
576 /* old device, to be removed */ 752 /* old device, to be removed */
577 struct device old_dev; 753 struct device old_dev;
@@ -637,6 +813,15 @@ struct omap_dss_device {
637 813
638 struct omap_dss_driver *driver; 814 struct omap_dss_driver *driver;
639 815
816 union {
817 const struct omapdss_dpi_ops *dpi;
818 const struct omapdss_sdi_ops *sdi;
819 const struct omapdss_dvi_ops *dvi;
820 const struct omapdss_hdmi_ops *hdmi;
821 const struct omapdss_atv_ops *atv;
822 const struct omapdss_dsi_ops *dsi;
823 } ops;
824
640 /* helper variable for driver suspend/resume */ 825 /* helper variable for driver suspend/resume */
641 bool activate_after_resume; 826 bool activate_after_resume;
642 827
@@ -671,11 +856,6 @@ struct omap_dss_hdmi_data
671 int hpd_gpio; 856 int hpd_gpio;
672}; 857};
673 858
674struct omap_dss_audio {
675 struct snd_aes_iec958 *iec;
676 struct snd_cea_861_aud_if *cea;
677};
678
679struct omap_dss_driver { 859struct omap_dss_driver {
680 struct device_driver driver; 860 struct device_driver driver;
681 861
@@ -780,6 +960,8 @@ struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
780int omap_dss_get_num_overlays(void); 960int omap_dss_get_num_overlays(void);
781struct omap_overlay *omap_dss_get_overlay(int num); 961struct omap_overlay *omap_dss_get_overlay(int num);
782 962
963int omapdss_register_output(struct omap_dss_device *output);
964void omapdss_unregister_output(struct omap_dss_device *output);
783struct omap_dss_device *omap_dss_get_output(enum omap_dss_output_id id); 965struct omap_dss_device *omap_dss_get_output(enum omap_dss_output_id id);
784struct omap_dss_device *omap_dss_find_output(const char *name); 966struct omap_dss_device *omap_dss_find_output(const char *name);
785struct omap_dss_device *omap_dss_find_output_by_node(struct device_node *node); 967struct omap_dss_device *omap_dss_find_output_by_node(struct device_node *node);