aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorJean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>2013-06-28 06:01:14 -0400
committerJean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>2013-06-28 06:01:14 -0400
commitb75bf98b5d2b7fdb876d3dd7eaec8246d4cc7174 (patch)
tree47e77ad068f9e91c4730d5144c0ad4aa51f1b05d /drivers/video
parent8e9804557ca1188f3a9d9129180f46c2c73ba942 (diff)
parentc545b59515cca4ccaf920e12582a43836cddaa2b (diff)
Merge tag 'omapdss-for-3.11-2' of git://gitorious.org/linux-omap-dss2/linux into fbdev/for-next
OMAP display subsystem changes for 3.11 (part 2/2) This is the second part of OMAP DSS changes for 3.11. This part contains the new DSS device model support. The current OMAP panel drivers use a custom DSS bus, and there's a hard limit of one external display block per video pipeline. In the new DSS device model the devices/drivers are made according to the control bus of the display block, usually platform, i2c or spi. The display blocks can also be chained so that we can have separate drivers for setups with both external encoder and panel. To allow the current board files, which use the old style panels, to function, the old display drivers are left in their current state, and new ones are added to drivers/video/omap2/displays-new/. When the board files have been converted to use the new style panels, we can remove the old code. This is planned to happen in v3.12. Having to support two very different DSS device models makes the driver somewhat confusing in some parts, and prevents us from properly cleaning up some other parts. These cleanups will be done when the old code is removed. The new device model is designed with CDF (Common Display Framework) in mind. While CDF is still under work, the new DSS device model should be much more similar to CDF's model than the old device model, which should make the eventual conversion to CDF much easier.
Diffstat (limited to 'drivers/video')
-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
27 files changed, 6513 insertions, 27 deletions
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 */