aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/omap2')
-rw-r--r--drivers/video/omap2/Kconfig10
-rw-r--r--drivers/video/omap2/Makefile5
-rw-r--r--drivers/video/omap2/displays-new/Kconfig80
-rw-r--r--drivers/video/omap2/displays-new/Makefile13
-rw-r--r--drivers/video/omap2/displays-new/connector-analog-tv.c318
-rw-r--r--drivers/video/omap2/displays-new/connector-dvi.c401
-rw-r--r--drivers/video/omap2/displays-new/connector-hdmi.c405
-rw-r--r--drivers/video/omap2/displays-new/encoder-tfp410.c308
-rw-r--r--drivers/video/omap2/displays-new/encoder-tpd12s015.c451
-rw-r--r--drivers/video/omap2/displays-new/panel-dpi.c270
-rw-r--r--drivers/video/omap2/displays-new/panel-dsi-cm.c1388
-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.c911
-rw-r--r--drivers/video/omap2/displays-new/panel-tpo-td028ttec1.c480
-rw-r--r--drivers/video/omap2/displays-new/panel-tpo-td043mtea1.c646
-rw-r--r--drivers/video/omap2/dss/Kconfig121
-rw-r--r--drivers/video/omap2/dss/Makefile15
-rw-r--r--drivers/video/omap2/dss/apply.c1700
-rw-r--r--drivers/video/omap2/dss/core.c360
-rw-r--r--drivers/video/omap2/dss/dispc-compat.c666
-rw-r--r--drivers/video/omap2/dss/dispc-compat.h30
-rw-r--r--drivers/video/omap2/dss/dispc.c3853
-rw-r--r--drivers/video/omap2/dss/dispc.h917
-rw-r--r--drivers/video/omap2/dss/dispc_coefs.c325
-rw-r--r--drivers/video/omap2/dss/display-sysfs.c345
-rw-r--r--drivers/video/omap2/dss/display.c338
-rw-r--r--drivers/video/omap2/dss/dpi.c774
-rw-r--r--drivers/video/omap2/dss/dsi.c5751
-rw-r--r--drivers/video/omap2/dss/dss-of.c159
-rw-r--r--drivers/video/omap2/dss/dss.c972
-rw-r--r--drivers/video/omap2/dss/dss.h438
-rw-r--r--drivers/video/omap2/dss/dss_features.c935
-rw-r--r--drivers/video/omap2/dss/dss_features.h117
-rw-r--r--drivers/video/omap2/dss/hdmi.h444
-rw-r--r--drivers/video/omap2/dss/hdmi4.c703
-rw-r--r--drivers/video/omap2/dss/hdmi4_core.c1036
-rw-r--r--drivers/video/omap2/dss/hdmi4_core.h276
-rw-r--r--drivers/video/omap2/dss/hdmi_common.c425
-rw-r--r--drivers/video/omap2/dss/hdmi_phy.c160
-rw-r--r--drivers/video/omap2/dss/hdmi_pll.c232
-rw-r--r--drivers/video/omap2/dss/hdmi_wp.c275
-rw-r--r--drivers/video/omap2/dss/manager-sysfs.c529
-rw-r--r--drivers/video/omap2/dss/manager.c263
-rw-r--r--drivers/video/omap2/dss/output.c254
-rw-r--r--drivers/video/omap2/dss/overlay-sysfs.c456
-rw-r--r--drivers/video/omap2/dss/overlay.c202
-rw-r--r--drivers/video/omap2/dss/rfbi.c1058
-rw-r--r--drivers/video/omap2/dss/sdi.c433
-rw-r--r--drivers/video/omap2/dss/venc.c980
-rw-r--r--drivers/video/omap2/dss/venc_panel.c232
-rw-r--r--drivers/video/omap2/omapfb/Kconfig27
-rw-r--r--drivers/video/omap2/omapfb/Makefile2
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c922
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c2656
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c605
-rw-r--r--drivers/video/omap2/omapfb/omapfb.h208
-rw-r--r--drivers/video/omap2/vrfb.c399
59 files changed, 0 insertions, 37355 deletions
diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
deleted file mode 100644
index 63b23f87081d..000000000000
--- a/drivers/video/omap2/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
1config OMAP2_VRFB
2 bool
3
4if ARCH_OMAP2PLUS
5
6source "drivers/video/omap2/dss/Kconfig"
7source "drivers/video/omap2/omapfb/Kconfig"
8source "drivers/video/omap2/displays-new/Kconfig"
9
10endif
diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
deleted file mode 100644
index bf8127df8c71..000000000000
--- a/drivers/video/omap2/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
1obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
2
3obj-$(CONFIG_OMAP2_DSS) += dss/
4obj-y += displays-new/
5obj-$(CONFIG_FB_OMAP2) += omapfb/
diff --git a/drivers/video/omap2/displays-new/Kconfig b/drivers/video/omap2/displays-new/Kconfig
deleted file mode 100644
index e6cfc38160d3..000000000000
--- a/drivers/video/omap2/displays-new/Kconfig
+++ /dev/null
@@ -1,80 +0,0 @@
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 depends on BACKLIGHT_CLASS_DEVICE
39 help
40 Driver for generic DSI command mode panels.
41
42config DISPLAY_PANEL_SONY_ACX565AKM
43 tristate "ACX565AKM Panel"
44 depends on SPI && BACKLIGHT_CLASS_DEVICE
45 help
46 This is the LCD panel used on Nokia N900
47
48config DISPLAY_PANEL_LGPHILIPS_LB035Q02
49 tristate "LG.Philips LB035Q02 LCD Panel"
50 depends on SPI
51 help
52 LCD Panel used on the Gumstix Overo Palo35
53
54config DISPLAY_PANEL_SHARP_LS037V7DW01
55 tristate "Sharp LS037V7DW01 LCD Panel"
56 depends on BACKLIGHT_CLASS_DEVICE
57 help
58 LCD Panel used in TI's SDP3430 and EVM boards
59
60config DISPLAY_PANEL_TPO_TD028TTEC1
61 tristate "TPO TD028TTEC1 LCD Panel"
62 depends on SPI
63 help
64 LCD panel used in Openmoko.
65
66config DISPLAY_PANEL_TPO_TD043MTEA1
67 tristate "TPO TD043MTEA1 LCD Panel"
68 depends on SPI
69 help
70 LCD Panel used in OMAP3 Pandora
71
72config DISPLAY_PANEL_NEC_NL8048HL11
73 tristate "NEC NL8048HL11 Panel"
74 depends on SPI
75 depends on BACKLIGHT_CLASS_DEVICE
76 help
77 This NEC NL8048HL11 panel is TFT LCD used in the
78 Zoom2/3/3630 sdp boards.
79
80endmenu
diff --git a/drivers/video/omap2/displays-new/Makefile b/drivers/video/omap2/displays-new/Makefile
deleted file mode 100644
index 0323a8a1c682..000000000000
--- a/drivers/video/omap2/displays-new/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
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_TD028TTEC1) += panel-tpo-td028ttec1.o
12obj-$(CONFIG_DISPLAY_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
13obj-$(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
deleted file mode 100644
index 5ee3b5505f7f..000000000000
--- a/drivers/video/omap2/displays-new/connector-analog-tv.c
+++ /dev/null
@@ -1,318 +0,0 @@
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#include <linux/of.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 struct device *dev;
25
26 struct omap_video_timings timings;
27
28 enum omap_dss_venc_type connector_type;
29 bool invert_polarity;
30};
31
32static const struct omap_video_timings tvc_pal_timings = {
33 .x_res = 720,
34 .y_res = 574,
35 .pixelclock = 13500000,
36 .hsw = 64,
37 .hfp = 12,
38 .hbp = 68,
39 .vsw = 5,
40 .vfp = 5,
41 .vbp = 41,
42
43 .interlace = true,
44};
45
46static const struct of_device_id tvc_of_match[];
47
48struct tvc_of_data {
49 enum omap_dss_venc_type connector_type;
50};
51
52#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
53
54static int tvc_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 dev_dbg(ddata->dev, "connect\n");
61
62 if (omapdss_device_is_connected(dssdev))
63 return 0;
64
65 r = in->ops.atv->connect(in, dssdev);
66 if (r)
67 return r;
68
69 return 0;
70}
71
72static void tvc_disconnect(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
77 dev_dbg(ddata->dev, "disconnect\n");
78
79 if (!omapdss_device_is_connected(dssdev))
80 return;
81
82 in->ops.atv->disconnect(in, dssdev);
83}
84
85static int tvc_enable(struct omap_dss_device *dssdev)
86{
87 struct panel_drv_data *ddata = to_panel_data(dssdev);
88 struct omap_dss_device *in = ddata->in;
89 int r;
90
91 dev_dbg(ddata->dev, "enable\n");
92
93 if (!omapdss_device_is_connected(dssdev))
94 return -ENODEV;
95
96 if (omapdss_device_is_enabled(dssdev))
97 return 0;
98
99 in->ops.atv->set_timings(in, &ddata->timings);
100
101 if (!ddata->dev->of_node) {
102 in->ops.atv->set_type(in, ddata->connector_type);
103
104 in->ops.atv->invert_vid_out_polarity(in,
105 ddata->invert_polarity);
106 }
107
108 r = in->ops.atv->enable(in);
109 if (r)
110 return r;
111
112 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
113
114 return r;
115}
116
117static void tvc_disable(struct omap_dss_device *dssdev)
118{
119 struct panel_drv_data *ddata = to_panel_data(dssdev);
120 struct omap_dss_device *in = ddata->in;
121
122 dev_dbg(ddata->dev, "disable\n");
123
124 if (!omapdss_device_is_enabled(dssdev))
125 return;
126
127 in->ops.atv->disable(in);
128
129 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
130}
131
132static void tvc_set_timings(struct omap_dss_device *dssdev,
133 struct omap_video_timings *timings)
134{
135 struct panel_drv_data *ddata = to_panel_data(dssdev);
136 struct omap_dss_device *in = ddata->in;
137
138 ddata->timings = *timings;
139 dssdev->panel.timings = *timings;
140
141 in->ops.atv->set_timings(in, timings);
142}
143
144static void tvc_get_timings(struct omap_dss_device *dssdev,
145 struct omap_video_timings *timings)
146{
147 struct panel_drv_data *ddata = to_panel_data(dssdev);
148
149 *timings = ddata->timings;
150}
151
152static int tvc_check_timings(struct omap_dss_device *dssdev,
153 struct omap_video_timings *timings)
154{
155 struct panel_drv_data *ddata = to_panel_data(dssdev);
156 struct omap_dss_device *in = ddata->in;
157
158 return in->ops.atv->check_timings(in, timings);
159}
160
161static u32 tvc_get_wss(struct omap_dss_device *dssdev)
162{
163 struct panel_drv_data *ddata = to_panel_data(dssdev);
164 struct omap_dss_device *in = ddata->in;
165
166 return in->ops.atv->get_wss(in);
167}
168
169static int tvc_set_wss(struct omap_dss_device *dssdev, u32 wss)
170{
171 struct panel_drv_data *ddata = to_panel_data(dssdev);
172 struct omap_dss_device *in = ddata->in;
173
174 return in->ops.atv->set_wss(in, wss);
175}
176
177static struct omap_dss_driver tvc_driver = {
178 .connect = tvc_connect,
179 .disconnect = tvc_disconnect,
180
181 .enable = tvc_enable,
182 .disable = tvc_disable,
183
184 .set_timings = tvc_set_timings,
185 .get_timings = tvc_get_timings,
186 .check_timings = tvc_check_timings,
187
188 .get_resolution = omapdss_default_get_resolution,
189
190 .get_wss = tvc_get_wss,
191 .set_wss = tvc_set_wss,
192};
193
194static int tvc_probe_pdata(struct platform_device *pdev)
195{
196 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
197 struct connector_atv_platform_data *pdata;
198 struct omap_dss_device *in, *dssdev;
199
200 pdata = dev_get_platdata(&pdev->dev);
201
202 in = omap_dss_find_output(pdata->source);
203 if (in == NULL) {
204 dev_err(&pdev->dev, "Failed to find video source\n");
205 return -EPROBE_DEFER;
206 }
207
208 ddata->in = in;
209
210 ddata->connector_type = pdata->connector_type;
211 ddata->invert_polarity = ddata->invert_polarity;
212
213 dssdev = &ddata->dssdev;
214 dssdev->name = pdata->name;
215
216 return 0;
217}
218
219static int tvc_probe_of(struct platform_device *pdev)
220{
221 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
222 struct device_node *node = pdev->dev.of_node;
223 struct omap_dss_device *in;
224
225 in = omapdss_of_find_source_for_first_ep(node);
226 if (IS_ERR(in)) {
227 dev_err(&pdev->dev, "failed to find video source\n");
228 return PTR_ERR(in);
229 }
230
231 ddata->in = in;
232
233 return 0;
234}
235
236static int tvc_probe(struct platform_device *pdev)
237{
238 struct panel_drv_data *ddata;
239 struct omap_dss_device *dssdev;
240 int r;
241
242 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
243 if (!ddata)
244 return -ENOMEM;
245
246 platform_set_drvdata(pdev, ddata);
247 ddata->dev = &pdev->dev;
248
249 if (dev_get_platdata(&pdev->dev)) {
250 r = tvc_probe_pdata(pdev);
251 if (r)
252 return r;
253 } else if (pdev->dev.of_node) {
254 r = tvc_probe_of(pdev);
255 if (r)
256 return r;
257 } else {
258 return -ENODEV;
259 }
260
261 ddata->timings = tvc_pal_timings;
262
263 dssdev = &ddata->dssdev;
264 dssdev->driver = &tvc_driver;
265 dssdev->dev = &pdev->dev;
266 dssdev->type = OMAP_DISPLAY_TYPE_VENC;
267 dssdev->owner = THIS_MODULE;
268 dssdev->panel.timings = tvc_pal_timings;
269
270 r = omapdss_register_display(dssdev);
271 if (r) {
272 dev_err(&pdev->dev, "Failed to register panel\n");
273 goto err_reg;
274 }
275
276 return 0;
277err_reg:
278 omap_dss_put_device(ddata->in);
279 return r;
280}
281
282static int __exit tvc_remove(struct platform_device *pdev)
283{
284 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
285 struct omap_dss_device *dssdev = &ddata->dssdev;
286 struct omap_dss_device *in = ddata->in;
287
288 omapdss_unregister_display(&ddata->dssdev);
289
290 tvc_disable(dssdev);
291 tvc_disconnect(dssdev);
292
293 omap_dss_put_device(in);
294
295 return 0;
296}
297
298static const struct of_device_id tvc_of_match[] = {
299 { .compatible = "omapdss,svideo-connector", },
300 { .compatible = "omapdss,composite-video-connector", },
301 {},
302};
303
304static struct platform_driver tvc_connector_driver = {
305 .probe = tvc_probe,
306 .remove = __exit_p(tvc_remove),
307 .driver = {
308 .name = "connector-analog-tv",
309 .owner = THIS_MODULE,
310 .of_match_table = tvc_of_match,
311 },
312};
313
314module_platform_driver(tvc_connector_driver);
315
316MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
317MODULE_DESCRIPTION("Analog TV Connector driver");
318MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/connector-dvi.c b/drivers/video/omap2/displays-new/connector-dvi.c
deleted file mode 100644
index 74de2bc50c4f..000000000000
--- a/drivers/video/omap2/displays-new/connector-dvi.c
+++ /dev/null
@@ -1,401 +0,0 @@
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 .pixelclock = 23500000,
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 if (ddata->i2c_adapter)
266 i2c_put_adapter(ddata->i2c_adapter);
267
268 dev_err(&pdev->dev, "Failed to find video source\n");
269 return -EPROBE_DEFER;
270 }
271
272 ddata->in = in;
273
274 dssdev = &ddata->dssdev;
275 dssdev->name = pdata->name;
276
277 return 0;
278}
279
280static int dvic_probe_of(struct platform_device *pdev)
281{
282 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
283 struct device_node *node = pdev->dev.of_node;
284 struct omap_dss_device *in;
285 struct device_node *adapter_node;
286 struct i2c_adapter *adapter;
287
288 in = omapdss_of_find_source_for_first_ep(node);
289 if (IS_ERR(in)) {
290 dev_err(&pdev->dev, "failed to find video source\n");
291 return PTR_ERR(in);
292 }
293
294 ddata->in = in;
295
296 adapter_node = of_parse_phandle(node, "ddc-i2c-bus", 0);
297 if (adapter_node) {
298 adapter = of_find_i2c_adapter_by_node(adapter_node);
299 if (adapter == NULL) {
300 dev_err(&pdev->dev, "failed to parse ddc-i2c-bus\n");
301 omap_dss_put_device(ddata->in);
302 return -EPROBE_DEFER;
303 }
304
305 ddata->i2c_adapter = adapter;
306 }
307
308 return 0;
309}
310
311static int dvic_probe(struct platform_device *pdev)
312{
313 struct panel_drv_data *ddata;
314 struct omap_dss_device *dssdev;
315 int r;
316
317 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
318 if (!ddata)
319 return -ENOMEM;
320
321 platform_set_drvdata(pdev, ddata);
322
323 if (dev_get_platdata(&pdev->dev)) {
324 r = dvic_probe_pdata(pdev);
325 if (r)
326 return r;
327 } else if (pdev->dev.of_node) {
328 r = dvic_probe_of(pdev);
329 if (r)
330 return r;
331 } else {
332 return -ENODEV;
333 }
334
335 ddata->timings = dvic_default_timings;
336
337 dssdev = &ddata->dssdev;
338 dssdev->driver = &dvic_driver;
339 dssdev->dev = &pdev->dev;
340 dssdev->type = OMAP_DISPLAY_TYPE_DVI;
341 dssdev->owner = THIS_MODULE;
342 dssdev->panel.timings = dvic_default_timings;
343
344 r = omapdss_register_display(dssdev);
345 if (r) {
346 dev_err(&pdev->dev, "Failed to register panel\n");
347 goto err_reg;
348 }
349
350 return 0;
351
352err_reg:
353 omap_dss_put_device(ddata->in);
354
355 if (ddata->i2c_adapter)
356 i2c_put_adapter(ddata->i2c_adapter);
357
358 return r;
359}
360
361static int __exit dvic_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_display(&ddata->dssdev);
368
369 dvic_disable(dssdev);
370 dvic_disconnect(dssdev);
371
372 omap_dss_put_device(in);
373
374 if (ddata->i2c_adapter)
375 i2c_put_adapter(ddata->i2c_adapter);
376
377 return 0;
378}
379
380static const struct of_device_id dvic_of_match[] = {
381 { .compatible = "omapdss,dvi-connector", },
382 {},
383};
384
385MODULE_DEVICE_TABLE(of, dvic_of_match);
386
387static struct platform_driver dvi_connector_driver = {
388 .probe = dvic_probe,
389 .remove = __exit_p(dvic_remove),
390 .driver = {
391 .name = "connector-dvi",
392 .owner = THIS_MODULE,
393 .of_match_table = dvic_of_match,
394 },
395};
396
397module_platform_driver(dvi_connector_driver);
398
399MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
400MODULE_DESCRIPTION("Generic DVI Connector driver");
401MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/connector-hdmi.c b/drivers/video/omap2/displays-new/connector-hdmi.c
deleted file mode 100644
index 29ed21b9dce5..000000000000
--- a/drivers/video/omap2/displays-new/connector-hdmi.c
+++ /dev/null
@@ -1,405 +0,0 @@
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#include <linux/of.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 hdmic_default_timings = {
23 .x_res = 640,
24 .y_res = 480,
25 .pixelclock = 25175000,
26 .hsw = 96,
27 .hfp = 16,
28 .hbp = 48,
29 .vsw = 2,
30 .vfp = 11,
31 .vbp = 31,
32
33 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
34 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
35
36 .interlace = false,
37};
38
39struct panel_drv_data {
40 struct omap_dss_device dssdev;
41 struct omap_dss_device *in;
42
43 struct device *dev;
44
45 struct omap_video_timings timings;
46};
47
48#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
49
50static int hdmic_connect(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 int r;
55
56 dev_dbg(ddata->dev, "connect\n");
57
58 if (omapdss_device_is_connected(dssdev))
59 return 0;
60
61 r = in->ops.hdmi->connect(in, dssdev);
62 if (r)
63 return r;
64
65 return 0;
66}
67
68static void hdmic_disconnect(struct omap_dss_device *dssdev)
69{
70 struct panel_drv_data *ddata = to_panel_data(dssdev);
71 struct omap_dss_device *in = ddata->in;
72
73 dev_dbg(ddata->dev, "disconnect\n");
74
75 if (!omapdss_device_is_connected(dssdev))
76 return;
77
78 in->ops.hdmi->disconnect(in, dssdev);
79}
80
81static int hdmic_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 dev_dbg(ddata->dev, "enable\n");
88
89 if (!omapdss_device_is_connected(dssdev))
90 return -ENODEV;
91
92 if (omapdss_device_is_enabled(dssdev))
93 return 0;
94
95 in->ops.hdmi->set_timings(in, &ddata->timings);
96
97 r = in->ops.hdmi->enable(in);
98 if (r)
99 return r;
100
101 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
102
103 return r;
104}
105
106static void hdmic_disable(struct omap_dss_device *dssdev)
107{
108 struct panel_drv_data *ddata = to_panel_data(dssdev);
109 struct omap_dss_device *in = ddata->in;
110
111 dev_dbg(ddata->dev, "disable\n");
112
113 if (!omapdss_device_is_enabled(dssdev))
114 return;
115
116 in->ops.hdmi->disable(in);
117
118 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
119}
120
121static void hdmic_set_timings(struct omap_dss_device *dssdev,
122 struct omap_video_timings *timings)
123{
124 struct panel_drv_data *ddata = to_panel_data(dssdev);
125 struct omap_dss_device *in = ddata->in;
126
127 ddata->timings = *timings;
128 dssdev->panel.timings = *timings;
129
130 in->ops.hdmi->set_timings(in, timings);
131}
132
133static void hdmic_get_timings(struct omap_dss_device *dssdev,
134 struct omap_video_timings *timings)
135{
136 struct panel_drv_data *ddata = to_panel_data(dssdev);
137
138 *timings = ddata->timings;
139}
140
141static int hdmic_check_timings(struct omap_dss_device *dssdev,
142 struct omap_video_timings *timings)
143{
144 struct panel_drv_data *ddata = to_panel_data(dssdev);
145 struct omap_dss_device *in = ddata->in;
146
147 return in->ops.hdmi->check_timings(in, timings);
148}
149
150static int hdmic_read_edid(struct omap_dss_device *dssdev,
151 u8 *edid, int len)
152{
153 struct panel_drv_data *ddata = to_panel_data(dssdev);
154 struct omap_dss_device *in = ddata->in;
155
156 return in->ops.hdmi->read_edid(in, edid, len);
157}
158
159static bool hdmic_detect(struct omap_dss_device *dssdev)
160{
161 struct panel_drv_data *ddata = to_panel_data(dssdev);
162 struct omap_dss_device *in = ddata->in;
163
164 return in->ops.hdmi->detect(in);
165}
166
167static int hdmic_audio_enable(struct omap_dss_device *dssdev)
168{
169 struct panel_drv_data *ddata = to_panel_data(dssdev);
170 struct omap_dss_device *in = ddata->in;
171 int r;
172
173 /* enable audio only if the display is active */
174 if (!omapdss_device_is_enabled(dssdev))
175 return -EPERM;
176
177 r = in->ops.hdmi->audio_enable(in);
178 if (r)
179 return r;
180
181 dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
182
183 return 0;
184}
185
186static void hdmic_audio_disable(struct omap_dss_device *dssdev)
187{
188 struct panel_drv_data *ddata = to_panel_data(dssdev);
189 struct omap_dss_device *in = ddata->in;
190
191 in->ops.hdmi->audio_disable(in);
192
193 dssdev->audio_state = OMAP_DSS_AUDIO_DISABLED;
194}
195
196static int hdmic_audio_start(struct omap_dss_device *dssdev)
197{
198 struct panel_drv_data *ddata = to_panel_data(dssdev);
199 struct omap_dss_device *in = ddata->in;
200 int r;
201
202 /*
203 * No need to check the panel state. It was checked when trasitioning
204 * to AUDIO_ENABLED.
205 */
206 if (dssdev->audio_state != OMAP_DSS_AUDIO_ENABLED)
207 return -EPERM;
208
209 r = in->ops.hdmi->audio_start(in);
210 if (r)
211 return r;
212
213 dssdev->audio_state = OMAP_DSS_AUDIO_PLAYING;
214
215 return 0;
216}
217
218static void hdmic_audio_stop(struct omap_dss_device *dssdev)
219{
220 struct panel_drv_data *ddata = to_panel_data(dssdev);
221 struct omap_dss_device *in = ddata->in;
222
223 in->ops.hdmi->audio_stop(in);
224
225 dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
226}
227
228static bool hdmic_audio_supported(struct omap_dss_device *dssdev)
229{
230 struct panel_drv_data *ddata = to_panel_data(dssdev);
231 struct omap_dss_device *in = ddata->in;
232
233 if (!omapdss_device_is_enabled(dssdev))
234 return false;
235
236 return in->ops.hdmi->audio_supported(in);
237}
238
239static int hdmic_audio_config(struct omap_dss_device *dssdev,
240 struct omap_dss_audio *audio)
241{
242 struct panel_drv_data *ddata = to_panel_data(dssdev);
243 struct omap_dss_device *in = ddata->in;
244 int r;
245
246 /* config audio only if the display is active */
247 if (!omapdss_device_is_enabled(dssdev))
248 return -EPERM;
249
250 r = in->ops.hdmi->audio_config(in, audio);
251 if (r)
252 return r;
253
254 dssdev->audio_state = OMAP_DSS_AUDIO_CONFIGURED;
255
256 return 0;
257}
258
259static struct omap_dss_driver hdmic_driver = {
260 .connect = hdmic_connect,
261 .disconnect = hdmic_disconnect,
262
263 .enable = hdmic_enable,
264 .disable = hdmic_disable,
265
266 .set_timings = hdmic_set_timings,
267 .get_timings = hdmic_get_timings,
268 .check_timings = hdmic_check_timings,
269
270 .get_resolution = omapdss_default_get_resolution,
271
272 .read_edid = hdmic_read_edid,
273 .detect = hdmic_detect,
274
275 .audio_enable = hdmic_audio_enable,
276 .audio_disable = hdmic_audio_disable,
277 .audio_start = hdmic_audio_start,
278 .audio_stop = hdmic_audio_stop,
279 .audio_supported = hdmic_audio_supported,
280 .audio_config = hdmic_audio_config,
281};
282
283static int hdmic_probe_pdata(struct platform_device *pdev)
284{
285 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
286 struct connector_hdmi_platform_data *pdata;
287 struct omap_dss_device *in, *dssdev;
288
289 pdata = dev_get_platdata(&pdev->dev);
290
291 in = omap_dss_find_output(pdata->source);
292 if (in == NULL) {
293 dev_err(&pdev->dev, "Failed to find video source\n");
294 return -EPROBE_DEFER;
295 }
296
297 ddata->in = in;
298
299 dssdev = &ddata->dssdev;
300 dssdev->name = pdata->name;
301
302 return 0;
303}
304
305static int hdmic_probe_of(struct platform_device *pdev)
306{
307 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
308 struct device_node *node = pdev->dev.of_node;
309 struct omap_dss_device *in;
310
311 in = omapdss_of_find_source_for_first_ep(node);
312 if (IS_ERR(in)) {
313 dev_err(&pdev->dev, "failed to find video source\n");
314 return PTR_ERR(in);
315 }
316
317 ddata->in = in;
318
319 return 0;
320}
321
322static int hdmic_probe(struct platform_device *pdev)
323{
324 struct panel_drv_data *ddata;
325 struct omap_dss_device *dssdev;
326 int r;
327
328 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
329 if (!ddata)
330 return -ENOMEM;
331
332 platform_set_drvdata(pdev, ddata);
333 ddata->dev = &pdev->dev;
334
335 if (dev_get_platdata(&pdev->dev)) {
336 r = hdmic_probe_pdata(pdev);
337 if (r)
338 return r;
339 } else if (pdev->dev.of_node) {
340 r = hdmic_probe_of(pdev);
341 if (r)
342 return r;
343 } else {
344 return -ENODEV;
345 }
346
347 ddata->timings = hdmic_default_timings;
348
349 dssdev = &ddata->dssdev;
350 dssdev->driver = &hdmic_driver;
351 dssdev->dev = &pdev->dev;
352 dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
353 dssdev->owner = THIS_MODULE;
354 dssdev->panel.timings = hdmic_default_timings;
355
356 r = omapdss_register_display(dssdev);
357 if (r) {
358 dev_err(&pdev->dev, "Failed to register panel\n");
359 goto err_reg;
360 }
361
362 return 0;
363err_reg:
364 omap_dss_put_device(ddata->in);
365 return r;
366}
367
368static int __exit hdmic_remove(struct platform_device *pdev)
369{
370 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
371 struct omap_dss_device *dssdev = &ddata->dssdev;
372 struct omap_dss_device *in = ddata->in;
373
374 omapdss_unregister_display(&ddata->dssdev);
375
376 hdmic_disable(dssdev);
377 hdmic_disconnect(dssdev);
378
379 omap_dss_put_device(in);
380
381 return 0;
382}
383
384static const struct of_device_id hdmic_of_match[] = {
385 { .compatible = "omapdss,hdmi-connector", },
386 {},
387};
388
389MODULE_DEVICE_TABLE(of, hdmic_of_match);
390
391static struct platform_driver hdmi_connector_driver = {
392 .probe = hdmic_probe,
393 .remove = __exit_p(hdmic_remove),
394 .driver = {
395 .name = "connector-hdmi",
396 .owner = THIS_MODULE,
397 .of_match_table = hdmic_of_match,
398 },
399};
400
401module_platform_driver(hdmi_connector_driver);
402
403MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
404MODULE_DESCRIPTION("HDMI Connector driver");
405MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/encoder-tfp410.c b/drivers/video/omap2/displays-new/encoder-tfp410.c
deleted file mode 100644
index b4e9a42a79e6..000000000000
--- a/drivers/video/omap2/displays-new/encoder-tfp410.c
+++ /dev/null
@@ -1,308 +0,0 @@
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#include <linux/of_gpio.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 pd_gpio;
26 int data_lines;
27
28 struct omap_video_timings timings;
29};
30
31#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
32
33static int tfp410_connect(struct omap_dss_device *dssdev,
34 struct omap_dss_device *dst)
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 -EBUSY;
42
43 r = in->ops.dpi->connect(in, dssdev);
44 if (r)
45 return r;
46
47 dst->src = dssdev;
48 dssdev->dst = dst;
49
50 return 0;
51}
52
53static void tfp410_disconnect(struct omap_dss_device *dssdev,
54 struct omap_dss_device *dst)
55{
56 struct panel_drv_data *ddata = to_panel_data(dssdev);
57 struct omap_dss_device *in = ddata->in;
58
59 WARN_ON(!omapdss_device_is_connected(dssdev));
60 if (!omapdss_device_is_connected(dssdev))
61 return;
62
63 WARN_ON(dst != dssdev->dst);
64 if (dst != dssdev->dst)
65 return;
66
67 dst->src = NULL;
68 dssdev->dst = NULL;
69
70 in->ops.dpi->disconnect(in, &ddata->dssdev);
71}
72
73static int tfp410_enable(struct omap_dss_device *dssdev)
74{
75 struct panel_drv_data *ddata = to_panel_data(dssdev);
76 struct omap_dss_device *in = ddata->in;
77 int r;
78
79 if (!omapdss_device_is_connected(dssdev))
80 return -ENODEV;
81
82 if (omapdss_device_is_enabled(dssdev))
83 return 0;
84
85 in->ops.dpi->set_timings(in, &ddata->timings);
86 if (ddata->data_lines)
87 in->ops.dpi->set_data_lines(in, ddata->data_lines);
88
89 r = in->ops.dpi->enable(in);
90 if (r)
91 return r;
92
93 if (gpio_is_valid(ddata->pd_gpio))
94 gpio_set_value_cansleep(ddata->pd_gpio, 1);
95
96 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
97
98 return 0;
99}
100
101static void tfp410_disable(struct omap_dss_device *dssdev)
102{
103 struct panel_drv_data *ddata = to_panel_data(dssdev);
104 struct omap_dss_device *in = ddata->in;
105
106 if (!omapdss_device_is_enabled(dssdev))
107 return;
108
109 if (gpio_is_valid(ddata->pd_gpio))
110 gpio_set_value_cansleep(ddata->pd_gpio, 0);
111
112 in->ops.dpi->disable(in);
113
114 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
115}
116
117static void tfp410_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.dpi->set_timings(in, timings);
127}
128
129static void tfp410_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 tfp410_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.dpi->check_timings(in, timings);
144}
145
146static const struct omapdss_dvi_ops tfp410_dvi_ops = {
147 .connect = tfp410_connect,
148 .disconnect = tfp410_disconnect,
149
150 .enable = tfp410_enable,
151 .disable = tfp410_disable,
152
153 .check_timings = tfp410_check_timings,
154 .set_timings = tfp410_set_timings,
155 .get_timings = tfp410_get_timings,
156};
157
158static int tfp410_probe_pdata(struct platform_device *pdev)
159{
160 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
161 struct encoder_tfp410_platform_data *pdata;
162 struct omap_dss_device *dssdev, *in;
163
164 pdata = dev_get_platdata(&pdev->dev);
165
166 ddata->pd_gpio = pdata->power_down_gpio;
167
168 ddata->data_lines = pdata->data_lines;
169
170 in = omap_dss_find_output(pdata->source);
171 if (in == NULL) {
172 dev_err(&pdev->dev, "Failed to find video source\n");
173 return -ENODEV;
174 }
175
176 ddata->in = in;
177
178 dssdev = &ddata->dssdev;
179 dssdev->name = pdata->name;
180
181 return 0;
182}
183
184static int tfp410_probe_of(struct platform_device *pdev)
185{
186 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
187 struct device_node *node = pdev->dev.of_node;
188 struct omap_dss_device *in;
189 int gpio;
190
191 gpio = of_get_named_gpio(node, "powerdown-gpios", 0);
192
193 if (gpio_is_valid(gpio) || gpio == -ENOENT) {
194 ddata->pd_gpio = gpio;
195 } else {
196 dev_err(&pdev->dev, "failed to parse PD gpio\n");
197 return gpio;
198 }
199
200 in = omapdss_of_find_source_for_first_ep(node);
201 if (IS_ERR(in)) {
202 dev_err(&pdev->dev, "failed to find video source\n");
203 return PTR_ERR(in);
204 }
205
206 ddata->in = in;
207
208 return 0;
209}
210
211static int tfp410_probe(struct platform_device *pdev)
212{
213 struct panel_drv_data *ddata;
214 struct omap_dss_device *dssdev;
215 int r;
216
217 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
218 if (!ddata)
219 return -ENOMEM;
220
221 platform_set_drvdata(pdev, ddata);
222
223 if (dev_get_platdata(&pdev->dev)) {
224 r = tfp410_probe_pdata(pdev);
225 if (r)
226 return r;
227 } else if (pdev->dev.of_node) {
228 r = tfp410_probe_of(pdev);
229 if (r)
230 return r;
231 } else {
232 return -ENODEV;
233 }
234
235 if (gpio_is_valid(ddata->pd_gpio)) {
236 r = devm_gpio_request_one(&pdev->dev, ddata->pd_gpio,
237 GPIOF_OUT_INIT_LOW, "tfp410 PD");
238 if (r) {
239 dev_err(&pdev->dev, "Failed to request PD GPIO %d\n",
240 ddata->pd_gpio);
241 goto err_gpio;
242 }
243 }
244
245 dssdev = &ddata->dssdev;
246 dssdev->ops.dvi = &tfp410_dvi_ops;
247 dssdev->dev = &pdev->dev;
248 dssdev->type = OMAP_DISPLAY_TYPE_DPI;
249 dssdev->output_type = OMAP_DISPLAY_TYPE_DVI;
250 dssdev->owner = THIS_MODULE;
251 dssdev->phy.dpi.data_lines = ddata->data_lines;
252
253 r = omapdss_register_output(dssdev);
254 if (r) {
255 dev_err(&pdev->dev, "Failed to register output\n");
256 goto err_reg;
257 }
258
259 return 0;
260err_reg:
261err_gpio:
262 omap_dss_put_device(ddata->in);
263 return r;
264}
265
266static int __exit tfp410_remove(struct platform_device *pdev)
267{
268 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
269 struct omap_dss_device *dssdev = &ddata->dssdev;
270 struct omap_dss_device *in = ddata->in;
271
272 omapdss_unregister_output(&ddata->dssdev);
273
274 WARN_ON(omapdss_device_is_enabled(dssdev));
275 if (omapdss_device_is_enabled(dssdev))
276 tfp410_disable(dssdev);
277
278 WARN_ON(omapdss_device_is_connected(dssdev));
279 if (omapdss_device_is_connected(dssdev))
280 tfp410_disconnect(dssdev, dssdev->dst);
281
282 omap_dss_put_device(in);
283
284 return 0;
285}
286
287static const struct of_device_id tfp410_of_match[] = {
288 { .compatible = "omapdss,ti,tfp410", },
289 {},
290};
291
292MODULE_DEVICE_TABLE(of, tfp410_of_match);
293
294static struct platform_driver tfp410_driver = {
295 .probe = tfp410_probe,
296 .remove = __exit_p(tfp410_remove),
297 .driver = {
298 .name = "tfp410",
299 .owner = THIS_MODULE,
300 .of_match_table = tfp410_of_match,
301 },
302};
303
304module_platform_driver(tfp410_driver);
305
306MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
307MODULE_DESCRIPTION("TFP410 DPI to DVI encoder driver");
308MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/encoder-tpd12s015.c b/drivers/video/omap2/displays-new/encoder-tpd12s015.c
deleted file mode 100644
index 7e33686171e3..000000000000
--- a/drivers/video/omap2/displays-new/encoder-tpd12s015.c
+++ /dev/null
@@ -1,451 +0,0 @@
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#include <linux/of_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 int ct_cp_hpd_gpio;
28 int ls_oe_gpio;
29 int hpd_gpio;
30
31 struct omap_video_timings timings;
32
33 struct completion hpd_completion;
34};
35
36#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
37
38static irqreturn_t tpd_hpd_irq_handler(int irq, void *data)
39{
40 struct panel_drv_data *ddata = data;
41 bool hpd;
42
43 hpd = gpio_get_value_cansleep(ddata->hpd_gpio);
44
45 dev_dbg(ddata->dssdev.dev, "hpd %d\n", hpd);
46
47 if (gpio_is_valid(ddata->ls_oe_gpio)) {
48 if (hpd)
49 gpio_set_value_cansleep(ddata->ls_oe_gpio, 1);
50 else
51 gpio_set_value_cansleep(ddata->ls_oe_gpio, 0);
52 }
53
54 complete_all(&ddata->hpd_completion);
55
56 return IRQ_HANDLED;
57}
58
59static int tpd_connect(struct omap_dss_device *dssdev,
60 struct omap_dss_device *dst)
61{
62 struct panel_drv_data *ddata = to_panel_data(dssdev);
63 struct omap_dss_device *in = ddata->in;
64 int r;
65
66 r = in->ops.hdmi->connect(in, dssdev);
67 if (r)
68 return r;
69
70 dst->src = dssdev;
71 dssdev->dst = dst;
72
73 reinit_completion(&ddata->hpd_completion);
74
75 gpio_set_value_cansleep(ddata->ct_cp_hpd_gpio, 1);
76 /* DC-DC converter needs at max 300us to get to 90% of 5V */
77 udelay(300);
78
79 /*
80 * If there's a cable connected, wait for the hpd irq to trigger,
81 * which turns on the level shifters.
82 */
83 if (gpio_get_value_cansleep(ddata->hpd_gpio)) {
84 unsigned long to;
85 to = wait_for_completion_timeout(&ddata->hpd_completion,
86 msecs_to_jiffies(250));
87 WARN_ON_ONCE(to == 0);
88 }
89
90 return 0;
91}
92
93static void tpd_disconnect(struct omap_dss_device *dssdev,
94 struct omap_dss_device *dst)
95{
96 struct panel_drv_data *ddata = to_panel_data(dssdev);
97 struct omap_dss_device *in = ddata->in;
98
99 WARN_ON(dst != dssdev->dst);
100
101 if (dst != dssdev->dst)
102 return;
103
104 gpio_set_value_cansleep(ddata->ct_cp_hpd_gpio, 0);
105
106 dst->src = NULL;
107 dssdev->dst = NULL;
108
109 in->ops.hdmi->disconnect(in, &ddata->dssdev);
110}
111
112static int tpd_enable(struct omap_dss_device *dssdev)
113{
114 struct panel_drv_data *ddata = to_panel_data(dssdev);
115 struct omap_dss_device *in = ddata->in;
116 int r;
117
118 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
119 return 0;
120
121 in->ops.hdmi->set_timings(in, &ddata->timings);
122
123 r = in->ops.hdmi->enable(in);
124 if (r)
125 return r;
126
127 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
128
129 return r;
130}
131
132static void tpd_disable(struct omap_dss_device *dssdev)
133{
134 struct panel_drv_data *ddata = to_panel_data(dssdev);
135 struct omap_dss_device *in = ddata->in;
136
137 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
138 return;
139
140 in->ops.hdmi->disable(in);
141
142 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
143}
144
145static void tpd_set_timings(struct omap_dss_device *dssdev,
146 struct omap_video_timings *timings)
147{
148 struct panel_drv_data *ddata = to_panel_data(dssdev);
149 struct omap_dss_device *in = ddata->in;
150
151 ddata->timings = *timings;
152 dssdev->panel.timings = *timings;
153
154 in->ops.hdmi->set_timings(in, timings);
155}
156
157static void tpd_get_timings(struct omap_dss_device *dssdev,
158 struct omap_video_timings *timings)
159{
160 struct panel_drv_data *ddata = to_panel_data(dssdev);
161
162 *timings = ddata->timings;
163}
164
165static int tpd_check_timings(struct omap_dss_device *dssdev,
166 struct omap_video_timings *timings)
167{
168 struct panel_drv_data *ddata = to_panel_data(dssdev);
169 struct omap_dss_device *in = ddata->in;
170 int r;
171
172 r = in->ops.hdmi->check_timings(in, timings);
173
174 return r;
175}
176
177static int tpd_read_edid(struct omap_dss_device *dssdev,
178 u8 *edid, int len)
179{
180 struct panel_drv_data *ddata = to_panel_data(dssdev);
181 struct omap_dss_device *in = ddata->in;
182
183 if (!gpio_get_value_cansleep(ddata->hpd_gpio))
184 return -ENODEV;
185
186 return in->ops.hdmi->read_edid(in, edid, len);
187}
188
189static bool tpd_detect(struct omap_dss_device *dssdev)
190{
191 struct panel_drv_data *ddata = to_panel_data(dssdev);
192
193 return gpio_get_value_cansleep(ddata->hpd_gpio);
194}
195
196static int tpd_audio_enable(struct omap_dss_device *dssdev)
197{
198 struct panel_drv_data *ddata = to_panel_data(dssdev);
199 struct omap_dss_device *in = ddata->in;
200
201 return in->ops.hdmi->audio_enable(in);
202}
203
204static void tpd_audio_disable(struct omap_dss_device *dssdev)
205{
206 struct panel_drv_data *ddata = to_panel_data(dssdev);
207 struct omap_dss_device *in = ddata->in;
208
209 in->ops.hdmi->audio_disable(in);
210}
211
212static int tpd_audio_start(struct omap_dss_device *dssdev)
213{
214 struct panel_drv_data *ddata = to_panel_data(dssdev);
215 struct omap_dss_device *in = ddata->in;
216
217 return in->ops.hdmi->audio_start(in);
218}
219
220static void tpd_audio_stop(struct omap_dss_device *dssdev)
221{
222 struct panel_drv_data *ddata = to_panel_data(dssdev);
223 struct omap_dss_device *in = ddata->in;
224
225 in->ops.hdmi->audio_stop(in);
226}
227
228static bool tpd_audio_supported(struct omap_dss_device *dssdev)
229{
230 struct panel_drv_data *ddata = to_panel_data(dssdev);
231 struct omap_dss_device *in = ddata->in;
232
233 return in->ops.hdmi->audio_supported(in);
234}
235
236static int tpd_audio_config(struct omap_dss_device *dssdev,
237 struct omap_dss_audio *audio)
238{
239 struct panel_drv_data *ddata = to_panel_data(dssdev);
240 struct omap_dss_device *in = ddata->in;
241
242 return in->ops.hdmi->audio_config(in, audio);
243}
244
245static const struct omapdss_hdmi_ops tpd_hdmi_ops = {
246 .connect = tpd_connect,
247 .disconnect = tpd_disconnect,
248
249 .enable = tpd_enable,
250 .disable = tpd_disable,
251
252 .check_timings = tpd_check_timings,
253 .set_timings = tpd_set_timings,
254 .get_timings = tpd_get_timings,
255
256 .read_edid = tpd_read_edid,
257 .detect = tpd_detect,
258
259 .audio_enable = tpd_audio_enable,
260 .audio_disable = tpd_audio_disable,
261 .audio_start = tpd_audio_start,
262 .audio_stop = tpd_audio_stop,
263 .audio_supported = tpd_audio_supported,
264 .audio_config = tpd_audio_config,
265};
266
267static int tpd_probe_pdata(struct platform_device *pdev)
268{
269 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
270 struct encoder_tpd12s015_platform_data *pdata;
271 struct omap_dss_device *dssdev, *in;
272
273 pdata = dev_get_platdata(&pdev->dev);
274
275 ddata->ct_cp_hpd_gpio = pdata->ct_cp_hpd_gpio;
276 ddata->ls_oe_gpio = pdata->ls_oe_gpio;
277 ddata->hpd_gpio = pdata->hpd_gpio;
278
279 in = omap_dss_find_output(pdata->source);
280 if (in == NULL) {
281 dev_err(&pdev->dev, "Failed to find video source\n");
282 return -ENODEV;
283 }
284
285 ddata->in = in;
286
287 dssdev = &ddata->dssdev;
288 dssdev->name = pdata->name;
289
290 return 0;
291}
292
293static int tpd_probe_of(struct platform_device *pdev)
294{
295 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
296 struct device_node *node = pdev->dev.of_node;
297 struct omap_dss_device *in;
298 int gpio;
299
300 /* CT CP HPD GPIO */
301 gpio = of_get_gpio(node, 0);
302 if (!gpio_is_valid(gpio)) {
303 dev_err(&pdev->dev, "failed to parse CT CP HPD gpio\n");
304 return gpio;
305 }
306 ddata->ct_cp_hpd_gpio = gpio;
307
308 /* LS OE GPIO */
309 gpio = of_get_gpio(node, 1);
310 if (gpio_is_valid(gpio) || gpio == -ENOENT) {
311 ddata->ls_oe_gpio = gpio;
312 } else {
313 dev_err(&pdev->dev, "failed to parse LS OE gpio\n");
314 return gpio;
315 }
316
317 /* HPD GPIO */
318 gpio = of_get_gpio(node, 2);
319 if (!gpio_is_valid(gpio)) {
320 dev_err(&pdev->dev, "failed to parse HPD gpio\n");
321 return gpio;
322 }
323 ddata->hpd_gpio = gpio;
324
325 in = omapdss_of_find_source_for_first_ep(node);
326 if (IS_ERR(in)) {
327 dev_err(&pdev->dev, "failed to find video source\n");
328 return PTR_ERR(in);
329 }
330
331 ddata->in = in;
332
333 return 0;
334}
335
336static int tpd_probe(struct platform_device *pdev)
337{
338 struct omap_dss_device *in, *dssdev;
339 struct panel_drv_data *ddata;
340 int r;
341
342 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
343 if (!ddata)
344 return -ENOMEM;
345
346 platform_set_drvdata(pdev, ddata);
347
348 init_completion(&ddata->hpd_completion);
349
350 if (dev_get_platdata(&pdev->dev)) {
351 r = tpd_probe_pdata(pdev);
352 if (r)
353 return r;
354 } else if (pdev->dev.of_node) {
355 r = tpd_probe_of(pdev);
356 if (r)
357 return r;
358 } else {
359 return -ENODEV;
360 }
361
362 r = devm_gpio_request_one(&pdev->dev, ddata->ct_cp_hpd_gpio,
363 GPIOF_OUT_INIT_LOW, "hdmi_ct_cp_hpd");
364 if (r)
365 goto err_gpio;
366
367 if (gpio_is_valid(ddata->ls_oe_gpio)) {
368 r = devm_gpio_request_one(&pdev->dev, ddata->ls_oe_gpio,
369 GPIOF_OUT_INIT_LOW, "hdmi_ls_oe");
370 if (r)
371 goto err_gpio;
372 }
373
374 r = devm_gpio_request_one(&pdev->dev, ddata->hpd_gpio,
375 GPIOF_DIR_IN, "hdmi_hpd");
376 if (r)
377 goto err_gpio;
378
379 r = devm_request_threaded_irq(&pdev->dev, gpio_to_irq(ddata->hpd_gpio),
380 NULL, tpd_hpd_irq_handler,
381 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
382 IRQF_ONESHOT, "hpd", ddata);
383 if (r)
384 goto err_irq;
385
386 dssdev = &ddata->dssdev;
387 dssdev->ops.hdmi = &tpd_hdmi_ops;
388 dssdev->dev = &pdev->dev;
389 dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
390 dssdev->output_type = OMAP_DISPLAY_TYPE_HDMI;
391 dssdev->owner = THIS_MODULE;
392
393 in = ddata->in;
394
395 r = omapdss_register_output(dssdev);
396 if (r) {
397 dev_err(&pdev->dev, "Failed to register output\n");
398 goto err_reg;
399 }
400
401 return 0;
402err_reg:
403err_irq:
404err_gpio:
405 omap_dss_put_device(ddata->in);
406 return r;
407}
408
409static int __exit tpd_remove(struct platform_device *pdev)
410{
411 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
412 struct omap_dss_device *dssdev = &ddata->dssdev;
413 struct omap_dss_device *in = ddata->in;
414
415 omapdss_unregister_output(&ddata->dssdev);
416
417 WARN_ON(omapdss_device_is_enabled(dssdev));
418 if (omapdss_device_is_enabled(dssdev))
419 tpd_disable(dssdev);
420
421 WARN_ON(omapdss_device_is_connected(dssdev));
422 if (omapdss_device_is_connected(dssdev))
423 tpd_disconnect(dssdev, dssdev->dst);
424
425 omap_dss_put_device(in);
426
427 return 0;
428}
429
430static const struct of_device_id tpd_of_match[] = {
431 { .compatible = "omapdss,ti,tpd12s015", },
432 {},
433};
434
435MODULE_DEVICE_TABLE(of, tpd_of_match);
436
437static struct platform_driver tpd_driver = {
438 .probe = tpd_probe,
439 .remove = __exit_p(tpd_remove),
440 .driver = {
441 .name = "tpd12s015",
442 .owner = THIS_MODULE,
443 .of_match_table = tpd_of_match,
444 },
445};
446
447module_platform_driver(tpd_driver);
448
449MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
450MODULE_DESCRIPTION("TPD12S015 driver");
451MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/panel-dpi.c b/drivers/video/omap2/displays-new/panel-dpi.c
deleted file mode 100644
index 5f8f7e7c81ef..000000000000
--- a/drivers/video/omap2/displays-new/panel-dpi.c
+++ /dev/null
@@ -1,270 +0,0 @@
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
deleted file mode 100644
index d6f14e8717e8..000000000000
--- a/drivers/video/omap2/displays-new/panel-dsi-cm.c
+++ /dev/null
@@ -1,1388 +0,0 @@
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#include <linux/of_device.h>
26#include <linux/of_gpio.h>
27
28#include <video/omapdss.h>
29#include <video/omap-panel-data.h>
30#include <video/mipi_display.h>
31
32/* DSI Virtual channel. Hardcoded for now. */
33#define TCH 0
34
35#define DCS_READ_NUM_ERRORS 0x05
36#define DCS_BRIGHTNESS 0x51
37#define DCS_CTRL_DISPLAY 0x53
38#define DCS_GET_ID1 0xda
39#define DCS_GET_ID2 0xdb
40#define DCS_GET_ID3 0xdc
41
42struct panel_drv_data {
43 struct omap_dss_device dssdev;
44 struct omap_dss_device *in;
45
46 struct omap_video_timings timings;
47
48 struct platform_device *pdev;
49
50 struct mutex lock;
51
52 struct backlight_device *bldev;
53
54 unsigned long hw_guard_end; /* next value of jiffies when we can
55 * issue the next sleep in/out command
56 */
57 unsigned long hw_guard_wait; /* max guard time in jiffies */
58
59 /* panel HW configuration from DT or platform data */
60 int reset_gpio;
61 int ext_te_gpio;
62
63 bool use_dsi_backlight;
64
65 struct omap_dsi_pin_config pin_config;
66
67 /* runtime variables */
68 bool enabled;
69
70 bool te_enabled;
71
72 atomic_t do_update;
73 int channel;
74
75 struct delayed_work te_timeout_work;
76
77 bool intro_printed;
78
79 struct workqueue_struct *workqueue;
80
81 bool ulps_enabled;
82 unsigned ulps_timeout;
83 struct delayed_work ulps_work;
84};
85
86#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
87
88static irqreturn_t dsicm_te_isr(int irq, void *data);
89static void dsicm_te_timeout_work_callback(struct work_struct *work);
90static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable);
91
92static int dsicm_panel_reset(struct panel_drv_data *ddata);
93
94static void dsicm_ulps_work(struct work_struct *work);
95
96static void hw_guard_start(struct panel_drv_data *ddata, int guard_msec)
97{
98 ddata->hw_guard_wait = msecs_to_jiffies(guard_msec);
99 ddata->hw_guard_end = jiffies + ddata->hw_guard_wait;
100}
101
102static void hw_guard_wait(struct panel_drv_data *ddata)
103{
104 unsigned long wait = ddata->hw_guard_end - jiffies;
105
106 if ((long)wait > 0 && wait <= ddata->hw_guard_wait) {
107 set_current_state(TASK_UNINTERRUPTIBLE);
108 schedule_timeout(wait);
109 }
110}
111
112static int dsicm_dcs_read_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 *data)
113{
114 struct omap_dss_device *in = ddata->in;
115 int r;
116 u8 buf[1];
117
118 r = in->ops.dsi->dcs_read(in, ddata->channel, dcs_cmd, buf, 1);
119
120 if (r < 0)
121 return r;
122
123 *data = buf[0];
124
125 return 0;
126}
127
128static int dsicm_dcs_write_0(struct panel_drv_data *ddata, u8 dcs_cmd)
129{
130 struct omap_dss_device *in = ddata->in;
131 return in->ops.dsi->dcs_write(in, ddata->channel, &dcs_cmd, 1);
132}
133
134static int dsicm_dcs_write_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 param)
135{
136 struct omap_dss_device *in = ddata->in;
137 u8 buf[2] = { dcs_cmd, param };
138
139 return in->ops.dsi->dcs_write(in, ddata->channel, buf, 2);
140}
141
142static int dsicm_sleep_in(struct panel_drv_data *ddata)
143
144{
145 struct omap_dss_device *in = ddata->in;
146 u8 cmd;
147 int r;
148
149 hw_guard_wait(ddata);
150
151 cmd = MIPI_DCS_ENTER_SLEEP_MODE;
152 r = in->ops.dsi->dcs_write_nosync(in, ddata->channel, &cmd, 1);
153 if (r)
154 return r;
155
156 hw_guard_start(ddata, 120);
157
158 usleep_range(5000, 10000);
159
160 return 0;
161}
162
163static int dsicm_sleep_out(struct panel_drv_data *ddata)
164{
165 int r;
166
167 hw_guard_wait(ddata);
168
169 r = dsicm_dcs_write_0(ddata, MIPI_DCS_EXIT_SLEEP_MODE);
170 if (r)
171 return r;
172
173 hw_guard_start(ddata, 120);
174
175 usleep_range(5000, 10000);
176
177 return 0;
178}
179
180static int dsicm_get_id(struct panel_drv_data *ddata, u8 *id1, u8 *id2, u8 *id3)
181{
182 int r;
183
184 r = dsicm_dcs_read_1(ddata, DCS_GET_ID1, id1);
185 if (r)
186 return r;
187 r = dsicm_dcs_read_1(ddata, DCS_GET_ID2, id2);
188 if (r)
189 return r;
190 r = dsicm_dcs_read_1(ddata, DCS_GET_ID3, id3);
191 if (r)
192 return r;
193
194 return 0;
195}
196
197static int dsicm_set_update_window(struct panel_drv_data *ddata,
198 u16 x, u16 y, u16 w, u16 h)
199{
200 struct omap_dss_device *in = ddata->in;
201 int r;
202 u16 x1 = x;
203 u16 x2 = x + w - 1;
204 u16 y1 = y;
205 u16 y2 = y + h - 1;
206
207 u8 buf[5];
208 buf[0] = MIPI_DCS_SET_COLUMN_ADDRESS;
209 buf[1] = (x1 >> 8) & 0xff;
210 buf[2] = (x1 >> 0) & 0xff;
211 buf[3] = (x2 >> 8) & 0xff;
212 buf[4] = (x2 >> 0) & 0xff;
213
214 r = in->ops.dsi->dcs_write_nosync(in, ddata->channel, buf, sizeof(buf));
215 if (r)
216 return r;
217
218 buf[0] = MIPI_DCS_SET_PAGE_ADDRESS;
219 buf[1] = (y1 >> 8) & 0xff;
220 buf[2] = (y1 >> 0) & 0xff;
221 buf[3] = (y2 >> 8) & 0xff;
222 buf[4] = (y2 >> 0) & 0xff;
223
224 r = in->ops.dsi->dcs_write_nosync(in, ddata->channel, buf, sizeof(buf));
225 if (r)
226 return r;
227
228 in->ops.dsi->bta_sync(in, ddata->channel);
229
230 return r;
231}
232
233static void dsicm_queue_ulps_work(struct panel_drv_data *ddata)
234{
235 if (ddata->ulps_timeout > 0)
236 queue_delayed_work(ddata->workqueue, &ddata->ulps_work,
237 msecs_to_jiffies(ddata->ulps_timeout));
238}
239
240static void dsicm_cancel_ulps_work(struct panel_drv_data *ddata)
241{
242 cancel_delayed_work(&ddata->ulps_work);
243}
244
245static int dsicm_enter_ulps(struct panel_drv_data *ddata)
246{
247 struct omap_dss_device *in = ddata->in;
248 int r;
249
250 if (ddata->ulps_enabled)
251 return 0;
252
253 dsicm_cancel_ulps_work(ddata);
254
255 r = _dsicm_enable_te(ddata, false);
256 if (r)
257 goto err;
258
259 if (gpio_is_valid(ddata->ext_te_gpio))
260 disable_irq(gpio_to_irq(ddata->ext_te_gpio));
261
262 in->ops.dsi->disable(in, false, true);
263
264 ddata->ulps_enabled = true;
265
266 return 0;
267
268err:
269 dev_err(&ddata->pdev->dev, "enter ULPS failed");
270 dsicm_panel_reset(ddata);
271
272 ddata->ulps_enabled = false;
273
274 dsicm_queue_ulps_work(ddata);
275
276 return r;
277}
278
279static int dsicm_exit_ulps(struct panel_drv_data *ddata)
280{
281 struct omap_dss_device *in = ddata->in;
282 int r;
283
284 if (!ddata->ulps_enabled)
285 return 0;
286
287 r = in->ops.dsi->enable(in);
288 if (r) {
289 dev_err(&ddata->pdev->dev, "failed to enable DSI\n");
290 goto err1;
291 }
292
293 in->ops.dsi->enable_hs(in, ddata->channel, true);
294
295 r = _dsicm_enable_te(ddata, true);
296 if (r) {
297 dev_err(&ddata->pdev->dev, "failed to re-enable TE");
298 goto err2;
299 }
300
301 if (gpio_is_valid(ddata->ext_te_gpio))
302 enable_irq(gpio_to_irq(ddata->ext_te_gpio));
303
304 dsicm_queue_ulps_work(ddata);
305
306 ddata->ulps_enabled = false;
307
308 return 0;
309
310err2:
311 dev_err(&ddata->pdev->dev, "failed to exit ULPS");
312
313 r = dsicm_panel_reset(ddata);
314 if (!r) {
315 if (gpio_is_valid(ddata->ext_te_gpio))
316 enable_irq(gpio_to_irq(ddata->ext_te_gpio));
317 ddata->ulps_enabled = false;
318 }
319err1:
320 dsicm_queue_ulps_work(ddata);
321
322 return r;
323}
324
325static int dsicm_wake_up(struct panel_drv_data *ddata)
326{
327 if (ddata->ulps_enabled)
328 return dsicm_exit_ulps(ddata);
329
330 dsicm_cancel_ulps_work(ddata);
331 dsicm_queue_ulps_work(ddata);
332 return 0;
333}
334
335static int dsicm_bl_update_status(struct backlight_device *dev)
336{
337 struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
338 struct omap_dss_device *in = ddata->in;
339 int r;
340 int level;
341
342 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
343 dev->props.power == FB_BLANK_UNBLANK)
344 level = dev->props.brightness;
345 else
346 level = 0;
347
348 dev_dbg(&ddata->pdev->dev, "update brightness to %d\n", level);
349
350 mutex_lock(&ddata->lock);
351
352 if (ddata->enabled) {
353 in->ops.dsi->bus_lock(in);
354
355 r = dsicm_wake_up(ddata);
356 if (!r)
357 r = dsicm_dcs_write_1(ddata, DCS_BRIGHTNESS, level);
358
359 in->ops.dsi->bus_unlock(in);
360 } else {
361 r = 0;
362 }
363
364 mutex_unlock(&ddata->lock);
365
366 return r;
367}
368
369static int dsicm_bl_get_intensity(struct backlight_device *dev)
370{
371 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
372 dev->props.power == FB_BLANK_UNBLANK)
373 return dev->props.brightness;
374
375 return 0;
376}
377
378static const struct backlight_ops dsicm_bl_ops = {
379 .get_brightness = dsicm_bl_get_intensity,
380 .update_status = dsicm_bl_update_status,
381};
382
383static void dsicm_get_resolution(struct omap_dss_device *dssdev,
384 u16 *xres, u16 *yres)
385{
386 *xres = dssdev->panel.timings.x_res;
387 *yres = dssdev->panel.timings.y_res;
388}
389
390static ssize_t dsicm_num_errors_show(struct device *dev,
391 struct device_attribute *attr, char *buf)
392{
393 struct platform_device *pdev = to_platform_device(dev);
394 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
395 struct omap_dss_device *in = ddata->in;
396 u8 errors = 0;
397 int r;
398
399 mutex_lock(&ddata->lock);
400
401 if (ddata->enabled) {
402 in->ops.dsi->bus_lock(in);
403
404 r = dsicm_wake_up(ddata);
405 if (!r)
406 r = dsicm_dcs_read_1(ddata, DCS_READ_NUM_ERRORS,
407 &errors);
408
409 in->ops.dsi->bus_unlock(in);
410 } else {
411 r = -ENODEV;
412 }
413
414 mutex_unlock(&ddata->lock);
415
416 if (r)
417 return r;
418
419 return snprintf(buf, PAGE_SIZE, "%d\n", errors);
420}
421
422static ssize_t dsicm_hw_revision_show(struct device *dev,
423 struct device_attribute *attr, char *buf)
424{
425 struct platform_device *pdev = to_platform_device(dev);
426 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
427 struct omap_dss_device *in = ddata->in;
428 u8 id1, id2, id3;
429 int r;
430
431 mutex_lock(&ddata->lock);
432
433 if (ddata->enabled) {
434 in->ops.dsi->bus_lock(in);
435
436 r = dsicm_wake_up(ddata);
437 if (!r)
438 r = dsicm_get_id(ddata, &id1, &id2, &id3);
439
440 in->ops.dsi->bus_unlock(in);
441 } else {
442 r = -ENODEV;
443 }
444
445 mutex_unlock(&ddata->lock);
446
447 if (r)
448 return r;
449
450 return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x\n", id1, id2, id3);
451}
452
453static ssize_t dsicm_store_ulps(struct device *dev,
454 struct device_attribute *attr,
455 const char *buf, size_t count)
456{
457 struct platform_device *pdev = to_platform_device(dev);
458 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
459 struct omap_dss_device *in = ddata->in;
460 unsigned long t;
461 int r;
462
463 r = kstrtoul(buf, 0, &t);
464 if (r)
465 return r;
466
467 mutex_lock(&ddata->lock);
468
469 if (ddata->enabled) {
470 in->ops.dsi->bus_lock(in);
471
472 if (t)
473 r = dsicm_enter_ulps(ddata);
474 else
475 r = dsicm_wake_up(ddata);
476
477 in->ops.dsi->bus_unlock(in);
478 }
479
480 mutex_unlock(&ddata->lock);
481
482 if (r)
483 return r;
484
485 return count;
486}
487
488static ssize_t dsicm_show_ulps(struct device *dev,
489 struct device_attribute *attr,
490 char *buf)
491{
492 struct platform_device *pdev = to_platform_device(dev);
493 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
494 unsigned t;
495
496 mutex_lock(&ddata->lock);
497 t = ddata->ulps_enabled;
498 mutex_unlock(&ddata->lock);
499
500 return snprintf(buf, PAGE_SIZE, "%u\n", t);
501}
502
503static ssize_t dsicm_store_ulps_timeout(struct device *dev,
504 struct device_attribute *attr,
505 const char *buf, size_t count)
506{
507 struct platform_device *pdev = to_platform_device(dev);
508 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
509 struct omap_dss_device *in = ddata->in;
510 unsigned long t;
511 int r;
512
513 r = kstrtoul(buf, 0, &t);
514 if (r)
515 return r;
516
517 mutex_lock(&ddata->lock);
518 ddata->ulps_timeout = t;
519
520 if (ddata->enabled) {
521 /* dsicm_wake_up will restart the timer */
522 in->ops.dsi->bus_lock(in);
523 r = dsicm_wake_up(ddata);
524 in->ops.dsi->bus_unlock(in);
525 }
526
527 mutex_unlock(&ddata->lock);
528
529 if (r)
530 return r;
531
532 return count;
533}
534
535static ssize_t dsicm_show_ulps_timeout(struct device *dev,
536 struct device_attribute *attr,
537 char *buf)
538{
539 struct platform_device *pdev = to_platform_device(dev);
540 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
541 unsigned t;
542
543 mutex_lock(&ddata->lock);
544 t = ddata->ulps_timeout;
545 mutex_unlock(&ddata->lock);
546
547 return snprintf(buf, PAGE_SIZE, "%u\n", t);
548}
549
550static DEVICE_ATTR(num_dsi_errors, S_IRUGO, dsicm_num_errors_show, NULL);
551static DEVICE_ATTR(hw_revision, S_IRUGO, dsicm_hw_revision_show, NULL);
552static DEVICE_ATTR(ulps, S_IRUGO | S_IWUSR,
553 dsicm_show_ulps, dsicm_store_ulps);
554static DEVICE_ATTR(ulps_timeout, S_IRUGO | S_IWUSR,
555 dsicm_show_ulps_timeout, dsicm_store_ulps_timeout);
556
557static struct attribute *dsicm_attrs[] = {
558 &dev_attr_num_dsi_errors.attr,
559 &dev_attr_hw_revision.attr,
560 &dev_attr_ulps.attr,
561 &dev_attr_ulps_timeout.attr,
562 NULL,
563};
564
565static struct attribute_group dsicm_attr_group = {
566 .attrs = dsicm_attrs,
567};
568
569static void dsicm_hw_reset(struct panel_drv_data *ddata)
570{
571 if (!gpio_is_valid(ddata->reset_gpio))
572 return;
573
574 gpio_set_value(ddata->reset_gpio, 1);
575 udelay(10);
576 /* reset the panel */
577 gpio_set_value(ddata->reset_gpio, 0);
578 /* assert reset */
579 udelay(10);
580 gpio_set_value(ddata->reset_gpio, 1);
581 /* wait after releasing reset */
582 usleep_range(5000, 10000);
583}
584
585static int dsicm_power_on(struct panel_drv_data *ddata)
586{
587 struct omap_dss_device *in = ddata->in;
588 u8 id1, id2, id3;
589 int r;
590 struct omap_dss_dsi_config dsi_config = {
591 .mode = OMAP_DSS_DSI_CMD_MODE,
592 .pixel_format = OMAP_DSS_DSI_FMT_RGB888,
593 .timings = &ddata->timings,
594 .hs_clk_min = 150000000,
595 .hs_clk_max = 300000000,
596 .lp_clk_min = 7000000,
597 .lp_clk_max = 10000000,
598 };
599
600 if (ddata->pin_config.num_pins > 0) {
601 r = in->ops.dsi->configure_pins(in, &ddata->pin_config);
602 if (r) {
603 dev_err(&ddata->pdev->dev,
604 "failed to configure DSI pins\n");
605 goto err0;
606 }
607 }
608
609 r = in->ops.dsi->set_config(in, &dsi_config);
610 if (r) {
611 dev_err(&ddata->pdev->dev, "failed to configure DSI\n");
612 goto err0;
613 }
614
615 r = in->ops.dsi->enable(in);
616 if (r) {
617 dev_err(&ddata->pdev->dev, "failed to enable DSI\n");
618 goto err0;
619 }
620
621 dsicm_hw_reset(ddata);
622
623 in->ops.dsi->enable_hs(in, ddata->channel, false);
624
625 r = dsicm_sleep_out(ddata);
626 if (r)
627 goto err;
628
629 r = dsicm_get_id(ddata, &id1, &id2, &id3);
630 if (r)
631 goto err;
632
633 r = dsicm_dcs_write_1(ddata, DCS_BRIGHTNESS, 0xff);
634 if (r)
635 goto err;
636
637 r = dsicm_dcs_write_1(ddata, DCS_CTRL_DISPLAY,
638 (1<<2) | (1<<5)); /* BL | BCTRL */
639 if (r)
640 goto err;
641
642 r = dsicm_dcs_write_1(ddata, MIPI_DCS_SET_PIXEL_FORMAT,
643 MIPI_DCS_PIXEL_FMT_24BIT);
644 if (r)
645 goto err;
646
647 r = dsicm_dcs_write_0(ddata, MIPI_DCS_SET_DISPLAY_ON);
648 if (r)
649 goto err;
650
651 r = _dsicm_enable_te(ddata, ddata->te_enabled);
652 if (r)
653 goto err;
654
655 r = in->ops.dsi->enable_video_output(in, ddata->channel);
656 if (r)
657 goto err;
658
659 ddata->enabled = 1;
660
661 if (!ddata->intro_printed) {
662 dev_info(&ddata->pdev->dev, "panel revision %02x.%02x.%02x\n",
663 id1, id2, id3);
664 ddata->intro_printed = true;
665 }
666
667 in->ops.dsi->enable_hs(in, ddata->channel, true);
668
669 return 0;
670err:
671 dev_err(&ddata->pdev->dev, "error while enabling panel, issuing HW reset\n");
672
673 dsicm_hw_reset(ddata);
674
675 in->ops.dsi->disable(in, true, false);
676err0:
677 return r;
678}
679
680static void dsicm_power_off(struct panel_drv_data *ddata)
681{
682 struct omap_dss_device *in = ddata->in;
683 int r;
684
685 in->ops.dsi->disable_video_output(in, ddata->channel);
686
687 r = dsicm_dcs_write_0(ddata, MIPI_DCS_SET_DISPLAY_OFF);
688 if (!r)
689 r = dsicm_sleep_in(ddata);
690
691 if (r) {
692 dev_err(&ddata->pdev->dev,
693 "error disabling panel, issuing HW reset\n");
694 dsicm_hw_reset(ddata);
695 }
696
697 in->ops.dsi->disable(in, true, false);
698
699 ddata->enabled = 0;
700}
701
702static int dsicm_panel_reset(struct panel_drv_data *ddata)
703{
704 dev_err(&ddata->pdev->dev, "performing LCD reset\n");
705
706 dsicm_power_off(ddata);
707 dsicm_hw_reset(ddata);
708 return dsicm_power_on(ddata);
709}
710
711static int dsicm_connect(struct omap_dss_device *dssdev)
712{
713 struct panel_drv_data *ddata = to_panel_data(dssdev);
714 struct omap_dss_device *in = ddata->in;
715 struct device *dev = &ddata->pdev->dev;
716 int r;
717
718 if (omapdss_device_is_connected(dssdev))
719 return 0;
720
721 r = in->ops.dsi->connect(in, dssdev);
722 if (r) {
723 dev_err(dev, "Failed to connect to video source\n");
724 return r;
725 }
726
727 r = in->ops.dsi->request_vc(ddata->in, &ddata->channel);
728 if (r) {
729 dev_err(dev, "failed to get virtual channel\n");
730 goto err_req_vc;
731 }
732
733 r = in->ops.dsi->set_vc_id(ddata->in, ddata->channel, TCH);
734 if (r) {
735 dev_err(dev, "failed to set VC_ID\n");
736 goto err_vc_id;
737 }
738
739 return 0;
740
741err_vc_id:
742 in->ops.dsi->release_vc(ddata->in, ddata->channel);
743err_req_vc:
744 in->ops.dsi->disconnect(in, dssdev);
745 return r;
746}
747
748static void dsicm_disconnect(struct omap_dss_device *dssdev)
749{
750 struct panel_drv_data *ddata = to_panel_data(dssdev);
751 struct omap_dss_device *in = ddata->in;
752
753 if (!omapdss_device_is_connected(dssdev))
754 return;
755
756 in->ops.dsi->release_vc(in, ddata->channel);
757 in->ops.dsi->disconnect(in, dssdev);
758}
759
760static int dsicm_enable(struct omap_dss_device *dssdev)
761{
762 struct panel_drv_data *ddata = to_panel_data(dssdev);
763 struct omap_dss_device *in = ddata->in;
764 int r;
765
766 dev_dbg(&ddata->pdev->dev, "enable\n");
767
768 mutex_lock(&ddata->lock);
769
770 if (!omapdss_device_is_connected(dssdev)) {
771 r = -ENODEV;
772 goto err;
773 }
774
775 if (omapdss_device_is_enabled(dssdev)) {
776 r = 0;
777 goto err;
778 }
779
780 in->ops.dsi->bus_lock(in);
781
782 r = dsicm_power_on(ddata);
783
784 in->ops.dsi->bus_unlock(in);
785
786 if (r)
787 goto err;
788
789 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
790
791 mutex_unlock(&ddata->lock);
792
793 return 0;
794err:
795 dev_dbg(&ddata->pdev->dev, "enable failed\n");
796 mutex_unlock(&ddata->lock);
797 return r;
798}
799
800static void dsicm_disable(struct omap_dss_device *dssdev)
801{
802 struct panel_drv_data *ddata = to_panel_data(dssdev);
803 struct omap_dss_device *in = ddata->in;
804 int r;
805
806 dev_dbg(&ddata->pdev->dev, "disable\n");
807
808 mutex_lock(&ddata->lock);
809
810 dsicm_cancel_ulps_work(ddata);
811
812 in->ops.dsi->bus_lock(in);
813
814 if (omapdss_device_is_enabled(dssdev)) {
815 r = dsicm_wake_up(ddata);
816 if (!r)
817 dsicm_power_off(ddata);
818 }
819
820 in->ops.dsi->bus_unlock(in);
821
822 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
823
824 mutex_unlock(&ddata->lock);
825}
826
827static void dsicm_framedone_cb(int err, void *data)
828{
829 struct panel_drv_data *ddata = data;
830 struct omap_dss_device *in = ddata->in;
831
832 dev_dbg(&ddata->pdev->dev, "framedone, err %d\n", err);
833 in->ops.dsi->bus_unlock(ddata->in);
834}
835
836static irqreturn_t dsicm_te_isr(int irq, void *data)
837{
838 struct panel_drv_data *ddata = data;
839 struct omap_dss_device *in = ddata->in;
840 int old;
841 int r;
842
843 old = atomic_cmpxchg(&ddata->do_update, 1, 0);
844
845 if (old) {
846 cancel_delayed_work(&ddata->te_timeout_work);
847
848 r = in->ops.dsi->update(in, ddata->channel, dsicm_framedone_cb,
849 ddata);
850 if (r)
851 goto err;
852 }
853
854 return IRQ_HANDLED;
855err:
856 dev_err(&ddata->pdev->dev, "start update failed\n");
857 in->ops.dsi->bus_unlock(in);
858 return IRQ_HANDLED;
859}
860
861static void dsicm_te_timeout_work_callback(struct work_struct *work)
862{
863 struct panel_drv_data *ddata = container_of(work, struct panel_drv_data,
864 te_timeout_work.work);
865 struct omap_dss_device *in = ddata->in;
866
867 dev_err(&ddata->pdev->dev, "TE not received for 250ms!\n");
868
869 atomic_set(&ddata->do_update, 0);
870 in->ops.dsi->bus_unlock(in);
871}
872
873static int dsicm_update(struct omap_dss_device *dssdev,
874 u16 x, u16 y, u16 w, u16 h)
875{
876 struct panel_drv_data *ddata = to_panel_data(dssdev);
877 struct omap_dss_device *in = ddata->in;
878 int r;
879
880 dev_dbg(&ddata->pdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
881
882 mutex_lock(&ddata->lock);
883 in->ops.dsi->bus_lock(in);
884
885 r = dsicm_wake_up(ddata);
886 if (r)
887 goto err;
888
889 if (!ddata->enabled) {
890 r = 0;
891 goto err;
892 }
893
894 /* XXX no need to send this every frame, but dsi break if not done */
895 r = dsicm_set_update_window(ddata, 0, 0,
896 dssdev->panel.timings.x_res,
897 dssdev->panel.timings.y_res);
898 if (r)
899 goto err;
900
901 if (ddata->te_enabled && gpio_is_valid(ddata->ext_te_gpio)) {
902 schedule_delayed_work(&ddata->te_timeout_work,
903 msecs_to_jiffies(250));
904 atomic_set(&ddata->do_update, 1);
905 } else {
906 r = in->ops.dsi->update(in, ddata->channel, dsicm_framedone_cb,
907 ddata);
908 if (r)
909 goto err;
910 }
911
912 /* note: no bus_unlock here. unlock is in framedone_cb */
913 mutex_unlock(&ddata->lock);
914 return 0;
915err:
916 in->ops.dsi->bus_unlock(in);
917 mutex_unlock(&ddata->lock);
918 return r;
919}
920
921static int dsicm_sync(struct omap_dss_device *dssdev)
922{
923 struct panel_drv_data *ddata = to_panel_data(dssdev);
924 struct omap_dss_device *in = ddata->in;
925
926 dev_dbg(&ddata->pdev->dev, "sync\n");
927
928 mutex_lock(&ddata->lock);
929 in->ops.dsi->bus_lock(in);
930 in->ops.dsi->bus_unlock(in);
931 mutex_unlock(&ddata->lock);
932
933 dev_dbg(&ddata->pdev->dev, "sync done\n");
934
935 return 0;
936}
937
938static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable)
939{
940 struct omap_dss_device *in = ddata->in;
941 int r;
942
943 if (enable)
944 r = dsicm_dcs_write_1(ddata, MIPI_DCS_SET_TEAR_ON, 0);
945 else
946 r = dsicm_dcs_write_0(ddata, MIPI_DCS_SET_TEAR_OFF);
947
948 if (!gpio_is_valid(ddata->ext_te_gpio))
949 in->ops.dsi->enable_te(in, enable);
950
951 /* possible panel bug */
952 msleep(100);
953
954 return r;
955}
956
957static int dsicm_enable_te(struct omap_dss_device *dssdev, bool enable)
958{
959 struct panel_drv_data *ddata = to_panel_data(dssdev);
960 struct omap_dss_device *in = ddata->in;
961 int r;
962
963 mutex_lock(&ddata->lock);
964
965 if (ddata->te_enabled == enable)
966 goto end;
967
968 in->ops.dsi->bus_lock(in);
969
970 if (ddata->enabled) {
971 r = dsicm_wake_up(ddata);
972 if (r)
973 goto err;
974
975 r = _dsicm_enable_te(ddata, enable);
976 if (r)
977 goto err;
978 }
979
980 ddata->te_enabled = enable;
981
982 in->ops.dsi->bus_unlock(in);
983end:
984 mutex_unlock(&ddata->lock);
985
986 return 0;
987err:
988 in->ops.dsi->bus_unlock(in);
989 mutex_unlock(&ddata->lock);
990
991 return r;
992}
993
994static int dsicm_get_te(struct omap_dss_device *dssdev)
995{
996 struct panel_drv_data *ddata = to_panel_data(dssdev);
997 int r;
998
999 mutex_lock(&ddata->lock);
1000 r = ddata->te_enabled;
1001 mutex_unlock(&ddata->lock);
1002
1003 return r;
1004}
1005
1006static int dsicm_memory_read(struct omap_dss_device *dssdev,
1007 void *buf, size_t size,
1008 u16 x, u16 y, u16 w, u16 h)
1009{
1010 struct panel_drv_data *ddata = to_panel_data(dssdev);
1011 struct omap_dss_device *in = ddata->in;
1012 int r;
1013 int first = 1;
1014 int plen;
1015 unsigned buf_used = 0;
1016
1017 if (size < w * h * 3)
1018 return -ENOMEM;
1019
1020 mutex_lock(&ddata->lock);
1021
1022 if (!ddata->enabled) {
1023 r = -ENODEV;
1024 goto err1;
1025 }
1026
1027 size = min(w * h * 3,
1028 dssdev->panel.timings.x_res *
1029 dssdev->panel.timings.y_res * 3);
1030
1031 in->ops.dsi->bus_lock(in);
1032
1033 r = dsicm_wake_up(ddata);
1034 if (r)
1035 goto err2;
1036
1037 /* plen 1 or 2 goes into short packet. until checksum error is fixed,
1038 * use short packets. plen 32 works, but bigger packets seem to cause
1039 * an error. */
1040 if (size % 2)
1041 plen = 1;
1042 else
1043 plen = 2;
1044
1045 dsicm_set_update_window(ddata, x, y, w, h);
1046
1047 r = in->ops.dsi->set_max_rx_packet_size(in, ddata->channel, plen);
1048 if (r)
1049 goto err2;
1050
1051 while (buf_used < size) {
1052 u8 dcs_cmd = first ? 0x2e : 0x3e;
1053 first = 0;
1054
1055 r = in->ops.dsi->dcs_read(in, ddata->channel, dcs_cmd,
1056 buf + buf_used, size - buf_used);
1057
1058 if (r < 0) {
1059 dev_err(dssdev->dev, "read error\n");
1060 goto err3;
1061 }
1062
1063 buf_used += r;
1064
1065 if (r < plen) {
1066 dev_err(&ddata->pdev->dev, "short read\n");
1067 break;
1068 }
1069
1070 if (signal_pending(current)) {
1071 dev_err(&ddata->pdev->dev, "signal pending, "
1072 "aborting memory read\n");
1073 r = -ERESTARTSYS;
1074 goto err3;
1075 }
1076 }
1077
1078 r = buf_used;
1079
1080err3:
1081 in->ops.dsi->set_max_rx_packet_size(in, ddata->channel, 1);
1082err2:
1083 in->ops.dsi->bus_unlock(in);
1084err1:
1085 mutex_unlock(&ddata->lock);
1086 return r;
1087}
1088
1089static void dsicm_ulps_work(struct work_struct *work)
1090{
1091 struct panel_drv_data *ddata = container_of(work, struct panel_drv_data,
1092 ulps_work.work);
1093 struct omap_dss_device *dssdev = &ddata->dssdev;
1094 struct omap_dss_device *in = ddata->in;
1095
1096 mutex_lock(&ddata->lock);
1097
1098 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE || !ddata->enabled) {
1099 mutex_unlock(&ddata->lock);
1100 return;
1101 }
1102
1103 in->ops.dsi->bus_lock(in);
1104
1105 dsicm_enter_ulps(ddata);
1106
1107 in->ops.dsi->bus_unlock(in);
1108 mutex_unlock(&ddata->lock);
1109}
1110
1111static struct omap_dss_driver dsicm_ops = {
1112 .connect = dsicm_connect,
1113 .disconnect = dsicm_disconnect,
1114
1115 .enable = dsicm_enable,
1116 .disable = dsicm_disable,
1117
1118 .update = dsicm_update,
1119 .sync = dsicm_sync,
1120
1121 .get_resolution = dsicm_get_resolution,
1122 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
1123
1124 .enable_te = dsicm_enable_te,
1125 .get_te = dsicm_get_te,
1126
1127 .memory_read = dsicm_memory_read,
1128};
1129
1130static int dsicm_probe_pdata(struct platform_device *pdev)
1131{
1132 const struct panel_dsicm_platform_data *pdata;
1133 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
1134 struct omap_dss_device *dssdev, *in;
1135
1136 pdata = dev_get_platdata(&pdev->dev);
1137
1138 in = omap_dss_find_output(pdata->source);
1139 if (in == NULL) {
1140 dev_err(&pdev->dev, "failed to find video source\n");
1141 return -EPROBE_DEFER;
1142 }
1143 ddata->in = in;
1144
1145 ddata->reset_gpio = pdata->reset_gpio;
1146
1147 if (pdata->use_ext_te)
1148 ddata->ext_te_gpio = pdata->ext_te_gpio;
1149 else
1150 ddata->ext_te_gpio = -1;
1151
1152 ddata->ulps_timeout = pdata->ulps_timeout;
1153
1154 ddata->use_dsi_backlight = pdata->use_dsi_backlight;
1155
1156 ddata->pin_config = pdata->pin_config;
1157
1158 dssdev = &ddata->dssdev;
1159 dssdev->name = pdata->name;
1160
1161 return 0;
1162}
1163
1164static int dsicm_probe_of(struct platform_device *pdev)
1165{
1166 struct device_node *node = pdev->dev.of_node;
1167 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
1168 struct omap_dss_device *in;
1169 int gpio;
1170
1171 gpio = of_get_named_gpio(node, "reset-gpios", 0);
1172 if (!gpio_is_valid(gpio)) {
1173 dev_err(&pdev->dev, "failed to parse reset gpio\n");
1174 return gpio;
1175 }
1176 ddata->reset_gpio = gpio;
1177
1178 gpio = of_get_named_gpio(node, "te-gpios", 0);
1179 if (gpio_is_valid(gpio) || gpio == -ENOENT) {
1180 ddata->ext_te_gpio = gpio;
1181 } else {
1182 dev_err(&pdev->dev, "failed to parse TE gpio\n");
1183 return gpio;
1184 }
1185
1186 in = omapdss_of_find_source_for_first_ep(node);
1187 if (IS_ERR(in)) {
1188 dev_err(&pdev->dev, "failed to find video source\n");
1189 return PTR_ERR(in);
1190 }
1191
1192 ddata->in = in;
1193
1194 /* TODO: ulps, backlight */
1195
1196 return 0;
1197}
1198
1199static int dsicm_probe(struct platform_device *pdev)
1200{
1201 struct backlight_properties props;
1202 struct panel_drv_data *ddata;
1203 struct backlight_device *bldev = NULL;
1204 struct device *dev = &pdev->dev;
1205 struct omap_dss_device *dssdev;
1206 int r;
1207
1208 dev_dbg(dev, "probe\n");
1209
1210 ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
1211 if (!ddata)
1212 return -ENOMEM;
1213
1214 platform_set_drvdata(pdev, ddata);
1215 ddata->pdev = pdev;
1216
1217 if (dev_get_platdata(dev)) {
1218 r = dsicm_probe_pdata(pdev);
1219 if (r)
1220 return r;
1221 } else if (pdev->dev.of_node) {
1222 r = dsicm_probe_of(pdev);
1223 if (r)
1224 return r;
1225 } else {
1226 return -ENODEV;
1227 }
1228
1229 ddata->timings.x_res = 864;
1230 ddata->timings.y_res = 480;
1231 ddata->timings.pixelclock = 864 * 480 * 60;
1232
1233 dssdev = &ddata->dssdev;
1234 dssdev->dev = dev;
1235 dssdev->driver = &dsicm_ops;
1236 dssdev->panel.timings = ddata->timings;
1237 dssdev->type = OMAP_DISPLAY_TYPE_DSI;
1238 dssdev->owner = THIS_MODULE;
1239
1240 dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
1241 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
1242 OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
1243
1244 r = omapdss_register_display(dssdev);
1245 if (r) {
1246 dev_err(dev, "Failed to register panel\n");
1247 goto err_reg;
1248 }
1249
1250 mutex_init(&ddata->lock);
1251
1252 atomic_set(&ddata->do_update, 0);
1253
1254 if (gpio_is_valid(ddata->reset_gpio)) {
1255 r = devm_gpio_request_one(dev, ddata->reset_gpio,
1256 GPIOF_OUT_INIT_LOW, "taal rst");
1257 if (r) {
1258 dev_err(dev, "failed to request reset gpio\n");
1259 return r;
1260 }
1261 }
1262
1263 if (gpio_is_valid(ddata->ext_te_gpio)) {
1264 r = devm_gpio_request_one(dev, ddata->ext_te_gpio,
1265 GPIOF_IN, "taal irq");
1266 if (r) {
1267 dev_err(dev, "GPIO request failed\n");
1268 return r;
1269 }
1270
1271 r = devm_request_irq(dev, gpio_to_irq(ddata->ext_te_gpio),
1272 dsicm_te_isr,
1273 IRQF_TRIGGER_RISING,
1274 "taal vsync", ddata);
1275
1276 if (r) {
1277 dev_err(dev, "IRQ request failed\n");
1278 return r;
1279 }
1280
1281 INIT_DEFERRABLE_WORK(&ddata->te_timeout_work,
1282 dsicm_te_timeout_work_callback);
1283
1284 dev_dbg(dev, "Using GPIO TE\n");
1285 }
1286
1287 ddata->workqueue = create_singlethread_workqueue("dsicm_wq");
1288 if (ddata->workqueue == NULL) {
1289 dev_err(dev, "can't create workqueue\n");
1290 return -ENOMEM;
1291 }
1292 INIT_DELAYED_WORK(&ddata->ulps_work, dsicm_ulps_work);
1293
1294 dsicm_hw_reset(ddata);
1295
1296 if (ddata->use_dsi_backlight) {
1297 memset(&props, 0, sizeof(struct backlight_properties));
1298 props.max_brightness = 255;
1299
1300 props.type = BACKLIGHT_RAW;
1301 bldev = backlight_device_register(dev_name(dev),
1302 dev, ddata, &dsicm_bl_ops, &props);
1303 if (IS_ERR(bldev)) {
1304 r = PTR_ERR(bldev);
1305 goto err_bl;
1306 }
1307
1308 ddata->bldev = bldev;
1309
1310 bldev->props.fb_blank = FB_BLANK_UNBLANK;
1311 bldev->props.power = FB_BLANK_UNBLANK;
1312 bldev->props.brightness = 255;
1313
1314 dsicm_bl_update_status(bldev);
1315 }
1316
1317 r = sysfs_create_group(&dev->kobj, &dsicm_attr_group);
1318 if (r) {
1319 dev_err(dev, "failed to create sysfs files\n");
1320 goto err_sysfs_create;
1321 }
1322
1323 return 0;
1324
1325err_sysfs_create:
1326 if (bldev != NULL)
1327 backlight_device_unregister(bldev);
1328err_bl:
1329 destroy_workqueue(ddata->workqueue);
1330err_reg:
1331 return r;
1332}
1333
1334static int __exit dsicm_remove(struct platform_device *pdev)
1335{
1336 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
1337 struct omap_dss_device *dssdev = &ddata->dssdev;
1338 struct backlight_device *bldev;
1339
1340 dev_dbg(&pdev->dev, "remove\n");
1341
1342 omapdss_unregister_display(dssdev);
1343
1344 dsicm_disable(dssdev);
1345 dsicm_disconnect(dssdev);
1346
1347 sysfs_remove_group(&pdev->dev.kobj, &dsicm_attr_group);
1348
1349 bldev = ddata->bldev;
1350 if (bldev != NULL) {
1351 bldev->props.power = FB_BLANK_POWERDOWN;
1352 dsicm_bl_update_status(bldev);
1353 backlight_device_unregister(bldev);
1354 }
1355
1356 omap_dss_put_device(ddata->in);
1357
1358 dsicm_cancel_ulps_work(ddata);
1359 destroy_workqueue(ddata->workqueue);
1360
1361 /* reset, to be sure that the panel is in a valid state */
1362 dsicm_hw_reset(ddata);
1363
1364 return 0;
1365}
1366
1367static const struct of_device_id dsicm_of_match[] = {
1368 { .compatible = "omapdss,panel-dsi-cm", },
1369 {},
1370};
1371
1372MODULE_DEVICE_TABLE(of, dsicm_of_match);
1373
1374static struct platform_driver dsicm_driver = {
1375 .probe = dsicm_probe,
1376 .remove = __exit_p(dsicm_remove),
1377 .driver = {
1378 .name = "panel-dsi-cm",
1379 .owner = THIS_MODULE,
1380 .of_match_table = dsicm_of_match,
1381 },
1382};
1383
1384module_platform_driver(dsicm_driver);
1385
1386MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
1387MODULE_DESCRIPTION("Generic DSI Command Mode Panel Driver");
1388MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays-new/panel-lgphilips-lb035q02.c
deleted file mode 100644
index 2e6b513222d9..000000000000
--- a/drivers/video/omap2/displays-new/panel-lgphilips-lb035q02.c
+++ /dev/null
@@ -1,358 +0,0 @@
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 .pixelclock = 6500000,
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
deleted file mode 100644
index 996fa004b48c..000000000000
--- a/drivers/video/omap2/displays-new/panel-nec-nl8048hl11.c
+++ /dev/null
@@ -1,394 +0,0 @@
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 23800000
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 .pixelclock = 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
deleted file mode 100644
index b2f710be565d..000000000000
--- a/drivers/video/omap2/displays-new/panel-sharp-ls037v7dw01.c
+++ /dev/null
@@ -1,324 +0,0 @@
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 .pixelclock = 19200000,
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
deleted file mode 100644
index c7ba4d8b928a..000000000000
--- a/drivers/video/omap2/displays-new/panel-sony-acx565akm.c
+++ /dev/null
@@ -1,911 +0,0 @@
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#include <linux/of.h>
34#include <linux/of_gpio.h>
35
36#include <video/omapdss.h>
37#include <video/omap-panel-data.h>
38
39#define MIPID_CMD_READ_DISP_ID 0x04
40#define MIPID_CMD_READ_RED 0x06
41#define MIPID_CMD_READ_GREEN 0x07
42#define MIPID_CMD_READ_BLUE 0x08
43#define MIPID_CMD_READ_DISP_STATUS 0x09
44#define MIPID_CMD_RDDSDR 0x0F
45#define MIPID_CMD_SLEEP_IN 0x10
46#define MIPID_CMD_SLEEP_OUT 0x11
47#define MIPID_CMD_DISP_OFF 0x28
48#define MIPID_CMD_DISP_ON 0x29
49#define MIPID_CMD_WRITE_DISP_BRIGHTNESS 0x51
50#define MIPID_CMD_READ_DISP_BRIGHTNESS 0x52
51#define MIPID_CMD_WRITE_CTRL_DISP 0x53
52
53#define CTRL_DISP_BRIGHTNESS_CTRL_ON (1 << 5)
54#define CTRL_DISP_AMBIENT_LIGHT_CTRL_ON (1 << 4)
55#define CTRL_DISP_BACKLIGHT_ON (1 << 2)
56#define CTRL_DISP_AUTO_BRIGHTNESS_ON (1 << 1)
57
58#define MIPID_CMD_READ_CTRL_DISP 0x54
59#define MIPID_CMD_WRITE_CABC 0x55
60#define MIPID_CMD_READ_CABC 0x56
61
62#define MIPID_VER_LPH8923 3
63#define MIPID_VER_LS041Y3 4
64#define MIPID_VER_L4F00311 8
65#define MIPID_VER_ACX565AKM 9
66
67struct panel_drv_data {
68 struct omap_dss_device dssdev;
69 struct omap_dss_device *in;
70
71 int reset_gpio;
72 int datapairs;
73
74 struct omap_video_timings videomode;
75
76 char *name;
77 int enabled;
78 int model;
79 int revision;
80 u8 display_id[3];
81 unsigned has_bc:1;
82 unsigned has_cabc:1;
83 unsigned cabc_mode;
84 unsigned long hw_guard_end; /* next value of jiffies
85 when we can issue the
86 next sleep in/out command */
87 unsigned long hw_guard_wait; /* max guard time in jiffies */
88
89 struct spi_device *spi;
90 struct mutex mutex;
91
92 struct backlight_device *bl_dev;
93};
94
95static const struct omap_video_timings acx565akm_panel_timings = {
96 .x_res = 800,
97 .y_res = 480,
98 .pixelclock = 24000000,
99 .hfp = 28,
100 .hsw = 4,
101 .hbp = 24,
102 .vfp = 3,
103 .vsw = 3,
104 .vbp = 4,
105
106 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
107 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
108
109 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
110 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
111 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
112};
113
114#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
115
116static void acx565akm_transfer(struct panel_drv_data *ddata, int cmd,
117 const u8 *wbuf, int wlen, u8 *rbuf, int rlen)
118{
119 struct spi_message m;
120 struct spi_transfer *x, xfer[5];
121 int r;
122
123 BUG_ON(ddata->spi == NULL);
124
125 spi_message_init(&m);
126
127 memset(xfer, 0, sizeof(xfer));
128 x = &xfer[0];
129
130 cmd &= 0xff;
131 x->tx_buf = &cmd;
132 x->bits_per_word = 9;
133 x->len = 2;
134
135 if (rlen > 1 && wlen == 0) {
136 /*
137 * Between the command and the response data there is a
138 * dummy clock cycle. Add an extra bit after the command
139 * word to account for this.
140 */
141 x->bits_per_word = 10;
142 cmd <<= 1;
143 }
144 spi_message_add_tail(x, &m);
145
146 if (wlen) {
147 x++;
148 x->tx_buf = wbuf;
149 x->len = wlen;
150 x->bits_per_word = 9;
151 spi_message_add_tail(x, &m);
152 }
153
154 if (rlen) {
155 x++;
156 x->rx_buf = rbuf;
157 x->len = rlen;
158 spi_message_add_tail(x, &m);
159 }
160
161 r = spi_sync(ddata->spi, &m);
162 if (r < 0)
163 dev_dbg(&ddata->spi->dev, "spi_sync %d\n", r);
164}
165
166static inline void acx565akm_cmd(struct panel_drv_data *ddata, int cmd)
167{
168 acx565akm_transfer(ddata, cmd, NULL, 0, NULL, 0);
169}
170
171static inline void acx565akm_write(struct panel_drv_data *ddata,
172 int reg, const u8 *buf, int len)
173{
174 acx565akm_transfer(ddata, reg, buf, len, NULL, 0);
175}
176
177static inline void acx565akm_read(struct panel_drv_data *ddata,
178 int reg, u8 *buf, int len)
179{
180 acx565akm_transfer(ddata, reg, NULL, 0, buf, len);
181}
182
183static void hw_guard_start(struct panel_drv_data *ddata, int guard_msec)
184{
185 ddata->hw_guard_wait = msecs_to_jiffies(guard_msec);
186 ddata->hw_guard_end = jiffies + ddata->hw_guard_wait;
187}
188
189static void hw_guard_wait(struct panel_drv_data *ddata)
190{
191 unsigned long wait = ddata->hw_guard_end - jiffies;
192
193 if ((long)wait > 0 && wait <= ddata->hw_guard_wait) {
194 set_current_state(TASK_UNINTERRUPTIBLE);
195 schedule_timeout(wait);
196 }
197}
198
199static void set_sleep_mode(struct panel_drv_data *ddata, int on)
200{
201 int cmd;
202
203 if (on)
204 cmd = MIPID_CMD_SLEEP_IN;
205 else
206 cmd = MIPID_CMD_SLEEP_OUT;
207 /*
208 * We have to keep 120msec between sleep in/out commands.
209 * (8.2.15, 8.2.16).
210 */
211 hw_guard_wait(ddata);
212 acx565akm_cmd(ddata, cmd);
213 hw_guard_start(ddata, 120);
214}
215
216static void set_display_state(struct panel_drv_data *ddata, int enabled)
217{
218 int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
219
220 acx565akm_cmd(ddata, cmd);
221}
222
223static int panel_enabled(struct panel_drv_data *ddata)
224{
225 u32 disp_status;
226 int enabled;
227
228 acx565akm_read(ddata, MIPID_CMD_READ_DISP_STATUS,
229 (u8 *)&disp_status, 4);
230 disp_status = __be32_to_cpu(disp_status);
231 enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
232 dev_dbg(&ddata->spi->dev,
233 "LCD panel %senabled by bootloader (status 0x%04x)\n",
234 enabled ? "" : "not ", disp_status);
235 return enabled;
236}
237
238static int panel_detect(struct panel_drv_data *ddata)
239{
240 acx565akm_read(ddata, MIPID_CMD_READ_DISP_ID, ddata->display_id, 3);
241 dev_dbg(&ddata->spi->dev, "MIPI display ID: %02x%02x%02x\n",
242 ddata->display_id[0],
243 ddata->display_id[1],
244 ddata->display_id[2]);
245
246 switch (ddata->display_id[0]) {
247 case 0x10:
248 ddata->model = MIPID_VER_ACX565AKM;
249 ddata->name = "acx565akm";
250 ddata->has_bc = 1;
251 ddata->has_cabc = 1;
252 break;
253 case 0x29:
254 ddata->model = MIPID_VER_L4F00311;
255 ddata->name = "l4f00311";
256 break;
257 case 0x45:
258 ddata->model = MIPID_VER_LPH8923;
259 ddata->name = "lph8923";
260 break;
261 case 0x83:
262 ddata->model = MIPID_VER_LS041Y3;
263 ddata->name = "ls041y3";
264 break;
265 default:
266 ddata->name = "unknown";
267 dev_err(&ddata->spi->dev, "invalid display ID\n");
268 return -ENODEV;
269 }
270
271 ddata->revision = ddata->display_id[1];
272
273 dev_info(&ddata->spi->dev, "omapfb: %s rev %02x LCD detected\n",
274 ddata->name, ddata->revision);
275
276 return 0;
277}
278
279/*----------------------Backlight Control-------------------------*/
280
281static void enable_backlight_ctrl(struct panel_drv_data *ddata, int enable)
282{
283 u16 ctrl;
284
285 acx565akm_read(ddata, MIPID_CMD_READ_CTRL_DISP, (u8 *)&ctrl, 1);
286 if (enable) {
287 ctrl |= CTRL_DISP_BRIGHTNESS_CTRL_ON |
288 CTRL_DISP_BACKLIGHT_ON;
289 } else {
290 ctrl &= ~(CTRL_DISP_BRIGHTNESS_CTRL_ON |
291 CTRL_DISP_BACKLIGHT_ON);
292 }
293
294 ctrl |= 1 << 8;
295 acx565akm_write(ddata, MIPID_CMD_WRITE_CTRL_DISP, (u8 *)&ctrl, 2);
296}
297
298static void set_cabc_mode(struct panel_drv_data *ddata, unsigned mode)
299{
300 u16 cabc_ctrl;
301
302 ddata->cabc_mode = mode;
303 if (!ddata->enabled)
304 return;
305 cabc_ctrl = 0;
306 acx565akm_read(ddata, MIPID_CMD_READ_CABC, (u8 *)&cabc_ctrl, 1);
307 cabc_ctrl &= ~3;
308 cabc_ctrl |= (1 << 8) | (mode & 3);
309 acx565akm_write(ddata, MIPID_CMD_WRITE_CABC, (u8 *)&cabc_ctrl, 2);
310}
311
312static unsigned get_cabc_mode(struct panel_drv_data *ddata)
313{
314 return ddata->cabc_mode;
315}
316
317static unsigned get_hw_cabc_mode(struct panel_drv_data *ddata)
318{
319 u8 cabc_ctrl;
320
321 acx565akm_read(ddata, MIPID_CMD_READ_CABC, &cabc_ctrl, 1);
322 return cabc_ctrl & 3;
323}
324
325static void acx565akm_set_brightness(struct panel_drv_data *ddata, int level)
326{
327 int bv;
328
329 bv = level | (1 << 8);
330 acx565akm_write(ddata, MIPID_CMD_WRITE_DISP_BRIGHTNESS, (u8 *)&bv, 2);
331
332 if (level)
333 enable_backlight_ctrl(ddata, 1);
334 else
335 enable_backlight_ctrl(ddata, 0);
336}
337
338static int acx565akm_get_actual_brightness(struct panel_drv_data *ddata)
339{
340 u8 bv;
341
342 acx565akm_read(ddata, MIPID_CMD_READ_DISP_BRIGHTNESS, &bv, 1);
343
344 return bv;
345}
346
347
348static int acx565akm_bl_update_status(struct backlight_device *dev)
349{
350 struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
351 int level;
352
353 dev_dbg(&ddata->spi->dev, "%s\n", __func__);
354
355 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
356 dev->props.power == FB_BLANK_UNBLANK)
357 level = dev->props.brightness;
358 else
359 level = 0;
360
361 if (ddata->has_bc)
362 acx565akm_set_brightness(ddata, level);
363 else
364 return -ENODEV;
365
366 return 0;
367}
368
369static int acx565akm_bl_get_intensity(struct backlight_device *dev)
370{
371 struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
372
373 dev_dbg(&dev->dev, "%s\n", __func__);
374
375 if (!ddata->has_bc)
376 return -ENODEV;
377
378 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
379 dev->props.power == FB_BLANK_UNBLANK) {
380 if (ddata->has_bc)
381 return acx565akm_get_actual_brightness(ddata);
382 else
383 return dev->props.brightness;
384 }
385
386 return 0;
387}
388
389static int acx565akm_bl_update_status_locked(struct backlight_device *dev)
390{
391 struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
392 int r;
393
394 mutex_lock(&ddata->mutex);
395 r = acx565akm_bl_update_status(dev);
396 mutex_unlock(&ddata->mutex);
397
398 return r;
399}
400
401static int acx565akm_bl_get_intensity_locked(struct backlight_device *dev)
402{
403 struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
404 int r;
405
406 mutex_lock(&ddata->mutex);
407 r = acx565akm_bl_get_intensity(dev);
408 mutex_unlock(&ddata->mutex);
409
410 return r;
411}
412
413static const struct backlight_ops acx565akm_bl_ops = {
414 .get_brightness = acx565akm_bl_get_intensity_locked,
415 .update_status = acx565akm_bl_update_status_locked,
416};
417
418/*--------------------Auto Brightness control via Sysfs---------------------*/
419
420static const char * const cabc_modes[] = {
421 "off", /* always used when CABC is not supported */
422 "ui",
423 "still-image",
424 "moving-image",
425};
426
427static ssize_t show_cabc_mode(struct device *dev,
428 struct device_attribute *attr,
429 char *buf)
430{
431 struct panel_drv_data *ddata = dev_get_drvdata(dev);
432 const char *mode_str;
433 int mode;
434 int len;
435
436 if (!ddata->has_cabc)
437 mode = 0;
438 else
439 mode = get_cabc_mode(ddata);
440 mode_str = "unknown";
441 if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes))
442 mode_str = cabc_modes[mode];
443 len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str);
444
445 return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1;
446}
447
448static ssize_t store_cabc_mode(struct device *dev,
449 struct device_attribute *attr,
450 const char *buf, size_t count)
451{
452 struct panel_drv_data *ddata = dev_get_drvdata(dev);
453 int i;
454
455 for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
456 const char *mode_str = cabc_modes[i];
457 int cmp_len = strlen(mode_str);
458
459 if (count > 0 && buf[count - 1] == '\n')
460 count--;
461 if (count != cmp_len)
462 continue;
463
464 if (strncmp(buf, mode_str, cmp_len) == 0)
465 break;
466 }
467
468 if (i == ARRAY_SIZE(cabc_modes))
469 return -EINVAL;
470
471 if (!ddata->has_cabc && i != 0)
472 return -EINVAL;
473
474 mutex_lock(&ddata->mutex);
475 set_cabc_mode(ddata, i);
476 mutex_unlock(&ddata->mutex);
477
478 return count;
479}
480
481static ssize_t show_cabc_available_modes(struct device *dev,
482 struct device_attribute *attr,
483 char *buf)
484{
485 struct panel_drv_data *ddata = dev_get_drvdata(dev);
486 int len;
487 int i;
488
489 if (!ddata->has_cabc)
490 return snprintf(buf, PAGE_SIZE, "%s\n", cabc_modes[0]);
491
492 for (i = 0, len = 0;
493 len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++)
494 len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s",
495 i ? " " : "", cabc_modes[i],
496 i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : "");
497
498 return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
499}
500
501static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
502 show_cabc_mode, store_cabc_mode);
503static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
504 show_cabc_available_modes, NULL);
505
506static struct attribute *bldev_attrs[] = {
507 &dev_attr_cabc_mode.attr,
508 &dev_attr_cabc_available_modes.attr,
509 NULL,
510};
511
512static struct attribute_group bldev_attr_group = {
513 .attrs = bldev_attrs,
514};
515
516static int acx565akm_connect(struct omap_dss_device *dssdev)
517{
518 struct panel_drv_data *ddata = to_panel_data(dssdev);
519 struct omap_dss_device *in = ddata->in;
520 int r;
521
522 if (omapdss_device_is_connected(dssdev))
523 return 0;
524
525 r = in->ops.sdi->connect(in, dssdev);
526 if (r)
527 return r;
528
529 return 0;
530}
531
532static void acx565akm_disconnect(struct omap_dss_device *dssdev)
533{
534 struct panel_drv_data *ddata = to_panel_data(dssdev);
535 struct omap_dss_device *in = ddata->in;
536
537 if (!omapdss_device_is_connected(dssdev))
538 return;
539
540 in->ops.sdi->disconnect(in, dssdev);
541}
542
543static int acx565akm_panel_power_on(struct omap_dss_device *dssdev)
544{
545 struct panel_drv_data *ddata = to_panel_data(dssdev);
546 struct omap_dss_device *in = ddata->in;
547 int r;
548
549 dev_dbg(&ddata->spi->dev, "%s\n", __func__);
550
551 in->ops.sdi->set_timings(in, &ddata->videomode);
552
553 if (ddata->datapairs > 0)
554 in->ops.sdi->set_datapairs(in, ddata->datapairs);
555
556 r = in->ops.sdi->enable(in);
557 if (r) {
558 pr_err("%s sdi enable failed\n", __func__);
559 return r;
560 }
561
562 /*FIXME tweak me */
563 msleep(50);
564
565 if (gpio_is_valid(ddata->reset_gpio))
566 gpio_set_value(ddata->reset_gpio, 1);
567
568 if (ddata->enabled) {
569 dev_dbg(&ddata->spi->dev, "panel already enabled\n");
570 return 0;
571 }
572
573 /*
574 * We have to meet all the following delay requirements:
575 * 1. tRW: reset pulse width 10usec (7.12.1)
576 * 2. tRT: reset cancel time 5msec (7.12.1)
577 * 3. Providing PCLK,HS,VS signals for 2 frames = ~50msec worst
578 * case (7.6.2)
579 * 4. 120msec before the sleep out command (7.12.1)
580 */
581 msleep(120);
582
583 set_sleep_mode(ddata, 0);
584 ddata->enabled = 1;
585
586 /* 5msec between sleep out and the next command. (8.2.16) */
587 usleep_range(5000, 10000);
588 set_display_state(ddata, 1);
589 set_cabc_mode(ddata, ddata->cabc_mode);
590
591 return acx565akm_bl_update_status(ddata->bl_dev);
592}
593
594static void acx565akm_panel_power_off(struct omap_dss_device *dssdev)
595{
596 struct panel_drv_data *ddata = to_panel_data(dssdev);
597 struct omap_dss_device *in = ddata->in;
598
599 dev_dbg(dssdev->dev, "%s\n", __func__);
600
601 if (!ddata->enabled)
602 return;
603
604 set_display_state(ddata, 0);
605 set_sleep_mode(ddata, 1);
606 ddata->enabled = 0;
607 /*
608 * We have to provide PCLK,HS,VS signals for 2 frames (worst case
609 * ~50msec) after sending the sleep in command and asserting the
610 * reset signal. We probably could assert the reset w/o the delay
611 * but we still delay to avoid possible artifacts. (7.6.1)
612 */
613 msleep(50);
614
615 if (gpio_is_valid(ddata->reset_gpio))
616 gpio_set_value(ddata->reset_gpio, 0);
617
618 /* FIXME need to tweak this delay */
619 msleep(100);
620
621 in->ops.sdi->disable(in);
622}
623
624static int acx565akm_enable(struct omap_dss_device *dssdev)
625{
626 struct panel_drv_data *ddata = to_panel_data(dssdev);
627 int r;
628
629 dev_dbg(dssdev->dev, "%s\n", __func__);
630
631 if (!omapdss_device_is_connected(dssdev))
632 return -ENODEV;
633
634 if (omapdss_device_is_enabled(dssdev))
635 return 0;
636
637 mutex_lock(&ddata->mutex);
638 r = acx565akm_panel_power_on(dssdev);
639 mutex_unlock(&ddata->mutex);
640 if (r)
641 return r;
642
643 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
644
645 return 0;
646}
647
648static void acx565akm_disable(struct omap_dss_device *dssdev)
649{
650 struct panel_drv_data *ddata = to_panel_data(dssdev);
651
652 dev_dbg(dssdev->dev, "%s\n", __func__);
653
654 if (!omapdss_device_is_enabled(dssdev))
655 return;
656
657 mutex_lock(&ddata->mutex);
658 acx565akm_panel_power_off(dssdev);
659 mutex_unlock(&ddata->mutex);
660
661 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
662}
663
664static void acx565akm_set_timings(struct omap_dss_device *dssdev,
665 struct omap_video_timings *timings)
666{
667 struct panel_drv_data *ddata = to_panel_data(dssdev);
668 struct omap_dss_device *in = ddata->in;
669
670 ddata->videomode = *timings;
671 dssdev->panel.timings = *timings;
672
673 in->ops.sdi->set_timings(in, timings);
674}
675
676static void acx565akm_get_timings(struct omap_dss_device *dssdev,
677 struct omap_video_timings *timings)
678{
679 struct panel_drv_data *ddata = to_panel_data(dssdev);
680
681 *timings = ddata->videomode;
682}
683
684static int acx565akm_check_timings(struct omap_dss_device *dssdev,
685 struct omap_video_timings *timings)
686{
687 struct panel_drv_data *ddata = to_panel_data(dssdev);
688 struct omap_dss_device *in = ddata->in;
689
690 return in->ops.sdi->check_timings(in, timings);
691}
692
693static struct omap_dss_driver acx565akm_ops = {
694 .connect = acx565akm_connect,
695 .disconnect = acx565akm_disconnect,
696
697 .enable = acx565akm_enable,
698 .disable = acx565akm_disable,
699
700 .set_timings = acx565akm_set_timings,
701 .get_timings = acx565akm_get_timings,
702 .check_timings = acx565akm_check_timings,
703
704 .get_resolution = omapdss_default_get_resolution,
705};
706
707static int acx565akm_probe_pdata(struct spi_device *spi)
708{
709 const struct panel_acx565akm_platform_data *pdata;
710 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
711 struct omap_dss_device *dssdev, *in;
712
713 pdata = dev_get_platdata(&spi->dev);
714
715 ddata->reset_gpio = pdata->reset_gpio;
716
717 in = omap_dss_find_output(pdata->source);
718 if (in == NULL) {
719 dev_err(&spi->dev, "failed to find video source '%s'\n",
720 pdata->source);
721 return -EPROBE_DEFER;
722 }
723 ddata->in = in;
724
725 ddata->datapairs = pdata->datapairs;
726
727 dssdev = &ddata->dssdev;
728 dssdev->name = pdata->name;
729
730 return 0;
731}
732
733static int acx565akm_probe_of(struct spi_device *spi)
734{
735 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
736 struct device_node *np = spi->dev.of_node;
737
738 ddata->reset_gpio = of_get_named_gpio(np, "reset-gpios", 0);
739
740 ddata->in = omapdss_of_find_source_for_first_ep(np);
741 if (IS_ERR(ddata->in)) {
742 dev_err(&spi->dev, "failed to find video source\n");
743 return PTR_ERR(ddata->in);
744 }
745
746 return 0;
747}
748
749static int acx565akm_probe(struct spi_device *spi)
750{
751 struct panel_drv_data *ddata;
752 struct omap_dss_device *dssdev;
753 struct backlight_device *bldev;
754 int max_brightness, brightness;
755 struct backlight_properties props;
756 int r;
757
758 dev_dbg(&spi->dev, "%s\n", __func__);
759
760 spi->mode = SPI_MODE_3;
761
762 ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
763 if (ddata == NULL)
764 return -ENOMEM;
765
766 dev_set_drvdata(&spi->dev, ddata);
767
768 ddata->spi = spi;
769
770 mutex_init(&ddata->mutex);
771
772 if (dev_get_platdata(&spi->dev)) {
773 r = acx565akm_probe_pdata(spi);
774 if (r)
775 return r;
776 } else if (spi->dev.of_node) {
777 r = acx565akm_probe_of(spi);
778 if (r)
779 return r;
780 } else {
781 dev_err(&spi->dev, "platform data missing!\n");
782 return -ENODEV;
783 }
784
785 if (gpio_is_valid(ddata->reset_gpio)) {
786 r = devm_gpio_request_one(&spi->dev, ddata->reset_gpio,
787 GPIOF_OUT_INIT_LOW, "lcd reset");
788 if (r)
789 goto err_gpio;
790 }
791
792 if (gpio_is_valid(ddata->reset_gpio))
793 gpio_set_value(ddata->reset_gpio, 1);
794
795 /*
796 * After reset we have to wait 5 msec before the first
797 * command can be sent.
798 */
799 usleep_range(5000, 10000);
800
801 ddata->enabled = panel_enabled(ddata);
802
803 r = panel_detect(ddata);
804
805 if (!ddata->enabled && gpio_is_valid(ddata->reset_gpio))
806 gpio_set_value(ddata->reset_gpio, 0);
807
808 if (r) {
809 dev_err(&spi->dev, "%s panel detect error\n", __func__);
810 goto err_detect;
811 }
812
813 memset(&props, 0, sizeof(props));
814 props.fb_blank = FB_BLANK_UNBLANK;
815 props.power = FB_BLANK_UNBLANK;
816 props.type = BACKLIGHT_RAW;
817
818 bldev = backlight_device_register("acx565akm", &ddata->spi->dev,
819 ddata, &acx565akm_bl_ops, &props);
820 ddata->bl_dev = bldev;
821 if (ddata->has_cabc) {
822 r = sysfs_create_group(&bldev->dev.kobj, &bldev_attr_group);
823 if (r) {
824 dev_err(&bldev->dev,
825 "%s failed to create sysfs files\n", __func__);
826 goto err_sysfs;
827 }
828 ddata->cabc_mode = get_hw_cabc_mode(ddata);
829 }
830
831 max_brightness = 255;
832
833 if (ddata->has_bc)
834 brightness = acx565akm_get_actual_brightness(ddata);
835 else
836 brightness = 0;
837
838 bldev->props.max_brightness = max_brightness;
839 bldev->props.brightness = brightness;
840
841 acx565akm_bl_update_status(bldev);
842
843
844 ddata->videomode = acx565akm_panel_timings;
845
846 dssdev = &ddata->dssdev;
847 dssdev->dev = &spi->dev;
848 dssdev->driver = &acx565akm_ops;
849 dssdev->type = OMAP_DISPLAY_TYPE_SDI;
850 dssdev->owner = THIS_MODULE;
851 dssdev->panel.timings = ddata->videomode;
852
853 r = omapdss_register_display(dssdev);
854 if (r) {
855 dev_err(&spi->dev, "Failed to register panel\n");
856 goto err_reg;
857 }
858
859 return 0;
860
861err_reg:
862 sysfs_remove_group(&bldev->dev.kobj, &bldev_attr_group);
863err_sysfs:
864 backlight_device_unregister(bldev);
865err_detect:
866err_gpio:
867 omap_dss_put_device(ddata->in);
868 return r;
869}
870
871static int acx565akm_remove(struct spi_device *spi)
872{
873 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
874 struct omap_dss_device *dssdev = &ddata->dssdev;
875 struct omap_dss_device *in = ddata->in;
876
877 dev_dbg(&ddata->spi->dev, "%s\n", __func__);
878
879 sysfs_remove_group(&ddata->bl_dev->dev.kobj, &bldev_attr_group);
880 backlight_device_unregister(ddata->bl_dev);
881
882 omapdss_unregister_display(dssdev);
883
884 acx565akm_disable(dssdev);
885 acx565akm_disconnect(dssdev);
886
887 omap_dss_put_device(in);
888
889 return 0;
890}
891
892static const struct of_device_id acx565akm_of_match[] = {
893 { .compatible = "omapdss,sony,acx565akm", },
894 {},
895};
896
897static struct spi_driver acx565akm_driver = {
898 .driver = {
899 .name = "acx565akm",
900 .owner = THIS_MODULE,
901 .of_match_table = acx565akm_of_match,
902 },
903 .probe = acx565akm_probe,
904 .remove = acx565akm_remove,
905};
906
907module_spi_driver(acx565akm_driver);
908
909MODULE_AUTHOR("Nokia Corporation");
910MODULE_DESCRIPTION("acx565akm LCD Driver");
911MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/panel-tpo-td028ttec1.c b/drivers/video/omap2/displays-new/panel-tpo-td028ttec1.c
deleted file mode 100644
index fae6adc005a7..000000000000
--- a/drivers/video/omap2/displays-new/panel-tpo-td028ttec1.c
+++ /dev/null
@@ -1,480 +0,0 @@
1/*
2 * Toppoly TD028TTEC1 panel support
3 *
4 * Copyright (C) 2008 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Neo 1973 code (jbt6k74.c):
8 * Copyright (C) 2006-2007 by OpenMoko, Inc.
9 * Author: Harald Welte <laforge@openmoko.org>
10 *
11 * Ported and adapted from Neo 1973 U-Boot by:
12 * H. Nikolaus Schaller <hns@goldelico.com>
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License version 2 as published by
16 * the Free Software Foundation.
17 *
18 * This program is distributed in the hope that it will be useful, but WITHOUT
19 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
21 * more details.
22 *
23 * You should have received a copy of the GNU General Public License along with
24 * this program. If not, see <http://www.gnu.org/licenses/>.
25 */
26
27#include <linux/module.h>
28#include <linux/delay.h>
29#include <linux/spi/spi.h>
30#include <linux/gpio.h>
31#include <video/omapdss.h>
32#include <video/omap-panel-data.h>
33
34struct panel_drv_data {
35 struct omap_dss_device dssdev;
36 struct omap_dss_device *in;
37
38 int data_lines;
39
40 struct omap_video_timings videomode;
41
42 struct spi_device *spi_dev;
43};
44
45static struct omap_video_timings td028ttec1_panel_timings = {
46 .x_res = 480,
47 .y_res = 640,
48 .pixelclock = 22153000,
49 .hfp = 24,
50 .hsw = 8,
51 .hbp = 8,
52 .vfp = 4,
53 .vsw = 2,
54 .vbp = 2,
55
56 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
57 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
58
59 .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
60 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
61 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
62};
63
64#define JBT_COMMAND 0x000
65#define JBT_DATA 0x100
66
67static int jbt_ret_write_0(struct panel_drv_data *ddata, u8 reg)
68{
69 int rc;
70 u16 tx_buf = JBT_COMMAND | reg;
71
72 rc = spi_write(ddata->spi_dev, (u8 *)&tx_buf,
73 1*sizeof(u16));
74 if (rc != 0)
75 dev_err(&ddata->spi_dev->dev,
76 "jbt_ret_write_0 spi_write ret %d\n", rc);
77
78 return rc;
79}
80
81static int jbt_reg_write_1(struct panel_drv_data *ddata, u8 reg, u8 data)
82{
83 int rc;
84 u16 tx_buf[2];
85
86 tx_buf[0] = JBT_COMMAND | reg;
87 tx_buf[1] = JBT_DATA | data;
88 rc = spi_write(ddata->spi_dev, (u8 *)tx_buf,
89 2*sizeof(u16));
90 if (rc != 0)
91 dev_err(&ddata->spi_dev->dev,
92 "jbt_reg_write_1 spi_write ret %d\n", rc);
93
94 return rc;
95}
96
97static int jbt_reg_write_2(struct panel_drv_data *ddata, u8 reg, u16 data)
98{
99 int rc;
100 u16 tx_buf[3];
101
102 tx_buf[0] = JBT_COMMAND | reg;
103 tx_buf[1] = JBT_DATA | (data >> 8);
104 tx_buf[2] = JBT_DATA | (data & 0xff);
105
106 rc = spi_write(ddata->spi_dev, (u8 *)tx_buf,
107 3*sizeof(u16));
108
109 if (rc != 0)
110 dev_err(&ddata->spi_dev->dev,
111 "jbt_reg_write_2 spi_write ret %d\n", rc);
112
113 return rc;
114}
115
116enum jbt_register {
117 JBT_REG_SLEEP_IN = 0x10,
118 JBT_REG_SLEEP_OUT = 0x11,
119
120 JBT_REG_DISPLAY_OFF = 0x28,
121 JBT_REG_DISPLAY_ON = 0x29,
122
123 JBT_REG_RGB_FORMAT = 0x3a,
124 JBT_REG_QUAD_RATE = 0x3b,
125
126 JBT_REG_POWER_ON_OFF = 0xb0,
127 JBT_REG_BOOSTER_OP = 0xb1,
128 JBT_REG_BOOSTER_MODE = 0xb2,
129 JBT_REG_BOOSTER_FREQ = 0xb3,
130 JBT_REG_OPAMP_SYSCLK = 0xb4,
131 JBT_REG_VSC_VOLTAGE = 0xb5,
132 JBT_REG_VCOM_VOLTAGE = 0xb6,
133 JBT_REG_EXT_DISPL = 0xb7,
134 JBT_REG_OUTPUT_CONTROL = 0xb8,
135 JBT_REG_DCCLK_DCEV = 0xb9,
136 JBT_REG_DISPLAY_MODE1 = 0xba,
137 JBT_REG_DISPLAY_MODE2 = 0xbb,
138 JBT_REG_DISPLAY_MODE = 0xbc,
139 JBT_REG_ASW_SLEW = 0xbd,
140 JBT_REG_DUMMY_DISPLAY = 0xbe,
141 JBT_REG_DRIVE_SYSTEM = 0xbf,
142
143 JBT_REG_SLEEP_OUT_FR_A = 0xc0,
144 JBT_REG_SLEEP_OUT_FR_B = 0xc1,
145 JBT_REG_SLEEP_OUT_FR_C = 0xc2,
146 JBT_REG_SLEEP_IN_LCCNT_D = 0xc3,
147 JBT_REG_SLEEP_IN_LCCNT_E = 0xc4,
148 JBT_REG_SLEEP_IN_LCCNT_F = 0xc5,
149 JBT_REG_SLEEP_IN_LCCNT_G = 0xc6,
150
151 JBT_REG_GAMMA1_FINE_1 = 0xc7,
152 JBT_REG_GAMMA1_FINE_2 = 0xc8,
153 JBT_REG_GAMMA1_INCLINATION = 0xc9,
154 JBT_REG_GAMMA1_BLUE_OFFSET = 0xca,
155
156 JBT_REG_BLANK_CONTROL = 0xcf,
157 JBT_REG_BLANK_TH_TV = 0xd0,
158 JBT_REG_CKV_ON_OFF = 0xd1,
159 JBT_REG_CKV_1_2 = 0xd2,
160 JBT_REG_OEV_TIMING = 0xd3,
161 JBT_REG_ASW_TIMING_1 = 0xd4,
162 JBT_REG_ASW_TIMING_2 = 0xd5,
163
164 JBT_REG_HCLOCK_VGA = 0xec,
165 JBT_REG_HCLOCK_QVGA = 0xed,
166};
167
168#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
169
170static int td028ttec1_panel_connect(struct omap_dss_device *dssdev)
171{
172 struct panel_drv_data *ddata = to_panel_data(dssdev);
173 struct omap_dss_device *in = ddata->in;
174 int r;
175
176 if (omapdss_device_is_connected(dssdev))
177 return 0;
178
179 r = in->ops.dpi->connect(in, dssdev);
180 if (r)
181 return r;
182
183 return 0;
184}
185
186static void td028ttec1_panel_disconnect(struct omap_dss_device *dssdev)
187{
188 struct panel_drv_data *ddata = to_panel_data(dssdev);
189 struct omap_dss_device *in = ddata->in;
190
191 if (!omapdss_device_is_connected(dssdev))
192 return;
193
194 in->ops.dpi->disconnect(in, dssdev);
195}
196
197static int td028ttec1_panel_enable(struct omap_dss_device *dssdev)
198{
199 struct panel_drv_data *ddata = to_panel_data(dssdev);
200 struct omap_dss_device *in = ddata->in;
201 int r;
202
203 if (!omapdss_device_is_connected(dssdev))
204 return -ENODEV;
205
206 if (omapdss_device_is_enabled(dssdev))
207 return 0;
208
209 in->ops.dpi->set_data_lines(in, ddata->data_lines);
210 in->ops.dpi->set_timings(in, &ddata->videomode);
211
212 r = in->ops.dpi->enable(in);
213 if (r)
214 return r;
215
216 dev_dbg(dssdev->dev, "td028ttec1_panel_enable() - state %d\n",
217 dssdev->state);
218
219 /* three times command zero */
220 r |= jbt_ret_write_0(ddata, 0x00);
221 usleep_range(1000, 2000);
222 r |= jbt_ret_write_0(ddata, 0x00);
223 usleep_range(1000, 2000);
224 r |= jbt_ret_write_0(ddata, 0x00);
225 usleep_range(1000, 2000);
226
227 if (r) {
228 dev_warn(dssdev->dev, "transfer error\n");
229 goto transfer_err;
230 }
231
232 /* deep standby out */
233 r |= jbt_reg_write_1(ddata, JBT_REG_POWER_ON_OFF, 0x17);
234
235 /* RGB I/F on, RAM write off, QVGA through, SIGCON enable */
236 r |= jbt_reg_write_1(ddata, JBT_REG_DISPLAY_MODE, 0x80);
237
238 /* Quad mode off */
239 r |= jbt_reg_write_1(ddata, JBT_REG_QUAD_RATE, 0x00);
240
241 /* AVDD on, XVDD on */
242 r |= jbt_reg_write_1(ddata, JBT_REG_POWER_ON_OFF, 0x16);
243
244 /* Output control */
245 r |= jbt_reg_write_2(ddata, JBT_REG_OUTPUT_CONTROL, 0xfff9);
246
247 /* Sleep mode off */
248 r |= jbt_ret_write_0(ddata, JBT_REG_SLEEP_OUT);
249
250 /* at this point we have like 50% grey */
251
252 /* initialize register set */
253 r |= jbt_reg_write_1(ddata, JBT_REG_DISPLAY_MODE1, 0x01);
254 r |= jbt_reg_write_1(ddata, JBT_REG_DISPLAY_MODE2, 0x00);
255 r |= jbt_reg_write_1(ddata, JBT_REG_RGB_FORMAT, 0x60);
256 r |= jbt_reg_write_1(ddata, JBT_REG_DRIVE_SYSTEM, 0x10);
257 r |= jbt_reg_write_1(ddata, JBT_REG_BOOSTER_OP, 0x56);
258 r |= jbt_reg_write_1(ddata, JBT_REG_BOOSTER_MODE, 0x33);
259 r |= jbt_reg_write_1(ddata, JBT_REG_BOOSTER_FREQ, 0x11);
260 r |= jbt_reg_write_1(ddata, JBT_REG_BOOSTER_FREQ, 0x11);
261 r |= jbt_reg_write_1(ddata, JBT_REG_OPAMP_SYSCLK, 0x02);
262 r |= jbt_reg_write_1(ddata, JBT_REG_VSC_VOLTAGE, 0x2b);
263 r |= jbt_reg_write_1(ddata, JBT_REG_VCOM_VOLTAGE, 0x40);
264 r |= jbt_reg_write_1(ddata, JBT_REG_EXT_DISPL, 0x03);
265 r |= jbt_reg_write_1(ddata, JBT_REG_DCCLK_DCEV, 0x04);
266 /*
267 * default of 0x02 in JBT_REG_ASW_SLEW responsible for 72Hz requirement
268 * to avoid red / blue flicker
269 */
270 r |= jbt_reg_write_1(ddata, JBT_REG_ASW_SLEW, 0x04);
271 r |= jbt_reg_write_1(ddata, JBT_REG_DUMMY_DISPLAY, 0x00);
272
273 r |= jbt_reg_write_1(ddata, JBT_REG_SLEEP_OUT_FR_A, 0x11);
274 r |= jbt_reg_write_1(ddata, JBT_REG_SLEEP_OUT_FR_B, 0x11);
275 r |= jbt_reg_write_1(ddata, JBT_REG_SLEEP_OUT_FR_C, 0x11);
276 r |= jbt_reg_write_2(ddata, JBT_REG_SLEEP_IN_LCCNT_D, 0x2040);
277 r |= jbt_reg_write_2(ddata, JBT_REG_SLEEP_IN_LCCNT_E, 0x60c0);
278 r |= jbt_reg_write_2(ddata, JBT_REG_SLEEP_IN_LCCNT_F, 0x1020);
279 r |= jbt_reg_write_2(ddata, JBT_REG_SLEEP_IN_LCCNT_G, 0x60c0);
280
281 r |= jbt_reg_write_2(ddata, JBT_REG_GAMMA1_FINE_1, 0x5533);
282 r |= jbt_reg_write_1(ddata, JBT_REG_GAMMA1_FINE_2, 0x00);
283 r |= jbt_reg_write_1(ddata, JBT_REG_GAMMA1_INCLINATION, 0x00);
284 r |= jbt_reg_write_1(ddata, JBT_REG_GAMMA1_BLUE_OFFSET, 0x00);
285
286 r |= jbt_reg_write_2(ddata, JBT_REG_HCLOCK_VGA, 0x1f0);
287 r |= jbt_reg_write_1(ddata, JBT_REG_BLANK_CONTROL, 0x02);
288 r |= jbt_reg_write_2(ddata, JBT_REG_BLANK_TH_TV, 0x0804);
289
290 r |= jbt_reg_write_1(ddata, JBT_REG_CKV_ON_OFF, 0x01);
291 r |= jbt_reg_write_2(ddata, JBT_REG_CKV_1_2, 0x0000);
292
293 r |= jbt_reg_write_2(ddata, JBT_REG_OEV_TIMING, 0x0d0e);
294 r |= jbt_reg_write_2(ddata, JBT_REG_ASW_TIMING_1, 0x11a4);
295 r |= jbt_reg_write_1(ddata, JBT_REG_ASW_TIMING_2, 0x0e);
296
297 r |= jbt_ret_write_0(ddata, JBT_REG_DISPLAY_ON);
298
299 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
300
301transfer_err:
302
303 return r ? -EIO : 0;
304}
305
306static void td028ttec1_panel_disable(struct omap_dss_device *dssdev)
307{
308 struct panel_drv_data *ddata = to_panel_data(dssdev);
309 struct omap_dss_device *in = ddata->in;
310
311 if (!omapdss_device_is_enabled(dssdev))
312 return;
313
314 dev_dbg(dssdev->dev, "td028ttec1_panel_disable()\n");
315
316 jbt_ret_write_0(ddata, JBT_REG_DISPLAY_OFF);
317 jbt_reg_write_2(ddata, JBT_REG_OUTPUT_CONTROL, 0x8002);
318 jbt_ret_write_0(ddata, JBT_REG_SLEEP_IN);
319 jbt_reg_write_1(ddata, JBT_REG_POWER_ON_OFF, 0x00);
320
321 in->ops.dpi->disable(in);
322
323 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
324}
325
326static void td028ttec1_panel_set_timings(struct omap_dss_device *dssdev,
327 struct omap_video_timings *timings)
328{
329 struct panel_drv_data *ddata = to_panel_data(dssdev);
330 struct omap_dss_device *in = ddata->in;
331
332 ddata->videomode = *timings;
333 dssdev->panel.timings = *timings;
334
335 in->ops.dpi->set_timings(in, timings);
336}
337
338static void td028ttec1_panel_get_timings(struct omap_dss_device *dssdev,
339 struct omap_video_timings *timings)
340{
341 struct panel_drv_data *ddata = to_panel_data(dssdev);
342
343 *timings = ddata->videomode;
344}
345
346static int td028ttec1_panel_check_timings(struct omap_dss_device *dssdev,
347 struct omap_video_timings *timings)
348{
349 struct panel_drv_data *ddata = to_panel_data(dssdev);
350 struct omap_dss_device *in = ddata->in;
351
352 return in->ops.dpi->check_timings(in, timings);
353}
354
355static struct omap_dss_driver td028ttec1_ops = {
356 .connect = td028ttec1_panel_connect,
357 .disconnect = td028ttec1_panel_disconnect,
358
359 .enable = td028ttec1_panel_enable,
360 .disable = td028ttec1_panel_disable,
361
362 .set_timings = td028ttec1_panel_set_timings,
363 .get_timings = td028ttec1_panel_get_timings,
364 .check_timings = td028ttec1_panel_check_timings,
365};
366
367static int td028ttec1_panel_probe_pdata(struct spi_device *spi)
368{
369 const struct panel_tpo_td028ttec1_platform_data *pdata;
370 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
371 struct omap_dss_device *dssdev, *in;
372
373 pdata = dev_get_platdata(&spi->dev);
374
375 in = omap_dss_find_output(pdata->source);
376 if (in == NULL) {
377 dev_err(&spi->dev, "failed to find video source '%s'\n",
378 pdata->source);
379 return -EPROBE_DEFER;
380 }
381
382 ddata->in = in;
383
384 ddata->data_lines = pdata->data_lines;
385
386 dssdev = &ddata->dssdev;
387 dssdev->name = pdata->name;
388
389 return 0;
390}
391
392static int td028ttec1_panel_probe(struct spi_device *spi)
393{
394 struct panel_drv_data *ddata;
395 struct omap_dss_device *dssdev;
396 int r;
397
398 dev_dbg(&spi->dev, "%s\n", __func__);
399
400 spi->bits_per_word = 9;
401 spi->mode = SPI_MODE_3;
402
403 r = spi_setup(spi);
404 if (r < 0) {
405 dev_err(&spi->dev, "spi_setup failed: %d\n", r);
406 return r;
407 }
408
409 ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
410 if (ddata == NULL)
411 return -ENOMEM;
412
413 dev_set_drvdata(&spi->dev, ddata);
414
415 ddata->spi_dev = spi;
416
417 if (dev_get_platdata(&spi->dev)) {
418 r = td028ttec1_panel_probe_pdata(spi);
419 if (r)
420 return r;
421 } else {
422 return -ENODEV;
423 }
424
425 ddata->videomode = td028ttec1_panel_timings;
426
427 dssdev = &ddata->dssdev;
428 dssdev->dev = &spi->dev;
429 dssdev->driver = &td028ttec1_ops;
430 dssdev->type = OMAP_DISPLAY_TYPE_DPI;
431 dssdev->owner = THIS_MODULE;
432 dssdev->panel.timings = ddata->videomode;
433 dssdev->phy.dpi.data_lines = ddata->data_lines;
434
435 r = omapdss_register_display(dssdev);
436 if (r) {
437 dev_err(&spi->dev, "Failed to register panel\n");
438 goto err_reg;
439 }
440
441 return 0;
442
443err_reg:
444 omap_dss_put_device(ddata->in);
445 return r;
446}
447
448static int td028ttec1_panel_remove(struct spi_device *spi)
449{
450 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
451 struct omap_dss_device *dssdev = &ddata->dssdev;
452 struct omap_dss_device *in = ddata->in;
453
454 dev_dbg(&ddata->spi_dev->dev, "%s\n", __func__);
455
456 omapdss_unregister_display(dssdev);
457
458 td028ttec1_panel_disable(dssdev);
459 td028ttec1_panel_disconnect(dssdev);
460
461 omap_dss_put_device(in);
462
463 return 0;
464}
465
466static struct spi_driver td028ttec1_spi_driver = {
467 .probe = td028ttec1_panel_probe,
468 .remove = td028ttec1_panel_remove,
469
470 .driver = {
471 .name = "panel-tpo-td028ttec1",
472 .owner = THIS_MODULE,
473 },
474};
475
476module_spi_driver(td028ttec1_spi_driver);
477
478MODULE_AUTHOR("H. Nikolaus Schaller <hns@goldelico.com>");
479MODULE_DESCRIPTION("Toppoly TD028TTEC1 panel driver");
480MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays-new/panel-tpo-td043mtea1.c
deleted file mode 100644
index 875b40263b33..000000000000
--- a/drivers/video/omap2/displays-new/panel-tpo-td043mtea1.c
+++ /dev/null
@@ -1,646 +0,0 @@
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 .pixelclock = 36000000,
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/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
deleted file mode 100644
index dde4281663b1..000000000000
--- a/drivers/video/omap2/dss/Kconfig
+++ /dev/null
@@ -1,121 +0,0 @@
1menuconfig OMAP2_DSS
2 tristate "OMAP2+ Display Subsystem support"
3 select VIDEOMODE_HELPERS
4 help
5 OMAP2+ Display Subsystem support.
6
7if OMAP2_DSS
8
9config OMAP2_DSS_DEBUG
10 bool "Debug support"
11 default n
12 help
13 This enables printing of debug messages. Alternatively, debug messages
14 can also be enabled by setting CONFIG_DYNAMIC_DEBUG and then setting
15 appropriate flags in <debugfs>/dynamic_debug/control.
16
17config OMAP2_DSS_DEBUGFS
18 bool "Debugfs filesystem support"
19 depends on DEBUG_FS
20 default n
21 help
22 This enables debugfs for OMAPDSS at <debugfs>/omapdss. This enables
23 querying about clock configuration and register configuration of dss,
24 dispc, dsi, hdmi and rfbi.
25
26config OMAP2_DSS_COLLECT_IRQ_STATS
27 bool "Collect DSS IRQ statistics"
28 depends on OMAP2_DSS_DEBUGFS
29 default n
30 help
31 Collect DSS IRQ statistics, printable via debugfs.
32
33 The statistics can be found from
34 <debugfs>/omapdss/dispc_irq for DISPC interrupts, and
35 <debugfs>/omapdss/dsi_irq for DSI interrupts.
36
37config OMAP2_DSS_DPI
38 bool "DPI support"
39 default y
40 help
41 DPI Interface. This is the Parallel Display Interface.
42
43config OMAP2_DSS_RFBI
44 bool "RFBI support"
45 depends on BROKEN
46 default n
47 help
48 MIPI DBI support (RFBI, Remote Framebuffer Interface, in Texas
49 Instrument's terminology).
50
51 DBI is a bus between the host processor and a peripheral,
52 such as a display or a framebuffer chip.
53
54 See http://www.mipi.org/ for DBI specifications.
55
56config OMAP2_DSS_VENC
57 bool "VENC support"
58 default y
59 help
60 OMAP Video Encoder support for S-Video and composite TV-out.
61
62config OMAP4_DSS_HDMI
63 bool "HDMI support"
64 default y
65 help
66 HDMI Interface. This adds the High Definition Multimedia Interface.
67 See http://www.hdmi.org/ for HDMI specification.
68
69config OMAP4_DSS_HDMI_AUDIO
70 bool
71
72config OMAP2_DSS_SDI
73 bool "SDI support"
74 default n
75 help
76 SDI (Serial Display Interface) support.
77
78 SDI is a high speed one-way display serial bus between the host
79 processor and a display.
80
81config OMAP2_DSS_DSI
82 bool "DSI support"
83 default n
84 help
85 MIPI DSI (Display Serial Interface) support.
86
87 DSI is a high speed half-duplex serial interface between the host
88 processor and a peripheral, such as a display or a framebuffer chip.
89
90 See http://www.mipi.org/ for DSI specifications.
91
92config OMAP2_DSS_MIN_FCK_PER_PCK
93 int "Minimum FCK/PCK ratio (for scaling)"
94 range 0 32
95 default 0
96 help
97 This can be used to adjust the minimum FCK/PCK ratio.
98
99 With this you can make sure that DISPC FCK is at least
100 n x PCK. Video plane scaling requires higher FCK than
101 normally.
102
103 If this is set to 0, there's no extra constraint on the
104 DISPC FCK. However, the FCK will at minimum be
105 2xPCK (if active matrix) or 3xPCK (if passive matrix).
106
107 Max FCK is 173MHz, so this doesn't work if your PCK
108 is very high.
109
110config OMAP2_DSS_SLEEP_AFTER_VENC_RESET
111 bool "Sleep 20ms after VENC reset"
112 default y
113 help
114 There is a 20ms sleep after VENC reset which seemed to fix the
115 reset. The reason for the bug is unclear, and it's also unclear
116 on what platforms this happens.
117
118 This option enables the sleep, and is enabled by default. You can
119 disable the sleep if it doesn't cause problems on your platform.
120
121endif
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
deleted file mode 100644
index 8aec8bda27cc..000000000000
--- a/drivers/video/omap2/dss/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
1obj-$(CONFIG_OMAP2_DSS) += omapdss.o
2# Core DSS files
3omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
4 output.o dss-of.o
5# DSS compat layer files
6omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \
7 dispc-compat.o display-sysfs.o
8omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
9omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
10omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
11omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
12omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
13omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi4.o hdmi_common.o hdmi_wp.o hdmi_pll.o \
14 hdmi_phy.o hdmi4_core.o
15ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
deleted file mode 100644
index 0a0b084ce65d..000000000000
--- a/drivers/video/omap2/dss/apply.c
+++ /dev/null
@@ -1,1700 +0,0 @@
1/*
2 * Copyright (C) 2011 Texas Instruments
3 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#define DSS_SUBSYS_NAME "APPLY"
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/slab.h>
23#include <linux/spinlock.h>
24#include <linux/jiffies.h>
25
26#include <video/omapdss.h>
27
28#include "dss.h"
29#include "dss_features.h"
30#include "dispc-compat.h"
31
32/*
33 * We have 4 levels of cache for the dispc settings. First two are in SW and
34 * the latter two in HW.
35 *
36 * set_info()
37 * v
38 * +--------------------+
39 * | user_info |
40 * +--------------------+
41 * v
42 * apply()
43 * v
44 * +--------------------+
45 * | info |
46 * +--------------------+
47 * v
48 * write_regs()
49 * v
50 * +--------------------+
51 * | shadow registers |
52 * +--------------------+
53 * v
54 * VFP or lcd/digit_enable
55 * v
56 * +--------------------+
57 * | registers |
58 * +--------------------+
59 */
60
61struct ovl_priv_data {
62
63 bool user_info_dirty;
64 struct omap_overlay_info user_info;
65
66 bool info_dirty;
67 struct omap_overlay_info info;
68
69 bool shadow_info_dirty;
70
71 bool extra_info_dirty;
72 bool shadow_extra_info_dirty;
73
74 bool enabled;
75 u32 fifo_low, fifo_high;
76
77 /*
78 * True if overlay is to be enabled. Used to check and calculate configs
79 * for the overlay before it is enabled in the HW.
80 */
81 bool enabling;
82};
83
84struct mgr_priv_data {
85
86 bool user_info_dirty;
87 struct omap_overlay_manager_info user_info;
88
89 bool info_dirty;
90 struct omap_overlay_manager_info info;
91
92 bool shadow_info_dirty;
93
94 /* If true, GO bit is up and shadow registers cannot be written.
95 * Never true for manual update displays */
96 bool busy;
97
98 /* If true, dispc output is enabled */
99 bool updating;
100
101 /* If true, a display is enabled using this manager */
102 bool enabled;
103
104 bool extra_info_dirty;
105 bool shadow_extra_info_dirty;
106
107 struct omap_video_timings timings;
108 struct dss_lcd_mgr_config lcd_config;
109
110 void (*framedone_handler)(void *);
111 void *framedone_handler_data;
112};
113
114static struct {
115 struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
116 struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];
117
118 bool irq_enabled;
119} dss_data;
120
121/* protects dss_data */
122static spinlock_t data_lock;
123/* lock for blocking functions */
124static DEFINE_MUTEX(apply_lock);
125static DECLARE_COMPLETION(extra_updated_completion);
126
127static void dss_register_vsync_isr(void);
128
129static struct ovl_priv_data *get_ovl_priv(struct omap_overlay *ovl)
130{
131 return &dss_data.ovl_priv_data_array[ovl->id];
132}
133
134static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr)
135{
136 return &dss_data.mgr_priv_data_array[mgr->id];
137}
138
139static void apply_init_priv(void)
140{
141 const int num_ovls = dss_feat_get_num_ovls();
142 struct mgr_priv_data *mp;
143 int i;
144
145 spin_lock_init(&data_lock);
146
147 for (i = 0; i < num_ovls; ++i) {
148 struct ovl_priv_data *op;
149
150 op = &dss_data.ovl_priv_data_array[i];
151
152 op->info.color_mode = OMAP_DSS_COLOR_RGB16;
153 op->info.rotation_type = OMAP_DSS_ROT_DMA;
154
155 op->info.global_alpha = 255;
156
157 switch (i) {
158 case 0:
159 op->info.zorder = 0;
160 break;
161 case 1:
162 op->info.zorder =
163 dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;
164 break;
165 case 2:
166 op->info.zorder =
167 dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0;
168 break;
169 case 3:
170 op->info.zorder =
171 dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;
172 break;
173 }
174
175 op->user_info = op->info;
176 }
177
178 /*
179 * Initialize some of the lcd_config fields for TV manager, this lets
180 * us prevent checking if the manager is LCD or TV at some places
181 */
182 mp = &dss_data.mgr_priv_data_array[OMAP_DSS_CHANNEL_DIGIT];
183
184 mp->lcd_config.video_port_width = 24;
185 mp->lcd_config.clock_info.lck_div = 1;
186 mp->lcd_config.clock_info.pck_div = 1;
187}
188
189/*
190 * A LCD manager's stallmode decides whether it is in manual or auto update. TV
191 * manager is always auto update, stallmode field for TV manager is false by
192 * default
193 */
194static bool ovl_manual_update(struct omap_overlay *ovl)
195{
196 struct mgr_priv_data *mp = get_mgr_priv(ovl->manager);
197
198 return mp->lcd_config.stallmode;
199}
200
201static bool mgr_manual_update(struct omap_overlay_manager *mgr)
202{
203 struct mgr_priv_data *mp = get_mgr_priv(mgr);
204
205 return mp->lcd_config.stallmode;
206}
207
208static int dss_check_settings_low(struct omap_overlay_manager *mgr,
209 bool applying)
210{
211 struct omap_overlay_info *oi;
212 struct omap_overlay_manager_info *mi;
213 struct omap_overlay *ovl;
214 struct omap_overlay_info *ois[MAX_DSS_OVERLAYS];
215 struct ovl_priv_data *op;
216 struct mgr_priv_data *mp;
217
218 mp = get_mgr_priv(mgr);
219
220 if (!mp->enabled)
221 return 0;
222
223 if (applying && mp->user_info_dirty)
224 mi = &mp->user_info;
225 else
226 mi = &mp->info;
227
228 /* collect the infos to be tested into the array */
229 list_for_each_entry(ovl, &mgr->overlays, list) {
230 op = get_ovl_priv(ovl);
231
232 if (!op->enabled && !op->enabling)
233 oi = NULL;
234 else if (applying && op->user_info_dirty)
235 oi = &op->user_info;
236 else
237 oi = &op->info;
238
239 ois[ovl->id] = oi;
240 }
241
242 return dss_mgr_check(mgr, mi, &mp->timings, &mp->lcd_config, ois);
243}
244
245/*
246 * check manager and overlay settings using overlay_info from data->info
247 */
248static int dss_check_settings(struct omap_overlay_manager *mgr)
249{
250 return dss_check_settings_low(mgr, false);
251}
252
253/*
254 * check manager and overlay settings using overlay_info from ovl->info if
255 * dirty and from data->info otherwise
256 */
257static int dss_check_settings_apply(struct omap_overlay_manager *mgr)
258{
259 return dss_check_settings_low(mgr, true);
260}
261
262static bool need_isr(void)
263{
264 const int num_mgrs = dss_feat_get_num_mgrs();
265 int i;
266
267 for (i = 0; i < num_mgrs; ++i) {
268 struct omap_overlay_manager *mgr;
269 struct mgr_priv_data *mp;
270 struct omap_overlay *ovl;
271
272 mgr = omap_dss_get_overlay_manager(i);
273 mp = get_mgr_priv(mgr);
274
275 if (!mp->enabled)
276 continue;
277
278 if (mgr_manual_update(mgr)) {
279 /* to catch FRAMEDONE */
280 if (mp->updating)
281 return true;
282 } else {
283 /* to catch GO bit going down */
284 if (mp->busy)
285 return true;
286
287 /* to write new values to registers */
288 if (mp->info_dirty)
289 return true;
290
291 /* to set GO bit */
292 if (mp->shadow_info_dirty)
293 return true;
294
295 /*
296 * NOTE: we don't check extra_info flags for disabled
297 * managers, once the manager is enabled, the extra_info
298 * related manager changes will be taken in by HW.
299 */
300
301 /* to write new values to registers */
302 if (mp->extra_info_dirty)
303 return true;
304
305 /* to set GO bit */
306 if (mp->shadow_extra_info_dirty)
307 return true;
308
309 list_for_each_entry(ovl, &mgr->overlays, list) {
310 struct ovl_priv_data *op;
311
312 op = get_ovl_priv(ovl);
313
314 /*
315 * NOTE: we check extra_info flags even for
316 * disabled overlays, as extra_infos need to be
317 * always written.
318 */
319
320 /* to write new values to registers */
321 if (op->extra_info_dirty)
322 return true;
323
324 /* to set GO bit */
325 if (op->shadow_extra_info_dirty)
326 return true;
327
328 if (!op->enabled)
329 continue;
330
331 /* to write new values to registers */
332 if (op->info_dirty)
333 return true;
334
335 /* to set GO bit */
336 if (op->shadow_info_dirty)
337 return true;
338 }
339 }
340 }
341
342 return false;
343}
344
345static bool need_go(struct omap_overlay_manager *mgr)
346{
347 struct omap_overlay *ovl;
348 struct mgr_priv_data *mp;
349 struct ovl_priv_data *op;
350
351 mp = get_mgr_priv(mgr);
352
353 if (mp->shadow_info_dirty || mp->shadow_extra_info_dirty)
354 return true;
355
356 list_for_each_entry(ovl, &mgr->overlays, list) {
357 op = get_ovl_priv(ovl);
358 if (op->shadow_info_dirty || op->shadow_extra_info_dirty)
359 return true;
360 }
361
362 return false;
363}
364
365/* returns true if an extra_info field is currently being updated */
366static bool extra_info_update_ongoing(void)
367{
368 const int num_mgrs = dss_feat_get_num_mgrs();
369 int i;
370
371 for (i = 0; i < num_mgrs; ++i) {
372 struct omap_overlay_manager *mgr;
373 struct omap_overlay *ovl;
374 struct mgr_priv_data *mp;
375
376 mgr = omap_dss_get_overlay_manager(i);
377 mp = get_mgr_priv(mgr);
378
379 if (!mp->enabled)
380 continue;
381
382 if (!mp->updating)
383 continue;
384
385 if (mp->extra_info_dirty || mp->shadow_extra_info_dirty)
386 return true;
387
388 list_for_each_entry(ovl, &mgr->overlays, list) {
389 struct ovl_priv_data *op = get_ovl_priv(ovl);
390
391 if (op->extra_info_dirty || op->shadow_extra_info_dirty)
392 return true;
393 }
394 }
395
396 return false;
397}
398
399/* wait until no extra_info updates are pending */
400static void wait_pending_extra_info_updates(void)
401{
402 bool updating;
403 unsigned long flags;
404 unsigned long t;
405 int r;
406
407 spin_lock_irqsave(&data_lock, flags);
408
409 updating = extra_info_update_ongoing();
410
411 if (!updating) {
412 spin_unlock_irqrestore(&data_lock, flags);
413 return;
414 }
415
416 init_completion(&extra_updated_completion);
417
418 spin_unlock_irqrestore(&data_lock, flags);
419
420 t = msecs_to_jiffies(500);
421 r = wait_for_completion_timeout(&extra_updated_completion, t);
422 if (r == 0)
423 DSSWARN("timeout in wait_pending_extra_info_updates\n");
424}
425
426static struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
427{
428 struct omap_dss_device *dssdev;
429
430 dssdev = mgr->output;
431 if (dssdev == NULL)
432 return NULL;
433
434 while (dssdev->dst)
435 dssdev = dssdev->dst;
436
437 if (dssdev->driver)
438 return dssdev;
439 else
440 return NULL;
441}
442
443static struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
444{
445 return ovl->manager ? dss_mgr_get_device(ovl->manager) : NULL;
446}
447
448static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
449{
450 unsigned long timeout = msecs_to_jiffies(500);
451 u32 irq;
452 int r;
453
454 if (mgr->output == NULL)
455 return -ENODEV;
456
457 r = dispc_runtime_get();
458 if (r)
459 return r;
460
461 switch (mgr->output->id) {
462 case OMAP_DSS_OUTPUT_VENC:
463 irq = DISPC_IRQ_EVSYNC_ODD;
464 break;
465 case OMAP_DSS_OUTPUT_HDMI:
466 irq = DISPC_IRQ_EVSYNC_EVEN;
467 break;
468 default:
469 irq = dispc_mgr_get_vsync_irq(mgr->id);
470 break;
471 }
472
473 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
474
475 dispc_runtime_put();
476
477 return r;
478}
479
480static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
481{
482 unsigned long timeout = msecs_to_jiffies(500);
483 struct mgr_priv_data *mp = get_mgr_priv(mgr);
484 u32 irq;
485 unsigned long flags;
486 int r;
487 int i;
488
489 spin_lock_irqsave(&data_lock, flags);
490
491 if (mgr_manual_update(mgr)) {
492 spin_unlock_irqrestore(&data_lock, flags);
493 return 0;
494 }
495
496 if (!mp->enabled) {
497 spin_unlock_irqrestore(&data_lock, flags);
498 return 0;
499 }
500
501 spin_unlock_irqrestore(&data_lock, flags);
502
503 r = dispc_runtime_get();
504 if (r)
505 return r;
506
507 irq = dispc_mgr_get_vsync_irq(mgr->id);
508
509 i = 0;
510 while (1) {
511 bool shadow_dirty, dirty;
512
513 spin_lock_irqsave(&data_lock, flags);
514 dirty = mp->info_dirty;
515 shadow_dirty = mp->shadow_info_dirty;
516 spin_unlock_irqrestore(&data_lock, flags);
517
518 if (!dirty && !shadow_dirty) {
519 r = 0;
520 break;
521 }
522
523 /* 4 iterations is the worst case:
524 * 1 - initial iteration, dirty = true (between VFP and VSYNC)
525 * 2 - first VSYNC, dirty = true
526 * 3 - dirty = false, shadow_dirty = true
527 * 4 - shadow_dirty = false */
528 if (i++ == 3) {
529 DSSERR("mgr(%d)->wait_for_go() not finishing\n",
530 mgr->id);
531 r = 0;
532 break;
533 }
534
535 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
536 if (r == -ERESTARTSYS)
537 break;
538
539 if (r) {
540 DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
541 break;
542 }
543 }
544
545 dispc_runtime_put();
546
547 return r;
548}
549
550static int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
551{
552 unsigned long timeout = msecs_to_jiffies(500);
553 struct ovl_priv_data *op;
554 struct mgr_priv_data *mp;
555 u32 irq;
556 unsigned long flags;
557 int r;
558 int i;
559
560 if (!ovl->manager)
561 return 0;
562
563 mp = get_mgr_priv(ovl->manager);
564
565 spin_lock_irqsave(&data_lock, flags);
566
567 if (ovl_manual_update(ovl)) {
568 spin_unlock_irqrestore(&data_lock, flags);
569 return 0;
570 }
571
572 if (!mp->enabled) {
573 spin_unlock_irqrestore(&data_lock, flags);
574 return 0;
575 }
576
577 spin_unlock_irqrestore(&data_lock, flags);
578
579 r = dispc_runtime_get();
580 if (r)
581 return r;
582
583 irq = dispc_mgr_get_vsync_irq(ovl->manager->id);
584
585 op = get_ovl_priv(ovl);
586 i = 0;
587 while (1) {
588 bool shadow_dirty, dirty;
589
590 spin_lock_irqsave(&data_lock, flags);
591 dirty = op->info_dirty;
592 shadow_dirty = op->shadow_info_dirty;
593 spin_unlock_irqrestore(&data_lock, flags);
594
595 if (!dirty && !shadow_dirty) {
596 r = 0;
597 break;
598 }
599
600 /* 4 iterations is the worst case:
601 * 1 - initial iteration, dirty = true (between VFP and VSYNC)
602 * 2 - first VSYNC, dirty = true
603 * 3 - dirty = false, shadow_dirty = true
604 * 4 - shadow_dirty = false */
605 if (i++ == 3) {
606 DSSERR("ovl(%d)->wait_for_go() not finishing\n",
607 ovl->id);
608 r = 0;
609 break;
610 }
611
612 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
613 if (r == -ERESTARTSYS)
614 break;
615
616 if (r) {
617 DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
618 break;
619 }
620 }
621
622 dispc_runtime_put();
623
624 return r;
625}
626
627static void dss_ovl_write_regs(struct omap_overlay *ovl)
628{
629 struct ovl_priv_data *op = get_ovl_priv(ovl);
630 struct omap_overlay_info *oi;
631 bool replication;
632 struct mgr_priv_data *mp;
633 int r;
634
635 DSSDBG("writing ovl %d regs\n", ovl->id);
636
637 if (!op->enabled || !op->info_dirty)
638 return;
639
640 oi = &op->info;
641
642 mp = get_mgr_priv(ovl->manager);
643
644 replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode);
645
646 r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings, false);
647 if (r) {
648 /*
649 * We can't do much here, as this function can be called from
650 * vsync interrupt.
651 */
652 DSSERR("dispc_ovl_setup failed for ovl %d\n", ovl->id);
653
654 /* This will leave fifo configurations in a nonoptimal state */
655 op->enabled = false;
656 dispc_ovl_enable(ovl->id, false);
657 return;
658 }
659
660 op->info_dirty = false;
661 if (mp->updating)
662 op->shadow_info_dirty = true;
663}
664
665static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
666{
667 struct ovl_priv_data *op = get_ovl_priv(ovl);
668 struct mgr_priv_data *mp;
669
670 DSSDBG("writing ovl %d regs extra\n", ovl->id);
671
672 if (!op->extra_info_dirty)
673 return;
674
675 /* note: write also when op->enabled == false, so that the ovl gets
676 * disabled */
677
678 dispc_ovl_enable(ovl->id, op->enabled);
679 dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
680
681 mp = get_mgr_priv(ovl->manager);
682
683 op->extra_info_dirty = false;
684 if (mp->updating)
685 op->shadow_extra_info_dirty = true;
686}
687
688static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
689{
690 struct mgr_priv_data *mp = get_mgr_priv(mgr);
691 struct omap_overlay *ovl;
692
693 DSSDBG("writing mgr %d regs\n", mgr->id);
694
695 if (!mp->enabled)
696 return;
697
698 WARN_ON(mp->busy);
699
700 /* Commit overlay settings */
701 list_for_each_entry(ovl, &mgr->overlays, list) {
702 dss_ovl_write_regs(ovl);
703 dss_ovl_write_regs_extra(ovl);
704 }
705
706 if (mp->info_dirty) {
707 dispc_mgr_setup(mgr->id, &mp->info);
708
709 mp->info_dirty = false;
710 if (mp->updating)
711 mp->shadow_info_dirty = true;
712 }
713}
714
715static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
716{
717 struct mgr_priv_data *mp = get_mgr_priv(mgr);
718
719 DSSDBG("writing mgr %d regs extra\n", mgr->id);
720
721 if (!mp->extra_info_dirty)
722 return;
723
724 dispc_mgr_set_timings(mgr->id, &mp->timings);
725
726 /* lcd_config parameters */
727 if (dss_mgr_is_lcd(mgr->id))
728 dispc_mgr_set_lcd_config(mgr->id, &mp->lcd_config);
729
730 mp->extra_info_dirty = false;
731 if (mp->updating)
732 mp->shadow_extra_info_dirty = true;
733}
734
735static void dss_write_regs(void)
736{
737 const int num_mgrs = omap_dss_get_num_overlay_managers();
738 int i;
739
740 for (i = 0; i < num_mgrs; ++i) {
741 struct omap_overlay_manager *mgr;
742 struct mgr_priv_data *mp;
743 int r;
744
745 mgr = omap_dss_get_overlay_manager(i);
746 mp = get_mgr_priv(mgr);
747
748 if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
749 continue;
750
751 r = dss_check_settings(mgr);
752 if (r) {
753 DSSERR("cannot write registers for manager %s: "
754 "illegal configuration\n", mgr->name);
755 continue;
756 }
757
758 dss_mgr_write_regs(mgr);
759 dss_mgr_write_regs_extra(mgr);
760 }
761}
762
763static void dss_set_go_bits(void)
764{
765 const int num_mgrs = omap_dss_get_num_overlay_managers();
766 int i;
767
768 for (i = 0; i < num_mgrs; ++i) {
769 struct omap_overlay_manager *mgr;
770 struct mgr_priv_data *mp;
771
772 mgr = omap_dss_get_overlay_manager(i);
773 mp = get_mgr_priv(mgr);
774
775 if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
776 continue;
777
778 if (!need_go(mgr))
779 continue;
780
781 mp->busy = true;
782
783 if (!dss_data.irq_enabled && need_isr())
784 dss_register_vsync_isr();
785
786 dispc_mgr_go(mgr->id);
787 }
788
789}
790
791static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
792{
793 struct omap_overlay *ovl;
794 struct mgr_priv_data *mp;
795 struct ovl_priv_data *op;
796
797 mp = get_mgr_priv(mgr);
798 mp->shadow_info_dirty = false;
799 mp->shadow_extra_info_dirty = false;
800
801 list_for_each_entry(ovl, &mgr->overlays, list) {
802 op = get_ovl_priv(ovl);
803 op->shadow_info_dirty = false;
804 op->shadow_extra_info_dirty = false;
805 }
806}
807
808static int dss_mgr_connect_compat(struct omap_overlay_manager *mgr,
809 struct omap_dss_device *dst)
810{
811 return mgr->set_output(mgr, dst);
812}
813
814static void dss_mgr_disconnect_compat(struct omap_overlay_manager *mgr,
815 struct omap_dss_device *dst)
816{
817 mgr->unset_output(mgr);
818}
819
820static void dss_mgr_start_update_compat(struct omap_overlay_manager *mgr)
821{
822 struct mgr_priv_data *mp = get_mgr_priv(mgr);
823 unsigned long flags;
824 int r;
825
826 spin_lock_irqsave(&data_lock, flags);
827
828 WARN_ON(mp->updating);
829
830 r = dss_check_settings(mgr);
831 if (r) {
832 DSSERR("cannot start manual update: illegal configuration\n");
833 spin_unlock_irqrestore(&data_lock, flags);
834 return;
835 }
836
837 dss_mgr_write_regs(mgr);
838 dss_mgr_write_regs_extra(mgr);
839
840 mp->updating = true;
841
842 if (!dss_data.irq_enabled && need_isr())
843 dss_register_vsync_isr();
844
845 dispc_mgr_enable_sync(mgr->id);
846
847 spin_unlock_irqrestore(&data_lock, flags);
848}
849
850static void dss_apply_irq_handler(void *data, u32 mask);
851
852static void dss_register_vsync_isr(void)
853{
854 const int num_mgrs = dss_feat_get_num_mgrs();
855 u32 mask;
856 int r, i;
857
858 mask = 0;
859 for (i = 0; i < num_mgrs; ++i)
860 mask |= dispc_mgr_get_vsync_irq(i);
861
862 for (i = 0; i < num_mgrs; ++i)
863 mask |= dispc_mgr_get_framedone_irq(i);
864
865 r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask);
866 WARN_ON(r);
867
868 dss_data.irq_enabled = true;
869}
870
871static void dss_unregister_vsync_isr(void)
872{
873 const int num_mgrs = dss_feat_get_num_mgrs();
874 u32 mask;
875 int r, i;
876
877 mask = 0;
878 for (i = 0; i < num_mgrs; ++i)
879 mask |= dispc_mgr_get_vsync_irq(i);
880
881 for (i = 0; i < num_mgrs; ++i)
882 mask |= dispc_mgr_get_framedone_irq(i);
883
884 r = omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, mask);
885 WARN_ON(r);
886
887 dss_data.irq_enabled = false;
888}
889
890static void dss_apply_irq_handler(void *data, u32 mask)
891{
892 const int num_mgrs = dss_feat_get_num_mgrs();
893 int i;
894 bool extra_updating;
895
896 spin_lock(&data_lock);
897
898 /* clear busy, updating flags, shadow_dirty flags */
899 for (i = 0; i < num_mgrs; i++) {
900 struct omap_overlay_manager *mgr;
901 struct mgr_priv_data *mp;
902
903 mgr = omap_dss_get_overlay_manager(i);
904 mp = get_mgr_priv(mgr);
905
906 if (!mp->enabled)
907 continue;
908
909 mp->updating = dispc_mgr_is_enabled(i);
910
911 if (!mgr_manual_update(mgr)) {
912 bool was_busy = mp->busy;
913 mp->busy = dispc_mgr_go_busy(i);
914
915 if (was_busy && !mp->busy)
916 mgr_clear_shadow_dirty(mgr);
917 }
918 }
919
920 dss_write_regs();
921 dss_set_go_bits();
922
923 extra_updating = extra_info_update_ongoing();
924 if (!extra_updating)
925 complete_all(&extra_updated_completion);
926
927 /* call framedone handlers for manual update displays */
928 for (i = 0; i < num_mgrs; i++) {
929 struct omap_overlay_manager *mgr;
930 struct mgr_priv_data *mp;
931
932 mgr = omap_dss_get_overlay_manager(i);
933 mp = get_mgr_priv(mgr);
934
935 if (!mgr_manual_update(mgr) || !mp->framedone_handler)
936 continue;
937
938 if (mask & dispc_mgr_get_framedone_irq(i))
939 mp->framedone_handler(mp->framedone_handler_data);
940 }
941
942 if (!need_isr())
943 dss_unregister_vsync_isr();
944
945 spin_unlock(&data_lock);
946}
947
948static void omap_dss_mgr_apply_ovl(struct omap_overlay *ovl)
949{
950 struct ovl_priv_data *op;
951
952 op = get_ovl_priv(ovl);
953
954 if (!op->user_info_dirty)
955 return;
956
957 op->user_info_dirty = false;
958 op->info_dirty = true;
959 op->info = op->user_info;
960}
961
962static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
963{
964 struct mgr_priv_data *mp;
965
966 mp = get_mgr_priv(mgr);
967
968 if (!mp->user_info_dirty)
969 return;
970
971 mp->user_info_dirty = false;
972 mp->info_dirty = true;
973 mp->info = mp->user_info;
974}
975
976static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
977{
978 unsigned long flags;
979 struct omap_overlay *ovl;
980 int r;
981
982 DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
983
984 spin_lock_irqsave(&data_lock, flags);
985
986 r = dss_check_settings_apply(mgr);
987 if (r) {
988 spin_unlock_irqrestore(&data_lock, flags);
989 DSSERR("failed to apply settings: illegal configuration.\n");
990 return r;
991 }
992
993 /* Configure overlays */
994 list_for_each_entry(ovl, &mgr->overlays, list)
995 omap_dss_mgr_apply_ovl(ovl);
996
997 /* Configure manager */
998 omap_dss_mgr_apply_mgr(mgr);
999
1000 dss_write_regs();
1001 dss_set_go_bits();
1002
1003 spin_unlock_irqrestore(&data_lock, flags);
1004
1005 return 0;
1006}
1007
1008static void dss_apply_ovl_enable(struct omap_overlay *ovl, bool enable)
1009{
1010 struct ovl_priv_data *op;
1011
1012 op = get_ovl_priv(ovl);
1013
1014 if (op->enabled == enable)
1015 return;
1016
1017 op->enabled = enable;
1018 op->extra_info_dirty = true;
1019}
1020
1021static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
1022 u32 fifo_low, u32 fifo_high)
1023{
1024 struct ovl_priv_data *op = get_ovl_priv(ovl);
1025
1026 if (op->fifo_low == fifo_low && op->fifo_high == fifo_high)
1027 return;
1028
1029 op->fifo_low = fifo_low;
1030 op->fifo_high = fifo_high;
1031 op->extra_info_dirty = true;
1032}
1033
1034static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
1035{
1036 struct ovl_priv_data *op = get_ovl_priv(ovl);
1037 u32 fifo_low, fifo_high;
1038 bool use_fifo_merge = false;
1039
1040 if (!op->enabled && !op->enabling)
1041 return;
1042
1043 dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high,
1044 use_fifo_merge, ovl_manual_update(ovl));
1045
1046 dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
1047}
1048
1049static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
1050{
1051 struct omap_overlay *ovl;
1052 struct mgr_priv_data *mp;
1053
1054 mp = get_mgr_priv(mgr);
1055
1056 if (!mp->enabled)
1057 return;
1058
1059 list_for_each_entry(ovl, &mgr->overlays, list)
1060 dss_ovl_setup_fifo(ovl);
1061}
1062
1063static void dss_setup_fifos(void)
1064{
1065 const int num_mgrs = omap_dss_get_num_overlay_managers();
1066 struct omap_overlay_manager *mgr;
1067 int i;
1068
1069 for (i = 0; i < num_mgrs; ++i) {
1070 mgr = omap_dss_get_overlay_manager(i);
1071 dss_mgr_setup_fifos(mgr);
1072 }
1073}
1074
1075static int dss_mgr_enable_compat(struct omap_overlay_manager *mgr)
1076{
1077 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1078 unsigned long flags;
1079 int r;
1080
1081 mutex_lock(&apply_lock);
1082
1083 if (mp->enabled)
1084 goto out;
1085
1086 spin_lock_irqsave(&data_lock, flags);
1087
1088 mp->enabled = true;
1089
1090 r = dss_check_settings(mgr);
1091 if (r) {
1092 DSSERR("failed to enable manager %d: check_settings failed\n",
1093 mgr->id);
1094 goto err;
1095 }
1096
1097 dss_setup_fifos();
1098
1099 dss_write_regs();
1100 dss_set_go_bits();
1101
1102 if (!mgr_manual_update(mgr))
1103 mp->updating = true;
1104
1105 if (!dss_data.irq_enabled && need_isr())
1106 dss_register_vsync_isr();
1107
1108 spin_unlock_irqrestore(&data_lock, flags);
1109
1110 if (!mgr_manual_update(mgr))
1111 dispc_mgr_enable_sync(mgr->id);
1112
1113out:
1114 mutex_unlock(&apply_lock);
1115
1116 return 0;
1117
1118err:
1119 mp->enabled = false;
1120 spin_unlock_irqrestore(&data_lock, flags);
1121 mutex_unlock(&apply_lock);
1122 return r;
1123}
1124
1125static void dss_mgr_disable_compat(struct omap_overlay_manager *mgr)
1126{
1127 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1128 unsigned long flags;
1129
1130 mutex_lock(&apply_lock);
1131
1132 if (!mp->enabled)
1133 goto out;
1134
1135 if (!mgr_manual_update(mgr))
1136 dispc_mgr_disable_sync(mgr->id);
1137
1138 spin_lock_irqsave(&data_lock, flags);
1139
1140 mp->updating = false;
1141 mp->enabled = false;
1142
1143 spin_unlock_irqrestore(&data_lock, flags);
1144
1145out:
1146 mutex_unlock(&apply_lock);
1147}
1148
1149static int dss_mgr_set_info(struct omap_overlay_manager *mgr,
1150 struct omap_overlay_manager_info *info)
1151{
1152 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1153 unsigned long flags;
1154 int r;
1155
1156 r = dss_mgr_simple_check(mgr, info);
1157 if (r)
1158 return r;
1159
1160 spin_lock_irqsave(&data_lock, flags);
1161
1162 mp->user_info = *info;
1163 mp->user_info_dirty = true;
1164
1165 spin_unlock_irqrestore(&data_lock, flags);
1166
1167 return 0;
1168}
1169
1170static void dss_mgr_get_info(struct omap_overlay_manager *mgr,
1171 struct omap_overlay_manager_info *info)
1172{
1173 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1174 unsigned long flags;
1175
1176 spin_lock_irqsave(&data_lock, flags);
1177
1178 *info = mp->user_info;
1179
1180 spin_unlock_irqrestore(&data_lock, flags);
1181}
1182
1183static int dss_mgr_set_output(struct omap_overlay_manager *mgr,
1184 struct omap_dss_device *output)
1185{
1186 int r;
1187
1188 mutex_lock(&apply_lock);
1189
1190 if (mgr->output) {
1191 DSSERR("manager %s is already connected to an output\n",
1192 mgr->name);
1193 r = -EINVAL;
1194 goto err;
1195 }
1196
1197 if ((mgr->supported_outputs & output->id) == 0) {
1198 DSSERR("output does not support manager %s\n",
1199 mgr->name);
1200 r = -EINVAL;
1201 goto err;
1202 }
1203
1204 output->manager = mgr;
1205 mgr->output = output;
1206
1207 mutex_unlock(&apply_lock);
1208
1209 return 0;
1210err:
1211 mutex_unlock(&apply_lock);
1212 return r;
1213}
1214
1215static int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
1216{
1217 int r;
1218 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1219 unsigned long flags;
1220
1221 mutex_lock(&apply_lock);
1222
1223 if (!mgr->output) {
1224 DSSERR("failed to unset output, output not set\n");
1225 r = -EINVAL;
1226 goto err;
1227 }
1228
1229 spin_lock_irqsave(&data_lock, flags);
1230
1231 if (mp->enabled) {
1232 DSSERR("output can't be unset when manager is enabled\n");
1233 r = -EINVAL;
1234 goto err1;
1235 }
1236
1237 spin_unlock_irqrestore(&data_lock, flags);
1238
1239 mgr->output->manager = NULL;
1240 mgr->output = NULL;
1241
1242 mutex_unlock(&apply_lock);
1243
1244 return 0;
1245err1:
1246 spin_unlock_irqrestore(&data_lock, flags);
1247err:
1248 mutex_unlock(&apply_lock);
1249
1250 return r;
1251}
1252
1253static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
1254 const struct omap_video_timings *timings)
1255{
1256 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1257
1258 mp->timings = *timings;
1259 mp->extra_info_dirty = true;
1260}
1261
1262static void dss_mgr_set_timings_compat(struct omap_overlay_manager *mgr,
1263 const struct omap_video_timings *timings)
1264{
1265 unsigned long flags;
1266 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1267
1268 spin_lock_irqsave(&data_lock, flags);
1269
1270 if (mp->updating) {
1271 DSSERR("cannot set timings for %s: manager needs to be disabled\n",
1272 mgr->name);
1273 goto out;
1274 }
1275
1276 dss_apply_mgr_timings(mgr, timings);
1277out:
1278 spin_unlock_irqrestore(&data_lock, flags);
1279}
1280
1281static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
1282 const struct dss_lcd_mgr_config *config)
1283{
1284 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1285
1286 mp->lcd_config = *config;
1287 mp->extra_info_dirty = true;
1288}
1289
1290static void dss_mgr_set_lcd_config_compat(struct omap_overlay_manager *mgr,
1291 const struct dss_lcd_mgr_config *config)
1292{
1293 unsigned long flags;
1294 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1295
1296 spin_lock_irqsave(&data_lock, flags);
1297
1298 if (mp->enabled) {
1299 DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n",
1300 mgr->name);
1301 goto out;
1302 }
1303
1304 dss_apply_mgr_lcd_config(mgr, config);
1305out:
1306 spin_unlock_irqrestore(&data_lock, flags);
1307}
1308
1309static int dss_ovl_set_info(struct omap_overlay *ovl,
1310 struct omap_overlay_info *info)
1311{
1312 struct ovl_priv_data *op = get_ovl_priv(ovl);
1313 unsigned long flags;
1314 int r;
1315
1316 r = dss_ovl_simple_check(ovl, info);
1317 if (r)
1318 return r;
1319
1320 spin_lock_irqsave(&data_lock, flags);
1321
1322 op->user_info = *info;
1323 op->user_info_dirty = true;
1324
1325 spin_unlock_irqrestore(&data_lock, flags);
1326
1327 return 0;
1328}
1329
1330static void dss_ovl_get_info(struct omap_overlay *ovl,
1331 struct omap_overlay_info *info)
1332{
1333 struct ovl_priv_data *op = get_ovl_priv(ovl);
1334 unsigned long flags;
1335
1336 spin_lock_irqsave(&data_lock, flags);
1337
1338 *info = op->user_info;
1339
1340 spin_unlock_irqrestore(&data_lock, flags);
1341}
1342
1343static int dss_ovl_set_manager(struct omap_overlay *ovl,
1344 struct omap_overlay_manager *mgr)
1345{
1346 struct ovl_priv_data *op = get_ovl_priv(ovl);
1347 unsigned long flags;
1348 int r;
1349
1350 if (!mgr)
1351 return -EINVAL;
1352
1353 mutex_lock(&apply_lock);
1354
1355 if (ovl->manager) {
1356 DSSERR("overlay '%s' already has a manager '%s'\n",
1357 ovl->name, ovl->manager->name);
1358 r = -EINVAL;
1359 goto err;
1360 }
1361
1362 r = dispc_runtime_get();
1363 if (r)
1364 goto err;
1365
1366 spin_lock_irqsave(&data_lock, flags);
1367
1368 if (op->enabled) {
1369 spin_unlock_irqrestore(&data_lock, flags);
1370 DSSERR("overlay has to be disabled to change the manager\n");
1371 r = -EINVAL;
1372 goto err1;
1373 }
1374
1375 dispc_ovl_set_channel_out(ovl->id, mgr->id);
1376
1377 ovl->manager = mgr;
1378 list_add_tail(&ovl->list, &mgr->overlays);
1379
1380 spin_unlock_irqrestore(&data_lock, flags);
1381
1382 dispc_runtime_put();
1383
1384 mutex_unlock(&apply_lock);
1385
1386 return 0;
1387
1388err1:
1389 dispc_runtime_put();
1390err:
1391 mutex_unlock(&apply_lock);
1392 return r;
1393}
1394
1395static int dss_ovl_unset_manager(struct omap_overlay *ovl)
1396{
1397 struct ovl_priv_data *op = get_ovl_priv(ovl);
1398 unsigned long flags;
1399 int r;
1400
1401 mutex_lock(&apply_lock);
1402
1403 if (!ovl->manager) {
1404 DSSERR("failed to detach overlay: manager not set\n");
1405 r = -EINVAL;
1406 goto err;
1407 }
1408
1409 spin_lock_irqsave(&data_lock, flags);
1410
1411 if (op->enabled) {
1412 spin_unlock_irqrestore(&data_lock, flags);
1413 DSSERR("overlay has to be disabled to unset the manager\n");
1414 r = -EINVAL;
1415 goto err;
1416 }
1417
1418 spin_unlock_irqrestore(&data_lock, flags);
1419
1420 /* wait for pending extra_info updates to ensure the ovl is disabled */
1421 wait_pending_extra_info_updates();
1422
1423 /*
1424 * For a manual update display, there is no guarantee that the overlay
1425 * is really disabled in HW, we may need an extra update from this
1426 * manager before the configurations can go in. Return an error if the
1427 * overlay needed an update from the manager.
1428 *
1429 * TODO: Instead of returning an error, try to do a dummy manager update
1430 * here to disable the overlay in hardware. Use the *GATED fields in
1431 * the DISPC_CONFIG registers to do a dummy update.
1432 */
1433 spin_lock_irqsave(&data_lock, flags);
1434
1435 if (ovl_manual_update(ovl) && op->extra_info_dirty) {
1436 spin_unlock_irqrestore(&data_lock, flags);
1437 DSSERR("need an update to change the manager\n");
1438 r = -EINVAL;
1439 goto err;
1440 }
1441
1442 ovl->manager = NULL;
1443 list_del(&ovl->list);
1444
1445 spin_unlock_irqrestore(&data_lock, flags);
1446
1447 mutex_unlock(&apply_lock);
1448
1449 return 0;
1450err:
1451 mutex_unlock(&apply_lock);
1452 return r;
1453}
1454
1455static bool dss_ovl_is_enabled(struct omap_overlay *ovl)
1456{
1457 struct ovl_priv_data *op = get_ovl_priv(ovl);
1458 unsigned long flags;
1459 bool e;
1460
1461 spin_lock_irqsave(&data_lock, flags);
1462
1463 e = op->enabled;
1464
1465 spin_unlock_irqrestore(&data_lock, flags);
1466
1467 return e;
1468}
1469
1470static int dss_ovl_enable(struct omap_overlay *ovl)
1471{
1472 struct ovl_priv_data *op = get_ovl_priv(ovl);
1473 unsigned long flags;
1474 int r;
1475
1476 mutex_lock(&apply_lock);
1477
1478 if (op->enabled) {
1479 r = 0;
1480 goto err1;
1481 }
1482
1483 if (ovl->manager == NULL || ovl->manager->output == NULL) {
1484 r = -EINVAL;
1485 goto err1;
1486 }
1487
1488 spin_lock_irqsave(&data_lock, flags);
1489
1490 op->enabling = true;
1491
1492 r = dss_check_settings(ovl->manager);
1493 if (r) {
1494 DSSERR("failed to enable overlay %d: check_settings failed\n",
1495 ovl->id);
1496 goto err2;
1497 }
1498
1499 dss_setup_fifos();
1500
1501 op->enabling = false;
1502 dss_apply_ovl_enable(ovl, true);
1503
1504 dss_write_regs();
1505 dss_set_go_bits();
1506
1507 spin_unlock_irqrestore(&data_lock, flags);
1508
1509 mutex_unlock(&apply_lock);
1510
1511 return 0;
1512err2:
1513 op->enabling = false;
1514 spin_unlock_irqrestore(&data_lock, flags);
1515err1:
1516 mutex_unlock(&apply_lock);
1517 return r;
1518}
1519
1520static int dss_ovl_disable(struct omap_overlay *ovl)
1521{
1522 struct ovl_priv_data *op = get_ovl_priv(ovl);
1523 unsigned long flags;
1524 int r;
1525
1526 mutex_lock(&apply_lock);
1527
1528 if (!op->enabled) {
1529 r = 0;
1530 goto err;
1531 }
1532
1533 if (ovl->manager == NULL || ovl->manager->output == NULL) {
1534 r = -EINVAL;
1535 goto err;
1536 }
1537
1538 spin_lock_irqsave(&data_lock, flags);
1539
1540 dss_apply_ovl_enable(ovl, false);
1541 dss_write_regs();
1542 dss_set_go_bits();
1543
1544 spin_unlock_irqrestore(&data_lock, flags);
1545
1546 mutex_unlock(&apply_lock);
1547
1548 return 0;
1549
1550err:
1551 mutex_unlock(&apply_lock);
1552 return r;
1553}
1554
1555static int dss_mgr_register_framedone_handler_compat(struct omap_overlay_manager *mgr,
1556 void (*handler)(void *), void *data)
1557{
1558 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1559
1560 if (mp->framedone_handler)
1561 return -EBUSY;
1562
1563 mp->framedone_handler = handler;
1564 mp->framedone_handler_data = data;
1565
1566 return 0;
1567}
1568
1569static void dss_mgr_unregister_framedone_handler_compat(struct omap_overlay_manager *mgr,
1570 void (*handler)(void *), void *data)
1571{
1572 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1573
1574 WARN_ON(mp->framedone_handler != handler ||
1575 mp->framedone_handler_data != data);
1576
1577 mp->framedone_handler = NULL;
1578 mp->framedone_handler_data = NULL;
1579}
1580
1581static const struct dss_mgr_ops apply_mgr_ops = {
1582 .connect = dss_mgr_connect_compat,
1583 .disconnect = dss_mgr_disconnect_compat,
1584 .start_update = dss_mgr_start_update_compat,
1585 .enable = dss_mgr_enable_compat,
1586 .disable = dss_mgr_disable_compat,
1587 .set_timings = dss_mgr_set_timings_compat,
1588 .set_lcd_config = dss_mgr_set_lcd_config_compat,
1589 .register_framedone_handler = dss_mgr_register_framedone_handler_compat,
1590 .unregister_framedone_handler = dss_mgr_unregister_framedone_handler_compat,
1591};
1592
1593static int compat_refcnt;
1594static DEFINE_MUTEX(compat_init_lock);
1595
1596int omapdss_compat_init(void)
1597{
1598 struct platform_device *pdev = dss_get_core_pdev();
1599 int i, r;
1600
1601 mutex_lock(&compat_init_lock);
1602
1603 if (compat_refcnt++ > 0)
1604 goto out;
1605
1606 apply_init_priv();
1607
1608 dss_init_overlay_managers_sysfs(pdev);
1609 dss_init_overlays(pdev);
1610
1611 for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
1612 struct omap_overlay_manager *mgr;
1613
1614 mgr = omap_dss_get_overlay_manager(i);
1615
1616 mgr->set_output = &dss_mgr_set_output;
1617 mgr->unset_output = &dss_mgr_unset_output;
1618 mgr->apply = &omap_dss_mgr_apply;
1619 mgr->set_manager_info = &dss_mgr_set_info;
1620 mgr->get_manager_info = &dss_mgr_get_info;
1621 mgr->wait_for_go = &dss_mgr_wait_for_go;
1622 mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
1623 mgr->get_device = &dss_mgr_get_device;
1624 }
1625
1626 for (i = 0; i < omap_dss_get_num_overlays(); i++) {
1627 struct omap_overlay *ovl = omap_dss_get_overlay(i);
1628
1629 ovl->is_enabled = &dss_ovl_is_enabled;
1630 ovl->enable = &dss_ovl_enable;
1631 ovl->disable = &dss_ovl_disable;
1632 ovl->set_manager = &dss_ovl_set_manager;
1633 ovl->unset_manager = &dss_ovl_unset_manager;
1634 ovl->set_overlay_info = &dss_ovl_set_info;
1635 ovl->get_overlay_info = &dss_ovl_get_info;
1636 ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
1637 ovl->get_device = &dss_ovl_get_device;
1638 }
1639
1640 r = dss_install_mgr_ops(&apply_mgr_ops);
1641 if (r)
1642 goto err_mgr_ops;
1643
1644 r = display_init_sysfs(pdev);
1645 if (r)
1646 goto err_disp_sysfs;
1647
1648 dispc_runtime_get();
1649
1650 r = dss_dispc_initialize_irq();
1651 if (r)
1652 goto err_init_irq;
1653
1654 dispc_runtime_put();
1655
1656out:
1657 mutex_unlock(&compat_init_lock);
1658
1659 return 0;
1660
1661err_init_irq:
1662 dispc_runtime_put();
1663 display_uninit_sysfs(pdev);
1664
1665err_disp_sysfs:
1666 dss_uninstall_mgr_ops();
1667
1668err_mgr_ops:
1669 dss_uninit_overlay_managers_sysfs(pdev);
1670 dss_uninit_overlays(pdev);
1671
1672 compat_refcnt--;
1673
1674 mutex_unlock(&compat_init_lock);
1675
1676 return r;
1677}
1678EXPORT_SYMBOL(omapdss_compat_init);
1679
1680void omapdss_compat_uninit(void)
1681{
1682 struct platform_device *pdev = dss_get_core_pdev();
1683
1684 mutex_lock(&compat_init_lock);
1685
1686 if (--compat_refcnt > 0)
1687 goto out;
1688
1689 dss_dispc_uninitialize_irq();
1690
1691 display_uninit_sysfs(pdev);
1692
1693 dss_uninstall_mgr_ops();
1694
1695 dss_uninit_overlay_managers_sysfs(pdev);
1696 dss_uninit_overlays(pdev);
1697out:
1698 mutex_unlock(&compat_init_lock);
1699}
1700EXPORT_SYMBOL(omapdss_compat_uninit);
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
deleted file mode 100644
index ffa45c894cd4..000000000000
--- a/drivers/video/omap2/dss/core.c
+++ /dev/null
@@ -1,360 +0,0 @@
1/*
2 * linux/drivers/video/omap2/dss/core.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
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#define DSS_SUBSYS_NAME "CORE"
24
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/clk.h>
28#include <linux/err.h>
29#include <linux/platform_device.h>
30#include <linux/seq_file.h>
31#include <linux/debugfs.h>
32#include <linux/io.h>
33#include <linux/device.h>
34#include <linux/regulator/consumer.h>
35#include <linux/suspend.h>
36#include <linux/slab.h>
37
38#include <video/omapdss.h>
39
40#include "dss.h"
41#include "dss_features.h"
42
43static struct {
44 struct platform_device *pdev;
45
46 const char *default_display_name;
47} core;
48
49static char *def_disp_name;
50module_param_named(def_disp, def_disp_name, charp, 0);
51MODULE_PARM_DESC(def_disp, "default display name");
52
53static bool dss_initialized;
54
55const char *omapdss_get_default_display_name(void)
56{
57 return core.default_display_name;
58}
59EXPORT_SYMBOL(omapdss_get_default_display_name);
60
61enum omapdss_version omapdss_get_version(void)
62{
63 struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
64 return pdata->version;
65}
66EXPORT_SYMBOL(omapdss_get_version);
67
68bool omapdss_is_initialized(void)
69{
70 return dss_initialized;
71}
72EXPORT_SYMBOL(omapdss_is_initialized);
73
74struct platform_device *dss_get_core_pdev(void)
75{
76 return core.pdev;
77}
78
79int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask)
80{
81 struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
82
83 if (!board_data->dsi_enable_pads)
84 return -ENOENT;
85
86 return board_data->dsi_enable_pads(dsi_id, lane_mask);
87}
88
89void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask)
90{
91 struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
92
93 if (!board_data->dsi_disable_pads)
94 return;
95
96 return board_data->dsi_disable_pads(dsi_id, lane_mask);
97}
98
99int dss_set_min_bus_tput(struct device *dev, unsigned long tput)
100{
101 struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
102
103 if (pdata->set_min_bus_tput)
104 return pdata->set_min_bus_tput(dev, tput);
105 else
106 return 0;
107}
108
109#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
110static int dss_debug_show(struct seq_file *s, void *unused)
111{
112 void (*func)(struct seq_file *) = s->private;
113 func(s);
114 return 0;
115}
116
117static int dss_debug_open(struct inode *inode, struct file *file)
118{
119 return single_open(file, dss_debug_show, inode->i_private);
120}
121
122static const struct file_operations dss_debug_fops = {
123 .open = dss_debug_open,
124 .read = seq_read,
125 .llseek = seq_lseek,
126 .release = single_release,
127};
128
129static struct dentry *dss_debugfs_dir;
130
131static int dss_initialize_debugfs(void)
132{
133 dss_debugfs_dir = debugfs_create_dir("omapdss", NULL);
134 if (IS_ERR(dss_debugfs_dir)) {
135 int err = PTR_ERR(dss_debugfs_dir);
136 dss_debugfs_dir = NULL;
137 return err;
138 }
139
140 debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
141 &dss_debug_dump_clocks, &dss_debug_fops);
142
143 return 0;
144}
145
146static void dss_uninitialize_debugfs(void)
147{
148 if (dss_debugfs_dir)
149 debugfs_remove_recursive(dss_debugfs_dir);
150}
151
152int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
153{
154 struct dentry *d;
155
156 d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir,
157 write, &dss_debug_fops);
158
159 return PTR_ERR_OR_ZERO(d);
160}
161#else /* CONFIG_OMAP2_DSS_DEBUGFS */
162static inline int dss_initialize_debugfs(void)
163{
164 return 0;
165}
166static inline void dss_uninitialize_debugfs(void)
167{
168}
169int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
170{
171 return 0;
172}
173#endif /* CONFIG_OMAP2_DSS_DEBUGFS */
174
175/* PLATFORM DEVICE */
176static int omap_dss_pm_notif(struct notifier_block *b, unsigned long v, void *d)
177{
178 DSSDBG("pm notif %lu\n", v);
179
180 switch (v) {
181 case PM_SUSPEND_PREPARE:
182 DSSDBG("suspending displays\n");
183 return dss_suspend_all_devices();
184
185 case PM_POST_SUSPEND:
186 DSSDBG("resuming displays\n");
187 return dss_resume_all_devices();
188
189 default:
190 return 0;
191 }
192}
193
194static struct notifier_block omap_dss_pm_notif_block = {
195 .notifier_call = omap_dss_pm_notif,
196};
197
198static int __init omap_dss_probe(struct platform_device *pdev)
199{
200 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
201 int r;
202
203 core.pdev = pdev;
204
205 dss_features_init(omapdss_get_version());
206
207 r = dss_initialize_debugfs();
208 if (r)
209 goto err_debugfs;
210
211 if (def_disp_name)
212 core.default_display_name = def_disp_name;
213 else if (pdata->default_display_name)
214 core.default_display_name = pdata->default_display_name;
215 else if (pdata->default_device)
216 core.default_display_name = pdata->default_device->name;
217
218 register_pm_notifier(&omap_dss_pm_notif_block);
219
220 return 0;
221
222err_debugfs:
223
224 return r;
225}
226
227static int omap_dss_remove(struct platform_device *pdev)
228{
229 unregister_pm_notifier(&omap_dss_pm_notif_block);
230
231 dss_uninitialize_debugfs();
232
233 return 0;
234}
235
236static void omap_dss_shutdown(struct platform_device *pdev)
237{
238 DSSDBG("shutdown\n");
239 dss_disable_all_devices();
240}
241
242static struct platform_driver omap_dss_driver = {
243 .remove = omap_dss_remove,
244 .shutdown = omap_dss_shutdown,
245 .driver = {
246 .name = "omapdss",
247 .owner = THIS_MODULE,
248 },
249};
250
251/* INIT */
252static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
253#ifdef CONFIG_OMAP2_DSS_DSI
254 dsi_init_platform_driver,
255#endif
256#ifdef CONFIG_OMAP2_DSS_DPI
257 dpi_init_platform_driver,
258#endif
259#ifdef CONFIG_OMAP2_DSS_SDI
260 sdi_init_platform_driver,
261#endif
262#ifdef CONFIG_OMAP2_DSS_RFBI
263 rfbi_init_platform_driver,
264#endif
265#ifdef CONFIG_OMAP2_DSS_VENC
266 venc_init_platform_driver,
267#endif
268#ifdef CONFIG_OMAP4_DSS_HDMI
269 hdmi4_init_platform_driver,
270#endif
271};
272
273static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
274#ifdef CONFIG_OMAP2_DSS_DSI
275 dsi_uninit_platform_driver,
276#endif
277#ifdef CONFIG_OMAP2_DSS_DPI
278 dpi_uninit_platform_driver,
279#endif
280#ifdef CONFIG_OMAP2_DSS_SDI
281 sdi_uninit_platform_driver,
282#endif
283#ifdef CONFIG_OMAP2_DSS_RFBI
284 rfbi_uninit_platform_driver,
285#endif
286#ifdef CONFIG_OMAP2_DSS_VENC
287 venc_uninit_platform_driver,
288#endif
289#ifdef CONFIG_OMAP4_DSS_HDMI
290 hdmi4_uninit_platform_driver,
291#endif
292};
293
294static bool dss_output_drv_loaded[ARRAY_SIZE(dss_output_drv_reg_funcs)];
295
296static int __init omap_dss_init(void)
297{
298 int r;
299 int i;
300
301 r = platform_driver_probe(&omap_dss_driver, omap_dss_probe);
302 if (r)
303 return r;
304
305 r = dss_init_platform_driver();
306 if (r) {
307 DSSERR("Failed to initialize DSS platform driver\n");
308 goto err_dss;
309 }
310
311 r = dispc_init_platform_driver();
312 if (r) {
313 DSSERR("Failed to initialize dispc platform driver\n");
314 goto err_dispc;
315 }
316
317 /*
318 * It's ok if the output-driver register fails. It happens, for example,
319 * when there is no output-device (e.g. SDI for OMAP4).
320 */
321 for (i = 0; i < ARRAY_SIZE(dss_output_drv_reg_funcs); ++i) {
322 r = dss_output_drv_reg_funcs[i]();
323 if (r == 0)
324 dss_output_drv_loaded[i] = true;
325 }
326
327 dss_initialized = true;
328
329 return 0;
330
331err_dispc:
332 dss_uninit_platform_driver();
333err_dss:
334 platform_driver_unregister(&omap_dss_driver);
335
336 return r;
337}
338
339static void __exit omap_dss_exit(void)
340{
341 int i;
342
343 for (i = 0; i < ARRAY_SIZE(dss_output_drv_unreg_funcs); ++i) {
344 if (dss_output_drv_loaded[i])
345 dss_output_drv_unreg_funcs[i]();
346 }
347
348 dispc_uninit_platform_driver();
349 dss_uninit_platform_driver();
350
351 platform_driver_unregister(&omap_dss_driver);
352}
353
354module_init(omap_dss_init);
355module_exit(omap_dss_exit);
356
357MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
358MODULE_DESCRIPTION("OMAP2/3 Display Subsystem");
359MODULE_LICENSE("GPL v2");
360
diff --git a/drivers/video/omap2/dss/dispc-compat.c b/drivers/video/omap2/dss/dispc-compat.c
deleted file mode 100644
index 83779c2b292a..000000000000
--- a/drivers/video/omap2/dss/dispc-compat.c
+++ /dev/null
@@ -1,666 +0,0 @@
1/*
2 * Copyright (C) 2012 Texas Instruments
3 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#define DSS_SUBSYS_NAME "APPLY"
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/slab.h>
23#include <linux/spinlock.h>
24#include <linux/jiffies.h>
25#include <linux/delay.h>
26#include <linux/interrupt.h>
27#include <linux/seq_file.h>
28
29#include <video/omapdss.h>
30
31#include "dss.h"
32#include "dss_features.h"
33#include "dispc-compat.h"
34
35#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
36 DISPC_IRQ_OCP_ERR | \
37 DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
38 DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
39 DISPC_IRQ_SYNC_LOST | \
40 DISPC_IRQ_SYNC_LOST_DIGIT)
41
42#define DISPC_MAX_NR_ISRS 8
43
44struct omap_dispc_isr_data {
45 omap_dispc_isr_t isr;
46 void *arg;
47 u32 mask;
48};
49
50struct dispc_irq_stats {
51 unsigned long last_reset;
52 unsigned irq_count;
53 unsigned irqs[32];
54};
55
56static struct {
57 spinlock_t irq_lock;
58 u32 irq_error_mask;
59 struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
60 u32 error_irqs;
61 struct work_struct error_work;
62
63#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
64 spinlock_t irq_stats_lock;
65 struct dispc_irq_stats irq_stats;
66#endif
67} dispc_compat;
68
69
70#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
71static void dispc_dump_irqs(struct seq_file *s)
72{
73 unsigned long flags;
74 struct dispc_irq_stats stats;
75
76 spin_lock_irqsave(&dispc_compat.irq_stats_lock, flags);
77
78 stats = dispc_compat.irq_stats;
79 memset(&dispc_compat.irq_stats, 0, sizeof(dispc_compat.irq_stats));
80 dispc_compat.irq_stats.last_reset = jiffies;
81
82 spin_unlock_irqrestore(&dispc_compat.irq_stats_lock, flags);
83
84 seq_printf(s, "period %u ms\n",
85 jiffies_to_msecs(jiffies - stats.last_reset));
86
87 seq_printf(s, "irqs %d\n", stats.irq_count);
88#define PIS(x) \
89 seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
90
91 PIS(FRAMEDONE);
92 PIS(VSYNC);
93 PIS(EVSYNC_EVEN);
94 PIS(EVSYNC_ODD);
95 PIS(ACBIAS_COUNT_STAT);
96 PIS(PROG_LINE_NUM);
97 PIS(GFX_FIFO_UNDERFLOW);
98 PIS(GFX_END_WIN);
99 PIS(PAL_GAMMA_MASK);
100 PIS(OCP_ERR);
101 PIS(VID1_FIFO_UNDERFLOW);
102 PIS(VID1_END_WIN);
103 PIS(VID2_FIFO_UNDERFLOW);
104 PIS(VID2_END_WIN);
105 if (dss_feat_get_num_ovls() > 3) {
106 PIS(VID3_FIFO_UNDERFLOW);
107 PIS(VID3_END_WIN);
108 }
109 PIS(SYNC_LOST);
110 PIS(SYNC_LOST_DIGIT);
111 PIS(WAKEUP);
112 if (dss_has_feature(FEAT_MGR_LCD2)) {
113 PIS(FRAMEDONE2);
114 PIS(VSYNC2);
115 PIS(ACBIAS_COUNT_STAT2);
116 PIS(SYNC_LOST2);
117 }
118 if (dss_has_feature(FEAT_MGR_LCD3)) {
119 PIS(FRAMEDONE3);
120 PIS(VSYNC3);
121 PIS(ACBIAS_COUNT_STAT3);
122 PIS(SYNC_LOST3);
123 }
124#undef PIS
125}
126#endif
127
128/* dispc.irq_lock has to be locked by the caller */
129static void _omap_dispc_set_irqs(void)
130{
131 u32 mask;
132 int i;
133 struct omap_dispc_isr_data *isr_data;
134
135 mask = dispc_compat.irq_error_mask;
136
137 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
138 isr_data = &dispc_compat.registered_isr[i];
139
140 if (isr_data->isr == NULL)
141 continue;
142
143 mask |= isr_data->mask;
144 }
145
146 dispc_write_irqenable(mask);
147}
148
149int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
150{
151 int i;
152 int ret;
153 unsigned long flags;
154 struct omap_dispc_isr_data *isr_data;
155
156 if (isr == NULL)
157 return -EINVAL;
158
159 spin_lock_irqsave(&dispc_compat.irq_lock, flags);
160
161 /* check for duplicate entry */
162 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
163 isr_data = &dispc_compat.registered_isr[i];
164 if (isr_data->isr == isr && isr_data->arg == arg &&
165 isr_data->mask == mask) {
166 ret = -EINVAL;
167 goto err;
168 }
169 }
170
171 isr_data = NULL;
172 ret = -EBUSY;
173
174 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
175 isr_data = &dispc_compat.registered_isr[i];
176
177 if (isr_data->isr != NULL)
178 continue;
179
180 isr_data->isr = isr;
181 isr_data->arg = arg;
182 isr_data->mask = mask;
183 ret = 0;
184
185 break;
186 }
187
188 if (ret)
189 goto err;
190
191 _omap_dispc_set_irqs();
192
193 spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
194
195 return 0;
196err:
197 spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
198
199 return ret;
200}
201EXPORT_SYMBOL(omap_dispc_register_isr);
202
203int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
204{
205 int i;
206 unsigned long flags;
207 int ret = -EINVAL;
208 struct omap_dispc_isr_data *isr_data;
209
210 spin_lock_irqsave(&dispc_compat.irq_lock, flags);
211
212 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
213 isr_data = &dispc_compat.registered_isr[i];
214 if (isr_data->isr != isr || isr_data->arg != arg ||
215 isr_data->mask != mask)
216 continue;
217
218 /* found the correct isr */
219
220 isr_data->isr = NULL;
221 isr_data->arg = NULL;
222 isr_data->mask = 0;
223
224 ret = 0;
225 break;
226 }
227
228 if (ret == 0)
229 _omap_dispc_set_irqs();
230
231 spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
232
233 return ret;
234}
235EXPORT_SYMBOL(omap_dispc_unregister_isr);
236
237static void print_irq_status(u32 status)
238{
239 if ((status & dispc_compat.irq_error_mask) == 0)
240 return;
241
242#define PIS(x) (status & DISPC_IRQ_##x) ? (#x " ") : ""
243
244 pr_debug("DISPC IRQ: 0x%x: %s%s%s%s%s%s%s%s%s\n",
245 status,
246 PIS(OCP_ERR),
247 PIS(GFX_FIFO_UNDERFLOW),
248 PIS(VID1_FIFO_UNDERFLOW),
249 PIS(VID2_FIFO_UNDERFLOW),
250 dss_feat_get_num_ovls() > 3 ? PIS(VID3_FIFO_UNDERFLOW) : "",
251 PIS(SYNC_LOST),
252 PIS(SYNC_LOST_DIGIT),
253 dss_has_feature(FEAT_MGR_LCD2) ? PIS(SYNC_LOST2) : "",
254 dss_has_feature(FEAT_MGR_LCD3) ? PIS(SYNC_LOST3) : "");
255#undef PIS
256}
257
258/* Called from dss.c. Note that we don't touch clocks here,
259 * but we presume they are on because we got an IRQ. However,
260 * an irq handler may turn the clocks off, so we may not have
261 * clock later in the function. */
262static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
263{
264 int i;
265 u32 irqstatus, irqenable;
266 u32 handledirqs = 0;
267 u32 unhandled_errors;
268 struct omap_dispc_isr_data *isr_data;
269 struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
270
271 spin_lock(&dispc_compat.irq_lock);
272
273 irqstatus = dispc_read_irqstatus();
274 irqenable = dispc_read_irqenable();
275
276 /* IRQ is not for us */
277 if (!(irqstatus & irqenable)) {
278 spin_unlock(&dispc_compat.irq_lock);
279 return IRQ_NONE;
280 }
281
282#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
283 spin_lock(&dispc_compat.irq_stats_lock);
284 dispc_compat.irq_stats.irq_count++;
285 dss_collect_irq_stats(irqstatus, dispc_compat.irq_stats.irqs);
286 spin_unlock(&dispc_compat.irq_stats_lock);
287#endif
288
289 print_irq_status(irqstatus);
290
291 /* Ack the interrupt. Do it here before clocks are possibly turned
292 * off */
293 dispc_clear_irqstatus(irqstatus);
294 /* flush posted write */
295 dispc_read_irqstatus();
296
297 /* make a copy and unlock, so that isrs can unregister
298 * themselves */
299 memcpy(registered_isr, dispc_compat.registered_isr,
300 sizeof(registered_isr));
301
302 spin_unlock(&dispc_compat.irq_lock);
303
304 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
305 isr_data = &registered_isr[i];
306
307 if (!isr_data->isr)
308 continue;
309
310 if (isr_data->mask & irqstatus) {
311 isr_data->isr(isr_data->arg, irqstatus);
312 handledirqs |= isr_data->mask;
313 }
314 }
315
316 spin_lock(&dispc_compat.irq_lock);
317
318 unhandled_errors = irqstatus & ~handledirqs & dispc_compat.irq_error_mask;
319
320 if (unhandled_errors) {
321 dispc_compat.error_irqs |= unhandled_errors;
322
323 dispc_compat.irq_error_mask &= ~unhandled_errors;
324 _omap_dispc_set_irqs();
325
326 schedule_work(&dispc_compat.error_work);
327 }
328
329 spin_unlock(&dispc_compat.irq_lock);
330
331 return IRQ_HANDLED;
332}
333
334static void dispc_error_worker(struct work_struct *work)
335{
336 int i;
337 u32 errors;
338 unsigned long flags;
339 static const unsigned fifo_underflow_bits[] = {
340 DISPC_IRQ_GFX_FIFO_UNDERFLOW,
341 DISPC_IRQ_VID1_FIFO_UNDERFLOW,
342 DISPC_IRQ_VID2_FIFO_UNDERFLOW,
343 DISPC_IRQ_VID3_FIFO_UNDERFLOW,
344 };
345
346 spin_lock_irqsave(&dispc_compat.irq_lock, flags);
347 errors = dispc_compat.error_irqs;
348 dispc_compat.error_irqs = 0;
349 spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
350
351 dispc_runtime_get();
352
353 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
354 struct omap_overlay *ovl;
355 unsigned bit;
356
357 ovl = omap_dss_get_overlay(i);
358 bit = fifo_underflow_bits[i];
359
360 if (bit & errors) {
361 DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n",
362 ovl->name);
363 ovl->disable(ovl);
364 msleep(50);
365 }
366 }
367
368 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
369 struct omap_overlay_manager *mgr;
370 unsigned bit;
371
372 mgr = omap_dss_get_overlay_manager(i);
373 bit = dispc_mgr_get_sync_lost_irq(i);
374
375 if (bit & errors) {
376 int j;
377
378 DSSERR("SYNC_LOST on channel %s, restarting the output "
379 "with video overlays disabled\n",
380 mgr->name);
381
382 dss_mgr_disable(mgr);
383
384 for (j = 0; j < omap_dss_get_num_overlays(); ++j) {
385 struct omap_overlay *ovl;
386 ovl = omap_dss_get_overlay(j);
387
388 if (ovl->id != OMAP_DSS_GFX &&
389 ovl->manager == mgr)
390 ovl->disable(ovl);
391 }
392
393 dss_mgr_enable(mgr);
394 }
395 }
396
397 if (errors & DISPC_IRQ_OCP_ERR) {
398 DSSERR("OCP_ERR\n");
399 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
400 struct omap_overlay_manager *mgr;
401
402 mgr = omap_dss_get_overlay_manager(i);
403 dss_mgr_disable(mgr);
404 }
405 }
406
407 spin_lock_irqsave(&dispc_compat.irq_lock, flags);
408 dispc_compat.irq_error_mask |= errors;
409 _omap_dispc_set_irqs();
410 spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
411
412 dispc_runtime_put();
413}
414
415int dss_dispc_initialize_irq(void)
416{
417 int r;
418
419#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
420 spin_lock_init(&dispc_compat.irq_stats_lock);
421 dispc_compat.irq_stats.last_reset = jiffies;
422 dss_debugfs_create_file("dispc_irq", dispc_dump_irqs);
423#endif
424
425 spin_lock_init(&dispc_compat.irq_lock);
426
427 memset(dispc_compat.registered_isr, 0,
428 sizeof(dispc_compat.registered_isr));
429
430 dispc_compat.irq_error_mask = DISPC_IRQ_MASK_ERROR;
431 if (dss_has_feature(FEAT_MGR_LCD2))
432 dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
433 if (dss_has_feature(FEAT_MGR_LCD3))
434 dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST3;
435 if (dss_feat_get_num_ovls() > 3)
436 dispc_compat.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;
437
438 /*
439 * there's SYNC_LOST_DIGIT waiting after enabling the DSS,
440 * so clear it
441 */
442 dispc_clear_irqstatus(dispc_read_irqstatus());
443
444 INIT_WORK(&dispc_compat.error_work, dispc_error_worker);
445
446 _omap_dispc_set_irqs();
447
448 r = dispc_request_irq(omap_dispc_irq_handler, &dispc_compat);
449 if (r) {
450 DSSERR("dispc_request_irq failed\n");
451 return r;
452 }
453
454 return 0;
455}
456
457void dss_dispc_uninitialize_irq(void)
458{
459 dispc_free_irq(&dispc_compat);
460}
461
462static void dispc_mgr_disable_isr(void *data, u32 mask)
463{
464 struct completion *compl = data;
465 complete(compl);
466}
467
468static void dispc_mgr_enable_lcd_out(enum omap_channel channel)
469{
470 dispc_mgr_enable(channel, true);
471}
472
473static void dispc_mgr_disable_lcd_out(enum omap_channel channel)
474{
475 DECLARE_COMPLETION_ONSTACK(framedone_compl);
476 int r;
477 u32 irq;
478
479 if (dispc_mgr_is_enabled(channel) == false)
480 return;
481
482 /*
483 * When we disable LCD output, we need to wait for FRAMEDONE to know
484 * that DISPC has finished with the LCD output.
485 */
486
487 irq = dispc_mgr_get_framedone_irq(channel);
488
489 r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
490 irq);
491 if (r)
492 DSSERR("failed to register FRAMEDONE isr\n");
493
494 dispc_mgr_enable(channel, false);
495
496 /* if we couldn't register for framedone, just sleep and exit */
497 if (r) {
498 msleep(100);
499 return;
500 }
501
502 if (!wait_for_completion_timeout(&framedone_compl,
503 msecs_to_jiffies(100)))
504 DSSERR("timeout waiting for FRAME DONE\n");
505
506 r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
507 irq);
508 if (r)
509 DSSERR("failed to unregister FRAMEDONE isr\n");
510}
511
512static void dispc_digit_out_enable_isr(void *data, u32 mask)
513{
514 struct completion *compl = data;
515
516 /* ignore any sync lost interrupts */
517 if (mask & (DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD))
518 complete(compl);
519}
520
521static void dispc_mgr_enable_digit_out(void)
522{
523 DECLARE_COMPLETION_ONSTACK(vsync_compl);
524 int r;
525 u32 irq_mask;
526
527 if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == true)
528 return;
529
530 /*
531 * Digit output produces some sync lost interrupts during the first
532 * frame when enabling. Those need to be ignored, so we register for the
533 * sync lost irq to prevent the error handler from triggering.
534 */
535
536 irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT) |
537 dispc_mgr_get_sync_lost_irq(OMAP_DSS_CHANNEL_DIGIT);
538
539 r = omap_dispc_register_isr(dispc_digit_out_enable_isr, &vsync_compl,
540 irq_mask);
541 if (r) {
542 DSSERR("failed to register %x isr\n", irq_mask);
543 return;
544 }
545
546 dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, true);
547
548 /* wait for the first evsync */
549 if (!wait_for_completion_timeout(&vsync_compl, msecs_to_jiffies(100)))
550 DSSERR("timeout waiting for digit out to start\n");
551
552 r = omap_dispc_unregister_isr(dispc_digit_out_enable_isr, &vsync_compl,
553 irq_mask);
554 if (r)
555 DSSERR("failed to unregister %x isr\n", irq_mask);
556}
557
558static void dispc_mgr_disable_digit_out(void)
559{
560 DECLARE_COMPLETION_ONSTACK(framedone_compl);
561 int r, i;
562 u32 irq_mask;
563 int num_irqs;
564
565 if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == false)
566 return;
567
568 /*
569 * When we disable the digit output, we need to wait for FRAMEDONE to
570 * know that DISPC has finished with the output.
571 */
572
573 irq_mask = dispc_mgr_get_framedone_irq(OMAP_DSS_CHANNEL_DIGIT);
574 num_irqs = 1;
575
576 if (!irq_mask) {
577 /*
578 * omap 2/3 don't have framedone irq for TV, so we need to use
579 * vsyncs for this.
580 */
581
582 irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT);
583 /*
584 * We need to wait for both even and odd vsyncs. Note that this
585 * is not totally reliable, as we could get a vsync interrupt
586 * before we disable the output, which leads to timeout in the
587 * wait_for_completion.
588 */
589 num_irqs = 2;
590 }
591
592 r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
593 irq_mask);
594 if (r)
595 DSSERR("failed to register %x isr\n", irq_mask);
596
597 dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, false);
598
599 /* if we couldn't register the irq, just sleep and exit */
600 if (r) {
601 msleep(100);
602 return;
603 }
604
605 for (i = 0; i < num_irqs; ++i) {
606 if (!wait_for_completion_timeout(&framedone_compl,
607 msecs_to_jiffies(100)))
608 DSSERR("timeout waiting for digit out to stop\n");
609 }
610
611 r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
612 irq_mask);
613 if (r)
614 DSSERR("failed to unregister %x isr\n", irq_mask);
615}
616
617void dispc_mgr_enable_sync(enum omap_channel channel)
618{
619 if (dss_mgr_is_lcd(channel))
620 dispc_mgr_enable_lcd_out(channel);
621 else if (channel == OMAP_DSS_CHANNEL_DIGIT)
622 dispc_mgr_enable_digit_out();
623 else
624 WARN_ON(1);
625}
626
627void dispc_mgr_disable_sync(enum omap_channel channel)
628{
629 if (dss_mgr_is_lcd(channel))
630 dispc_mgr_disable_lcd_out(channel);
631 else if (channel == OMAP_DSS_CHANNEL_DIGIT)
632 dispc_mgr_disable_digit_out();
633 else
634 WARN_ON(1);
635}
636
637int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
638 unsigned long timeout)
639{
640 void dispc_irq_wait_handler(void *data, u32 mask)
641 {
642 complete((struct completion *)data);
643 }
644
645 int r;
646 DECLARE_COMPLETION_ONSTACK(completion);
647
648 r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
649 irqmask);
650
651 if (r)
652 return r;
653
654 timeout = wait_for_completion_interruptible_timeout(&completion,
655 timeout);
656
657 omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
658
659 if (timeout == 0)
660 return -ETIMEDOUT;
661
662 if (timeout == -ERESTARTSYS)
663 return -ERESTARTSYS;
664
665 return 0;
666}
diff --git a/drivers/video/omap2/dss/dispc-compat.h b/drivers/video/omap2/dss/dispc-compat.h
deleted file mode 100644
index 14a69b3d4fb0..000000000000
--- a/drivers/video/omap2/dss/dispc-compat.h
+++ /dev/null
@@ -1,30 +0,0 @@
1/*
2 * Copyright (C) 2012 Texas Instruments
3 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef __OMAP2_DSS_DISPC_COMPAT_H
19#define __OMAP2_DSS_DISPC_COMPAT_H
20
21void dispc_mgr_enable_sync(enum omap_channel channel);
22void dispc_mgr_disable_sync(enum omap_channel channel);
23
24int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
25 unsigned long timeout);
26
27int dss_dispc_initialize_irq(void);
28void dss_dispc_uninitialize_irq(void);
29
30#endif
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
deleted file mode 100644
index f18397c33e8f..000000000000
--- a/drivers/video/omap2/dss/dispc.c
+++ /dev/null
@@ -1,3853 +0,0 @@
1/*
2 * linux/drivers/video/omap2/dss/dispc.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
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#define DSS_SUBSYS_NAME "DISPC"
24
25#include <linux/kernel.h>
26#include <linux/dma-mapping.h>
27#include <linux/vmalloc.h>
28#include <linux/export.h>
29#include <linux/clk.h>
30#include <linux/io.h>
31#include <linux/jiffies.h>
32#include <linux/seq_file.h>
33#include <linux/delay.h>
34#include <linux/workqueue.h>
35#include <linux/hardirq.h>
36#include <linux/platform_device.h>
37#include <linux/pm_runtime.h>
38#include <linux/sizes.h>
39
40#include <video/omapdss.h>
41
42#include "dss.h"
43#include "dss_features.h"
44#include "dispc.h"
45
46/* DISPC */
47#define DISPC_SZ_REGS SZ_4K
48
49enum omap_burst_size {
50 BURST_SIZE_X2 = 0,
51 BURST_SIZE_X4 = 1,
52 BURST_SIZE_X8 = 2,
53};
54
55#define REG_GET(idx, start, end) \
56 FLD_GET(dispc_read_reg(idx), start, end)
57
58#define REG_FLD_MOD(idx, val, start, end) \
59 dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
60
61struct dispc_features {
62 u8 sw_start;
63 u8 fp_start;
64 u8 bp_start;
65 u16 sw_max;
66 u16 vp_max;
67 u16 hp_max;
68 u8 mgr_width_start;
69 u8 mgr_height_start;
70 u16 mgr_width_max;
71 u16 mgr_height_max;
72 unsigned long max_lcd_pclk;
73 unsigned long max_tv_pclk;
74 int (*calc_scaling) (unsigned long pclk, unsigned long lclk,
75 const struct omap_video_timings *mgr_timings,
76 u16 width, u16 height, u16 out_width, u16 out_height,
77 enum omap_color_mode color_mode, bool *five_taps,
78 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
79 u16 pos_x, unsigned long *core_clk, bool mem_to_mem);
80 unsigned long (*calc_core_clk) (unsigned long pclk,
81 u16 width, u16 height, u16 out_width, u16 out_height,
82 bool mem_to_mem);
83 u8 num_fifos;
84
85 /* swap GFX & WB fifos */
86 bool gfx_fifo_workaround:1;
87
88 /* no DISPC_IRQ_FRAMEDONETV on this SoC */
89 bool no_framedone_tv:1;
90
91 /* revert to the OMAP4 mechanism of DISPC Smart Standby operation */
92 bool mstandby_workaround:1;
93
94 bool set_max_preload:1;
95};
96
97#define DISPC_MAX_NR_FIFOS 5
98
99static struct {
100 struct platform_device *pdev;
101 void __iomem *base;
102
103 int irq;
104 irq_handler_t user_handler;
105 void *user_data;
106
107 unsigned long core_clk_rate;
108 unsigned long tv_pclk_rate;
109
110 u32 fifo_size[DISPC_MAX_NR_FIFOS];
111 /* maps which plane is using a fifo. fifo-id -> plane-id */
112 int fifo_assignment[DISPC_MAX_NR_FIFOS];
113
114 bool ctx_valid;
115 u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
116
117 const struct dispc_features *feat;
118
119 bool is_enabled;
120} dispc;
121
122enum omap_color_component {
123 /* used for all color formats for OMAP3 and earlier
124 * and for RGB and Y color component on OMAP4
125 */
126 DISPC_COLOR_COMPONENT_RGB_Y = 1 << 0,
127 /* used for UV component for
128 * OMAP_DSS_COLOR_YUV2, OMAP_DSS_COLOR_UYVY, OMAP_DSS_COLOR_NV12
129 * color formats on OMAP4
130 */
131 DISPC_COLOR_COMPONENT_UV = 1 << 1,
132};
133
134enum mgr_reg_fields {
135 DISPC_MGR_FLD_ENABLE,
136 DISPC_MGR_FLD_STNTFT,
137 DISPC_MGR_FLD_GO,
138 DISPC_MGR_FLD_TFTDATALINES,
139 DISPC_MGR_FLD_STALLMODE,
140 DISPC_MGR_FLD_TCKENABLE,
141 DISPC_MGR_FLD_TCKSELECTION,
142 DISPC_MGR_FLD_CPR,
143 DISPC_MGR_FLD_FIFOHANDCHECK,
144 /* used to maintain a count of the above fields */
145 DISPC_MGR_FLD_NUM,
146};
147
148struct dispc_reg_field {
149 u16 reg;
150 u8 high;
151 u8 low;
152};
153
154static const struct {
155 const char *name;
156 u32 vsync_irq;
157 u32 framedone_irq;
158 u32 sync_lost_irq;
159 struct dispc_reg_field reg_desc[DISPC_MGR_FLD_NUM];
160} mgr_desc[] = {
161 [OMAP_DSS_CHANNEL_LCD] = {
162 .name = "LCD",
163 .vsync_irq = DISPC_IRQ_VSYNC,
164 .framedone_irq = DISPC_IRQ_FRAMEDONE,
165 .sync_lost_irq = DISPC_IRQ_SYNC_LOST,
166 .reg_desc = {
167 [DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL, 0, 0 },
168 [DISPC_MGR_FLD_STNTFT] = { DISPC_CONTROL, 3, 3 },
169 [DISPC_MGR_FLD_GO] = { DISPC_CONTROL, 5, 5 },
170 [DISPC_MGR_FLD_TFTDATALINES] = { DISPC_CONTROL, 9, 8 },
171 [DISPC_MGR_FLD_STALLMODE] = { DISPC_CONTROL, 11, 11 },
172 [DISPC_MGR_FLD_TCKENABLE] = { DISPC_CONFIG, 10, 10 },
173 [DISPC_MGR_FLD_TCKSELECTION] = { DISPC_CONFIG, 11, 11 },
174 [DISPC_MGR_FLD_CPR] = { DISPC_CONFIG, 15, 15 },
175 [DISPC_MGR_FLD_FIFOHANDCHECK] = { DISPC_CONFIG, 16, 16 },
176 },
177 },
178 [OMAP_DSS_CHANNEL_DIGIT] = {
179 .name = "DIGIT",
180 .vsync_irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN,
181 .framedone_irq = DISPC_IRQ_FRAMEDONETV,
182 .sync_lost_irq = DISPC_IRQ_SYNC_LOST_DIGIT,
183 .reg_desc = {
184 [DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL, 1, 1 },
185 [DISPC_MGR_FLD_STNTFT] = { },
186 [DISPC_MGR_FLD_GO] = { DISPC_CONTROL, 6, 6 },
187 [DISPC_MGR_FLD_TFTDATALINES] = { },
188 [DISPC_MGR_FLD_STALLMODE] = { },
189 [DISPC_MGR_FLD_TCKENABLE] = { DISPC_CONFIG, 12, 12 },
190 [DISPC_MGR_FLD_TCKSELECTION] = { DISPC_CONFIG, 13, 13 },
191 [DISPC_MGR_FLD_CPR] = { },
192 [DISPC_MGR_FLD_FIFOHANDCHECK] = { DISPC_CONFIG, 16, 16 },
193 },
194 },
195 [OMAP_DSS_CHANNEL_LCD2] = {
196 .name = "LCD2",
197 .vsync_irq = DISPC_IRQ_VSYNC2,
198 .framedone_irq = DISPC_IRQ_FRAMEDONE2,
199 .sync_lost_irq = DISPC_IRQ_SYNC_LOST2,
200 .reg_desc = {
201 [DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL2, 0, 0 },
202 [DISPC_MGR_FLD_STNTFT] = { DISPC_CONTROL2, 3, 3 },
203 [DISPC_MGR_FLD_GO] = { DISPC_CONTROL2, 5, 5 },
204 [DISPC_MGR_FLD_TFTDATALINES] = { DISPC_CONTROL2, 9, 8 },
205 [DISPC_MGR_FLD_STALLMODE] = { DISPC_CONTROL2, 11, 11 },
206 [DISPC_MGR_FLD_TCKENABLE] = { DISPC_CONFIG2, 10, 10 },
207 [DISPC_MGR_FLD_TCKSELECTION] = { DISPC_CONFIG2, 11, 11 },
208 [DISPC_MGR_FLD_CPR] = { DISPC_CONFIG2, 15, 15 },
209 [DISPC_MGR_FLD_FIFOHANDCHECK] = { DISPC_CONFIG2, 16, 16 },
210 },
211 },
212 [OMAP_DSS_CHANNEL_LCD3] = {
213 .name = "LCD3",
214 .vsync_irq = DISPC_IRQ_VSYNC3,
215 .framedone_irq = DISPC_IRQ_FRAMEDONE3,
216 .sync_lost_irq = DISPC_IRQ_SYNC_LOST3,
217 .reg_desc = {
218 [DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL3, 0, 0 },
219 [DISPC_MGR_FLD_STNTFT] = { DISPC_CONTROL3, 3, 3 },
220 [DISPC_MGR_FLD_GO] = { DISPC_CONTROL3, 5, 5 },
221 [DISPC_MGR_FLD_TFTDATALINES] = { DISPC_CONTROL3, 9, 8 },
222 [DISPC_MGR_FLD_STALLMODE] = { DISPC_CONTROL3, 11, 11 },
223 [DISPC_MGR_FLD_TCKENABLE] = { DISPC_CONFIG3, 10, 10 },
224 [DISPC_MGR_FLD_TCKSELECTION] = { DISPC_CONFIG3, 11, 11 },
225 [DISPC_MGR_FLD_CPR] = { DISPC_CONFIG3, 15, 15 },
226 [DISPC_MGR_FLD_FIFOHANDCHECK] = { DISPC_CONFIG3, 16, 16 },
227 },
228 },
229};
230
231struct color_conv_coef {
232 int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
233 int full_range;
234};
235
236static unsigned long dispc_plane_pclk_rate(enum omap_plane plane);
237static unsigned long dispc_plane_lclk_rate(enum omap_plane plane);
238
239static inline void dispc_write_reg(const u16 idx, u32 val)
240{
241 __raw_writel(val, dispc.base + idx);
242}
243
244static inline u32 dispc_read_reg(const u16 idx)
245{
246 return __raw_readl(dispc.base + idx);
247}
248
249static u32 mgr_fld_read(enum omap_channel channel, enum mgr_reg_fields regfld)
250{
251 const struct dispc_reg_field rfld = mgr_desc[channel].reg_desc[regfld];
252 return REG_GET(rfld.reg, rfld.high, rfld.low);
253}
254
255static void mgr_fld_write(enum omap_channel channel,
256 enum mgr_reg_fields regfld, int val) {
257 const struct dispc_reg_field rfld = mgr_desc[channel].reg_desc[regfld];
258 REG_FLD_MOD(rfld.reg, val, rfld.high, rfld.low);
259}
260
261#define SR(reg) \
262 dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
263#define RR(reg) \
264 dispc_write_reg(DISPC_##reg, dispc.ctx[DISPC_##reg / sizeof(u32)])
265
266static void dispc_save_context(void)
267{
268 int i, j;
269
270 DSSDBG("dispc_save_context\n");
271
272 SR(IRQENABLE);
273 SR(CONTROL);
274 SR(CONFIG);
275 SR(LINE_NUMBER);
276 if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
277 dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
278 SR(GLOBAL_ALPHA);
279 if (dss_has_feature(FEAT_MGR_LCD2)) {
280 SR(CONTROL2);
281 SR(CONFIG2);
282 }
283 if (dss_has_feature(FEAT_MGR_LCD3)) {
284 SR(CONTROL3);
285 SR(CONFIG3);
286 }
287
288 for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
289 SR(DEFAULT_COLOR(i));
290 SR(TRANS_COLOR(i));
291 SR(SIZE_MGR(i));
292 if (i == OMAP_DSS_CHANNEL_DIGIT)
293 continue;
294 SR(TIMING_H(i));
295 SR(TIMING_V(i));
296 SR(POL_FREQ(i));
297 SR(DIVISORo(i));
298
299 SR(DATA_CYCLE1(i));
300 SR(DATA_CYCLE2(i));
301 SR(DATA_CYCLE3(i));
302
303 if (dss_has_feature(FEAT_CPR)) {
304 SR(CPR_COEF_R(i));
305 SR(CPR_COEF_G(i));
306 SR(CPR_COEF_B(i));
307 }
308 }
309
310 for (i = 0; i < dss_feat_get_num_ovls(); i++) {
311 SR(OVL_BA0(i));
312 SR(OVL_BA1(i));
313 SR(OVL_POSITION(i));
314 SR(OVL_SIZE(i));
315 SR(OVL_ATTRIBUTES(i));
316 SR(OVL_FIFO_THRESHOLD(i));
317 SR(OVL_ROW_INC(i));
318 SR(OVL_PIXEL_INC(i));
319 if (dss_has_feature(FEAT_PRELOAD))
320 SR(OVL_PRELOAD(i));
321 if (i == OMAP_DSS_GFX) {
322 SR(OVL_WINDOW_SKIP(i));
323 SR(OVL_TABLE_BA(i));
324 continue;
325 }
326 SR(OVL_FIR(i));
327 SR(OVL_PICTURE_SIZE(i));
328 SR(OVL_ACCU0(i));
329 SR(OVL_ACCU1(i));
330
331 for (j = 0; j < 8; j++)
332 SR(OVL_FIR_COEF_H(i, j));
333
334 for (j = 0; j < 8; j++)
335 SR(OVL_FIR_COEF_HV(i, j));
336
337 for (j = 0; j < 5; j++)
338 SR(OVL_CONV_COEF(i, j));
339
340 if (dss_has_feature(FEAT_FIR_COEF_V)) {
341 for (j = 0; j < 8; j++)
342 SR(OVL_FIR_COEF_V(i, j));
343 }
344
345 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
346 SR(OVL_BA0_UV(i));
347 SR(OVL_BA1_UV(i));
348 SR(OVL_FIR2(i));
349 SR(OVL_ACCU2_0(i));
350 SR(OVL_ACCU2_1(i));
351
352 for (j = 0; j < 8; j++)
353 SR(OVL_FIR_COEF_H2(i, j));
354
355 for (j = 0; j < 8; j++)
356 SR(OVL_FIR_COEF_HV2(i, j));
357
358 for (j = 0; j < 8; j++)
359 SR(OVL_FIR_COEF_V2(i, j));
360 }
361 if (dss_has_feature(FEAT_ATTR2))
362 SR(OVL_ATTRIBUTES2(i));
363 }
364
365 if (dss_has_feature(FEAT_CORE_CLK_DIV))
366 SR(DIVISOR);
367
368 dispc.ctx_valid = true;
369
370 DSSDBG("context saved\n");
371}
372
373static void dispc_restore_context(void)
374{
375 int i, j;
376
377 DSSDBG("dispc_restore_context\n");
378
379 if (!dispc.ctx_valid)
380 return;
381
382 /*RR(IRQENABLE);*/
383 /*RR(CONTROL);*/
384 RR(CONFIG);
385 RR(LINE_NUMBER);
386 if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
387 dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
388 RR(GLOBAL_ALPHA);
389 if (dss_has_feature(FEAT_MGR_LCD2))
390 RR(CONFIG2);
391 if (dss_has_feature(FEAT_MGR_LCD3))
392 RR(CONFIG3);
393
394 for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
395 RR(DEFAULT_COLOR(i));
396 RR(TRANS_COLOR(i));
397 RR(SIZE_MGR(i));
398 if (i == OMAP_DSS_CHANNEL_DIGIT)
399 continue;
400 RR(TIMING_H(i));
401 RR(TIMING_V(i));
402 RR(POL_FREQ(i));
403 RR(DIVISORo(i));
404
405 RR(DATA_CYCLE1(i));
406 RR(DATA_CYCLE2(i));
407 RR(DATA_CYCLE3(i));
408
409 if (dss_has_feature(FEAT_CPR)) {
410 RR(CPR_COEF_R(i));
411 RR(CPR_COEF_G(i));
412 RR(CPR_COEF_B(i));
413 }
414 }
415
416 for (i = 0; i < dss_feat_get_num_ovls(); i++) {
417 RR(OVL_BA0(i));
418 RR(OVL_BA1(i));
419 RR(OVL_POSITION(i));
420 RR(OVL_SIZE(i));
421 RR(OVL_ATTRIBUTES(i));
422 RR(OVL_FIFO_THRESHOLD(i));
423 RR(OVL_ROW_INC(i));
424 RR(OVL_PIXEL_INC(i));
425 if (dss_has_feature(FEAT_PRELOAD))
426 RR(OVL_PRELOAD(i));
427 if (i == OMAP_DSS_GFX) {
428 RR(OVL_WINDOW_SKIP(i));
429 RR(OVL_TABLE_BA(i));
430 continue;
431 }
432 RR(OVL_FIR(i));
433 RR(OVL_PICTURE_SIZE(i));
434 RR(OVL_ACCU0(i));
435 RR(OVL_ACCU1(i));
436
437 for (j = 0; j < 8; j++)
438 RR(OVL_FIR_COEF_H(i, j));
439
440 for (j = 0; j < 8; j++)
441 RR(OVL_FIR_COEF_HV(i, j));
442
443 for (j = 0; j < 5; j++)
444 RR(OVL_CONV_COEF(i, j));
445
446 if (dss_has_feature(FEAT_FIR_COEF_V)) {
447 for (j = 0; j < 8; j++)
448 RR(OVL_FIR_COEF_V(i, j));
449 }
450
451 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
452 RR(OVL_BA0_UV(i));
453 RR(OVL_BA1_UV(i));
454 RR(OVL_FIR2(i));
455 RR(OVL_ACCU2_0(i));
456 RR(OVL_ACCU2_1(i));
457
458 for (j = 0; j < 8; j++)
459 RR(OVL_FIR_COEF_H2(i, j));
460
461 for (j = 0; j < 8; j++)
462 RR(OVL_FIR_COEF_HV2(i, j));
463
464 for (j = 0; j < 8; j++)
465 RR(OVL_FIR_COEF_V2(i, j));
466 }
467 if (dss_has_feature(FEAT_ATTR2))
468 RR(OVL_ATTRIBUTES2(i));
469 }
470
471 if (dss_has_feature(FEAT_CORE_CLK_DIV))
472 RR(DIVISOR);
473
474 /* enable last, because LCD & DIGIT enable are here */
475 RR(CONTROL);
476 if (dss_has_feature(FEAT_MGR_LCD2))
477 RR(CONTROL2);
478 if (dss_has_feature(FEAT_MGR_LCD3))
479 RR(CONTROL3);
480 /* clear spurious SYNC_LOST_DIGIT interrupts */
481 dispc_clear_irqstatus(DISPC_IRQ_SYNC_LOST_DIGIT);
482
483 /*
484 * enable last so IRQs won't trigger before
485 * the context is fully restored
486 */
487 RR(IRQENABLE);
488
489 DSSDBG("context restored\n");
490}
491
492#undef SR
493#undef RR
494
495int dispc_runtime_get(void)
496{
497 int r;
498
499 DSSDBG("dispc_runtime_get\n");
500
501 r = pm_runtime_get_sync(&dispc.pdev->dev);
502 WARN_ON(r < 0);
503 return r < 0 ? r : 0;
504}
505EXPORT_SYMBOL(dispc_runtime_get);
506
507void dispc_runtime_put(void)
508{
509 int r;
510
511 DSSDBG("dispc_runtime_put\n");
512
513 r = pm_runtime_put_sync(&dispc.pdev->dev);
514 WARN_ON(r < 0 && r != -ENOSYS);
515}
516EXPORT_SYMBOL(dispc_runtime_put);
517
518u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
519{
520 return mgr_desc[channel].vsync_irq;
521}
522EXPORT_SYMBOL(dispc_mgr_get_vsync_irq);
523
524u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
525{
526 if (channel == OMAP_DSS_CHANNEL_DIGIT && dispc.feat->no_framedone_tv)
527 return 0;
528
529 return mgr_desc[channel].framedone_irq;
530}
531EXPORT_SYMBOL(dispc_mgr_get_framedone_irq);
532
533u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel)
534{
535 return mgr_desc[channel].sync_lost_irq;
536}
537EXPORT_SYMBOL(dispc_mgr_get_sync_lost_irq);
538
539u32 dispc_wb_get_framedone_irq(void)
540{
541 return DISPC_IRQ_FRAMEDONEWB;
542}
543
544bool dispc_mgr_go_busy(enum omap_channel channel)
545{
546 return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
547}
548EXPORT_SYMBOL(dispc_mgr_go_busy);
549
550void dispc_mgr_go(enum omap_channel channel)
551{
552 WARN_ON(dispc_mgr_is_enabled(channel) == false);
553 WARN_ON(dispc_mgr_go_busy(channel));
554
555 DSSDBG("GO %s\n", mgr_desc[channel].name);
556
557 mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1);
558}
559EXPORT_SYMBOL(dispc_mgr_go);
560
561bool dispc_wb_go_busy(void)
562{
563 return REG_GET(DISPC_CONTROL2, 6, 6) == 1;
564}
565
566void dispc_wb_go(void)
567{
568 enum omap_plane plane = OMAP_DSS_WB;
569 bool enable, go;
570
571 enable = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0) == 1;
572
573 if (!enable)
574 return;
575
576 go = REG_GET(DISPC_CONTROL2, 6, 6) == 1;
577 if (go) {
578 DSSERR("GO bit not down for WB\n");
579 return;
580 }
581
582 REG_FLD_MOD(DISPC_CONTROL2, 1, 6, 6);
583}
584
585static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value)
586{
587 dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value);
588}
589
590static void dispc_ovl_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
591{
592 dispc_write_reg(DISPC_OVL_FIR_COEF_HV(plane, reg), value);
593}
594
595static void dispc_ovl_write_firv_reg(enum omap_plane plane, int reg, u32 value)
596{
597 dispc_write_reg(DISPC_OVL_FIR_COEF_V(plane, reg), value);
598}
599
600static void dispc_ovl_write_firh2_reg(enum omap_plane plane, int reg, u32 value)
601{
602 BUG_ON(plane == OMAP_DSS_GFX);
603
604 dispc_write_reg(DISPC_OVL_FIR_COEF_H2(plane, reg), value);
605}
606
607static void dispc_ovl_write_firhv2_reg(enum omap_plane plane, int reg,
608 u32 value)
609{
610 BUG_ON(plane == OMAP_DSS_GFX);
611
612 dispc_write_reg(DISPC_OVL_FIR_COEF_HV2(plane, reg), value);
613}
614
615static void dispc_ovl_write_firv2_reg(enum omap_plane plane, int reg, u32 value)
616{
617 BUG_ON(plane == OMAP_DSS_GFX);
618
619 dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value);
620}
621
622static void dispc_ovl_set_scale_coef(enum omap_plane plane, int fir_hinc,
623 int fir_vinc, int five_taps,
624 enum omap_color_component color_comp)
625{
626 const struct dispc_coef *h_coef, *v_coef;
627 int i;
628
629 h_coef = dispc_ovl_get_scale_coef(fir_hinc, true);
630 v_coef = dispc_ovl_get_scale_coef(fir_vinc, five_taps);
631
632 for (i = 0; i < 8; i++) {
633 u32 h, hv;
634
635 h = FLD_VAL(h_coef[i].hc0_vc00, 7, 0)
636 | FLD_VAL(h_coef[i].hc1_vc0, 15, 8)
637 | FLD_VAL(h_coef[i].hc2_vc1, 23, 16)
638 | FLD_VAL(h_coef[i].hc3_vc2, 31, 24);
639 hv = FLD_VAL(h_coef[i].hc4_vc22, 7, 0)
640 | FLD_VAL(v_coef[i].hc1_vc0, 15, 8)
641 | FLD_VAL(v_coef[i].hc2_vc1, 23, 16)
642 | FLD_VAL(v_coef[i].hc3_vc2, 31, 24);
643
644 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) {
645 dispc_ovl_write_firh_reg(plane, i, h);
646 dispc_ovl_write_firhv_reg(plane, i, hv);
647 } else {
648 dispc_ovl_write_firh2_reg(plane, i, h);
649 dispc_ovl_write_firhv2_reg(plane, i, hv);
650 }
651
652 }
653
654 if (five_taps) {
655 for (i = 0; i < 8; i++) {
656 u32 v;
657 v = FLD_VAL(v_coef[i].hc0_vc00, 7, 0)
658 | FLD_VAL(v_coef[i].hc4_vc22, 15, 8);
659 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y)
660 dispc_ovl_write_firv_reg(plane, i, v);
661 else
662 dispc_ovl_write_firv2_reg(plane, i, v);
663 }
664 }
665}
666
667
668static void dispc_ovl_write_color_conv_coef(enum omap_plane plane,
669 const struct color_conv_coef *ct)
670{
671#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
672
673 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 0), CVAL(ct->rcr, ct->ry));
674 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 1), CVAL(ct->gy, ct->rcb));
675 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 2), CVAL(ct->gcb, ct->gcr));
676 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 3), CVAL(ct->bcr, ct->by));
677 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 4), CVAL(0, ct->bcb));
678
679 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), ct->full_range, 11, 11);
680
681#undef CVAL
682}
683
684static void dispc_setup_color_conv_coef(void)
685{
686 int i;
687 int num_ovl = dss_feat_get_num_ovls();
688 int num_wb = dss_feat_get_num_wbs();
689 const struct color_conv_coef ctbl_bt601_5_ovl = {
690 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
691 };
692 const struct color_conv_coef ctbl_bt601_5_wb = {
693 66, 112, -38, 129, -94, -74, 25, -18, 112, 0,
694 };
695
696 for (i = 1; i < num_ovl; i++)
697 dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_ovl);
698
699 for (; i < num_wb; i++)
700 dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_wb);
701}
702
703static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr)
704{
705 dispc_write_reg(DISPC_OVL_BA0(plane), paddr);
706}
707
708static void dispc_ovl_set_ba1(enum omap_plane plane, u32 paddr)
709{
710 dispc_write_reg(DISPC_OVL_BA1(plane), paddr);
711}
712
713static void dispc_ovl_set_ba0_uv(enum omap_plane plane, u32 paddr)
714{
715 dispc_write_reg(DISPC_OVL_BA0_UV(plane), paddr);
716}
717
718static void dispc_ovl_set_ba1_uv(enum omap_plane plane, u32 paddr)
719{
720 dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr);
721}
722
723static void dispc_ovl_set_pos(enum omap_plane plane,
724 enum omap_overlay_caps caps, int x, int y)
725{
726 u32 val;
727
728 if ((caps & OMAP_DSS_OVL_CAP_POS) == 0)
729 return;
730
731 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
732
733 dispc_write_reg(DISPC_OVL_POSITION(plane), val);
734}
735
736static void dispc_ovl_set_input_size(enum omap_plane plane, int width,
737 int height)
738{
739 u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
740
741 if (plane == OMAP_DSS_GFX || plane == OMAP_DSS_WB)
742 dispc_write_reg(DISPC_OVL_SIZE(plane), val);
743 else
744 dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
745}
746
747static void dispc_ovl_set_output_size(enum omap_plane plane, int width,
748 int height)
749{
750 u32 val;
751
752 BUG_ON(plane == OMAP_DSS_GFX);
753
754 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
755
756 if (plane == OMAP_DSS_WB)
757 dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
758 else
759 dispc_write_reg(DISPC_OVL_SIZE(plane), val);
760}
761
762static void dispc_ovl_set_zorder(enum omap_plane plane,
763 enum omap_overlay_caps caps, u8 zorder)
764{
765 if ((caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
766 return;
767
768 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26);
769}
770
771static void dispc_ovl_enable_zorder_planes(void)
772{
773 int i;
774
775 if (!dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
776 return;
777
778 for (i = 0; i < dss_feat_get_num_ovls(); i++)
779 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25);
780}
781
782static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane,
783 enum omap_overlay_caps caps, bool enable)
784{
785 if ((caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
786 return;
787
788 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);
789}
790
791static void dispc_ovl_setup_global_alpha(enum omap_plane plane,
792 enum omap_overlay_caps caps, u8 global_alpha)
793{
794 static const unsigned shifts[] = { 0, 8, 16, 24, };
795 int shift;
796
797 if ((caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
798 return;
799
800 shift = shifts[plane];
801 REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, shift + 7, shift);
802}
803
804static void dispc_ovl_set_pix_inc(enum omap_plane plane, s32 inc)
805{
806 dispc_write_reg(DISPC_OVL_PIXEL_INC(plane), inc);
807}
808
809static void dispc_ovl_set_row_inc(enum omap_plane plane, s32 inc)
810{
811 dispc_write_reg(DISPC_OVL_ROW_INC(plane), inc);
812}
813
814static void dispc_ovl_set_color_mode(enum omap_plane plane,
815 enum omap_color_mode color_mode)
816{
817 u32 m = 0;
818 if (plane != OMAP_DSS_GFX) {
819 switch (color_mode) {
820 case OMAP_DSS_COLOR_NV12:
821 m = 0x0; break;
822 case OMAP_DSS_COLOR_RGBX16:
823 m = 0x1; break;
824 case OMAP_DSS_COLOR_RGBA16:
825 m = 0x2; break;
826 case OMAP_DSS_COLOR_RGB12U:
827 m = 0x4; break;
828 case OMAP_DSS_COLOR_ARGB16:
829 m = 0x5; break;
830 case OMAP_DSS_COLOR_RGB16:
831 m = 0x6; break;
832 case OMAP_DSS_COLOR_ARGB16_1555:
833 m = 0x7; break;
834 case OMAP_DSS_COLOR_RGB24U:
835 m = 0x8; break;
836 case OMAP_DSS_COLOR_RGB24P:
837 m = 0x9; break;
838 case OMAP_DSS_COLOR_YUV2:
839 m = 0xa; break;
840 case OMAP_DSS_COLOR_UYVY:
841 m = 0xb; break;
842 case OMAP_DSS_COLOR_ARGB32:
843 m = 0xc; break;
844 case OMAP_DSS_COLOR_RGBA32:
845 m = 0xd; break;
846 case OMAP_DSS_COLOR_RGBX32:
847 m = 0xe; break;
848 case OMAP_DSS_COLOR_XRGB16_1555:
849 m = 0xf; break;
850 default:
851 BUG(); return;
852 }
853 } else {
854 switch (color_mode) {
855 case OMAP_DSS_COLOR_CLUT1:
856 m = 0x0; break;
857 case OMAP_DSS_COLOR_CLUT2:
858 m = 0x1; break;
859 case OMAP_DSS_COLOR_CLUT4:
860 m = 0x2; break;
861 case OMAP_DSS_COLOR_CLUT8:
862 m = 0x3; break;
863 case OMAP_DSS_COLOR_RGB12U:
864 m = 0x4; break;
865 case OMAP_DSS_COLOR_ARGB16:
866 m = 0x5; break;
867 case OMAP_DSS_COLOR_RGB16:
868 m = 0x6; break;
869 case OMAP_DSS_COLOR_ARGB16_1555:
870 m = 0x7; break;
871 case OMAP_DSS_COLOR_RGB24U:
872 m = 0x8; break;
873 case OMAP_DSS_COLOR_RGB24P:
874 m = 0x9; break;
875 case OMAP_DSS_COLOR_RGBX16:
876 m = 0xa; break;
877 case OMAP_DSS_COLOR_RGBA16:
878 m = 0xb; break;
879 case OMAP_DSS_COLOR_ARGB32:
880 m = 0xc; break;
881 case OMAP_DSS_COLOR_RGBA32:
882 m = 0xd; break;
883 case OMAP_DSS_COLOR_RGBX32:
884 m = 0xe; break;
885 case OMAP_DSS_COLOR_XRGB16_1555:
886 m = 0xf; break;
887 default:
888 BUG(); return;
889 }
890 }
891
892 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
893}
894
895static void dispc_ovl_configure_burst_type(enum omap_plane plane,
896 enum omap_dss_rotation_type rotation_type)
897{
898 if (dss_has_feature(FEAT_BURST_2D) == 0)
899 return;
900
901 if (rotation_type == OMAP_DSS_ROT_TILER)
902 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), 1, 29, 29);
903 else
904 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), 0, 29, 29);
905}
906
907void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
908{
909 int shift;
910 u32 val;
911 int chan = 0, chan2 = 0;
912
913 switch (plane) {
914 case OMAP_DSS_GFX:
915 shift = 8;
916 break;
917 case OMAP_DSS_VIDEO1:
918 case OMAP_DSS_VIDEO2:
919 case OMAP_DSS_VIDEO3:
920 shift = 16;
921 break;
922 default:
923 BUG();
924 return;
925 }
926
927 val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
928 if (dss_has_feature(FEAT_MGR_LCD2)) {
929 switch (channel) {
930 case OMAP_DSS_CHANNEL_LCD:
931 chan = 0;
932 chan2 = 0;
933 break;
934 case OMAP_DSS_CHANNEL_DIGIT:
935 chan = 1;
936 chan2 = 0;
937 break;
938 case OMAP_DSS_CHANNEL_LCD2:
939 chan = 0;
940 chan2 = 1;
941 break;
942 case OMAP_DSS_CHANNEL_LCD3:
943 if (dss_has_feature(FEAT_MGR_LCD3)) {
944 chan = 0;
945 chan2 = 2;
946 } else {
947 BUG();
948 return;
949 }
950 break;
951 default:
952 BUG();
953 return;
954 }
955
956 val = FLD_MOD(val, chan, shift, shift);
957 val = FLD_MOD(val, chan2, 31, 30);
958 } else {
959 val = FLD_MOD(val, channel, shift, shift);
960 }
961 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
962}
963EXPORT_SYMBOL(dispc_ovl_set_channel_out);
964
965static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
966{
967 int shift;
968 u32 val;
969 enum omap_channel channel;
970
971 switch (plane) {
972 case OMAP_DSS_GFX:
973 shift = 8;
974 break;
975 case OMAP_DSS_VIDEO1:
976 case OMAP_DSS_VIDEO2:
977 case OMAP_DSS_VIDEO3:
978 shift = 16;
979 break;
980 default:
981 BUG();
982 return 0;
983 }
984
985 val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
986
987 if (dss_has_feature(FEAT_MGR_LCD3)) {
988 if (FLD_GET(val, 31, 30) == 0)
989 channel = FLD_GET(val, shift, shift);
990 else if (FLD_GET(val, 31, 30) == 1)
991 channel = OMAP_DSS_CHANNEL_LCD2;
992 else
993 channel = OMAP_DSS_CHANNEL_LCD3;
994 } else if (dss_has_feature(FEAT_MGR_LCD2)) {
995 if (FLD_GET(val, 31, 30) == 0)
996 channel = FLD_GET(val, shift, shift);
997 else
998 channel = OMAP_DSS_CHANNEL_LCD2;
999 } else {
1000 channel = FLD_GET(val, shift, shift);
1001 }
1002
1003 return channel;
1004}
1005
1006void dispc_wb_set_channel_in(enum dss_writeback_channel channel)
1007{
1008 enum omap_plane plane = OMAP_DSS_WB;
1009
1010 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), channel, 18, 16);
1011}
1012
1013static void dispc_ovl_set_burst_size(enum omap_plane plane,
1014 enum omap_burst_size burst_size)
1015{
1016 static const unsigned shifts[] = { 6, 14, 14, 14, 14, };
1017 int shift;
1018
1019 shift = shifts[plane];
1020 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), burst_size, shift + 1, shift);
1021}
1022
1023static void dispc_configure_burst_sizes(void)
1024{
1025 int i;
1026 const int burst_size = BURST_SIZE_X8;
1027
1028 /* Configure burst size always to maximum size */
1029 for (i = 0; i < dss_feat_get_num_ovls(); ++i)
1030 dispc_ovl_set_burst_size(i, burst_size);
1031}
1032
1033static u32 dispc_ovl_get_burst_size(enum omap_plane plane)
1034{
1035 unsigned unit = dss_feat_get_burst_size_unit();
1036 /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */
1037 return unit * 8;
1038}
1039
1040void dispc_enable_gamma_table(bool enable)
1041{
1042 /*
1043 * This is partially implemented to support only disabling of
1044 * the gamma table.
1045 */
1046 if (enable) {
1047 DSSWARN("Gamma table enabling for TV not yet supported");
1048 return;
1049 }
1050
1051 REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);
1052}
1053
1054static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
1055{
1056 if (channel == OMAP_DSS_CHANNEL_DIGIT)
1057 return;
1058
1059 mgr_fld_write(channel, DISPC_MGR_FLD_CPR, enable);
1060}
1061
1062static void dispc_mgr_set_cpr_coef(enum omap_channel channel,
1063 const struct omap_dss_cpr_coefs *coefs)
1064{
1065 u32 coef_r, coef_g, coef_b;
1066
1067 if (!dss_mgr_is_lcd(channel))
1068 return;
1069
1070 coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) |
1071 FLD_VAL(coefs->rb, 9, 0);
1072 coef_g = FLD_VAL(coefs->gr, 31, 22) | FLD_VAL(coefs->gg, 20, 11) |
1073 FLD_VAL(coefs->gb, 9, 0);
1074 coef_b = FLD_VAL(coefs->br, 31, 22) | FLD_VAL(coefs->bg, 20, 11) |
1075 FLD_VAL(coefs->bb, 9, 0);
1076
1077 dispc_write_reg(DISPC_CPR_COEF_R(channel), coef_r);
1078 dispc_write_reg(DISPC_CPR_COEF_G(channel), coef_g);
1079 dispc_write_reg(DISPC_CPR_COEF_B(channel), coef_b);
1080}
1081
1082static void dispc_ovl_set_vid_color_conv(enum omap_plane plane, bool enable)
1083{
1084 u32 val;
1085
1086 BUG_ON(plane == OMAP_DSS_GFX);
1087
1088 val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
1089 val = FLD_MOD(val, enable, 9, 9);
1090 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
1091}
1092
1093static void dispc_ovl_enable_replication(enum omap_plane plane,
1094 enum omap_overlay_caps caps, bool enable)
1095{
1096 static const unsigned shifts[] = { 5, 10, 10, 10 };
1097 int shift;
1098
1099 if ((caps & OMAP_DSS_OVL_CAP_REPLICATION) == 0)
1100 return;
1101
1102 shift = shifts[plane];
1103 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift);
1104}
1105
1106static void dispc_mgr_set_size(enum omap_channel channel, u16 width,
1107 u16 height)
1108{
1109 u32 val;
1110
1111 val = FLD_VAL(height - 1, dispc.feat->mgr_height_start, 16) |
1112 FLD_VAL(width - 1, dispc.feat->mgr_width_start, 0);
1113
1114 dispc_write_reg(DISPC_SIZE_MGR(channel), val);
1115}
1116
1117static void dispc_init_fifos(void)
1118{
1119 u32 size;
1120 int fifo;
1121 u8 start, end;
1122 u32 unit;
1123
1124 unit = dss_feat_get_buffer_size_unit();
1125
1126 dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
1127
1128 for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) {
1129 size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(fifo), start, end);
1130 size *= unit;
1131 dispc.fifo_size[fifo] = size;
1132
1133 /*
1134 * By default fifos are mapped directly to overlays, fifo 0 to
1135 * ovl 0, fifo 1 to ovl 1, etc.
1136 */
1137 dispc.fifo_assignment[fifo] = fifo;
1138 }
1139
1140 /*
1141 * The GFX fifo on OMAP4 is smaller than the other fifos. The small fifo
1142 * causes problems with certain use cases, like using the tiler in 2D
1143 * mode. The below hack swaps the fifos of GFX and WB planes, thus
1144 * giving GFX plane a larger fifo. WB but should work fine with a
1145 * smaller fifo.
1146 */
1147 if (dispc.feat->gfx_fifo_workaround) {
1148 u32 v;
1149
1150 v = dispc_read_reg(DISPC_GLOBAL_BUFFER);
1151
1152 v = FLD_MOD(v, 4, 2, 0); /* GFX BUF top to WB */
1153 v = FLD_MOD(v, 4, 5, 3); /* GFX BUF bottom to WB */
1154 v = FLD_MOD(v, 0, 26, 24); /* WB BUF top to GFX */
1155 v = FLD_MOD(v, 0, 29, 27); /* WB BUF bottom to GFX */
1156
1157 dispc_write_reg(DISPC_GLOBAL_BUFFER, v);
1158
1159 dispc.fifo_assignment[OMAP_DSS_GFX] = OMAP_DSS_WB;
1160 dispc.fifo_assignment[OMAP_DSS_WB] = OMAP_DSS_GFX;
1161 }
1162}
1163
1164static u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
1165{
1166 int fifo;
1167 u32 size = 0;
1168
1169 for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) {
1170 if (dispc.fifo_assignment[fifo] == plane)
1171 size += dispc.fifo_size[fifo];
1172 }
1173
1174 return size;
1175}
1176
1177void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
1178{
1179 u8 hi_start, hi_end, lo_start, lo_end;
1180 u32 unit;
1181
1182 unit = dss_feat_get_buffer_size_unit();
1183
1184 WARN_ON(low % unit != 0);
1185 WARN_ON(high % unit != 0);
1186
1187 low /= unit;
1188 high /= unit;
1189
1190 dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
1191 dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
1192
1193 DSSDBG("fifo(%d) threshold (bytes), old %u/%u, new %u/%u\n",
1194 plane,
1195 REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
1196 lo_start, lo_end) * unit,
1197 REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
1198 hi_start, hi_end) * unit,
1199 low * unit, high * unit);
1200
1201 dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane),
1202 FLD_VAL(high, hi_start, hi_end) |
1203 FLD_VAL(low, lo_start, lo_end));
1204
1205 /*
1206 * configure the preload to the pipeline's high threhold, if HT it's too
1207 * large for the preload field, set the threshold to the maximum value
1208 * that can be held by the preload register
1209 */
1210 if (dss_has_feature(FEAT_PRELOAD) && dispc.feat->set_max_preload &&
1211 plane != OMAP_DSS_WB)
1212 dispc_write_reg(DISPC_OVL_PRELOAD(plane), min(high, 0xfffu));
1213}
1214EXPORT_SYMBOL(dispc_ovl_set_fifo_threshold);
1215
1216void dispc_enable_fifomerge(bool enable)
1217{
1218 if (!dss_has_feature(FEAT_FIFO_MERGE)) {
1219 WARN_ON(enable);
1220 return;
1221 }
1222
1223 DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
1224 REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
1225}
1226
1227void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
1228 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
1229 bool manual_update)
1230{
1231 /*
1232 * All sizes are in bytes. Both the buffer and burst are made of
1233 * buffer_units, and the fifo thresholds must be buffer_unit aligned.
1234 */
1235
1236 unsigned buf_unit = dss_feat_get_buffer_size_unit();
1237 unsigned ovl_fifo_size, total_fifo_size, burst_size;
1238 int i;
1239
1240 burst_size = dispc_ovl_get_burst_size(plane);
1241 ovl_fifo_size = dispc_ovl_get_fifo_size(plane);
1242
1243 if (use_fifomerge) {
1244 total_fifo_size = 0;
1245 for (i = 0; i < dss_feat_get_num_ovls(); ++i)
1246 total_fifo_size += dispc_ovl_get_fifo_size(i);
1247 } else {
1248 total_fifo_size = ovl_fifo_size;
1249 }
1250
1251 /*
1252 * We use the same low threshold for both fifomerge and non-fifomerge
1253 * cases, but for fifomerge we calculate the high threshold using the
1254 * combined fifo size
1255 */
1256
1257 if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) {
1258 *fifo_low = ovl_fifo_size - burst_size * 2;
1259 *fifo_high = total_fifo_size - burst_size;
1260 } else if (plane == OMAP_DSS_WB) {
1261 /*
1262 * Most optimal configuration for writeback is to push out data
1263 * to the interconnect the moment writeback pushes enough pixels
1264 * in the FIFO to form a burst
1265 */
1266 *fifo_low = 0;
1267 *fifo_high = burst_size;
1268 } else {
1269 *fifo_low = ovl_fifo_size - burst_size;
1270 *fifo_high = total_fifo_size - buf_unit;
1271 }
1272}
1273EXPORT_SYMBOL(dispc_ovl_compute_fifo_thresholds);
1274
1275static void dispc_ovl_set_fir(enum omap_plane plane,
1276 int hinc, int vinc,
1277 enum omap_color_component color_comp)
1278{
1279 u32 val;
1280
1281 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) {
1282 u8 hinc_start, hinc_end, vinc_start, vinc_end;
1283
1284 dss_feat_get_reg_field(FEAT_REG_FIRHINC,
1285 &hinc_start, &hinc_end);
1286 dss_feat_get_reg_field(FEAT_REG_FIRVINC,
1287 &vinc_start, &vinc_end);
1288 val = FLD_VAL(vinc, vinc_start, vinc_end) |
1289 FLD_VAL(hinc, hinc_start, hinc_end);
1290
1291 dispc_write_reg(DISPC_OVL_FIR(plane), val);
1292 } else {
1293 val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0);
1294 dispc_write_reg(DISPC_OVL_FIR2(plane), val);
1295 }
1296}
1297
1298static void dispc_ovl_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
1299{
1300 u32 val;
1301 u8 hor_start, hor_end, vert_start, vert_end;
1302
1303 dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end);
1304 dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end);
1305
1306 val = FLD_VAL(vaccu, vert_start, vert_end) |
1307 FLD_VAL(haccu, hor_start, hor_end);
1308
1309 dispc_write_reg(DISPC_OVL_ACCU0(plane), val);
1310}
1311
1312static void dispc_ovl_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
1313{
1314 u32 val;
1315 u8 hor_start, hor_end, vert_start, vert_end;
1316
1317 dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end);
1318 dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end);
1319
1320 val = FLD_VAL(vaccu, vert_start, vert_end) |
1321 FLD_VAL(haccu, hor_start, hor_end);
1322
1323 dispc_write_reg(DISPC_OVL_ACCU1(plane), val);
1324}
1325
1326static void dispc_ovl_set_vid_accu2_0(enum omap_plane plane, int haccu,
1327 int vaccu)
1328{
1329 u32 val;
1330
1331 val = FLD_VAL(vaccu, 26, 16) | FLD_VAL(haccu, 10, 0);
1332 dispc_write_reg(DISPC_OVL_ACCU2_0(plane), val);
1333}
1334
1335static void dispc_ovl_set_vid_accu2_1(enum omap_plane plane, int haccu,
1336 int vaccu)
1337{
1338 u32 val;
1339
1340 val = FLD_VAL(vaccu, 26, 16) | FLD_VAL(haccu, 10, 0);
1341 dispc_write_reg(DISPC_OVL_ACCU2_1(plane), val);
1342}
1343
1344static void dispc_ovl_set_scale_param(enum omap_plane plane,
1345 u16 orig_width, u16 orig_height,
1346 u16 out_width, u16 out_height,
1347 bool five_taps, u8 rotation,
1348 enum omap_color_component color_comp)
1349{
1350 int fir_hinc, fir_vinc;
1351
1352 fir_hinc = 1024 * orig_width / out_width;
1353 fir_vinc = 1024 * orig_height / out_height;
1354
1355 dispc_ovl_set_scale_coef(plane, fir_hinc, fir_vinc, five_taps,
1356 color_comp);
1357 dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp);
1358}
1359
1360static void dispc_ovl_set_accu_uv(enum omap_plane plane,
1361 u16 orig_width, u16 orig_height, u16 out_width, u16 out_height,
1362 bool ilace, enum omap_color_mode color_mode, u8 rotation)
1363{
1364 int h_accu2_0, h_accu2_1;
1365 int v_accu2_0, v_accu2_1;
1366 int chroma_hinc, chroma_vinc;
1367 int idx;
1368
1369 struct accu {
1370 s8 h0_m, h0_n;
1371 s8 h1_m, h1_n;
1372 s8 v0_m, v0_n;
1373 s8 v1_m, v1_n;
1374 };
1375
1376 const struct accu *accu_table;
1377 const struct accu *accu_val;
1378
1379 static const struct accu accu_nv12[4] = {
1380 { 0, 1, 0, 1 , -1, 2, 0, 1 },
1381 { 1, 2, -3, 4 , 0, 1, 0, 1 },
1382 { -1, 1, 0, 1 , -1, 2, 0, 1 },
1383 { -1, 2, -1, 2 , -1, 1, 0, 1 },
1384 };
1385
1386 static const struct accu accu_nv12_ilace[4] = {
1387 { 0, 1, 0, 1 , -3, 4, -1, 4 },
1388 { -1, 4, -3, 4 , 0, 1, 0, 1 },
1389 { -1, 1, 0, 1 , -1, 4, -3, 4 },
1390 { -3, 4, -3, 4 , -1, 1, 0, 1 },
1391 };
1392
1393 static const struct accu accu_yuv[4] = {
1394 { 0, 1, 0, 1, 0, 1, 0, 1 },
1395 { 0, 1, 0, 1, 0, 1, 0, 1 },
1396 { -1, 1, 0, 1, 0, 1, 0, 1 },
1397 { 0, 1, 0, 1, -1, 1, 0, 1 },
1398 };
1399
1400 switch (rotation) {
1401 case OMAP_DSS_ROT_0:
1402 idx = 0;
1403 break;
1404 case OMAP_DSS_ROT_90:
1405 idx = 1;
1406 break;
1407 case OMAP_DSS_ROT_180:
1408 idx = 2;
1409 break;
1410 case OMAP_DSS_ROT_270:
1411 idx = 3;
1412 break;
1413 default:
1414 BUG();
1415 return;
1416 }
1417
1418 switch (color_mode) {
1419 case OMAP_DSS_COLOR_NV12:
1420 if (ilace)
1421 accu_table = accu_nv12_ilace;
1422 else
1423 accu_table = accu_nv12;
1424 break;
1425 case OMAP_DSS_COLOR_YUV2:
1426 case OMAP_DSS_COLOR_UYVY:
1427 accu_table = accu_yuv;
1428 break;
1429 default:
1430 BUG();
1431 return;
1432 }
1433
1434 accu_val = &accu_table[idx];
1435
1436 chroma_hinc = 1024 * orig_width / out_width;
1437 chroma_vinc = 1024 * orig_height / out_height;
1438
1439 h_accu2_0 = (accu_val->h0_m * chroma_hinc / accu_val->h0_n) % 1024;
1440 h_accu2_1 = (accu_val->h1_m * chroma_hinc / accu_val->h1_n) % 1024;
1441 v_accu2_0 = (accu_val->v0_m * chroma_vinc / accu_val->v0_n) % 1024;
1442 v_accu2_1 = (accu_val->v1_m * chroma_vinc / accu_val->v1_n) % 1024;
1443
1444 dispc_ovl_set_vid_accu2_0(plane, h_accu2_0, v_accu2_0);
1445 dispc_ovl_set_vid_accu2_1(plane, h_accu2_1, v_accu2_1);
1446}
1447
1448static void dispc_ovl_set_scaling_common(enum omap_plane plane,
1449 u16 orig_width, u16 orig_height,
1450 u16 out_width, u16 out_height,
1451 bool ilace, bool five_taps,
1452 bool fieldmode, enum omap_color_mode color_mode,
1453 u8 rotation)
1454{
1455 int accu0 = 0;
1456 int accu1 = 0;
1457 u32 l;
1458
1459 dispc_ovl_set_scale_param(plane, orig_width, orig_height,
1460 out_width, out_height, five_taps,
1461 rotation, DISPC_COLOR_COMPONENT_RGB_Y);
1462 l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
1463
1464 /* RESIZEENABLE and VERTICALTAPS */
1465 l &= ~((0x3 << 5) | (0x1 << 21));
1466 l |= (orig_width != out_width) ? (1 << 5) : 0;
1467 l |= (orig_height != out_height) ? (1 << 6) : 0;
1468 l |= five_taps ? (1 << 21) : 0;
1469
1470 /* VRESIZECONF and HRESIZECONF */
1471 if (dss_has_feature(FEAT_RESIZECONF)) {
1472 l &= ~(0x3 << 7);
1473 l |= (orig_width <= out_width) ? 0 : (1 << 7);
1474 l |= (orig_height <= out_height) ? 0 : (1 << 8);
1475 }
1476
1477 /* LINEBUFFERSPLIT */
1478 if (dss_has_feature(FEAT_LINEBUFFERSPLIT)) {
1479 l &= ~(0x1 << 22);
1480 l |= five_taps ? (1 << 22) : 0;
1481 }
1482
1483 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), l);
1484
1485 /*
1486 * field 0 = even field = bottom field
1487 * field 1 = odd field = top field
1488 */
1489 if (ilace && !fieldmode) {
1490 accu1 = 0;
1491 accu0 = ((1024 * orig_height / out_height) / 2) & 0x3ff;
1492 if (accu0 >= 1024/2) {
1493 accu1 = 1024/2;
1494 accu0 -= accu1;
1495 }
1496 }
1497
1498 dispc_ovl_set_vid_accu0(plane, 0, accu0);
1499 dispc_ovl_set_vid_accu1(plane, 0, accu1);
1500}
1501
1502static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1503 u16 orig_width, u16 orig_height,
1504 u16 out_width, u16 out_height,
1505 bool ilace, bool five_taps,
1506 bool fieldmode, enum omap_color_mode color_mode,
1507 u8 rotation)
1508{
1509 int scale_x = out_width != orig_width;
1510 int scale_y = out_height != orig_height;
1511 bool chroma_upscale = plane != OMAP_DSS_WB ? true : false;
1512
1513 if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE))
1514 return;
1515 if ((color_mode != OMAP_DSS_COLOR_YUV2 &&
1516 color_mode != OMAP_DSS_COLOR_UYVY &&
1517 color_mode != OMAP_DSS_COLOR_NV12)) {
1518 /* reset chroma resampling for RGB formats */
1519 if (plane != OMAP_DSS_WB)
1520 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8);
1521 return;
1522 }
1523
1524 dispc_ovl_set_accu_uv(plane, orig_width, orig_height, out_width,
1525 out_height, ilace, color_mode, rotation);
1526
1527 switch (color_mode) {
1528 case OMAP_DSS_COLOR_NV12:
1529 if (chroma_upscale) {
1530 /* UV is subsampled by 2 horizontally and vertically */
1531 orig_height >>= 1;
1532 orig_width >>= 1;
1533 } else {
1534 /* UV is downsampled by 2 horizontally and vertically */
1535 orig_height <<= 1;
1536 orig_width <<= 1;
1537 }
1538
1539 break;
1540 case OMAP_DSS_COLOR_YUV2:
1541 case OMAP_DSS_COLOR_UYVY:
1542 /* For YUV422 with 90/270 rotation, we don't upsample chroma */
1543 if (rotation == OMAP_DSS_ROT_0 ||
1544 rotation == OMAP_DSS_ROT_180) {
1545 if (chroma_upscale)
1546 /* UV is subsampled by 2 horizontally */
1547 orig_width >>= 1;
1548 else
1549 /* UV is downsampled by 2 horizontally */
1550 orig_width <<= 1;
1551 }
1552
1553 /* must use FIR for YUV422 if rotated */
1554 if (rotation != OMAP_DSS_ROT_0)
1555 scale_x = scale_y = true;
1556
1557 break;
1558 default:
1559 BUG();
1560 return;
1561 }
1562
1563 if (out_width != orig_width)
1564 scale_x = true;
1565 if (out_height != orig_height)
1566 scale_y = true;
1567
1568 dispc_ovl_set_scale_param(plane, orig_width, orig_height,
1569 out_width, out_height, five_taps,
1570 rotation, DISPC_COLOR_COMPONENT_UV);
1571
1572 if (plane != OMAP_DSS_WB)
1573 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane),
1574 (scale_x || scale_y) ? 1 : 0, 8, 8);
1575
1576 /* set H scaling */
1577 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5);
1578 /* set V scaling */
1579 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6);
1580}
1581
1582static void dispc_ovl_set_scaling(enum omap_plane plane,
1583 u16 orig_width, u16 orig_height,
1584 u16 out_width, u16 out_height,
1585 bool ilace, bool five_taps,
1586 bool fieldmode, enum omap_color_mode color_mode,
1587 u8 rotation)
1588{
1589 BUG_ON(plane == OMAP_DSS_GFX);
1590
1591 dispc_ovl_set_scaling_common(plane,
1592 orig_width, orig_height,
1593 out_width, out_height,
1594 ilace, five_taps,
1595 fieldmode, color_mode,
1596 rotation);
1597
1598 dispc_ovl_set_scaling_uv(plane,
1599 orig_width, orig_height,
1600 out_width, out_height,
1601 ilace, five_taps,
1602 fieldmode, color_mode,
1603 rotation);
1604}
1605
1606static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation,
1607 enum omap_dss_rotation_type rotation_type,
1608 bool mirroring, enum omap_color_mode color_mode)
1609{
1610 bool row_repeat = false;
1611 int vidrot = 0;
1612
1613 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1614 color_mode == OMAP_DSS_COLOR_UYVY) {
1615
1616 if (mirroring) {
1617 switch (rotation) {
1618 case OMAP_DSS_ROT_0:
1619 vidrot = 2;
1620 break;
1621 case OMAP_DSS_ROT_90:
1622 vidrot = 1;
1623 break;
1624 case OMAP_DSS_ROT_180:
1625 vidrot = 0;
1626 break;
1627 case OMAP_DSS_ROT_270:
1628 vidrot = 3;
1629 break;
1630 }
1631 } else {
1632 switch (rotation) {
1633 case OMAP_DSS_ROT_0:
1634 vidrot = 0;
1635 break;
1636 case OMAP_DSS_ROT_90:
1637 vidrot = 1;
1638 break;
1639 case OMAP_DSS_ROT_180:
1640 vidrot = 2;
1641 break;
1642 case OMAP_DSS_ROT_270:
1643 vidrot = 3;
1644 break;
1645 }
1646 }
1647
1648 if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270)
1649 row_repeat = true;
1650 else
1651 row_repeat = false;
1652 }
1653
1654 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12);
1655 if (dss_has_feature(FEAT_ROWREPEATENABLE))
1656 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane),
1657 row_repeat ? 1 : 0, 18, 18);
1658
1659 if (color_mode == OMAP_DSS_COLOR_NV12) {
1660 bool doublestride = (rotation_type == OMAP_DSS_ROT_TILER) &&
1661 (rotation == OMAP_DSS_ROT_0 ||
1662 rotation == OMAP_DSS_ROT_180);
1663 /* DOUBLESTRIDE */
1664 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), doublestride, 22, 22);
1665 }
1666
1667}
1668
1669static int color_mode_to_bpp(enum omap_color_mode color_mode)
1670{
1671 switch (color_mode) {
1672 case OMAP_DSS_COLOR_CLUT1:
1673 return 1;
1674 case OMAP_DSS_COLOR_CLUT2:
1675 return 2;
1676 case OMAP_DSS_COLOR_CLUT4:
1677 return 4;
1678 case OMAP_DSS_COLOR_CLUT8:
1679 case OMAP_DSS_COLOR_NV12:
1680 return 8;
1681 case OMAP_DSS_COLOR_RGB12U:
1682 case OMAP_DSS_COLOR_RGB16:
1683 case OMAP_DSS_COLOR_ARGB16:
1684 case OMAP_DSS_COLOR_YUV2:
1685 case OMAP_DSS_COLOR_UYVY:
1686 case OMAP_DSS_COLOR_RGBA16:
1687 case OMAP_DSS_COLOR_RGBX16:
1688 case OMAP_DSS_COLOR_ARGB16_1555:
1689 case OMAP_DSS_COLOR_XRGB16_1555:
1690 return 16;
1691 case OMAP_DSS_COLOR_RGB24P:
1692 return 24;
1693 case OMAP_DSS_COLOR_RGB24U:
1694 case OMAP_DSS_COLOR_ARGB32:
1695 case OMAP_DSS_COLOR_RGBA32:
1696 case OMAP_DSS_COLOR_RGBX32:
1697 return 32;
1698 default:
1699 BUG();
1700 return 0;
1701 }
1702}
1703
1704static s32 pixinc(int pixels, u8 ps)
1705{
1706 if (pixels == 1)
1707 return 1;
1708 else if (pixels > 1)
1709 return 1 + (pixels - 1) * ps;
1710 else if (pixels < 0)
1711 return 1 - (-pixels + 1) * ps;
1712 else
1713 BUG();
1714 return 0;
1715}
1716
1717static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
1718 u16 screen_width,
1719 u16 width, u16 height,
1720 enum omap_color_mode color_mode, bool fieldmode,
1721 unsigned int field_offset,
1722 unsigned *offset0, unsigned *offset1,
1723 s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim)
1724{
1725 u8 ps;
1726
1727 /* FIXME CLUT formats */
1728 switch (color_mode) {
1729 case OMAP_DSS_COLOR_CLUT1:
1730 case OMAP_DSS_COLOR_CLUT2:
1731 case OMAP_DSS_COLOR_CLUT4:
1732 case OMAP_DSS_COLOR_CLUT8:
1733 BUG();
1734 return;
1735 case OMAP_DSS_COLOR_YUV2:
1736 case OMAP_DSS_COLOR_UYVY:
1737 ps = 4;
1738 break;
1739 default:
1740 ps = color_mode_to_bpp(color_mode) / 8;
1741 break;
1742 }
1743
1744 DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
1745 width, height);
1746
1747 /*
1748 * field 0 = even field = bottom field
1749 * field 1 = odd field = top field
1750 */
1751 switch (rotation + mirror * 4) {
1752 case OMAP_DSS_ROT_0:
1753 case OMAP_DSS_ROT_180:
1754 /*
1755 * If the pixel format is YUV or UYVY divide the width
1756 * of the image by 2 for 0 and 180 degree rotation.
1757 */
1758 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1759 color_mode == OMAP_DSS_COLOR_UYVY)
1760 width = width >> 1;
1761 case OMAP_DSS_ROT_90:
1762 case OMAP_DSS_ROT_270:
1763 *offset1 = 0;
1764 if (field_offset)
1765 *offset0 = field_offset * screen_width * ps;
1766 else
1767 *offset0 = 0;
1768
1769 *row_inc = pixinc(1 +
1770 (y_predecim * screen_width - x_predecim * width) +
1771 (fieldmode ? screen_width : 0), ps);
1772 *pix_inc = pixinc(x_predecim, ps);
1773 break;
1774
1775 case OMAP_DSS_ROT_0 + 4:
1776 case OMAP_DSS_ROT_180 + 4:
1777 /* If the pixel format is YUV or UYVY divide the width
1778 * of the image by 2 for 0 degree and 180 degree
1779 */
1780 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1781 color_mode == OMAP_DSS_COLOR_UYVY)
1782 width = width >> 1;
1783 case OMAP_DSS_ROT_90 + 4:
1784 case OMAP_DSS_ROT_270 + 4:
1785 *offset1 = 0;
1786 if (field_offset)
1787 *offset0 = field_offset * screen_width * ps;
1788 else
1789 *offset0 = 0;
1790 *row_inc = pixinc(1 -
1791 (y_predecim * screen_width + x_predecim * width) -
1792 (fieldmode ? screen_width : 0), ps);
1793 *pix_inc = pixinc(x_predecim, ps);
1794 break;
1795
1796 default:
1797 BUG();
1798 return;
1799 }
1800}
1801
1802static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1803 u16 screen_width,
1804 u16 width, u16 height,
1805 enum omap_color_mode color_mode, bool fieldmode,
1806 unsigned int field_offset,
1807 unsigned *offset0, unsigned *offset1,
1808 s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim)
1809{
1810 u8 ps;
1811 u16 fbw, fbh;
1812
1813 /* FIXME CLUT formats */
1814 switch (color_mode) {
1815 case OMAP_DSS_COLOR_CLUT1:
1816 case OMAP_DSS_COLOR_CLUT2:
1817 case OMAP_DSS_COLOR_CLUT4:
1818 case OMAP_DSS_COLOR_CLUT8:
1819 BUG();
1820 return;
1821 default:
1822 ps = color_mode_to_bpp(color_mode) / 8;
1823 break;
1824 }
1825
1826 DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
1827 width, height);
1828
1829 /* width & height are overlay sizes, convert to fb sizes */
1830
1831 if (rotation == OMAP_DSS_ROT_0 || rotation == OMAP_DSS_ROT_180) {
1832 fbw = width;
1833 fbh = height;
1834 } else {
1835 fbw = height;
1836 fbh = width;
1837 }
1838
1839 /*
1840 * field 0 = even field = bottom field
1841 * field 1 = odd field = top field
1842 */
1843 switch (rotation + mirror * 4) {
1844 case OMAP_DSS_ROT_0:
1845 *offset1 = 0;
1846 if (field_offset)
1847 *offset0 = *offset1 + field_offset * screen_width * ps;
1848 else
1849 *offset0 = *offset1;
1850 *row_inc = pixinc(1 +
1851 (y_predecim * screen_width - fbw * x_predecim) +
1852 (fieldmode ? screen_width : 0), ps);
1853 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1854 color_mode == OMAP_DSS_COLOR_UYVY)
1855 *pix_inc = pixinc(x_predecim, 2 * ps);
1856 else
1857 *pix_inc = pixinc(x_predecim, ps);
1858 break;
1859 case OMAP_DSS_ROT_90:
1860 *offset1 = screen_width * (fbh - 1) * ps;
1861 if (field_offset)
1862 *offset0 = *offset1 + field_offset * ps;
1863 else
1864 *offset0 = *offset1;
1865 *row_inc = pixinc(screen_width * (fbh * x_predecim - 1) +
1866 y_predecim + (fieldmode ? 1 : 0), ps);
1867 *pix_inc = pixinc(-x_predecim * screen_width, ps);
1868 break;
1869 case OMAP_DSS_ROT_180:
1870 *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
1871 if (field_offset)
1872 *offset0 = *offset1 - field_offset * screen_width * ps;
1873 else
1874 *offset0 = *offset1;
1875 *row_inc = pixinc(-1 -
1876 (y_predecim * screen_width - fbw * x_predecim) -
1877 (fieldmode ? screen_width : 0), ps);
1878 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1879 color_mode == OMAP_DSS_COLOR_UYVY)
1880 *pix_inc = pixinc(-x_predecim, 2 * ps);
1881 else
1882 *pix_inc = pixinc(-x_predecim, ps);
1883 break;
1884 case OMAP_DSS_ROT_270:
1885 *offset1 = (fbw - 1) * ps;
1886 if (field_offset)
1887 *offset0 = *offset1 - field_offset * ps;
1888 else
1889 *offset0 = *offset1;
1890 *row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) -
1891 y_predecim - (fieldmode ? 1 : 0), ps);
1892 *pix_inc = pixinc(x_predecim * screen_width, ps);
1893 break;
1894
1895 /* mirroring */
1896 case OMAP_DSS_ROT_0 + 4:
1897 *offset1 = (fbw - 1) * ps;
1898 if (field_offset)
1899 *offset0 = *offset1 + field_offset * screen_width * ps;
1900 else
1901 *offset0 = *offset1;
1902 *row_inc = pixinc(y_predecim * screen_width * 2 - 1 +
1903 (fieldmode ? screen_width : 0),
1904 ps);
1905 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1906 color_mode == OMAP_DSS_COLOR_UYVY)
1907 *pix_inc = pixinc(-x_predecim, 2 * ps);
1908 else
1909 *pix_inc = pixinc(-x_predecim, ps);
1910 break;
1911
1912 case OMAP_DSS_ROT_90 + 4:
1913 *offset1 = 0;
1914 if (field_offset)
1915 *offset0 = *offset1 + field_offset * ps;
1916 else
1917 *offset0 = *offset1;
1918 *row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) +
1919 y_predecim + (fieldmode ? 1 : 0),
1920 ps);
1921 *pix_inc = pixinc(x_predecim * screen_width, ps);
1922 break;
1923
1924 case OMAP_DSS_ROT_180 + 4:
1925 *offset1 = screen_width * (fbh - 1) * ps;
1926 if (field_offset)
1927 *offset0 = *offset1 - field_offset * screen_width * ps;
1928 else
1929 *offset0 = *offset1;
1930 *row_inc = pixinc(1 - y_predecim * screen_width * 2 -
1931 (fieldmode ? screen_width : 0),
1932 ps);
1933 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1934 color_mode == OMAP_DSS_COLOR_UYVY)
1935 *pix_inc = pixinc(x_predecim, 2 * ps);
1936 else
1937 *pix_inc = pixinc(x_predecim, ps);
1938 break;
1939
1940 case OMAP_DSS_ROT_270 + 4:
1941 *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
1942 if (field_offset)
1943 *offset0 = *offset1 - field_offset * ps;
1944 else
1945 *offset0 = *offset1;
1946 *row_inc = pixinc(screen_width * (fbh * x_predecim - 1) -
1947 y_predecim - (fieldmode ? 1 : 0),
1948 ps);
1949 *pix_inc = pixinc(-x_predecim * screen_width, ps);
1950 break;
1951
1952 default:
1953 BUG();
1954 return;
1955 }
1956}
1957
1958static void calc_tiler_rotation_offset(u16 screen_width, u16 width,
1959 enum omap_color_mode color_mode, bool fieldmode,
1960 unsigned int field_offset, unsigned *offset0, unsigned *offset1,
1961 s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim)
1962{
1963 u8 ps;
1964
1965 switch (color_mode) {
1966 case OMAP_DSS_COLOR_CLUT1:
1967 case OMAP_DSS_COLOR_CLUT2:
1968 case OMAP_DSS_COLOR_CLUT4:
1969 case OMAP_DSS_COLOR_CLUT8:
1970 BUG();
1971 return;
1972 default:
1973 ps = color_mode_to_bpp(color_mode) / 8;
1974 break;
1975 }
1976
1977 DSSDBG("scrw %d, width %d\n", screen_width, width);
1978
1979 /*
1980 * field 0 = even field = bottom field
1981 * field 1 = odd field = top field
1982 */
1983 *offset1 = 0;
1984 if (field_offset)
1985 *offset0 = *offset1 + field_offset * screen_width * ps;
1986 else
1987 *offset0 = *offset1;
1988 *row_inc = pixinc(1 + (y_predecim * screen_width - width * x_predecim) +
1989 (fieldmode ? screen_width : 0), ps);
1990 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1991 color_mode == OMAP_DSS_COLOR_UYVY)
1992 *pix_inc = pixinc(x_predecim, 2 * ps);
1993 else
1994 *pix_inc = pixinc(x_predecim, ps);
1995}
1996
1997/*
1998 * This function is used to avoid synclosts in OMAP3, because of some
1999 * undocumented horizontal position and timing related limitations.
2000 */
2001static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk,
2002 const struct omap_video_timings *t, u16 pos_x,
2003 u16 width, u16 height, u16 out_width, u16 out_height,
2004 bool five_taps)
2005{
2006 const int ds = DIV_ROUND_UP(height, out_height);
2007 unsigned long nonactive;
2008 static const u8 limits[3] = { 8, 10, 20 };
2009 u64 val, blank;
2010 int i;
2011
2012 nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
2013
2014 i = 0;
2015 if (out_height < height)
2016 i++;
2017 if (out_width < width)
2018 i++;
2019 blank = div_u64((u64)(t->hbp + t->hsw + t->hfp) * lclk, pclk);
2020 DSSDBG("blanking period + ppl = %llu (limit = %u)\n", blank, limits[i]);
2021 if (blank <= limits[i])
2022 return -EINVAL;
2023
2024 /* FIXME add checks for 3-tap filter once the limitations are known */
2025 if (!five_taps)
2026 return 0;
2027
2028 /*
2029 * Pixel data should be prepared before visible display point starts.
2030 * So, atleast DS-2 lines must have already been fetched by DISPC
2031 * during nonactive - pos_x period.
2032 */
2033 val = div_u64((u64)(nonactive - pos_x) * lclk, pclk);
2034 DSSDBG("(nonactive - pos_x) * pcd = %llu max(0, DS - 2) * width = %d\n",
2035 val, max(0, ds - 2) * width);
2036 if (val < max(0, ds - 2) * width)
2037 return -EINVAL;
2038
2039 /*
2040 * All lines need to be refilled during the nonactive period of which
2041 * only one line can be loaded during the active period. So, atleast
2042 * DS - 1 lines should be loaded during nonactive period.
2043 */
2044 val = div_u64((u64)nonactive * lclk, pclk);
2045 DSSDBG("nonactive * pcd = %llu, max(0, DS - 1) * width = %d\n",
2046 val, max(0, ds - 1) * width);
2047 if (val < max(0, ds - 1) * width)
2048 return -EINVAL;
2049
2050 return 0;
2051}
2052
2053static unsigned long calc_core_clk_five_taps(unsigned long pclk,
2054 const struct omap_video_timings *mgr_timings, u16 width,
2055 u16 height, u16 out_width, u16 out_height,
2056 enum omap_color_mode color_mode)
2057{
2058 u32 core_clk = 0;
2059 u64 tmp;
2060
2061 if (height <= out_height && width <= out_width)
2062 return (unsigned long) pclk;
2063
2064 if (height > out_height) {
2065 unsigned int ppl = mgr_timings->x_res;
2066
2067 tmp = pclk * height * out_width;
2068 do_div(tmp, 2 * out_height * ppl);
2069 core_clk = tmp;
2070
2071 if (height > 2 * out_height) {
2072 if (ppl == out_width)
2073 return 0;
2074
2075 tmp = pclk * (height - 2 * out_height) * out_width;
2076 do_div(tmp, 2 * out_height * (ppl - out_width));
2077 core_clk = max_t(u32, core_clk, tmp);
2078 }
2079 }
2080
2081 if (width > out_width) {
2082 tmp = pclk * width;
2083 do_div(tmp, out_width);
2084 core_clk = max_t(u32, core_clk, tmp);
2085
2086 if (color_mode == OMAP_DSS_COLOR_RGB24U)
2087 core_clk <<= 1;
2088 }
2089
2090 return core_clk;
2091}
2092
2093static unsigned long calc_core_clk_24xx(unsigned long pclk, u16 width,
2094 u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
2095{
2096 if (height > out_height && width > out_width)
2097 return pclk * 4;
2098 else
2099 return pclk * 2;
2100}
2101
2102static unsigned long calc_core_clk_34xx(unsigned long pclk, u16 width,
2103 u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
2104{
2105 unsigned int hf, vf;
2106
2107 /*
2108 * FIXME how to determine the 'A' factor
2109 * for the no downscaling case ?
2110 */
2111
2112 if (width > 3 * out_width)
2113 hf = 4;
2114 else if (width > 2 * out_width)
2115 hf = 3;
2116 else if (width > out_width)
2117 hf = 2;
2118 else
2119 hf = 1;
2120 if (height > out_height)
2121 vf = 2;
2122 else
2123 vf = 1;
2124
2125 return pclk * vf * hf;
2126}
2127
2128static unsigned long calc_core_clk_44xx(unsigned long pclk, u16 width,
2129 u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
2130{
2131 /*
2132 * If the overlay/writeback is in mem to mem mode, there are no
2133 * downscaling limitations with respect to pixel clock, return 1 as
2134 * required core clock to represent that we have sufficient enough
2135 * core clock to do maximum downscaling
2136 */
2137 if (mem_to_mem)
2138 return 1;
2139
2140 if (width > out_width)
2141 return DIV_ROUND_UP(pclk, out_width) * width;
2142 else
2143 return pclk;
2144}
2145
2146static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk,
2147 const struct omap_video_timings *mgr_timings,
2148 u16 width, u16 height, u16 out_width, u16 out_height,
2149 enum omap_color_mode color_mode, bool *five_taps,
2150 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
2151 u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
2152{
2153 int error;
2154 u16 in_width, in_height;
2155 int min_factor = min(*decim_x, *decim_y);
2156 const int maxsinglelinewidth =
2157 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2158
2159 *five_taps = false;
2160
2161 do {
2162 in_height = height / *decim_y;
2163 in_width = width / *decim_x;
2164 *core_clk = dispc.feat->calc_core_clk(pclk, in_width,
2165 in_height, out_width, out_height, mem_to_mem);
2166 error = (in_width > maxsinglelinewidth || !*core_clk ||
2167 *core_clk > dispc_core_clk_rate());
2168 if (error) {
2169 if (*decim_x == *decim_y) {
2170 *decim_x = min_factor;
2171 ++*decim_y;
2172 } else {
2173 swap(*decim_x, *decim_y);
2174 if (*decim_x < *decim_y)
2175 ++*decim_x;
2176 }
2177 }
2178 } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
2179
2180 if (in_width > maxsinglelinewidth) {
2181 DSSERR("Cannot scale max input width exceeded");
2182 return -EINVAL;
2183 }
2184 return 0;
2185}
2186
2187static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk,
2188 const struct omap_video_timings *mgr_timings,
2189 u16 width, u16 height, u16 out_width, u16 out_height,
2190 enum omap_color_mode color_mode, bool *five_taps,
2191 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
2192 u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
2193{
2194 int error;
2195 u16 in_width, in_height;
2196 int min_factor = min(*decim_x, *decim_y);
2197 const int maxsinglelinewidth =
2198 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2199
2200 do {
2201 in_height = height / *decim_y;
2202 in_width = width / *decim_x;
2203 *five_taps = in_height > out_height;
2204
2205 if (in_width > maxsinglelinewidth)
2206 if (in_height > out_height &&
2207 in_height < out_height * 2)
2208 *five_taps = false;
2209again:
2210 if (*five_taps)
2211 *core_clk = calc_core_clk_five_taps(pclk, mgr_timings,
2212 in_width, in_height, out_width,
2213 out_height, color_mode);
2214 else
2215 *core_clk = dispc.feat->calc_core_clk(pclk, in_width,
2216 in_height, out_width, out_height,
2217 mem_to_mem);
2218
2219 error = check_horiz_timing_omap3(pclk, lclk, mgr_timings,
2220 pos_x, in_width, in_height, out_width,
2221 out_height, *five_taps);
2222 if (error && *five_taps) {
2223 *five_taps = false;
2224 goto again;
2225 }
2226
2227 error = (error || in_width > maxsinglelinewidth * 2 ||
2228 (in_width > maxsinglelinewidth && *five_taps) ||
2229 !*core_clk || *core_clk > dispc_core_clk_rate());
2230 if (error) {
2231 if (*decim_x == *decim_y) {
2232 *decim_x = min_factor;
2233 ++*decim_y;
2234 } else {
2235 swap(*decim_x, *decim_y);
2236 if (*decim_x < *decim_y)
2237 ++*decim_x;
2238 }
2239 }
2240 } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
2241
2242 if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, width,
2243 height, out_width, out_height, *five_taps)) {
2244 DSSERR("horizontal timing too tight\n");
2245 return -EINVAL;
2246 }
2247
2248 if (in_width > (maxsinglelinewidth * 2)) {
2249 DSSERR("Cannot setup scaling");
2250 DSSERR("width exceeds maximum width possible");
2251 return -EINVAL;
2252 }
2253
2254 if (in_width > maxsinglelinewidth && *five_taps) {
2255 DSSERR("cannot setup scaling with five taps");
2256 return -EINVAL;
2257 }
2258 return 0;
2259}
2260
2261static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk,
2262 const struct omap_video_timings *mgr_timings,
2263 u16 width, u16 height, u16 out_width, u16 out_height,
2264 enum omap_color_mode color_mode, bool *five_taps,
2265 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
2266 u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
2267{
2268 u16 in_width, in_width_max;
2269 int decim_x_min = *decim_x;
2270 u16 in_height = height / *decim_y;
2271 const int maxsinglelinewidth =
2272 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2273 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
2274
2275 if (mem_to_mem) {
2276 in_width_max = out_width * maxdownscale;
2277 } else {
2278 in_width_max = dispc_core_clk_rate() /
2279 DIV_ROUND_UP(pclk, out_width);
2280 }
2281
2282 *decim_x = DIV_ROUND_UP(width, in_width_max);
2283
2284 *decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min;
2285 if (*decim_x > *x_predecim)
2286 return -EINVAL;
2287
2288 do {
2289 in_width = width / *decim_x;
2290 } while (*decim_x <= *x_predecim &&
2291 in_width > maxsinglelinewidth && ++*decim_x);
2292
2293 if (in_width > maxsinglelinewidth) {
2294 DSSERR("Cannot scale width exceeds max line width");
2295 return -EINVAL;
2296 }
2297
2298 *core_clk = dispc.feat->calc_core_clk(pclk, in_width, in_height,
2299 out_width, out_height, mem_to_mem);
2300 return 0;
2301}
2302
2303static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
2304 enum omap_overlay_caps caps,
2305 const struct omap_video_timings *mgr_timings,
2306 u16 width, u16 height, u16 out_width, u16 out_height,
2307 enum omap_color_mode color_mode, bool *five_taps,
2308 int *x_predecim, int *y_predecim, u16 pos_x,
2309 enum omap_dss_rotation_type rotation_type, bool mem_to_mem)
2310{
2311 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
2312 const int max_decim_limit = 16;
2313 unsigned long core_clk = 0;
2314 int decim_x, decim_y, ret;
2315
2316 if (width == out_width && height == out_height)
2317 return 0;
2318
2319 if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
2320 return -EINVAL;
2321
2322 if (mem_to_mem) {
2323 *x_predecim = *y_predecim = 1;
2324 } else {
2325 *x_predecim = max_decim_limit;
2326 *y_predecim = (rotation_type == OMAP_DSS_ROT_TILER &&
2327 dss_has_feature(FEAT_BURST_2D)) ?
2328 2 : max_decim_limit;
2329 }
2330
2331 if (color_mode == OMAP_DSS_COLOR_CLUT1 ||
2332 color_mode == OMAP_DSS_COLOR_CLUT2 ||
2333 color_mode == OMAP_DSS_COLOR_CLUT4 ||
2334 color_mode == OMAP_DSS_COLOR_CLUT8) {
2335 *x_predecim = 1;
2336 *y_predecim = 1;
2337 *five_taps = false;
2338 return 0;
2339 }
2340
2341 decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale);
2342 decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale);
2343
2344 if (decim_x > *x_predecim || out_width > width * 8)
2345 return -EINVAL;
2346
2347 if (decim_y > *y_predecim || out_height > height * 8)
2348 return -EINVAL;
2349
2350 ret = dispc.feat->calc_scaling(pclk, lclk, mgr_timings, width, height,
2351 out_width, out_height, color_mode, five_taps,
2352 x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk,
2353 mem_to_mem);
2354 if (ret)
2355 return ret;
2356
2357 DSSDBG("required core clk rate = %lu Hz\n", core_clk);
2358 DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate());
2359
2360 if (!core_clk || core_clk > dispc_core_clk_rate()) {
2361 DSSERR("failed to set up scaling, "
2362 "required core clk rate = %lu Hz, "
2363 "current core clk rate = %lu Hz\n",
2364 core_clk, dispc_core_clk_rate());
2365 return -EINVAL;
2366 }
2367
2368 *x_predecim = decim_x;
2369 *y_predecim = decim_y;
2370 return 0;
2371}
2372
2373int dispc_ovl_check(enum omap_plane plane, enum omap_channel channel,
2374 const struct omap_overlay_info *oi,
2375 const struct omap_video_timings *timings,
2376 int *x_predecim, int *y_predecim)
2377{
2378 enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
2379 bool five_taps = true;
2380 bool fieldmode = false;
2381 u16 in_height = oi->height;
2382 u16 in_width = oi->width;
2383 bool ilace = timings->interlace;
2384 u16 out_width, out_height;
2385 int pos_x = oi->pos_x;
2386 unsigned long pclk = dispc_mgr_pclk_rate(channel);
2387 unsigned long lclk = dispc_mgr_lclk_rate(channel);
2388
2389 out_width = oi->out_width == 0 ? oi->width : oi->out_width;
2390 out_height = oi->out_height == 0 ? oi->height : oi->out_height;
2391
2392 if (ilace && oi->height == out_height)
2393 fieldmode = true;
2394
2395 if (ilace) {
2396 if (fieldmode)
2397 in_height /= 2;
2398 out_height /= 2;
2399
2400 DSSDBG("adjusting for ilace: height %d, out_height %d\n",
2401 in_height, out_height);
2402 }
2403
2404 if (!dss_feat_color_mode_supported(plane, oi->color_mode))
2405 return -EINVAL;
2406
2407 return dispc_ovl_calc_scaling(pclk, lclk, caps, timings, in_width,
2408 in_height, out_width, out_height, oi->color_mode,
2409 &five_taps, x_predecim, y_predecim, pos_x,
2410 oi->rotation_type, false);
2411}
2412EXPORT_SYMBOL(dispc_ovl_check);
2413
2414static int dispc_ovl_setup_common(enum omap_plane plane,
2415 enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr,
2416 u16 screen_width, int pos_x, int pos_y, u16 width, u16 height,
2417 u16 out_width, u16 out_height, enum omap_color_mode color_mode,
2418 u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha,
2419 u8 global_alpha, enum omap_dss_rotation_type rotation_type,
2420 bool replication, const struct omap_video_timings *mgr_timings,
2421 bool mem_to_mem)
2422{
2423 bool five_taps = true;
2424 bool fieldmode = false;
2425 int r, cconv = 0;
2426 unsigned offset0, offset1;
2427 s32 row_inc;
2428 s32 pix_inc;
2429 u16 frame_width, frame_height;
2430 unsigned int field_offset = 0;
2431 u16 in_height = height;
2432 u16 in_width = width;
2433 int x_predecim = 1, y_predecim = 1;
2434 bool ilace = mgr_timings->interlace;
2435 unsigned long pclk = dispc_plane_pclk_rate(plane);
2436 unsigned long lclk = dispc_plane_lclk_rate(plane);
2437
2438 if (paddr == 0)
2439 return -EINVAL;
2440
2441 out_width = out_width == 0 ? width : out_width;
2442 out_height = out_height == 0 ? height : out_height;
2443
2444 if (ilace && height == out_height)
2445 fieldmode = true;
2446
2447 if (ilace) {
2448 if (fieldmode)
2449 in_height /= 2;
2450 pos_y /= 2;
2451 out_height /= 2;
2452
2453 DSSDBG("adjusting for ilace: height %d, pos_y %d, "
2454 "out_height %d\n", in_height, pos_y,
2455 out_height);
2456 }
2457
2458 if (!dss_feat_color_mode_supported(plane, color_mode))
2459 return -EINVAL;
2460
2461 r = dispc_ovl_calc_scaling(pclk, lclk, caps, mgr_timings, in_width,
2462 in_height, out_width, out_height, color_mode,
2463 &five_taps, &x_predecim, &y_predecim, pos_x,
2464 rotation_type, mem_to_mem);
2465 if (r)
2466 return r;
2467
2468 in_width = in_width / x_predecim;
2469 in_height = in_height / y_predecim;
2470
2471 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
2472 color_mode == OMAP_DSS_COLOR_UYVY ||
2473 color_mode == OMAP_DSS_COLOR_NV12)
2474 cconv = 1;
2475
2476 if (ilace && !fieldmode) {
2477 /*
2478 * when downscaling the bottom field may have to start several
2479 * source lines below the top field. Unfortunately ACCUI
2480 * registers will only hold the fractional part of the offset
2481 * so the integer part must be added to the base address of the
2482 * bottom field.
2483 */
2484 if (!in_height || in_height == out_height)
2485 field_offset = 0;
2486 else
2487 field_offset = in_height / out_height / 2;
2488 }
2489
2490 /* Fields are independent but interleaved in memory. */
2491 if (fieldmode)
2492 field_offset = 1;
2493
2494 offset0 = 0;
2495 offset1 = 0;
2496 row_inc = 0;
2497 pix_inc = 0;
2498
2499 if (plane == OMAP_DSS_WB) {
2500 frame_width = out_width;
2501 frame_height = out_height;
2502 } else {
2503 frame_width = in_width;
2504 frame_height = height;
2505 }
2506
2507 if (rotation_type == OMAP_DSS_ROT_TILER)
2508 calc_tiler_rotation_offset(screen_width, frame_width,
2509 color_mode, fieldmode, field_offset,
2510 &offset0, &offset1, &row_inc, &pix_inc,
2511 x_predecim, y_predecim);
2512 else if (rotation_type == OMAP_DSS_ROT_DMA)
2513 calc_dma_rotation_offset(rotation, mirror, screen_width,
2514 frame_width, frame_height,
2515 color_mode, fieldmode, field_offset,
2516 &offset0, &offset1, &row_inc, &pix_inc,
2517 x_predecim, y_predecim);
2518 else
2519 calc_vrfb_rotation_offset(rotation, mirror,
2520 screen_width, frame_width, frame_height,
2521 color_mode, fieldmode, field_offset,
2522 &offset0, &offset1, &row_inc, &pix_inc,
2523 x_predecim, y_predecim);
2524
2525 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
2526 offset0, offset1, row_inc, pix_inc);
2527
2528 dispc_ovl_set_color_mode(plane, color_mode);
2529
2530 dispc_ovl_configure_burst_type(plane, rotation_type);
2531
2532 dispc_ovl_set_ba0(plane, paddr + offset0);
2533 dispc_ovl_set_ba1(plane, paddr + offset1);
2534
2535 if (OMAP_DSS_COLOR_NV12 == color_mode) {
2536 dispc_ovl_set_ba0_uv(plane, p_uv_addr + offset0);
2537 dispc_ovl_set_ba1_uv(plane, p_uv_addr + offset1);
2538 }
2539
2540 dispc_ovl_set_row_inc(plane, row_inc);
2541 dispc_ovl_set_pix_inc(plane, pix_inc);
2542
2543 DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, in_width,
2544 in_height, out_width, out_height);
2545
2546 dispc_ovl_set_pos(plane, caps, pos_x, pos_y);
2547
2548 dispc_ovl_set_input_size(plane, in_width, in_height);
2549
2550 if (caps & OMAP_DSS_OVL_CAP_SCALE) {
2551 dispc_ovl_set_scaling(plane, in_width, in_height, out_width,
2552 out_height, ilace, five_taps, fieldmode,
2553 color_mode, rotation);
2554 dispc_ovl_set_output_size(plane, out_width, out_height);
2555 dispc_ovl_set_vid_color_conv(plane, cconv);
2556 }
2557
2558 dispc_ovl_set_rotation_attrs(plane, rotation, rotation_type, mirror,
2559 color_mode);
2560
2561 dispc_ovl_set_zorder(plane, caps, zorder);
2562 dispc_ovl_set_pre_mult_alpha(plane, caps, pre_mult_alpha);
2563 dispc_ovl_setup_global_alpha(plane, caps, global_alpha);
2564
2565 dispc_ovl_enable_replication(plane, caps, replication);
2566
2567 return 0;
2568}
2569
2570int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
2571 bool replication, const struct omap_video_timings *mgr_timings,
2572 bool mem_to_mem)
2573{
2574 int r;
2575 enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
2576 enum omap_channel channel;
2577
2578 channel = dispc_ovl_get_channel_out(plane);
2579
2580 DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
2581 "%dx%d, cmode %x, rot %d, mir %d, chan %d repl %d\n",
2582 plane, oi->paddr, oi->p_uv_addr, oi->screen_width, oi->pos_x,
2583 oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height,
2584 oi->color_mode, oi->rotation, oi->mirror, channel, replication);
2585
2586 r = dispc_ovl_setup_common(plane, caps, oi->paddr, oi->p_uv_addr,
2587 oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
2588 oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
2589 oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
2590 oi->rotation_type, replication, mgr_timings, mem_to_mem);
2591
2592 return r;
2593}
2594EXPORT_SYMBOL(dispc_ovl_setup);
2595
2596int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
2597 bool mem_to_mem, const struct omap_video_timings *mgr_timings)
2598{
2599 int r;
2600 u32 l;
2601 enum omap_plane plane = OMAP_DSS_WB;
2602 const int pos_x = 0, pos_y = 0;
2603 const u8 zorder = 0, global_alpha = 0;
2604 const bool replication = false;
2605 bool truncation;
2606 int in_width = mgr_timings->x_res;
2607 int in_height = mgr_timings->y_res;
2608 enum omap_overlay_caps caps =
2609 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA;
2610
2611 DSSDBG("dispc_wb_setup, pa %x, pa_uv %x, %d,%d -> %dx%d, cmode %x, "
2612 "rot %d, mir %d\n", wi->paddr, wi->p_uv_addr, in_width,
2613 in_height, wi->width, wi->height, wi->color_mode, wi->rotation,
2614 wi->mirror);
2615
2616 r = dispc_ovl_setup_common(plane, caps, wi->paddr, wi->p_uv_addr,
2617 wi->buf_width, pos_x, pos_y, in_width, in_height, wi->width,
2618 wi->height, wi->color_mode, wi->rotation, wi->mirror, zorder,
2619 wi->pre_mult_alpha, global_alpha, wi->rotation_type,
2620 replication, mgr_timings, mem_to_mem);
2621
2622 switch (wi->color_mode) {
2623 case OMAP_DSS_COLOR_RGB16:
2624 case OMAP_DSS_COLOR_RGB24P:
2625 case OMAP_DSS_COLOR_ARGB16:
2626 case OMAP_DSS_COLOR_RGBA16:
2627 case OMAP_DSS_COLOR_RGB12U:
2628 case OMAP_DSS_COLOR_ARGB16_1555:
2629 case OMAP_DSS_COLOR_XRGB16_1555:
2630 case OMAP_DSS_COLOR_RGBX16:
2631 truncation = true;
2632 break;
2633 default:
2634 truncation = false;
2635 break;
2636 }
2637
2638 /* setup extra DISPC_WB_ATTRIBUTES */
2639 l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
2640 l = FLD_MOD(l, truncation, 10, 10); /* TRUNCATIONENABLE */
2641 l = FLD_MOD(l, mem_to_mem, 19, 19); /* WRITEBACKMODE */
2642 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), l);
2643
2644 return r;
2645}
2646
2647int dispc_ovl_enable(enum omap_plane plane, bool enable)
2648{
2649 DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
2650
2651 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
2652
2653 return 0;
2654}
2655EXPORT_SYMBOL(dispc_ovl_enable);
2656
2657bool dispc_ovl_enabled(enum omap_plane plane)
2658{
2659 return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
2660}
2661EXPORT_SYMBOL(dispc_ovl_enabled);
2662
2663void dispc_mgr_enable(enum omap_channel channel, bool enable)
2664{
2665 mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable);
2666 /* flush posted write */
2667 mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
2668}
2669EXPORT_SYMBOL(dispc_mgr_enable);
2670
2671bool dispc_mgr_is_enabled(enum omap_channel channel)
2672{
2673 return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
2674}
2675EXPORT_SYMBOL(dispc_mgr_is_enabled);
2676
2677void dispc_wb_enable(bool enable)
2678{
2679 dispc_ovl_enable(OMAP_DSS_WB, enable);
2680}
2681
2682bool dispc_wb_is_enabled(void)
2683{
2684 return dispc_ovl_enabled(OMAP_DSS_WB);
2685}
2686
2687static void dispc_lcd_enable_signal_polarity(bool act_high)
2688{
2689 if (!dss_has_feature(FEAT_LCDENABLEPOL))
2690 return;
2691
2692 REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
2693}
2694
2695void dispc_lcd_enable_signal(bool enable)
2696{
2697 if (!dss_has_feature(FEAT_LCDENABLESIGNAL))
2698 return;
2699
2700 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
2701}
2702
2703void dispc_pck_free_enable(bool enable)
2704{
2705 if (!dss_has_feature(FEAT_PCKFREEENABLE))
2706 return;
2707
2708 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
2709}
2710
2711static void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable)
2712{
2713 mgr_fld_write(channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable);
2714}
2715
2716
2717static void dispc_mgr_set_lcd_type_tft(enum omap_channel channel)
2718{
2719 mgr_fld_write(channel, DISPC_MGR_FLD_STNTFT, 1);
2720}
2721
2722void dispc_set_loadmode(enum omap_dss_load_mode mode)
2723{
2724 REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
2725}
2726
2727
2728static void dispc_mgr_set_default_color(enum omap_channel channel, u32 color)
2729{
2730 dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
2731}
2732
2733static void dispc_mgr_set_trans_key(enum omap_channel ch,
2734 enum omap_dss_trans_key_type type,
2735 u32 trans_key)
2736{
2737 mgr_fld_write(ch, DISPC_MGR_FLD_TCKSELECTION, type);
2738
2739 dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
2740}
2741
2742static void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable)
2743{
2744 mgr_fld_write(ch, DISPC_MGR_FLD_TCKENABLE, enable);
2745}
2746
2747static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch,
2748 bool enable)
2749{
2750 if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
2751 return;
2752
2753 if (ch == OMAP_DSS_CHANNEL_LCD)
2754 REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
2755 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2756 REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
2757}
2758
2759void dispc_mgr_setup(enum omap_channel channel,
2760 const struct omap_overlay_manager_info *info)
2761{
2762 dispc_mgr_set_default_color(channel, info->default_color);
2763 dispc_mgr_set_trans_key(channel, info->trans_key_type, info->trans_key);
2764 dispc_mgr_enable_trans_key(channel, info->trans_enabled);
2765 dispc_mgr_enable_alpha_fixed_zorder(channel,
2766 info->partial_alpha_enabled);
2767 if (dss_has_feature(FEAT_CPR)) {
2768 dispc_mgr_enable_cpr(channel, info->cpr_enable);
2769 dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs);
2770 }
2771}
2772EXPORT_SYMBOL(dispc_mgr_setup);
2773
2774static void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
2775{
2776 int code;
2777
2778 switch (data_lines) {
2779 case 12:
2780 code = 0;
2781 break;
2782 case 16:
2783 code = 1;
2784 break;
2785 case 18:
2786 code = 2;
2787 break;
2788 case 24:
2789 code = 3;
2790 break;
2791 default:
2792 BUG();
2793 return;
2794 }
2795
2796 mgr_fld_write(channel, DISPC_MGR_FLD_TFTDATALINES, code);
2797}
2798
2799static void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
2800{
2801 u32 l;
2802 int gpout0, gpout1;
2803
2804 switch (mode) {
2805 case DSS_IO_PAD_MODE_RESET:
2806 gpout0 = 0;
2807 gpout1 = 0;
2808 break;
2809 case DSS_IO_PAD_MODE_RFBI:
2810 gpout0 = 1;
2811 gpout1 = 0;
2812 break;
2813 case DSS_IO_PAD_MODE_BYPASS:
2814 gpout0 = 1;
2815 gpout1 = 1;
2816 break;
2817 default:
2818 BUG();
2819 return;
2820 }
2821
2822 l = dispc_read_reg(DISPC_CONTROL);
2823 l = FLD_MOD(l, gpout0, 15, 15);
2824 l = FLD_MOD(l, gpout1, 16, 16);
2825 dispc_write_reg(DISPC_CONTROL, l);
2826}
2827
2828static void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable)
2829{
2830 mgr_fld_write(channel, DISPC_MGR_FLD_STALLMODE, enable);
2831}
2832
2833void dispc_mgr_set_lcd_config(enum omap_channel channel,
2834 const struct dss_lcd_mgr_config *config)
2835{
2836 dispc_mgr_set_io_pad_mode(config->io_pad_mode);
2837
2838 dispc_mgr_enable_stallmode(channel, config->stallmode);
2839 dispc_mgr_enable_fifohandcheck(channel, config->fifohandcheck);
2840
2841 dispc_mgr_set_clock_div(channel, &config->clock_info);
2842
2843 dispc_mgr_set_tft_data_lines(channel, config->video_port_width);
2844
2845 dispc_lcd_enable_signal_polarity(config->lcden_sig_polarity);
2846
2847 dispc_mgr_set_lcd_type_tft(channel);
2848}
2849EXPORT_SYMBOL(dispc_mgr_set_lcd_config);
2850
2851static bool _dispc_mgr_size_ok(u16 width, u16 height)
2852{
2853 return width <= dispc.feat->mgr_width_max &&
2854 height <= dispc.feat->mgr_height_max;
2855}
2856
2857static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
2858 int vsw, int vfp, int vbp)
2859{
2860 if (hsw < 1 || hsw > dispc.feat->sw_max ||
2861 hfp < 1 || hfp > dispc.feat->hp_max ||
2862 hbp < 1 || hbp > dispc.feat->hp_max ||
2863 vsw < 1 || vsw > dispc.feat->sw_max ||
2864 vfp < 0 || vfp > dispc.feat->vp_max ||
2865 vbp < 0 || vbp > dispc.feat->vp_max)
2866 return false;
2867 return true;
2868}
2869
2870static bool _dispc_mgr_pclk_ok(enum omap_channel channel,
2871 unsigned long pclk)
2872{
2873 if (dss_mgr_is_lcd(channel))
2874 return pclk <= dispc.feat->max_lcd_pclk ? true : false;
2875 else
2876 return pclk <= dispc.feat->max_tv_pclk ? true : false;
2877}
2878
2879bool dispc_mgr_timings_ok(enum omap_channel channel,
2880 const struct omap_video_timings *timings)
2881{
2882 bool timings_ok;
2883
2884 timings_ok = _dispc_mgr_size_ok(timings->x_res, timings->y_res);
2885
2886 timings_ok &= _dispc_mgr_pclk_ok(channel, timings->pixelclock);
2887
2888 if (dss_mgr_is_lcd(channel)) {
2889 timings_ok &= _dispc_lcd_timings_ok(timings->hsw, timings->hfp,
2890 timings->hbp, timings->vsw, timings->vfp,
2891 timings->vbp);
2892 }
2893
2894 return timings_ok;
2895}
2896
2897static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
2898 int hfp, int hbp, int vsw, int vfp, int vbp,
2899 enum omap_dss_signal_level vsync_level,
2900 enum omap_dss_signal_level hsync_level,
2901 enum omap_dss_signal_edge data_pclk_edge,
2902 enum omap_dss_signal_level de_level,
2903 enum omap_dss_signal_edge sync_pclk_edge)
2904
2905{
2906 u32 timing_h, timing_v, l;
2907 bool onoff, rf, ipc;
2908
2909 timing_h = FLD_VAL(hsw-1, dispc.feat->sw_start, 0) |
2910 FLD_VAL(hfp-1, dispc.feat->fp_start, 8) |
2911 FLD_VAL(hbp-1, dispc.feat->bp_start, 20);
2912 timing_v = FLD_VAL(vsw-1, dispc.feat->sw_start, 0) |
2913 FLD_VAL(vfp, dispc.feat->fp_start, 8) |
2914 FLD_VAL(vbp, dispc.feat->bp_start, 20);
2915
2916 dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
2917 dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
2918
2919 switch (data_pclk_edge) {
2920 case OMAPDSS_DRIVE_SIG_RISING_EDGE:
2921 ipc = false;
2922 break;
2923 case OMAPDSS_DRIVE_SIG_FALLING_EDGE:
2924 ipc = true;
2925 break;
2926 case OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES:
2927 default:
2928 BUG();
2929 }
2930
2931 switch (sync_pclk_edge) {
2932 case OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES:
2933 onoff = false;
2934 rf = false;
2935 break;
2936 case OMAPDSS_DRIVE_SIG_FALLING_EDGE:
2937 onoff = true;
2938 rf = false;
2939 break;
2940 case OMAPDSS_DRIVE_SIG_RISING_EDGE:
2941 onoff = true;
2942 rf = true;
2943 break;
2944 default:
2945 BUG();
2946 }
2947
2948 l = dispc_read_reg(DISPC_POL_FREQ(channel));
2949 l |= FLD_VAL(onoff, 17, 17);
2950 l |= FLD_VAL(rf, 16, 16);
2951 l |= FLD_VAL(de_level, 15, 15);
2952 l |= FLD_VAL(ipc, 14, 14);
2953 l |= FLD_VAL(hsync_level, 13, 13);
2954 l |= FLD_VAL(vsync_level, 12, 12);
2955 dispc_write_reg(DISPC_POL_FREQ(channel), l);
2956}
2957
2958/* change name to mode? */
2959void dispc_mgr_set_timings(enum omap_channel channel,
2960 const struct omap_video_timings *timings)
2961{
2962 unsigned xtot, ytot;
2963 unsigned long ht, vt;
2964 struct omap_video_timings t = *timings;
2965
2966 DSSDBG("channel %d xres %u yres %u\n", channel, t.x_res, t.y_res);
2967
2968 if (!dispc_mgr_timings_ok(channel, &t)) {
2969 BUG();
2970 return;
2971 }
2972
2973 if (dss_mgr_is_lcd(channel)) {
2974 _dispc_mgr_set_lcd_timings(channel, t.hsw, t.hfp, t.hbp, t.vsw,
2975 t.vfp, t.vbp, t.vsync_level, t.hsync_level,
2976 t.data_pclk_edge, t.de_level, t.sync_pclk_edge);
2977
2978 xtot = t.x_res + t.hfp + t.hsw + t.hbp;
2979 ytot = t.y_res + t.vfp + t.vsw + t.vbp;
2980
2981 ht = timings->pixelclock / xtot;
2982 vt = timings->pixelclock / xtot / ytot;
2983
2984 DSSDBG("pck %u\n", timings->pixelclock);
2985 DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
2986 t.hsw, t.hfp, t.hbp, t.vsw, t.vfp, t.vbp);
2987 DSSDBG("vsync_level %d hsync_level %d data_pclk_edge %d de_level %d sync_pclk_edge %d\n",
2988 t.vsync_level, t.hsync_level, t.data_pclk_edge,
2989 t.de_level, t.sync_pclk_edge);
2990
2991 DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
2992 } else {
2993 if (t.interlace == true)
2994 t.y_res /= 2;
2995 }
2996
2997 dispc_mgr_set_size(channel, t.x_res, t.y_res);
2998}
2999EXPORT_SYMBOL(dispc_mgr_set_timings);
3000
3001static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
3002 u16 pck_div)
3003{
3004 BUG_ON(lck_div < 1);
3005 BUG_ON(pck_div < 1);
3006
3007 dispc_write_reg(DISPC_DIVISORo(channel),
3008 FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
3009
3010 if (dss_has_feature(FEAT_CORE_CLK_DIV) == false &&
3011 channel == OMAP_DSS_CHANNEL_LCD)
3012 dispc.core_clk_rate = dispc_fclk_rate() / lck_div;
3013}
3014
3015static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div,
3016 int *pck_div)
3017{
3018 u32 l;
3019 l = dispc_read_reg(DISPC_DIVISORo(channel));
3020 *lck_div = FLD_GET(l, 23, 16);
3021 *pck_div = FLD_GET(l, 7, 0);
3022}
3023
3024unsigned long dispc_fclk_rate(void)
3025{
3026 struct platform_device *dsidev;
3027 unsigned long r = 0;
3028
3029 switch (dss_get_dispc_clk_source()) {
3030 case OMAP_DSS_CLK_SRC_FCK:
3031 r = dss_get_dispc_clk_rate();
3032 break;
3033 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
3034 dsidev = dsi_get_dsidev_from_id(0);
3035 r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
3036 break;
3037 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
3038 dsidev = dsi_get_dsidev_from_id(1);
3039 r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
3040 break;
3041 default:
3042 BUG();
3043 return 0;
3044 }
3045
3046 return r;
3047}
3048
3049unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
3050{
3051 struct platform_device *dsidev;
3052 int lcd;
3053 unsigned long r;
3054 u32 l;
3055
3056 if (dss_mgr_is_lcd(channel)) {
3057 l = dispc_read_reg(DISPC_DIVISORo(channel));
3058
3059 lcd = FLD_GET(l, 23, 16);
3060
3061 switch (dss_get_lcd_clk_source(channel)) {
3062 case OMAP_DSS_CLK_SRC_FCK:
3063 r = dss_get_dispc_clk_rate();
3064 break;
3065 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
3066 dsidev = dsi_get_dsidev_from_id(0);
3067 r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
3068 break;
3069 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
3070 dsidev = dsi_get_dsidev_from_id(1);
3071 r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
3072 break;
3073 default:
3074 BUG();
3075 return 0;
3076 }
3077
3078 return r / lcd;
3079 } else {
3080 return dispc_fclk_rate();
3081 }
3082}
3083
3084unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
3085{
3086 unsigned long r;
3087
3088 if (dss_mgr_is_lcd(channel)) {
3089 int pcd;
3090 u32 l;
3091
3092 l = dispc_read_reg(DISPC_DIVISORo(channel));
3093
3094 pcd = FLD_GET(l, 7, 0);
3095
3096 r = dispc_mgr_lclk_rate(channel);
3097
3098 return r / pcd;
3099 } else {
3100 return dispc.tv_pclk_rate;
3101 }
3102}
3103
3104void dispc_set_tv_pclk(unsigned long pclk)
3105{
3106 dispc.tv_pclk_rate = pclk;
3107}
3108
3109unsigned long dispc_core_clk_rate(void)
3110{
3111 return dispc.core_clk_rate;
3112}
3113
3114static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
3115{
3116 enum omap_channel channel;
3117
3118 if (plane == OMAP_DSS_WB)
3119 return 0;
3120
3121 channel = dispc_ovl_get_channel_out(plane);
3122
3123 return dispc_mgr_pclk_rate(channel);
3124}
3125
3126static unsigned long dispc_plane_lclk_rate(enum omap_plane plane)
3127{
3128 enum omap_channel channel;
3129
3130 if (plane == OMAP_DSS_WB)
3131 return 0;
3132
3133 channel = dispc_ovl_get_channel_out(plane);
3134
3135 return dispc_mgr_lclk_rate(channel);
3136}
3137
3138static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
3139{
3140 int lcd, pcd;
3141 enum omap_dss_clk_source lcd_clk_src;
3142
3143 seq_printf(s, "- %s -\n", mgr_desc[channel].name);
3144
3145 lcd_clk_src = dss_get_lcd_clk_source(channel);
3146
3147 seq_printf(s, "%s clk source = %s (%s)\n", mgr_desc[channel].name,
3148 dss_get_generic_clk_source_name(lcd_clk_src),
3149 dss_feat_get_clk_source_name(lcd_clk_src));
3150
3151 dispc_mgr_get_lcd_divisor(channel, &lcd, &pcd);
3152
3153 seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
3154 dispc_mgr_lclk_rate(channel), lcd);
3155 seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
3156 dispc_mgr_pclk_rate(channel), pcd);
3157}
3158
3159void dispc_dump_clocks(struct seq_file *s)
3160{
3161 int lcd;
3162 u32 l;
3163 enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source();
3164
3165 if (dispc_runtime_get())
3166 return;
3167
3168 seq_printf(s, "- DISPC -\n");
3169
3170 seq_printf(s, "dispc fclk source = %s (%s)\n",
3171 dss_get_generic_clk_source_name(dispc_clk_src),
3172 dss_feat_get_clk_source_name(dispc_clk_src));
3173
3174 seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate());
3175
3176 if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
3177 seq_printf(s, "- DISPC-CORE-CLK -\n");
3178 l = dispc_read_reg(DISPC_DIVISOR);
3179 lcd = FLD_GET(l, 23, 16);
3180
3181 seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
3182 (dispc_fclk_rate()/lcd), lcd);
3183 }
3184
3185 dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD);
3186
3187 if (dss_has_feature(FEAT_MGR_LCD2))
3188 dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD2);
3189 if (dss_has_feature(FEAT_MGR_LCD3))
3190 dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD3);
3191
3192 dispc_runtime_put();
3193}
3194
3195static void dispc_dump_regs(struct seq_file *s)
3196{
3197 int i, j;
3198 const char *mgr_names[] = {
3199 [OMAP_DSS_CHANNEL_LCD] = "LCD",
3200 [OMAP_DSS_CHANNEL_DIGIT] = "TV",
3201 [OMAP_DSS_CHANNEL_LCD2] = "LCD2",
3202 [OMAP_DSS_CHANNEL_LCD3] = "LCD3",
3203 };
3204 const char *ovl_names[] = {
3205 [OMAP_DSS_GFX] = "GFX",
3206 [OMAP_DSS_VIDEO1] = "VID1",
3207 [OMAP_DSS_VIDEO2] = "VID2",
3208 [OMAP_DSS_VIDEO3] = "VID3",
3209 };
3210 const char **p_names;
3211
3212#define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r))
3213
3214 if (dispc_runtime_get())
3215 return;
3216
3217 /* DISPC common registers */
3218 DUMPREG(DISPC_REVISION);
3219 DUMPREG(DISPC_SYSCONFIG);
3220 DUMPREG(DISPC_SYSSTATUS);
3221 DUMPREG(DISPC_IRQSTATUS);
3222 DUMPREG(DISPC_IRQENABLE);
3223 DUMPREG(DISPC_CONTROL);
3224 DUMPREG(DISPC_CONFIG);
3225 DUMPREG(DISPC_CAPABLE);
3226 DUMPREG(DISPC_LINE_STATUS);
3227 DUMPREG(DISPC_LINE_NUMBER);
3228 if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
3229 dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
3230 DUMPREG(DISPC_GLOBAL_ALPHA);
3231 if (dss_has_feature(FEAT_MGR_LCD2)) {
3232 DUMPREG(DISPC_CONTROL2);
3233 DUMPREG(DISPC_CONFIG2);
3234 }
3235 if (dss_has_feature(FEAT_MGR_LCD3)) {
3236 DUMPREG(DISPC_CONTROL3);
3237 DUMPREG(DISPC_CONFIG3);
3238 }
3239 if (dss_has_feature(FEAT_MFLAG))
3240 DUMPREG(DISPC_GLOBAL_MFLAG_ATTRIBUTE);
3241
3242#undef DUMPREG
3243
3244#define DISPC_REG(i, name) name(i)
3245#define DUMPREG(i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \
3246 (int)(48 - strlen(#r) - strlen(p_names[i])), " ", \
3247 dispc_read_reg(DISPC_REG(i, r)))
3248
3249 p_names = mgr_names;
3250
3251 /* DISPC channel specific registers */
3252 for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
3253 DUMPREG(i, DISPC_DEFAULT_COLOR);
3254 DUMPREG(i, DISPC_TRANS_COLOR);
3255 DUMPREG(i, DISPC_SIZE_MGR);
3256
3257 if (i == OMAP_DSS_CHANNEL_DIGIT)
3258 continue;
3259
3260 DUMPREG(i, DISPC_DEFAULT_COLOR);
3261 DUMPREG(i, DISPC_TRANS_COLOR);
3262 DUMPREG(i, DISPC_TIMING_H);
3263 DUMPREG(i, DISPC_TIMING_V);
3264 DUMPREG(i, DISPC_POL_FREQ);
3265 DUMPREG(i, DISPC_DIVISORo);
3266 DUMPREG(i, DISPC_SIZE_MGR);
3267
3268 DUMPREG(i, DISPC_DATA_CYCLE1);
3269 DUMPREG(i, DISPC_DATA_CYCLE2);
3270 DUMPREG(i, DISPC_DATA_CYCLE3);
3271
3272 if (dss_has_feature(FEAT_CPR)) {
3273 DUMPREG(i, DISPC_CPR_COEF_R);
3274 DUMPREG(i, DISPC_CPR_COEF_G);
3275 DUMPREG(i, DISPC_CPR_COEF_B);
3276 }
3277 }
3278
3279 p_names = ovl_names;
3280
3281 for (i = 0; i < dss_feat_get_num_ovls(); i++) {
3282 DUMPREG(i, DISPC_OVL_BA0);
3283 DUMPREG(i, DISPC_OVL_BA1);
3284 DUMPREG(i, DISPC_OVL_POSITION);
3285 DUMPREG(i, DISPC_OVL_SIZE);
3286 DUMPREG(i, DISPC_OVL_ATTRIBUTES);
3287 DUMPREG(i, DISPC_OVL_FIFO_THRESHOLD);
3288 DUMPREG(i, DISPC_OVL_FIFO_SIZE_STATUS);
3289 DUMPREG(i, DISPC_OVL_ROW_INC);
3290 DUMPREG(i, DISPC_OVL_PIXEL_INC);
3291 if (dss_has_feature(FEAT_PRELOAD))
3292 DUMPREG(i, DISPC_OVL_PRELOAD);
3293
3294 if (i == OMAP_DSS_GFX) {
3295 DUMPREG(i, DISPC_OVL_WINDOW_SKIP);
3296 DUMPREG(i, DISPC_OVL_TABLE_BA);
3297 continue;
3298 }
3299
3300 DUMPREG(i, DISPC_OVL_FIR);
3301 DUMPREG(i, DISPC_OVL_PICTURE_SIZE);
3302 DUMPREG(i, DISPC_OVL_ACCU0);
3303 DUMPREG(i, DISPC_OVL_ACCU1);
3304 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
3305 DUMPREG(i, DISPC_OVL_BA0_UV);
3306 DUMPREG(i, DISPC_OVL_BA1_UV);
3307 DUMPREG(i, DISPC_OVL_FIR2);
3308 DUMPREG(i, DISPC_OVL_ACCU2_0);
3309 DUMPREG(i, DISPC_OVL_ACCU2_1);
3310 }
3311 if (dss_has_feature(FEAT_ATTR2))
3312 DUMPREG(i, DISPC_OVL_ATTRIBUTES2);
3313 if (dss_has_feature(FEAT_PRELOAD))
3314 DUMPREG(i, DISPC_OVL_PRELOAD);
3315 if (dss_has_feature(FEAT_MFLAG))
3316 DUMPREG(i, DISPC_OVL_MFLAG_THRESHOLD);
3317 }
3318
3319#undef DISPC_REG
3320#undef DUMPREG
3321
3322#define DISPC_REG(plane, name, i) name(plane, i)
3323#define DUMPREG(plane, name, i) \
3324 seq_printf(s, "%s_%d(%s)%*s %08x\n", #name, i, p_names[plane], \
3325 (int)(46 - strlen(#name) - strlen(p_names[plane])), " ", \
3326 dispc_read_reg(DISPC_REG(plane, name, i)))
3327
3328 /* Video pipeline coefficient registers */
3329
3330 /* start from OMAP_DSS_VIDEO1 */
3331 for (i = 1; i < dss_feat_get_num_ovls(); i++) {
3332 for (j = 0; j < 8; j++)
3333 DUMPREG(i, DISPC_OVL_FIR_COEF_H, j);
3334
3335 for (j = 0; j < 8; j++)
3336 DUMPREG(i, DISPC_OVL_FIR_COEF_HV, j);
3337
3338 for (j = 0; j < 5; j++)
3339 DUMPREG(i, DISPC_OVL_CONV_COEF, j);
3340
3341 if (dss_has_feature(FEAT_FIR_COEF_V)) {
3342 for (j = 0; j < 8; j++)
3343 DUMPREG(i, DISPC_OVL_FIR_COEF_V, j);
3344 }
3345
3346 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
3347 for (j = 0; j < 8; j++)
3348 DUMPREG(i, DISPC_OVL_FIR_COEF_H2, j);
3349
3350 for (j = 0; j < 8; j++)
3351 DUMPREG(i, DISPC_OVL_FIR_COEF_HV2, j);
3352
3353 for (j = 0; j < 8; j++)
3354 DUMPREG(i, DISPC_OVL_FIR_COEF_V2, j);
3355 }
3356 }
3357
3358 dispc_runtime_put();
3359
3360#undef DISPC_REG
3361#undef DUMPREG
3362}
3363
3364/* calculate clock rates using dividers in cinfo */
3365int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
3366 struct dispc_clock_info *cinfo)
3367{
3368 if (cinfo->lck_div > 255 || cinfo->lck_div == 0)
3369 return -EINVAL;
3370 if (cinfo->pck_div < 1 || cinfo->pck_div > 255)
3371 return -EINVAL;
3372
3373 cinfo->lck = dispc_fclk_rate / cinfo->lck_div;
3374 cinfo->pck = cinfo->lck / cinfo->pck_div;
3375
3376 return 0;
3377}
3378
3379bool dispc_div_calc(unsigned long dispc,
3380 unsigned long pck_min, unsigned long pck_max,
3381 dispc_div_calc_func func, void *data)
3382{
3383 int lckd, lckd_start, lckd_stop;
3384 int pckd, pckd_start, pckd_stop;
3385 unsigned long pck, lck;
3386 unsigned long lck_max;
3387 unsigned long pckd_hw_min, pckd_hw_max;
3388 unsigned min_fck_per_pck;
3389 unsigned long fck;
3390
3391#ifdef CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK
3392 min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
3393#else
3394 min_fck_per_pck = 0;
3395#endif
3396
3397 pckd_hw_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD);
3398 pckd_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD);
3399
3400 lck_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
3401
3402 pck_min = pck_min ? pck_min : 1;
3403 pck_max = pck_max ? pck_max : ULONG_MAX;
3404
3405 lckd_start = max(DIV_ROUND_UP(dispc, lck_max), 1ul);
3406 lckd_stop = min(dispc / pck_min, 255ul);
3407
3408 for (lckd = lckd_start; lckd <= lckd_stop; ++lckd) {
3409 lck = dispc / lckd;
3410
3411 pckd_start = max(DIV_ROUND_UP(lck, pck_max), pckd_hw_min);
3412 pckd_stop = min(lck / pck_min, pckd_hw_max);
3413
3414 for (pckd = pckd_start; pckd <= pckd_stop; ++pckd) {
3415 pck = lck / pckd;
3416
3417 /*
3418 * For OMAP2/3 the DISPC fclk is the same as LCD's logic
3419 * clock, which means we're configuring DISPC fclk here
3420 * also. Thus we need to use the calculated lck. For
3421 * OMAP4+ the DISPC fclk is a separate clock.
3422 */
3423 if (dss_has_feature(FEAT_CORE_CLK_DIV))
3424 fck = dispc_core_clk_rate();
3425 else
3426 fck = lck;
3427
3428 if (fck < pck * min_fck_per_pck)
3429 continue;
3430
3431 if (func(lckd, pckd, lck, pck, data))
3432 return true;
3433 }
3434 }
3435
3436 return false;
3437}
3438
3439void dispc_mgr_set_clock_div(enum omap_channel channel,
3440 const struct dispc_clock_info *cinfo)
3441{
3442 DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);
3443 DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div);
3444
3445 dispc_mgr_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div);
3446}
3447
3448int dispc_mgr_get_clock_div(enum omap_channel channel,
3449 struct dispc_clock_info *cinfo)
3450{
3451 unsigned long fck;
3452
3453 fck = dispc_fclk_rate();
3454
3455 cinfo->lck_div = REG_GET(DISPC_DIVISORo(channel), 23, 16);
3456 cinfo->pck_div = REG_GET(DISPC_DIVISORo(channel), 7, 0);
3457
3458 cinfo->lck = fck / cinfo->lck_div;
3459 cinfo->pck = cinfo->lck / cinfo->pck_div;
3460
3461 return 0;
3462}
3463
3464u32 dispc_read_irqstatus(void)
3465{
3466 return dispc_read_reg(DISPC_IRQSTATUS);
3467}
3468EXPORT_SYMBOL(dispc_read_irqstatus);
3469
3470void dispc_clear_irqstatus(u32 mask)
3471{
3472 dispc_write_reg(DISPC_IRQSTATUS, mask);
3473}
3474EXPORT_SYMBOL(dispc_clear_irqstatus);
3475
3476u32 dispc_read_irqenable(void)
3477{
3478 return dispc_read_reg(DISPC_IRQENABLE);
3479}
3480EXPORT_SYMBOL(dispc_read_irqenable);
3481
3482void dispc_write_irqenable(u32 mask)
3483{
3484 u32 old_mask = dispc_read_reg(DISPC_IRQENABLE);
3485
3486 /* clear the irqstatus for newly enabled irqs */
3487 dispc_clear_irqstatus((mask ^ old_mask) & mask);
3488
3489 dispc_write_reg(DISPC_IRQENABLE, mask);
3490}
3491EXPORT_SYMBOL(dispc_write_irqenable);
3492
3493void dispc_enable_sidle(void)
3494{
3495 REG_FLD_MOD(DISPC_SYSCONFIG, 2, 4, 3); /* SIDLEMODE: smart idle */
3496}
3497
3498void dispc_disable_sidle(void)
3499{
3500 REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */
3501}
3502
3503static void _omap_dispc_initial_config(void)
3504{
3505 u32 l;
3506
3507 /* Exclusively enable DISPC_CORE_CLK and set divider to 1 */
3508 if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
3509 l = dispc_read_reg(DISPC_DIVISOR);
3510 /* Use DISPC_DIVISOR.LCD, instead of DISPC_DIVISOR1.LCD */
3511 l = FLD_MOD(l, 1, 0, 0);
3512 l = FLD_MOD(l, 1, 23, 16);
3513 dispc_write_reg(DISPC_DIVISOR, l);
3514
3515 dispc.core_clk_rate = dispc_fclk_rate();
3516 }
3517
3518 /* FUNCGATED */
3519 if (dss_has_feature(FEAT_FUNCGATED))
3520 REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
3521
3522 dispc_setup_color_conv_coef();
3523
3524 dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
3525
3526 dispc_init_fifos();
3527
3528 dispc_configure_burst_sizes();
3529
3530 dispc_ovl_enable_zorder_planes();
3531
3532 if (dispc.feat->mstandby_workaround)
3533 REG_FLD_MOD(DISPC_MSTANDBY_CTRL, 1, 0, 0);
3534}
3535
3536static const struct dispc_features omap24xx_dispc_feats __initconst = {
3537 .sw_start = 5,
3538 .fp_start = 15,
3539 .bp_start = 27,
3540 .sw_max = 64,
3541 .vp_max = 255,
3542 .hp_max = 256,
3543 .mgr_width_start = 10,
3544 .mgr_height_start = 26,
3545 .mgr_width_max = 2048,
3546 .mgr_height_max = 2048,
3547 .max_lcd_pclk = 66500000,
3548 .calc_scaling = dispc_ovl_calc_scaling_24xx,
3549 .calc_core_clk = calc_core_clk_24xx,
3550 .num_fifos = 3,
3551 .no_framedone_tv = true,
3552 .set_max_preload = false,
3553};
3554
3555static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
3556 .sw_start = 5,
3557 .fp_start = 15,
3558 .bp_start = 27,
3559 .sw_max = 64,
3560 .vp_max = 255,
3561 .hp_max = 256,
3562 .mgr_width_start = 10,
3563 .mgr_height_start = 26,
3564 .mgr_width_max = 2048,
3565 .mgr_height_max = 2048,
3566 .max_lcd_pclk = 173000000,
3567 .max_tv_pclk = 59000000,
3568 .calc_scaling = dispc_ovl_calc_scaling_34xx,
3569 .calc_core_clk = calc_core_clk_34xx,
3570 .num_fifos = 3,
3571 .no_framedone_tv = true,
3572 .set_max_preload = false,
3573};
3574
3575static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
3576 .sw_start = 7,
3577 .fp_start = 19,
3578 .bp_start = 31,
3579 .sw_max = 256,
3580 .vp_max = 4095,
3581 .hp_max = 4096,
3582 .mgr_width_start = 10,
3583 .mgr_height_start = 26,
3584 .mgr_width_max = 2048,
3585 .mgr_height_max = 2048,
3586 .max_lcd_pclk = 173000000,
3587 .max_tv_pclk = 59000000,
3588 .calc_scaling = dispc_ovl_calc_scaling_34xx,
3589 .calc_core_clk = calc_core_clk_34xx,
3590 .num_fifos = 3,
3591 .no_framedone_tv = true,
3592 .set_max_preload = false,
3593};
3594
3595static const struct dispc_features omap44xx_dispc_feats __initconst = {
3596 .sw_start = 7,
3597 .fp_start = 19,
3598 .bp_start = 31,
3599 .sw_max = 256,
3600 .vp_max = 4095,
3601 .hp_max = 4096,
3602 .mgr_width_start = 10,
3603 .mgr_height_start = 26,
3604 .mgr_width_max = 2048,
3605 .mgr_height_max = 2048,
3606 .max_lcd_pclk = 170000000,
3607 .max_tv_pclk = 185625000,
3608 .calc_scaling = dispc_ovl_calc_scaling_44xx,
3609 .calc_core_clk = calc_core_clk_44xx,
3610 .num_fifos = 5,
3611 .gfx_fifo_workaround = true,
3612 .set_max_preload = true,
3613};
3614
3615static const struct dispc_features omap54xx_dispc_feats __initconst = {
3616 .sw_start = 7,
3617 .fp_start = 19,
3618 .bp_start = 31,
3619 .sw_max = 256,
3620 .vp_max = 4095,
3621 .hp_max = 4096,
3622 .mgr_width_start = 11,
3623 .mgr_height_start = 27,
3624 .mgr_width_max = 4096,
3625 .mgr_height_max = 4096,
3626 .max_lcd_pclk = 170000000,
3627 .max_tv_pclk = 186000000,
3628 .calc_scaling = dispc_ovl_calc_scaling_44xx,
3629 .calc_core_clk = calc_core_clk_44xx,
3630 .num_fifos = 5,
3631 .gfx_fifo_workaround = true,
3632 .mstandby_workaround = true,
3633 .set_max_preload = true,
3634};
3635
3636static int __init dispc_init_features(struct platform_device *pdev)
3637{
3638 const struct dispc_features *src;
3639 struct dispc_features *dst;
3640
3641 dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
3642 if (!dst) {
3643 dev_err(&pdev->dev, "Failed to allocate DISPC Features\n");
3644 return -ENOMEM;
3645 }
3646
3647 switch (omapdss_get_version()) {
3648 case OMAPDSS_VER_OMAP24xx:
3649 src = &omap24xx_dispc_feats;
3650 break;
3651
3652 case OMAPDSS_VER_OMAP34xx_ES1:
3653 src = &omap34xx_rev1_0_dispc_feats;
3654 break;
3655
3656 case OMAPDSS_VER_OMAP34xx_ES3:
3657 case OMAPDSS_VER_OMAP3630:
3658 case OMAPDSS_VER_AM35xx:
3659 src = &omap34xx_rev3_0_dispc_feats;
3660 break;
3661
3662 case OMAPDSS_VER_OMAP4430_ES1:
3663 case OMAPDSS_VER_OMAP4430_ES2:
3664 case OMAPDSS_VER_OMAP4:
3665 src = &omap44xx_dispc_feats;
3666 break;
3667
3668 case OMAPDSS_VER_OMAP5:
3669 src = &omap54xx_dispc_feats;
3670 break;
3671
3672 default:
3673 return -ENODEV;
3674 }
3675
3676 memcpy(dst, src, sizeof(*dst));
3677 dispc.feat = dst;
3678
3679 return 0;
3680}
3681
3682static irqreturn_t dispc_irq_handler(int irq, void *arg)
3683{
3684 if (!dispc.is_enabled)
3685 return IRQ_NONE;
3686
3687 return dispc.user_handler(irq, dispc.user_data);
3688}
3689
3690int dispc_request_irq(irq_handler_t handler, void *dev_id)
3691{
3692 int r;
3693
3694 if (dispc.user_handler != NULL)
3695 return -EBUSY;
3696
3697 dispc.user_handler = handler;
3698 dispc.user_data = dev_id;
3699
3700 /* ensure the dispc_irq_handler sees the values above */
3701 smp_wmb();
3702
3703 r = devm_request_irq(&dispc.pdev->dev, dispc.irq, dispc_irq_handler,
3704 IRQF_SHARED, "OMAP DISPC", &dispc);
3705 if (r) {
3706 dispc.user_handler = NULL;
3707 dispc.user_data = NULL;
3708 }
3709
3710 return r;
3711}
3712EXPORT_SYMBOL(dispc_request_irq);
3713
3714void dispc_free_irq(void *dev_id)
3715{
3716 devm_free_irq(&dispc.pdev->dev, dispc.irq, &dispc);
3717
3718 dispc.user_handler = NULL;
3719 dispc.user_data = NULL;
3720}
3721EXPORT_SYMBOL(dispc_free_irq);
3722
3723/* DISPC HW IP initialisation */
3724static int __init omap_dispchw_probe(struct platform_device *pdev)
3725{
3726 u32 rev;
3727 int r = 0;
3728 struct resource *dispc_mem;
3729
3730 dispc.pdev = pdev;
3731
3732 r = dispc_init_features(dispc.pdev);
3733 if (r)
3734 return r;
3735
3736 dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
3737 if (!dispc_mem) {
3738 DSSERR("can't get IORESOURCE_MEM DISPC\n");
3739 return -EINVAL;
3740 }
3741
3742 dispc.base = devm_ioremap(&pdev->dev, dispc_mem->start,
3743 resource_size(dispc_mem));
3744 if (!dispc.base) {
3745 DSSERR("can't ioremap DISPC\n");
3746 return -ENOMEM;
3747 }
3748
3749 dispc.irq = platform_get_irq(dispc.pdev, 0);
3750 if (dispc.irq < 0) {
3751 DSSERR("platform_get_irq failed\n");
3752 return -ENODEV;
3753 }
3754
3755 pm_runtime_enable(&pdev->dev);
3756
3757 r = dispc_runtime_get();
3758 if (r)
3759 goto err_runtime_get;
3760
3761 _omap_dispc_initial_config();
3762
3763 rev = dispc_read_reg(DISPC_REVISION);
3764 dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
3765 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
3766
3767 dispc_runtime_put();
3768
3769 dss_init_overlay_managers();
3770
3771 dss_debugfs_create_file("dispc", dispc_dump_regs);
3772
3773 return 0;
3774
3775err_runtime_get:
3776 pm_runtime_disable(&pdev->dev);
3777 return r;
3778}
3779
3780static int __exit omap_dispchw_remove(struct platform_device *pdev)
3781{
3782 pm_runtime_disable(&pdev->dev);
3783
3784 dss_uninit_overlay_managers();
3785
3786 return 0;
3787}
3788
3789static int dispc_runtime_suspend(struct device *dev)
3790{
3791 dispc.is_enabled = false;
3792 /* ensure the dispc_irq_handler sees the is_enabled value */
3793 smp_wmb();
3794 /* wait for current handler to finish before turning the DISPC off */
3795 synchronize_irq(dispc.irq);
3796
3797 dispc_save_context();
3798
3799 return 0;
3800}
3801
3802static int dispc_runtime_resume(struct device *dev)
3803{
3804 /*
3805 * The reset value for load mode is 0 (OMAP_DSS_LOAD_CLUT_AND_FRAME)
3806 * but we always initialize it to 2 (OMAP_DSS_LOAD_FRAME_ONLY) in
3807 * _omap_dispc_initial_config(). We can thus use it to detect if
3808 * we have lost register context.
3809 */
3810 if (REG_GET(DISPC_CONFIG, 2, 1) != OMAP_DSS_LOAD_FRAME_ONLY) {
3811 _omap_dispc_initial_config();
3812
3813 dispc_restore_context();
3814 }
3815
3816 dispc.is_enabled = true;
3817 /* ensure the dispc_irq_handler sees the is_enabled value */
3818 smp_wmb();
3819
3820 return 0;
3821}
3822
3823static const struct dev_pm_ops dispc_pm_ops = {
3824 .runtime_suspend = dispc_runtime_suspend,
3825 .runtime_resume = dispc_runtime_resume,
3826};
3827
3828static const struct of_device_id dispc_of_match[] = {
3829 { .compatible = "ti,omap2-dispc", },
3830 { .compatible = "ti,omap3-dispc", },
3831 { .compatible = "ti,omap4-dispc", },
3832 {},
3833};
3834
3835static struct platform_driver omap_dispchw_driver = {
3836 .remove = __exit_p(omap_dispchw_remove),
3837 .driver = {
3838 .name = "omapdss_dispc",
3839 .owner = THIS_MODULE,
3840 .pm = &dispc_pm_ops,
3841 .of_match_table = dispc_of_match,
3842 },
3843};
3844
3845int __init dispc_init_platform_driver(void)
3846{
3847 return platform_driver_probe(&omap_dispchw_driver, omap_dispchw_probe);
3848}
3849
3850void __exit dispc_uninit_platform_driver(void)
3851{
3852 platform_driver_unregister(&omap_dispchw_driver);
3853}
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h
deleted file mode 100644
index 78edb449c763..000000000000
--- a/drivers/video/omap2/dss/dispc.h
+++ /dev/null
@@ -1,917 +0,0 @@
1/*
2 * linux/drivers/video/omap2/dss/dispc.h
3 *
4 * Copyright (C) 2011 Texas Instruments
5 * Author: Archit Taneja <archit@ti.com>
6 *
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 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#ifndef __OMAP2_DISPC_REG_H
22#define __OMAP2_DISPC_REG_H
23
24/* DISPC common registers */
25#define DISPC_REVISION 0x0000
26#define DISPC_SYSCONFIG 0x0010
27#define DISPC_SYSSTATUS 0x0014
28#define DISPC_IRQSTATUS 0x0018
29#define DISPC_IRQENABLE 0x001C
30#define DISPC_CONTROL 0x0040
31#define DISPC_CONFIG 0x0044
32#define DISPC_CAPABLE 0x0048
33#define DISPC_LINE_STATUS 0x005C
34#define DISPC_LINE_NUMBER 0x0060
35#define DISPC_GLOBAL_ALPHA 0x0074
36#define DISPC_CONTROL2 0x0238
37#define DISPC_CONFIG2 0x0620
38#define DISPC_DIVISOR 0x0804
39#define DISPC_GLOBAL_BUFFER 0x0800
40#define DISPC_CONTROL3 0x0848
41#define DISPC_CONFIG3 0x084C
42#define DISPC_MSTANDBY_CTRL 0x0858
43#define DISPC_GLOBAL_MFLAG_ATTRIBUTE 0x085C
44
45/* DISPC overlay registers */
46#define DISPC_OVL_BA0(n) (DISPC_OVL_BASE(n) + \
47 DISPC_BA0_OFFSET(n))
48#define DISPC_OVL_BA1(n) (DISPC_OVL_BASE(n) + \
49 DISPC_BA1_OFFSET(n))
50#define DISPC_OVL_BA0_UV(n) (DISPC_OVL_BASE(n) + \
51 DISPC_BA0_UV_OFFSET(n))
52#define DISPC_OVL_BA1_UV(n) (DISPC_OVL_BASE(n) + \
53 DISPC_BA1_UV_OFFSET(n))
54#define DISPC_OVL_POSITION(n) (DISPC_OVL_BASE(n) + \
55 DISPC_POS_OFFSET(n))
56#define DISPC_OVL_SIZE(n) (DISPC_OVL_BASE(n) + \
57 DISPC_SIZE_OFFSET(n))
58#define DISPC_OVL_ATTRIBUTES(n) (DISPC_OVL_BASE(n) + \
59 DISPC_ATTR_OFFSET(n))
60#define DISPC_OVL_ATTRIBUTES2(n) (DISPC_OVL_BASE(n) + \
61 DISPC_ATTR2_OFFSET(n))
62#define DISPC_OVL_FIFO_THRESHOLD(n) (DISPC_OVL_BASE(n) + \
63 DISPC_FIFO_THRESH_OFFSET(n))
64#define DISPC_OVL_FIFO_SIZE_STATUS(n) (DISPC_OVL_BASE(n) + \
65 DISPC_FIFO_SIZE_STATUS_OFFSET(n))
66#define DISPC_OVL_ROW_INC(n) (DISPC_OVL_BASE(n) + \
67 DISPC_ROW_INC_OFFSET(n))
68#define DISPC_OVL_PIXEL_INC(n) (DISPC_OVL_BASE(n) + \
69 DISPC_PIX_INC_OFFSET(n))
70#define DISPC_OVL_WINDOW_SKIP(n) (DISPC_OVL_BASE(n) + \
71 DISPC_WINDOW_SKIP_OFFSET(n))
72#define DISPC_OVL_TABLE_BA(n) (DISPC_OVL_BASE(n) + \
73 DISPC_TABLE_BA_OFFSET(n))
74#define DISPC_OVL_FIR(n) (DISPC_OVL_BASE(n) + \
75 DISPC_FIR_OFFSET(n))
76#define DISPC_OVL_FIR2(n) (DISPC_OVL_BASE(n) + \
77 DISPC_FIR2_OFFSET(n))
78#define DISPC_OVL_PICTURE_SIZE(n) (DISPC_OVL_BASE(n) + \
79 DISPC_PIC_SIZE_OFFSET(n))
80#define DISPC_OVL_ACCU0(n) (DISPC_OVL_BASE(n) + \
81 DISPC_ACCU0_OFFSET(n))
82#define DISPC_OVL_ACCU1(n) (DISPC_OVL_BASE(n) + \
83 DISPC_ACCU1_OFFSET(n))
84#define DISPC_OVL_ACCU2_0(n) (DISPC_OVL_BASE(n) + \
85 DISPC_ACCU2_0_OFFSET(n))
86#define DISPC_OVL_ACCU2_1(n) (DISPC_OVL_BASE(n) + \
87 DISPC_ACCU2_1_OFFSET(n))
88#define DISPC_OVL_FIR_COEF_H(n, i) (DISPC_OVL_BASE(n) + \
89 DISPC_FIR_COEF_H_OFFSET(n, i))
90#define DISPC_OVL_FIR_COEF_HV(n, i) (DISPC_OVL_BASE(n) + \
91 DISPC_FIR_COEF_HV_OFFSET(n, i))
92#define DISPC_OVL_FIR_COEF_H2(n, i) (DISPC_OVL_BASE(n) + \
93 DISPC_FIR_COEF_H2_OFFSET(n, i))
94#define DISPC_OVL_FIR_COEF_HV2(n, i) (DISPC_OVL_BASE(n) + \
95 DISPC_FIR_COEF_HV2_OFFSET(n, i))
96#define DISPC_OVL_CONV_COEF(n, i) (DISPC_OVL_BASE(n) + \
97 DISPC_CONV_COEF_OFFSET(n, i))
98#define DISPC_OVL_FIR_COEF_V(n, i) (DISPC_OVL_BASE(n) + \
99 DISPC_FIR_COEF_V_OFFSET(n, i))
100#define DISPC_OVL_FIR_COEF_V2(n, i) (DISPC_OVL_BASE(n) + \
101 DISPC_FIR_COEF_V2_OFFSET(n, i))
102#define DISPC_OVL_PRELOAD(n) (DISPC_OVL_BASE(n) + \
103 DISPC_PRELOAD_OFFSET(n))
104#define DISPC_OVL_MFLAG_THRESHOLD(n) (DISPC_OVL_BASE(n) + \
105 DISPC_MFLAG_THRESHOLD_OFFSET(n))
106
107/* DISPC up/downsampling FIR filter coefficient structure */
108struct dispc_coef {
109 s8 hc4_vc22;
110 s8 hc3_vc2;
111 u8 hc2_vc1;
112 s8 hc1_vc0;
113 s8 hc0_vc00;
114};
115
116const struct dispc_coef *dispc_ovl_get_scale_coef(int inc, int five_taps);
117
118/* DISPC manager/channel specific registers */
119static inline u16 DISPC_DEFAULT_COLOR(enum omap_channel channel)
120{
121 switch (channel) {
122 case OMAP_DSS_CHANNEL_LCD:
123 return 0x004C;
124 case OMAP_DSS_CHANNEL_DIGIT:
125 return 0x0050;
126 case OMAP_DSS_CHANNEL_LCD2:
127 return 0x03AC;
128 case OMAP_DSS_CHANNEL_LCD3:
129 return 0x0814;
130 default:
131 BUG();
132 return 0;
133 }
134}
135
136static inline u16 DISPC_TRANS_COLOR(enum omap_channel channel)
137{
138 switch (channel) {
139 case OMAP_DSS_CHANNEL_LCD:
140 return 0x0054;
141 case OMAP_DSS_CHANNEL_DIGIT:
142 return 0x0058;
143 case OMAP_DSS_CHANNEL_LCD2:
144 return 0x03B0;
145 case OMAP_DSS_CHANNEL_LCD3:
146 return 0x0818;
147 default:
148 BUG();
149 return 0;
150 }
151}
152
153static inline u16 DISPC_TIMING_H(enum omap_channel channel)
154{
155 switch (channel) {
156 case OMAP_DSS_CHANNEL_LCD:
157 return 0x0064;
158 case OMAP_DSS_CHANNEL_DIGIT:
159 BUG();
160 return 0;
161 case OMAP_DSS_CHANNEL_LCD2:
162 return 0x0400;
163 case OMAP_DSS_CHANNEL_LCD3:
164 return 0x0840;
165 default:
166 BUG();
167 return 0;
168 }
169}
170
171static inline u16 DISPC_TIMING_V(enum omap_channel channel)
172{
173 switch (channel) {
174 case OMAP_DSS_CHANNEL_LCD:
175 return 0x0068;
176 case OMAP_DSS_CHANNEL_DIGIT:
177 BUG();
178 return 0;
179 case OMAP_DSS_CHANNEL_LCD2:
180 return 0x0404;
181 case OMAP_DSS_CHANNEL_LCD3:
182 return 0x0844;
183 default:
184 BUG();
185 return 0;
186 }
187}
188
189static inline u16 DISPC_POL_FREQ(enum omap_channel channel)
190{
191 switch (channel) {
192 case OMAP_DSS_CHANNEL_LCD:
193 return 0x006C;
194 case OMAP_DSS_CHANNEL_DIGIT:
195 BUG();
196 return 0;
197 case OMAP_DSS_CHANNEL_LCD2:
198 return 0x0408;
199 case OMAP_DSS_CHANNEL_LCD3:
200 return 0x083C;
201 default:
202 BUG();
203 return 0;
204 }
205}
206
207static inline u16 DISPC_DIVISORo(enum omap_channel channel)
208{
209 switch (channel) {
210 case OMAP_DSS_CHANNEL_LCD:
211 return 0x0070;
212 case OMAP_DSS_CHANNEL_DIGIT:
213 BUG();
214 return 0;
215 case OMAP_DSS_CHANNEL_LCD2:
216 return 0x040C;
217 case OMAP_DSS_CHANNEL_LCD3:
218 return 0x0838;
219 default:
220 BUG();
221 return 0;
222 }
223}
224
225/* Named as DISPC_SIZE_LCD, DISPC_SIZE_DIGIT and DISPC_SIZE_LCD2 in TRM */
226static inline u16 DISPC_SIZE_MGR(enum omap_channel channel)
227{
228 switch (channel) {
229 case OMAP_DSS_CHANNEL_LCD:
230 return 0x007C;
231 case OMAP_DSS_CHANNEL_DIGIT:
232 return 0x0078;
233 case OMAP_DSS_CHANNEL_LCD2:
234 return 0x03CC;
235 case OMAP_DSS_CHANNEL_LCD3:
236 return 0x0834;
237 default:
238 BUG();
239 return 0;
240 }
241}
242
243static inline u16 DISPC_DATA_CYCLE1(enum omap_channel channel)
244{
245 switch (channel) {
246 case OMAP_DSS_CHANNEL_LCD:
247 return 0x01D4;
248 case OMAP_DSS_CHANNEL_DIGIT:
249 BUG();
250 return 0;
251 case OMAP_DSS_CHANNEL_LCD2:
252 return 0x03C0;
253 case OMAP_DSS_CHANNEL_LCD3:
254 return 0x0828;
255 default:
256 BUG();
257 return 0;
258 }
259}
260
261static inline u16 DISPC_DATA_CYCLE2(enum omap_channel channel)
262{
263 switch (channel) {
264 case OMAP_DSS_CHANNEL_LCD:
265 return 0x01D8;
266 case OMAP_DSS_CHANNEL_DIGIT:
267 BUG();
268 return 0;
269 case OMAP_DSS_CHANNEL_LCD2:
270 return 0x03C4;
271 case OMAP_DSS_CHANNEL_LCD3:
272 return 0x082C;
273 default:
274 BUG();
275 return 0;
276 }
277}
278
279static inline u16 DISPC_DATA_CYCLE3(enum omap_channel channel)
280{
281 switch (channel) {
282 case OMAP_DSS_CHANNEL_LCD:
283 return 0x01DC;
284 case OMAP_DSS_CHANNEL_DIGIT:
285 BUG();
286 return 0;
287 case OMAP_DSS_CHANNEL_LCD2:
288 return 0x03C8;
289 case OMAP_DSS_CHANNEL_LCD3:
290 return 0x0830;
291 default:
292 BUG();
293 return 0;
294 }
295}
296
297static inline u16 DISPC_CPR_COEF_R(enum omap_channel channel)
298{
299 switch (channel) {
300 case OMAP_DSS_CHANNEL_LCD:
301 return 0x0220;
302 case OMAP_DSS_CHANNEL_DIGIT:
303 BUG();
304 return 0;
305 case OMAP_DSS_CHANNEL_LCD2:
306 return 0x03BC;
307 case OMAP_DSS_CHANNEL_LCD3:
308 return 0x0824;
309 default:
310 BUG();
311 return 0;
312 }
313}
314
315static inline u16 DISPC_CPR_COEF_G(enum omap_channel channel)
316{
317 switch (channel) {
318 case OMAP_DSS_CHANNEL_LCD:
319 return 0x0224;
320 case OMAP_DSS_CHANNEL_DIGIT:
321 BUG();
322 return 0;
323 case OMAP_DSS_CHANNEL_LCD2:
324 return 0x03B8;
325 case OMAP_DSS_CHANNEL_LCD3:
326 return 0x0820;
327 default:
328 BUG();
329 return 0;
330 }
331}
332
333static inline u16 DISPC_CPR_COEF_B(enum omap_channel channel)
334{
335 switch (channel) {
336 case OMAP_DSS_CHANNEL_LCD:
337 return 0x0228;
338 case OMAP_DSS_CHANNEL_DIGIT:
339 BUG();
340 return 0;
341 case OMAP_DSS_CHANNEL_LCD2:
342 return 0x03B4;
343 case OMAP_DSS_CHANNEL_LCD3:
344 return 0x081C;
345 default:
346 BUG();
347 return 0;
348 }
349}
350
351/* DISPC overlay register base addresses */
352static inline u16 DISPC_OVL_BASE(enum omap_plane plane)
353{
354 switch (plane) {
355 case OMAP_DSS_GFX:
356 return 0x0080;
357 case OMAP_DSS_VIDEO1:
358 return 0x00BC;
359 case OMAP_DSS_VIDEO2:
360 return 0x014C;
361 case OMAP_DSS_VIDEO3:
362 return 0x0300;
363 case OMAP_DSS_WB:
364 return 0x0500;
365 default:
366 BUG();
367 return 0;
368 }
369}
370
371/* DISPC overlay register offsets */
372static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane)
373{
374 switch (plane) {
375 case OMAP_DSS_GFX:
376 case OMAP_DSS_VIDEO1:
377 case OMAP_DSS_VIDEO2:
378 return 0x0000;
379 case OMAP_DSS_VIDEO3:
380 case OMAP_DSS_WB:
381 return 0x0008;
382 default:
383 BUG();
384 return 0;
385 }
386}
387
388static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane)
389{
390 switch (plane) {
391 case OMAP_DSS_GFX:
392 case OMAP_DSS_VIDEO1:
393 case OMAP_DSS_VIDEO2:
394 return 0x0004;
395 case OMAP_DSS_VIDEO3:
396 case OMAP_DSS_WB:
397 return 0x000C;
398 default:
399 BUG();
400 return 0;
401 }
402}
403
404static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)
405{
406 switch (plane) {
407 case OMAP_DSS_GFX:
408 BUG();
409 return 0;
410 case OMAP_DSS_VIDEO1:
411 return 0x0544;
412 case OMAP_DSS_VIDEO2:
413 return 0x04BC;
414 case OMAP_DSS_VIDEO3:
415 return 0x0310;
416 case OMAP_DSS_WB:
417 return 0x0118;
418 default:
419 BUG();
420 return 0;
421 }
422}
423
424static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)
425{
426 switch (plane) {
427 case OMAP_DSS_GFX:
428 BUG();
429 return 0;
430 case OMAP_DSS_VIDEO1:
431 return 0x0548;
432 case OMAP_DSS_VIDEO2:
433 return 0x04C0;
434 case OMAP_DSS_VIDEO3:
435 return 0x0314;
436 case OMAP_DSS_WB:
437 return 0x011C;
438 default:
439 BUG();
440 return 0;
441 }
442}
443
444static inline u16 DISPC_POS_OFFSET(enum omap_plane plane)
445{
446 switch (plane) {
447 case OMAP_DSS_GFX:
448 case OMAP_DSS_VIDEO1:
449 case OMAP_DSS_VIDEO2:
450 return 0x0008;
451 case OMAP_DSS_VIDEO3:
452 return 0x009C;
453 default:
454 BUG();
455 return 0;
456 }
457}
458
459static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane)
460{
461 switch (plane) {
462 case OMAP_DSS_GFX:
463 case OMAP_DSS_VIDEO1:
464 case OMAP_DSS_VIDEO2:
465 return 0x000C;
466 case OMAP_DSS_VIDEO3:
467 case OMAP_DSS_WB:
468 return 0x00A8;
469 default:
470 BUG();
471 return 0;
472 }
473}
474
475static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane)
476{
477 switch (plane) {
478 case OMAP_DSS_GFX:
479 return 0x0020;
480 case OMAP_DSS_VIDEO1:
481 case OMAP_DSS_VIDEO2:
482 return 0x0010;
483 case OMAP_DSS_VIDEO3:
484 case OMAP_DSS_WB:
485 return 0x0070;
486 default:
487 BUG();
488 return 0;
489 }
490}
491
492static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)
493{
494 switch (plane) {
495 case OMAP_DSS_GFX:
496 BUG();
497 return 0;
498 case OMAP_DSS_VIDEO1:
499 return 0x0568;
500 case OMAP_DSS_VIDEO2:
501 return 0x04DC;
502 case OMAP_DSS_VIDEO3:
503 return 0x032C;
504 case OMAP_DSS_WB:
505 return 0x0310;
506 default:
507 BUG();
508 return 0;
509 }
510}
511
512static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane)
513{
514 switch (plane) {
515 case OMAP_DSS_GFX:
516 return 0x0024;
517 case OMAP_DSS_VIDEO1:
518 case OMAP_DSS_VIDEO2:
519 return 0x0014;
520 case OMAP_DSS_VIDEO3:
521 case OMAP_DSS_WB:
522 return 0x008C;
523 default:
524 BUG();
525 return 0;
526 }
527}
528
529static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane)
530{
531 switch (plane) {
532 case OMAP_DSS_GFX:
533 return 0x0028;
534 case OMAP_DSS_VIDEO1:
535 case OMAP_DSS_VIDEO2:
536 return 0x0018;
537 case OMAP_DSS_VIDEO3:
538 case OMAP_DSS_WB:
539 return 0x0088;
540 default:
541 BUG();
542 return 0;
543 }
544}
545
546static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane)
547{
548 switch (plane) {
549 case OMAP_DSS_GFX:
550 return 0x002C;
551 case OMAP_DSS_VIDEO1:
552 case OMAP_DSS_VIDEO2:
553 return 0x001C;
554 case OMAP_DSS_VIDEO3:
555 case OMAP_DSS_WB:
556 return 0x00A4;
557 default:
558 BUG();
559 return 0;
560 }
561}
562
563static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane)
564{
565 switch (plane) {
566 case OMAP_DSS_GFX:
567 return 0x0030;
568 case OMAP_DSS_VIDEO1:
569 case OMAP_DSS_VIDEO2:
570 return 0x0020;
571 case OMAP_DSS_VIDEO3:
572 case OMAP_DSS_WB:
573 return 0x0098;
574 default:
575 BUG();
576 return 0;
577 }
578}
579
580static inline u16 DISPC_WINDOW_SKIP_OFFSET(enum omap_plane plane)
581{
582 switch (plane) {
583 case OMAP_DSS_GFX:
584 return 0x0034;
585 case OMAP_DSS_VIDEO1:
586 case OMAP_DSS_VIDEO2:
587 case OMAP_DSS_VIDEO3:
588 BUG();
589 return 0;
590 default:
591 BUG();
592 return 0;
593 }
594}
595
596static inline u16 DISPC_TABLE_BA_OFFSET(enum omap_plane plane)
597{
598 switch (plane) {
599 case OMAP_DSS_GFX:
600 return 0x0038;
601 case OMAP_DSS_VIDEO1:
602 case OMAP_DSS_VIDEO2:
603 case OMAP_DSS_VIDEO3:
604 BUG();
605 return 0;
606 default:
607 BUG();
608 return 0;
609 }
610}
611
612static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)
613{
614 switch (plane) {
615 case OMAP_DSS_GFX:
616 BUG();
617 return 0;
618 case OMAP_DSS_VIDEO1:
619 case OMAP_DSS_VIDEO2:
620 return 0x0024;
621 case OMAP_DSS_VIDEO3:
622 case OMAP_DSS_WB:
623 return 0x0090;
624 default:
625 BUG();
626 return 0;
627 }
628}
629
630static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)
631{
632 switch (plane) {
633 case OMAP_DSS_GFX:
634 BUG();
635 return 0;
636 case OMAP_DSS_VIDEO1:
637 return 0x0580;
638 case OMAP_DSS_VIDEO2:
639 return 0x055C;
640 case OMAP_DSS_VIDEO3:
641 return 0x0424;
642 case OMAP_DSS_WB:
643 return 0x290;
644 default:
645 BUG();
646 return 0;
647 }
648}
649
650static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)
651{
652 switch (plane) {
653 case OMAP_DSS_GFX:
654 BUG();
655 return 0;
656 case OMAP_DSS_VIDEO1:
657 case OMAP_DSS_VIDEO2:
658 return 0x0028;
659 case OMAP_DSS_VIDEO3:
660 case OMAP_DSS_WB:
661 return 0x0094;
662 default:
663 BUG();
664 return 0;
665 }
666}
667
668
669static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)
670{
671 switch (plane) {
672 case OMAP_DSS_GFX:
673 BUG();
674 return 0;
675 case OMAP_DSS_VIDEO1:
676 case OMAP_DSS_VIDEO2:
677 return 0x002C;
678 case OMAP_DSS_VIDEO3:
679 case OMAP_DSS_WB:
680 return 0x0000;
681 default:
682 BUG();
683 return 0;
684 }
685}
686
687static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)
688{
689 switch (plane) {
690 case OMAP_DSS_GFX:
691 BUG();
692 return 0;
693 case OMAP_DSS_VIDEO1:
694 return 0x0584;
695 case OMAP_DSS_VIDEO2:
696 return 0x0560;
697 case OMAP_DSS_VIDEO3:
698 return 0x0428;
699 case OMAP_DSS_WB:
700 return 0x0294;
701 default:
702 BUG();
703 return 0;
704 }
705}
706
707static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)
708{
709 switch (plane) {
710 case OMAP_DSS_GFX:
711 BUG();
712 return 0;
713 case OMAP_DSS_VIDEO1:
714 case OMAP_DSS_VIDEO2:
715 return 0x0030;
716 case OMAP_DSS_VIDEO3:
717 case OMAP_DSS_WB:
718 return 0x0004;
719 default:
720 BUG();
721 return 0;
722 }
723}
724
725static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)
726{
727 switch (plane) {
728 case OMAP_DSS_GFX:
729 BUG();
730 return 0;
731 case OMAP_DSS_VIDEO1:
732 return 0x0588;
733 case OMAP_DSS_VIDEO2:
734 return 0x0564;
735 case OMAP_DSS_VIDEO3:
736 return 0x042C;
737 case OMAP_DSS_WB:
738 return 0x0298;
739 default:
740 BUG();
741 return 0;
742 }
743}
744
745/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
746static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)
747{
748 switch (plane) {
749 case OMAP_DSS_GFX:
750 BUG();
751 return 0;
752 case OMAP_DSS_VIDEO1:
753 case OMAP_DSS_VIDEO2:
754 return 0x0034 + i * 0x8;
755 case OMAP_DSS_VIDEO3:
756 case OMAP_DSS_WB:
757 return 0x0010 + i * 0x8;
758 default:
759 BUG();
760 return 0;
761 }
762}
763
764/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
765static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)
766{
767 switch (plane) {
768 case OMAP_DSS_GFX:
769 BUG();
770 return 0;
771 case OMAP_DSS_VIDEO1:
772 return 0x058C + i * 0x8;
773 case OMAP_DSS_VIDEO2:
774 return 0x0568 + i * 0x8;
775 case OMAP_DSS_VIDEO3:
776 return 0x0430 + i * 0x8;
777 case OMAP_DSS_WB:
778 return 0x02A0 + i * 0x8;
779 default:
780 BUG();
781 return 0;
782 }
783}
784
785/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
786static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)
787{
788 switch (plane) {
789 case OMAP_DSS_GFX:
790 BUG();
791 return 0;
792 case OMAP_DSS_VIDEO1:
793 case OMAP_DSS_VIDEO2:
794 return 0x0038 + i * 0x8;
795 case OMAP_DSS_VIDEO3:
796 case OMAP_DSS_WB:
797 return 0x0014 + i * 0x8;
798 default:
799 BUG();
800 return 0;
801 }
802}
803
804/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
805static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)
806{
807 switch (plane) {
808 case OMAP_DSS_GFX:
809 BUG();
810 return 0;
811 case OMAP_DSS_VIDEO1:
812 return 0x0590 + i * 8;
813 case OMAP_DSS_VIDEO2:
814 return 0x056C + i * 0x8;
815 case OMAP_DSS_VIDEO3:
816 return 0x0434 + i * 0x8;
817 case OMAP_DSS_WB:
818 return 0x02A4 + i * 0x8;
819 default:
820 BUG();
821 return 0;
822 }
823}
824
825/* coef index i = {0, 1, 2, 3, 4,} */
826static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i)
827{
828 switch (plane) {
829 case OMAP_DSS_GFX:
830 BUG();
831 return 0;
832 case OMAP_DSS_VIDEO1:
833 case OMAP_DSS_VIDEO2:
834 case OMAP_DSS_VIDEO3:
835 case OMAP_DSS_WB:
836 return 0x0074 + i * 0x4;
837 default:
838 BUG();
839 return 0;
840 }
841}
842
843/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
844static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)
845{
846 switch (plane) {
847 case OMAP_DSS_GFX:
848 BUG();
849 return 0;
850 case OMAP_DSS_VIDEO1:
851 return 0x0124 + i * 0x4;
852 case OMAP_DSS_VIDEO2:
853 return 0x00B4 + i * 0x4;
854 case OMAP_DSS_VIDEO3:
855 case OMAP_DSS_WB:
856 return 0x0050 + i * 0x4;
857 default:
858 BUG();
859 return 0;
860 }
861}
862
863/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
864static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)
865{
866 switch (plane) {
867 case OMAP_DSS_GFX:
868 BUG();
869 return 0;
870 case OMAP_DSS_VIDEO1:
871 return 0x05CC + i * 0x4;
872 case OMAP_DSS_VIDEO2:
873 return 0x05A8 + i * 0x4;
874 case OMAP_DSS_VIDEO3:
875 return 0x0470 + i * 0x4;
876 case OMAP_DSS_WB:
877 return 0x02E0 + i * 0x4;
878 default:
879 BUG();
880 return 0;
881 }
882}
883
884static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane)
885{
886 switch (plane) {
887 case OMAP_DSS_GFX:
888 return 0x01AC;
889 case OMAP_DSS_VIDEO1:
890 return 0x0174;
891 case OMAP_DSS_VIDEO2:
892 return 0x00E8;
893 case OMAP_DSS_VIDEO3:
894 return 0x00A0;
895 default:
896 BUG();
897 return 0;
898 }
899}
900
901static inline u16 DISPC_MFLAG_THRESHOLD_OFFSET(enum omap_plane plane)
902{
903 switch (plane) {
904 case OMAP_DSS_GFX:
905 return 0x0860;
906 case OMAP_DSS_VIDEO1:
907 return 0x0864;
908 case OMAP_DSS_VIDEO2:
909 return 0x0868;
910 case OMAP_DSS_VIDEO3:
911 return 0x086c;
912 default:
913 BUG();
914 return 0;
915 }
916}
917#endif
diff --git a/drivers/video/omap2/dss/dispc_coefs.c b/drivers/video/omap2/dss/dispc_coefs.c
deleted file mode 100644
index 038c15b04215..000000000000
--- a/drivers/video/omap2/dss/dispc_coefs.c
+++ /dev/null
@@ -1,325 +0,0 @@
1/*
2 * linux/drivers/video/omap2/dss/dispc_coefs.c
3 *
4 * Copyright (C) 2011 Texas Instruments
5 * Author: Chandrabhanu Mahapatra <cmahapatra@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 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/kernel.h>
21#include <video/omapdss.h>
22
23#include "dispc.h"
24
25static const struct dispc_coef coef3_M8[8] = {
26 { 0, 0, 128, 0, 0 },
27 { 0, -4, 123, 9, 0 },
28 { 0, -4, 108, 24, 0 },
29 { 0, -2, 87, 43, 0 },
30 { 0, 64, 64, 0, 0 },
31 { 0, 43, 87, -2, 0 },
32 { 0, 24, 108, -4, 0 },
33 { 0, 9, 123, -4, 0 },
34};
35
36static const struct dispc_coef coef3_M9[8] = {
37 { 0, 6, 116, 6, 0 },
38 { 0, 0, 112, 16, 0 },
39 { 0, -2, 100, 30, 0 },
40 { 0, -2, 83, 47, 0 },
41 { 0, 64, 64, 0, 0 },
42 { 0, 47, 83, -2, 0 },
43 { 0, 30, 100, -2, 0 },
44 { 0, 16, 112, 0, 0 },
45};
46
47static const struct dispc_coef coef3_M10[8] = {
48 { 0, 10, 108, 10, 0 },
49 { 0, 3, 104, 21, 0 },
50 { 0, 0, 94, 34, 0 },
51 { 0, -1, 80, 49, 0 },
52 { 0, 64, 64, 0, 0 },
53 { 0, 49, 80, -1, 0 },
54 { 0, 34, 94, 0, 0 },
55 { 0, 21, 104, 3, 0 },
56};
57
58static const struct dispc_coef coef3_M11[8] = {
59 { 0, 14, 100, 14, 0 },
60 { 0, 6, 98, 24, 0 },
61 { 0, 2, 90, 36, 0 },
62 { 0, 0, 78, 50, 0 },
63 { 0, 64, 64, 0, 0 },
64 { 0, 50, 78, 0, 0 },
65 { 0, 36, 90, 2, 0 },
66 { 0, 24, 98, 6, 0 },
67};
68
69static const struct dispc_coef coef3_M12[8] = {
70 { 0, 16, 96, 16, 0 },
71 { 0, 9, 93, 26, 0 },
72 { 0, 4, 86, 38, 0 },
73 { 0, 1, 76, 51, 0 },
74 { 0, 64, 64, 0, 0 },
75 { 0, 51, 76, 1, 0 },
76 { 0, 38, 86, 4, 0 },
77 { 0, 26, 93, 9, 0 },
78};
79
80static const struct dispc_coef coef3_M13[8] = {
81 { 0, 18, 92, 18, 0 },
82 { 0, 10, 90, 28, 0 },
83 { 0, 5, 83, 40, 0 },
84 { 0, 1, 75, 52, 0 },
85 { 0, 64, 64, 0, 0 },
86 { 0, 52, 75, 1, 0 },
87 { 0, 40, 83, 5, 0 },
88 { 0, 28, 90, 10, 0 },
89};
90
91static const struct dispc_coef coef3_M14[8] = {
92 { 0, 20, 88, 20, 0 },
93 { 0, 12, 86, 30, 0 },
94 { 0, 6, 81, 41, 0 },
95 { 0, 2, 74, 52, 0 },
96 { 0, 64, 64, 0, 0 },
97 { 0, 52, 74, 2, 0 },
98 { 0, 41, 81, 6, 0 },
99 { 0, 30, 86, 12, 0 },
100};
101
102static const struct dispc_coef coef3_M16[8] = {
103 { 0, 22, 84, 22, 0 },
104 { 0, 14, 82, 32, 0 },
105 { 0, 8, 78, 42, 0 },
106 { 0, 3, 72, 53, 0 },
107 { 0, 64, 64, 0, 0 },
108 { 0, 53, 72, 3, 0 },
109 { 0, 42, 78, 8, 0 },
110 { 0, 32, 82, 14, 0 },
111};
112
113static const struct dispc_coef coef3_M19[8] = {
114 { 0, 24, 80, 24, 0 },
115 { 0, 16, 79, 33, 0 },
116 { 0, 9, 76, 43, 0 },
117 { 0, 4, 70, 54, 0 },
118 { 0, 64, 64, 0, 0 },
119 { 0, 54, 70, 4, 0 },
120 { 0, 43, 76, 9, 0 },
121 { 0, 33, 79, 16, 0 },
122};
123
124static const struct dispc_coef coef3_M22[8] = {
125 { 0, 25, 78, 25, 0 },
126 { 0, 17, 77, 34, 0 },
127 { 0, 10, 74, 44, 0 },
128 { 0, 5, 69, 54, 0 },
129 { 0, 64, 64, 0, 0 },
130 { 0, 54, 69, 5, 0 },
131 { 0, 44, 74, 10, 0 },
132 { 0, 34, 77, 17, 0 },
133};
134
135static const struct dispc_coef coef3_M26[8] = {
136 { 0, 26, 76, 26, 0 },
137 { 0, 19, 74, 35, 0 },
138 { 0, 11, 72, 45, 0 },
139 { 0, 5, 69, 54, 0 },
140 { 0, 64, 64, 0, 0 },
141 { 0, 54, 69, 5, 0 },
142 { 0, 45, 72, 11, 0 },
143 { 0, 35, 74, 19, 0 },
144};
145
146static const struct dispc_coef coef3_M32[8] = {
147 { 0, 27, 74, 27, 0 },
148 { 0, 19, 73, 36, 0 },
149 { 0, 12, 71, 45, 0 },
150 { 0, 6, 68, 54, 0 },
151 { 0, 64, 64, 0, 0 },
152 { 0, 54, 68, 6, 0 },
153 { 0, 45, 71, 12, 0 },
154 { 0, 36, 73, 19, 0 },
155};
156
157static const struct dispc_coef coef5_M8[8] = {
158 { 0, 0, 128, 0, 0 },
159 { -2, 14, 125, -10, 1 },
160 { -6, 33, 114, -15, 2 },
161 { -10, 55, 98, -16, 1 },
162 { 0, -14, 78, 78, -14 },
163 { 1, -16, 98, 55, -10 },
164 { 2, -15, 114, 33, -6 },
165 { 1, -10, 125, 14, -2 },
166};
167
168static const struct dispc_coef coef5_M9[8] = {
169 { -3, 10, 114, 10, -3 },
170 { -6, 24, 111, 0, -1 },
171 { -8, 40, 103, -7, 0 },
172 { -11, 58, 91, -11, 1 },
173 { 0, -12, 76, 76, -12 },
174 { 1, -11, 91, 58, -11 },
175 { 0, -7, 103, 40, -8 },
176 { -1, 0, 111, 24, -6 },
177};
178
179static const struct dispc_coef coef5_M10[8] = {
180 { -4, 18, 100, 18, -4 },
181 { -6, 30, 99, 8, -3 },
182 { -8, 44, 93, 0, -1 },
183 { -9, 58, 84, -5, 0 },
184 { 0, -8, 72, 72, -8 },
185 { 0, -5, 84, 58, -9 },
186 { -1, 0, 93, 44, -8 },
187 { -3, 8, 99, 30, -6 },
188};
189
190static const struct dispc_coef coef5_M11[8] = {
191 { -5, 23, 92, 23, -5 },
192 { -6, 34, 90, 13, -3 },
193 { -6, 45, 85, 6, -2 },
194 { -6, 57, 78, 0, -1 },
195 { 0, -4, 68, 68, -4 },
196 { -1, 0, 78, 57, -6 },
197 { -2, 6, 85, 45, -6 },
198 { -3, 13, 90, 34, -6 },
199};
200
201static const struct dispc_coef coef5_M12[8] = {
202 { -4, 26, 84, 26, -4 },
203 { -5, 36, 82, 18, -3 },
204 { -4, 46, 78, 10, -2 },
205 { -3, 55, 72, 5, -1 },
206 { 0, 0, 64, 64, 0 },
207 { -1, 5, 72, 55, -3 },
208 { -2, 10, 78, 46, -4 },
209 { -3, 18, 82, 36, -5 },
210};
211
212static const struct dispc_coef coef5_M13[8] = {
213 { -3, 28, 78, 28, -3 },
214 { -3, 37, 76, 21, -3 },
215 { -2, 45, 73, 14, -2 },
216 { 0, 53, 68, 8, -1 },
217 { 0, 3, 61, 61, 3 },
218 { -1, 8, 68, 53, 0 },
219 { -2, 14, 73, 45, -2 },
220 { -3, 21, 76, 37, -3 },
221};
222
223static const struct dispc_coef coef5_M14[8] = {
224 { -2, 30, 72, 30, -2 },
225 { -1, 37, 71, 23, -2 },
226 { 0, 45, 69, 16, -2 },
227 { 3, 52, 64, 10, -1 },
228 { 0, 6, 58, 58, 6 },
229 { -1, 10, 64, 52, 3 },
230 { -2, 16, 69, 45, 0 },
231 { -2, 23, 71, 37, -1 },
232};
233
234static const struct dispc_coef coef5_M16[8] = {
235 { 0, 31, 66, 31, 0 },
236 { 1, 38, 65, 25, -1 },
237 { 3, 44, 62, 20, -1 },
238 { 6, 49, 59, 14, 0 },
239 { 0, 10, 54, 54, 10 },
240 { 0, 14, 59, 49, 6 },
241 { -1, 20, 62, 44, 3 },
242 { -1, 25, 65, 38, 1 },
243};
244
245static const struct dispc_coef coef5_M19[8] = {
246 { 3, 32, 58, 32, 3 },
247 { 4, 38, 58, 27, 1 },
248 { 7, 42, 55, 23, 1 },
249 { 10, 46, 54, 18, 0 },
250 { 0, 14, 50, 50, 14 },
251 { 0, 18, 54, 46, 10 },
252 { 1, 23, 55, 42, 7 },
253 { 1, 27, 58, 38, 4 },
254};
255
256static const struct dispc_coef coef5_M22[8] = {
257 { 4, 33, 54, 33, 4 },
258 { 6, 37, 54, 28, 3 },
259 { 9, 41, 53, 24, 1 },
260 { 12, 45, 51, 20, 0 },
261 { 0, 16, 48, 48, 16 },
262 { 0, 20, 51, 45, 12 },
263 { 1, 24, 53, 41, 9 },
264 { 3, 28, 54, 37, 6 },
265};
266
267static const struct dispc_coef coef5_M26[8] = {
268 { 6, 33, 50, 33, 6 },
269 { 8, 36, 51, 29, 4 },
270 { 11, 40, 50, 25, 2 },
271 { 14, 43, 48, 22, 1 },
272 { 0, 18, 46, 46, 18 },
273 { 1, 22, 48, 43, 14 },
274 { 2, 25, 50, 40, 11 },
275 { 4, 29, 51, 36, 8 },
276};
277
278static const struct dispc_coef coef5_M32[8] = {
279 { 7, 33, 48, 33, 7 },
280 { 10, 36, 48, 29, 5 },
281 { 13, 39, 47, 26, 3 },
282 { 16, 42, 46, 23, 1 },
283 { 0, 19, 45, 45, 19 },
284 { 1, 23, 46, 42, 16 },
285 { 3, 26, 47, 39, 13 },
286 { 5, 29, 48, 36, 10 },
287};
288
289const struct dispc_coef *dispc_ovl_get_scale_coef(int inc, int five_taps)
290{
291 int i;
292 static const struct {
293 int Mmin;
294 int Mmax;
295 const struct dispc_coef *coef_3;
296 const struct dispc_coef *coef_5;
297 } coefs[] = {
298 { 27, 32, coef3_M32, coef5_M32 },
299 { 23, 26, coef3_M26, coef5_M26 },
300 { 20, 22, coef3_M22, coef5_M22 },
301 { 17, 19, coef3_M19, coef5_M19 },
302 { 15, 16, coef3_M16, coef5_M16 },
303 { 14, 14, coef3_M14, coef5_M14 },
304 { 13, 13, coef3_M13, coef5_M13 },
305 { 12, 12, coef3_M12, coef5_M12 },
306 { 11, 11, coef3_M11, coef5_M11 },
307 { 10, 10, coef3_M10, coef5_M10 },
308 { 9, 9, coef3_M9, coef5_M9 },
309 { 4, 8, coef3_M8, coef5_M8 },
310 /*
311 * When upscaling more than two times, blockiness and outlines
312 * around the image are observed when M8 tables are used. M11,
313 * M16 and M19 tables are used to prevent this.
314 */
315 { 3, 3, coef3_M11, coef5_M11 },
316 { 2, 2, coef3_M16, coef5_M16 },
317 { 0, 1, coef3_M19, coef5_M19 },
318 };
319
320 inc /= 128;
321 for (i = 0; i < ARRAY_SIZE(coefs); ++i)
322 if (inc >= coefs[i].Mmin && inc <= coefs[i].Mmax)
323 return five_taps ? coefs[i].coef_5 : coefs[i].coef_3;
324 return NULL;
325}
diff --git a/drivers/video/omap2/dss/display-sysfs.c b/drivers/video/omap2/dss/display-sysfs.c
deleted file mode 100644
index 5a2095a98ed8..000000000000
--- a/drivers/video/omap2/dss/display-sysfs.c
+++ /dev/null
@@ -1,345 +0,0 @@
1/*
2 * Copyright (C) 2009 Nokia Corporation
3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4 *
5 * Some code and ideas taken from drivers/video/omap/ driver
6 * by Imre Deak.
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 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#define DSS_SUBSYS_NAME "DISPLAY"
22
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/platform_device.h>
26#include <linux/sysfs.h>
27
28#include <video/omapdss.h>
29#include "dss.h"
30
31static struct omap_dss_device *to_dss_device_sysfs(struct device *dev)
32{
33 struct omap_dss_device *dssdev = NULL;
34
35 for_each_dss_dev(dssdev) {
36 if (dssdev->dev == dev) {
37 omap_dss_put_device(dssdev);
38 return dssdev;
39 }
40 }
41
42 return NULL;
43}
44
45static ssize_t display_name_show(struct device *dev,
46 struct device_attribute *attr, char *buf)
47{
48 struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
49
50 return snprintf(buf, PAGE_SIZE, "%s\n",
51 dssdev->name ?
52 dssdev->name : "");
53}
54
55static ssize_t display_enabled_show(struct device *dev,
56 struct device_attribute *attr, char *buf)
57{
58 struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
59
60 return snprintf(buf, PAGE_SIZE, "%d\n",
61 omapdss_device_is_enabled(dssdev));
62}
63
64static ssize_t display_enabled_store(struct device *dev,
65 struct device_attribute *attr,
66 const char *buf, size_t size)
67{
68 struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
69 int r;
70 bool enable;
71
72 r = strtobool(buf, &enable);
73 if (r)
74 return r;
75
76 if (enable == omapdss_device_is_enabled(dssdev))
77 return size;
78
79 if (omapdss_device_is_connected(dssdev) == false)
80 return -ENODEV;
81
82 if (enable) {
83 r = dssdev->driver->enable(dssdev);
84 if (r)
85 return r;
86 } else {
87 dssdev->driver->disable(dssdev);
88 }
89
90 return size;
91}
92
93static ssize_t display_tear_show(struct device *dev,
94 struct device_attribute *attr, char *buf)
95{
96 struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
97 return snprintf(buf, PAGE_SIZE, "%d\n",
98 dssdev->driver->get_te ?
99 dssdev->driver->get_te(dssdev) : 0);
100}
101
102static ssize_t display_tear_store(struct device *dev,
103 struct device_attribute *attr, const char *buf, size_t size)
104{
105 struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
106 int r;
107 bool te;
108
109 if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
110 return -ENOENT;
111
112 r = strtobool(buf, &te);
113 if (r)
114 return r;
115
116 r = dssdev->driver->enable_te(dssdev, te);
117 if (r)
118 return r;
119
120 return size;
121}
122
123static ssize_t display_timings_show(struct device *dev,
124 struct device_attribute *attr, char *buf)
125{
126 struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
127 struct omap_video_timings t;
128
129 if (!dssdev->driver->get_timings)
130 return -ENOENT;
131
132 dssdev->driver->get_timings(dssdev, &t);
133
134 return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
135 t.pixelclock,
136 t.x_res, t.hfp, t.hbp, t.hsw,
137 t.y_res, t.vfp, t.vbp, t.vsw);
138}
139
140static ssize_t display_timings_store(struct device *dev,
141 struct device_attribute *attr, const char *buf, size_t size)
142{
143 struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
144 struct omap_video_timings t = dssdev->panel.timings;
145 int r, found;
146
147 if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
148 return -ENOENT;
149
150 found = 0;
151#ifdef CONFIG_OMAP2_DSS_VENC
152 if (strncmp("pal", buf, 3) == 0) {
153 t = omap_dss_pal_timings;
154 found = 1;
155 } else if (strncmp("ntsc", buf, 4) == 0) {
156 t = omap_dss_ntsc_timings;
157 found = 1;
158 }
159#endif
160 if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
161 &t.pixelclock,
162 &t.x_res, &t.hfp, &t.hbp, &t.hsw,
163 &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
164 return -EINVAL;
165
166 r = dssdev->driver->check_timings(dssdev, &t);
167 if (r)
168 return r;
169
170 dssdev->driver->disable(dssdev);
171 dssdev->driver->set_timings(dssdev, &t);
172 r = dssdev->driver->enable(dssdev);
173 if (r)
174 return r;
175
176 return size;
177}
178
179static ssize_t display_rotate_show(struct device *dev,
180 struct device_attribute *attr, char *buf)
181{
182 struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
183 int rotate;
184 if (!dssdev->driver->get_rotate)
185 return -ENOENT;
186 rotate = dssdev->driver->get_rotate(dssdev);
187 return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
188}
189
190static ssize_t display_rotate_store(struct device *dev,
191 struct device_attribute *attr, const char *buf, size_t size)
192{
193 struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
194 int rot, r;
195
196 if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
197 return -ENOENT;
198
199 r = kstrtoint(buf, 0, &rot);
200 if (r)
201 return r;
202
203 r = dssdev->driver->set_rotate(dssdev, rot);
204 if (r)
205 return r;
206
207 return size;
208}
209
210static ssize_t display_mirror_show(struct device *dev,
211 struct device_attribute *attr, char *buf)
212{
213 struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
214 int mirror;
215 if (!dssdev->driver->get_mirror)
216 return -ENOENT;
217 mirror = dssdev->driver->get_mirror(dssdev);
218 return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
219}
220
221static ssize_t display_mirror_store(struct device *dev,
222 struct device_attribute *attr, const char *buf, size_t size)
223{
224 struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
225 int r;
226 bool mirror;
227
228 if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
229 return -ENOENT;
230
231 r = strtobool(buf, &mirror);
232 if (r)
233 return r;
234
235 r = dssdev->driver->set_mirror(dssdev, mirror);
236 if (r)
237 return r;
238
239 return size;
240}
241
242static ssize_t display_wss_show(struct device *dev,
243 struct device_attribute *attr, char *buf)
244{
245 struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
246 unsigned int wss;
247
248 if (!dssdev->driver->get_wss)
249 return -ENOENT;
250
251 wss = dssdev->driver->get_wss(dssdev);
252
253 return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
254}
255
256static ssize_t display_wss_store(struct device *dev,
257 struct device_attribute *attr, const char *buf, size_t size)
258{
259 struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
260 u32 wss;
261 int r;
262
263 if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
264 return -ENOENT;
265
266 r = kstrtou32(buf, 0, &wss);
267 if (r)
268 return r;
269
270 if (wss > 0xfffff)
271 return -EINVAL;
272
273 r = dssdev->driver->set_wss(dssdev, wss);
274 if (r)
275 return r;
276
277 return size;
278}
279
280static DEVICE_ATTR(display_name, S_IRUGO, display_name_show, NULL);
281static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
282 display_enabled_show, display_enabled_store);
283static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
284 display_tear_show, display_tear_store);
285static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
286 display_timings_show, display_timings_store);
287static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
288 display_rotate_show, display_rotate_store);
289static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
290 display_mirror_show, display_mirror_store);
291static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
292 display_wss_show, display_wss_store);
293
294static const struct attribute *display_sysfs_attrs[] = {
295 &dev_attr_display_name.attr,
296 &dev_attr_enabled.attr,
297 &dev_attr_tear_elim.attr,
298 &dev_attr_timings.attr,
299 &dev_attr_rotate.attr,
300 &dev_attr_mirror.attr,
301 &dev_attr_wss.attr,
302 NULL
303};
304
305int display_init_sysfs(struct platform_device *pdev)
306{
307 struct omap_dss_device *dssdev = NULL;
308 int r;
309
310 for_each_dss_dev(dssdev) {
311 struct kobject *kobj = &dssdev->dev->kobj;
312
313 r = sysfs_create_files(kobj, display_sysfs_attrs);
314 if (r) {
315 DSSERR("failed to create sysfs files\n");
316 goto err;
317 }
318
319 r = sysfs_create_link(&pdev->dev.kobj, kobj, dssdev->alias);
320 if (r) {
321 sysfs_remove_files(kobj, display_sysfs_attrs);
322
323 DSSERR("failed to create sysfs display link\n");
324 goto err;
325 }
326 }
327
328 return 0;
329
330err:
331 display_uninit_sysfs(pdev);
332
333 return r;
334}
335
336void display_uninit_sysfs(struct platform_device *pdev)
337{
338 struct omap_dss_device *dssdev = NULL;
339
340 for_each_dss_dev(dssdev) {
341 sysfs_remove_link(&pdev->dev.kobj, dssdev->alias);
342 sysfs_remove_files(&dssdev->dev->kobj,
343 display_sysfs_attrs);
344 }
345}
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
deleted file mode 100644
index 2412a0dd0c13..000000000000
--- a/drivers/video/omap2/dss/display.c
+++ /dev/null
@@ -1,338 +0,0 @@
1/*
2 * linux/drivers/video/omap2/dss/display.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
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#define DSS_SUBSYS_NAME "DISPLAY"
24
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/jiffies.h>
28#include <linux/platform_device.h>
29#include <linux/of.h>
30
31#include <video/omapdss.h>
32#include "dss.h"
33#include "dss_features.h"
34
35void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
36 u16 *xres, u16 *yres)
37{
38 *xres = dssdev->panel.timings.x_res;
39 *yres = dssdev->panel.timings.y_res;
40}
41EXPORT_SYMBOL(omapdss_default_get_resolution);
42
43int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
44{
45 switch (dssdev->type) {
46 case OMAP_DISPLAY_TYPE_DPI:
47 if (dssdev->phy.dpi.data_lines == 24)
48 return 24;
49 else
50 return 16;
51
52 case OMAP_DISPLAY_TYPE_DBI:
53 if (dssdev->ctrl.pixel_size == 24)
54 return 24;
55 else
56 return 16;
57 case OMAP_DISPLAY_TYPE_DSI:
58 if (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) > 16)
59 return 24;
60 else
61 return 16;
62 case OMAP_DISPLAY_TYPE_VENC:
63 case OMAP_DISPLAY_TYPE_SDI:
64 case OMAP_DISPLAY_TYPE_HDMI:
65 case OMAP_DISPLAY_TYPE_DVI:
66 return 24;
67 default:
68 BUG();
69 return 0;
70 }
71}
72EXPORT_SYMBOL(omapdss_default_get_recommended_bpp);
73
74void omapdss_default_get_timings(struct omap_dss_device *dssdev,
75 struct omap_video_timings *timings)
76{
77 *timings = dssdev->panel.timings;
78}
79EXPORT_SYMBOL(omapdss_default_get_timings);
80
81int dss_suspend_all_devices(void)
82{
83 struct omap_dss_device *dssdev = NULL;
84
85 for_each_dss_dev(dssdev) {
86 if (!dssdev->driver)
87 continue;
88
89 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
90 dssdev->driver->disable(dssdev);
91 dssdev->activate_after_resume = true;
92 } else {
93 dssdev->activate_after_resume = false;
94 }
95 }
96
97 return 0;
98}
99
100int dss_resume_all_devices(void)
101{
102 struct omap_dss_device *dssdev = NULL;
103
104 for_each_dss_dev(dssdev) {
105 if (!dssdev->driver)
106 continue;
107
108 if (dssdev->activate_after_resume) {
109 dssdev->driver->enable(dssdev);
110 dssdev->activate_after_resume = false;
111 }
112 }
113
114 return 0;
115}
116
117void dss_disable_all_devices(void)
118{
119 struct omap_dss_device *dssdev = NULL;
120
121 for_each_dss_dev(dssdev) {
122 if (!dssdev->driver)
123 continue;
124
125 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
126 dssdev->driver->disable(dssdev);
127 }
128}
129
130static LIST_HEAD(panel_list);
131static DEFINE_MUTEX(panel_list_mutex);
132static int disp_num_counter;
133
134int omapdss_register_display(struct omap_dss_device *dssdev)
135{
136 struct omap_dss_driver *drv = dssdev->driver;
137 int id;
138
139 /*
140 * Note: this presumes all the displays are either using DT or non-DT,
141 * which normally should be the case. This also presumes that all
142 * displays either have an DT alias, or none has.
143 */
144
145 if (dssdev->dev->of_node) {
146 id = of_alias_get_id(dssdev->dev->of_node, "display");
147
148 if (id < 0)
149 id = disp_num_counter++;
150 } else {
151 id = disp_num_counter++;
152 }
153
154 snprintf(dssdev->alias, sizeof(dssdev->alias), "display%d", id);
155
156 /* Use 'label' property for name, if it exists */
157 if (dssdev->dev->of_node)
158 of_property_read_string(dssdev->dev->of_node, "label",
159 &dssdev->name);
160
161 if (dssdev->name == NULL)
162 dssdev->name = dssdev->alias;
163
164 if (drv && drv->get_resolution == NULL)
165 drv->get_resolution = omapdss_default_get_resolution;
166 if (drv && drv->get_recommended_bpp == NULL)
167 drv->get_recommended_bpp = omapdss_default_get_recommended_bpp;
168 if (drv && drv->get_timings == NULL)
169 drv->get_timings = omapdss_default_get_timings;
170
171 mutex_lock(&panel_list_mutex);
172 list_add_tail(&dssdev->panel_list, &panel_list);
173 mutex_unlock(&panel_list_mutex);
174 return 0;
175}
176EXPORT_SYMBOL(omapdss_register_display);
177
178void omapdss_unregister_display(struct omap_dss_device *dssdev)
179{
180 mutex_lock(&panel_list_mutex);
181 list_del(&dssdev->panel_list);
182 mutex_unlock(&panel_list_mutex);
183}
184EXPORT_SYMBOL(omapdss_unregister_display);
185
186struct omap_dss_device *omap_dss_get_device(struct omap_dss_device *dssdev)
187{
188 if (!try_module_get(dssdev->owner))
189 return NULL;
190
191 if (get_device(dssdev->dev) == NULL) {
192 module_put(dssdev->owner);
193 return NULL;
194 }
195
196 return dssdev;
197}
198EXPORT_SYMBOL(omap_dss_get_device);
199
200void omap_dss_put_device(struct omap_dss_device *dssdev)
201{
202 put_device(dssdev->dev);
203 module_put(dssdev->owner);
204}
205EXPORT_SYMBOL(omap_dss_put_device);
206
207/*
208 * ref count of the found device is incremented.
209 * ref count of from-device is decremented.
210 */
211struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from)
212{
213 struct list_head *l;
214 struct omap_dss_device *dssdev;
215
216 mutex_lock(&panel_list_mutex);
217
218 if (list_empty(&panel_list)) {
219 dssdev = NULL;
220 goto out;
221 }
222
223 if (from == NULL) {
224 dssdev = list_first_entry(&panel_list, struct omap_dss_device,
225 panel_list);
226 omap_dss_get_device(dssdev);
227 goto out;
228 }
229
230 omap_dss_put_device(from);
231
232 list_for_each(l, &panel_list) {
233 dssdev = list_entry(l, struct omap_dss_device, panel_list);
234 if (dssdev == from) {
235 if (list_is_last(l, &panel_list)) {
236 dssdev = NULL;
237 goto out;
238 }
239
240 dssdev = list_entry(l->next, struct omap_dss_device,
241 panel_list);
242 omap_dss_get_device(dssdev);
243 goto out;
244 }
245 }
246
247 WARN(1, "'from' dssdev not found\n");
248
249 dssdev = NULL;
250out:
251 mutex_unlock(&panel_list_mutex);
252 return dssdev;
253}
254EXPORT_SYMBOL(omap_dss_get_next_device);
255
256struct omap_dss_device *omap_dss_find_device(void *data,
257 int (*match)(struct omap_dss_device *dssdev, void *data))
258{
259 struct omap_dss_device *dssdev = NULL;
260
261 while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL) {
262 if (match(dssdev, data))
263 return dssdev;
264 }
265
266 return NULL;
267}
268EXPORT_SYMBOL(omap_dss_find_device);
269
270void videomode_to_omap_video_timings(const struct videomode *vm,
271 struct omap_video_timings *ovt)
272{
273 memset(ovt, 0, sizeof(*ovt));
274
275 ovt->pixelclock = vm->pixelclock;
276 ovt->x_res = vm->hactive;
277 ovt->hbp = vm->hback_porch;
278 ovt->hfp = vm->hfront_porch;
279 ovt->hsw = vm->hsync_len;
280 ovt->y_res = vm->vactive;
281 ovt->vbp = vm->vback_porch;
282 ovt->vfp = vm->vfront_porch;
283 ovt->vsw = vm->vsync_len;
284
285 ovt->vsync_level = vm->flags & DISPLAY_FLAGS_VSYNC_HIGH ?
286 OMAPDSS_SIG_ACTIVE_HIGH :
287 OMAPDSS_SIG_ACTIVE_LOW;
288 ovt->hsync_level = vm->flags & DISPLAY_FLAGS_HSYNC_HIGH ?
289 OMAPDSS_SIG_ACTIVE_HIGH :
290 OMAPDSS_SIG_ACTIVE_LOW;
291 ovt->de_level = vm->flags & DISPLAY_FLAGS_DE_HIGH ?
292 OMAPDSS_SIG_ACTIVE_HIGH :
293 OMAPDSS_SIG_ACTIVE_LOW;
294 ovt->data_pclk_edge = vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE ?
295 OMAPDSS_DRIVE_SIG_RISING_EDGE :
296 OMAPDSS_DRIVE_SIG_FALLING_EDGE;
297
298 ovt->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
299}
300EXPORT_SYMBOL(videomode_to_omap_video_timings);
301
302void omap_video_timings_to_videomode(const struct omap_video_timings *ovt,
303 struct videomode *vm)
304{
305 memset(vm, 0, sizeof(*vm));
306
307 vm->pixelclock = ovt->pixelclock;
308
309 vm->hactive = ovt->x_res;
310 vm->hback_porch = ovt->hbp;
311 vm->hfront_porch = ovt->hfp;
312 vm->hsync_len = ovt->hsw;
313 vm->vactive = ovt->y_res;
314 vm->vback_porch = ovt->vbp;
315 vm->vfront_porch = ovt->vfp;
316 vm->vsync_len = ovt->vsw;
317
318 if (ovt->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
319 vm->flags |= DISPLAY_FLAGS_HSYNC_HIGH;
320 else
321 vm->flags |= DISPLAY_FLAGS_HSYNC_LOW;
322
323 if (ovt->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
324 vm->flags |= DISPLAY_FLAGS_VSYNC_HIGH;
325 else
326 vm->flags |= DISPLAY_FLAGS_VSYNC_LOW;
327
328 if (ovt->de_level == OMAPDSS_SIG_ACTIVE_HIGH)
329 vm->flags |= DISPLAY_FLAGS_DE_HIGH;
330 else
331 vm->flags |= DISPLAY_FLAGS_DE_LOW;
332
333 if (ovt->data_pclk_edge == OMAPDSS_DRIVE_SIG_RISING_EDGE)
334 vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE;
335 else
336 vm->flags |= DISPLAY_FLAGS_PIXDATA_NEGEDGE;
337}
338EXPORT_SYMBOL(omap_video_timings_to_videomode);
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
deleted file mode 100644
index 157921db447a..000000000000
--- a/drivers/video/omap2/dss/dpi.c
+++ /dev/null
@@ -1,774 +0,0 @@
1/*
2 * linux/drivers/video/omap2/dss/dpi.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
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#define DSS_SUBSYS_NAME "DPI"
24
25#include <linux/kernel.h>
26#include <linux/delay.h>
27#include <linux/export.h>
28#include <linux/err.h>
29#include <linux/errno.h>
30#include <linux/platform_device.h>
31#include <linux/regulator/consumer.h>
32#include <linux/string.h>
33#include <linux/of.h>
34
35#include <video/omapdss.h>
36
37#include "dss.h"
38#include "dss_features.h"
39
40static struct {
41 struct platform_device *pdev;
42
43 struct regulator *vdds_dsi_reg;
44 struct platform_device *dsidev;
45
46 struct mutex lock;
47
48 struct omap_video_timings timings;
49 struct dss_lcd_mgr_config mgr_config;
50 int data_lines;
51
52 struct omap_dss_device output;
53
54 bool port_initialized;
55} dpi;
56
57static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
58{
59 /*
60 * XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL
61 * would also be used for DISPC fclk. Meaning, when the DPI output is
62 * disabled, DISPC clock will be disabled, and TV out will stop.
63 */
64 switch (omapdss_get_version()) {
65 case OMAPDSS_VER_OMAP24xx:
66 case OMAPDSS_VER_OMAP34xx_ES1:
67 case OMAPDSS_VER_OMAP34xx_ES3:
68 case OMAPDSS_VER_OMAP3630:
69 case OMAPDSS_VER_AM35xx:
70 return NULL;
71
72 case OMAPDSS_VER_OMAP4430_ES1:
73 case OMAPDSS_VER_OMAP4430_ES2:
74 case OMAPDSS_VER_OMAP4:
75 switch (channel) {
76 case OMAP_DSS_CHANNEL_LCD:
77 return dsi_get_dsidev_from_id(0);
78 case OMAP_DSS_CHANNEL_LCD2:
79 return dsi_get_dsidev_from_id(1);
80 default:
81 return NULL;
82 }
83
84 case OMAPDSS_VER_OMAP5:
85 switch (channel) {
86 case OMAP_DSS_CHANNEL_LCD:
87 return dsi_get_dsidev_from_id(0);
88 case OMAP_DSS_CHANNEL_LCD3:
89 return dsi_get_dsidev_from_id(1);
90 default:
91 return NULL;
92 }
93
94 default:
95 return NULL;
96 }
97}
98
99static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
100{
101 switch (channel) {
102 case OMAP_DSS_CHANNEL_LCD:
103 return OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC;
104 case OMAP_DSS_CHANNEL_LCD2:
105 return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
106 default:
107 /* this shouldn't happen */
108 WARN_ON(1);
109 return OMAP_DSS_CLK_SRC_FCK;
110 }
111}
112
113struct dpi_clk_calc_ctx {
114 struct platform_device *dsidev;
115
116 /* inputs */
117
118 unsigned long pck_min, pck_max;
119
120 /* outputs */
121
122 struct dsi_clock_info dsi_cinfo;
123 unsigned long fck;
124 struct dispc_clock_info dispc_cinfo;
125};
126
127static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
128 unsigned long pck, void *data)
129{
130 struct dpi_clk_calc_ctx *ctx = data;
131
132 /*
133 * Odd dividers give us uneven duty cycle, causing problem when level
134 * shifted. So skip all odd dividers when the pixel clock is on the
135 * higher side.
136 */
137 if (ctx->pck_min >= 100000000) {
138 if (lckd > 1 && lckd % 2 != 0)
139 return false;
140
141 if (pckd > 1 && pckd % 2 != 0)
142 return false;
143 }
144
145 ctx->dispc_cinfo.lck_div = lckd;
146 ctx->dispc_cinfo.pck_div = pckd;
147 ctx->dispc_cinfo.lck = lck;
148 ctx->dispc_cinfo.pck = pck;
149
150 return true;
151}
152
153
154static bool dpi_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
155 void *data)
156{
157 struct dpi_clk_calc_ctx *ctx = data;
158
159 /*
160 * Odd dividers give us uneven duty cycle, causing problem when level
161 * shifted. So skip all odd dividers when the pixel clock is on the
162 * higher side.
163 */
164 if (regm_dispc > 1 && regm_dispc % 2 != 0 && ctx->pck_min >= 100000000)
165 return false;
166
167 ctx->dsi_cinfo.regm_dispc = regm_dispc;
168 ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
169
170 return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max,
171 dpi_calc_dispc_cb, ctx);
172}
173
174
175static bool dpi_calc_pll_cb(int regn, int regm, unsigned long fint,
176 unsigned long pll,
177 void *data)
178{
179 struct dpi_clk_calc_ctx *ctx = data;
180
181 ctx->dsi_cinfo.regn = regn;
182 ctx->dsi_cinfo.regm = regm;
183 ctx->dsi_cinfo.fint = fint;
184 ctx->dsi_cinfo.clkin4ddr = pll;
185
186 return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->pck_min,
187 dpi_calc_hsdiv_cb, ctx);
188}
189
190static bool dpi_calc_dss_cb(unsigned long fck, void *data)
191{
192 struct dpi_clk_calc_ctx *ctx = data;
193
194 ctx->fck = fck;
195
196 return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max,
197 dpi_calc_dispc_cb, ctx);
198}
199
200static bool dpi_dsi_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
201{
202 unsigned long clkin;
203 unsigned long pll_min, pll_max;
204
205 clkin = dsi_get_pll_clkin(dpi.dsidev);
206
207 memset(ctx, 0, sizeof(*ctx));
208 ctx->dsidev = dpi.dsidev;
209 ctx->pck_min = pck - 1000;
210 ctx->pck_max = pck + 1000;
211 ctx->dsi_cinfo.clkin = clkin;
212
213 pll_min = 0;
214 pll_max = 0;
215
216 return dsi_pll_calc(dpi.dsidev, clkin,
217 pll_min, pll_max,
218 dpi_calc_pll_cb, ctx);
219}
220
221static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
222{
223 int i;
224
225 /*
226 * DSS fck gives us very few possibilities, so finding a good pixel
227 * clock may not be possible. We try multiple times to find the clock,
228 * each time widening the pixel clock range we look for, up to
229 * +/- ~15MHz.
230 */
231
232 for (i = 0; i < 25; ++i) {
233 bool ok;
234
235 memset(ctx, 0, sizeof(*ctx));
236 if (pck > 1000 * i * i * i)
237 ctx->pck_min = max(pck - 1000 * i * i * i, 0lu);
238 else
239 ctx->pck_min = 0;
240 ctx->pck_max = pck + 1000 * i * i * i;
241
242 ok = dss_div_calc(pck, ctx->pck_min, dpi_calc_dss_cb, ctx);
243 if (ok)
244 return ok;
245 }
246
247 return false;
248}
249
250
251
252static int dpi_set_dsi_clk(enum omap_channel channel,
253 unsigned long pck_req, unsigned long *fck, int *lck_div,
254 int *pck_div)
255{
256 struct dpi_clk_calc_ctx ctx;
257 int r;
258 bool ok;
259
260 ok = dpi_dsi_clk_calc(pck_req, &ctx);
261 if (!ok)
262 return -EINVAL;
263
264 r = dsi_pll_set_clock_div(dpi.dsidev, &ctx.dsi_cinfo);
265 if (r)
266 return r;
267
268 dss_select_lcd_clk_source(channel,
269 dpi_get_alt_clk_src(channel));
270
271 dpi.mgr_config.clock_info = ctx.dispc_cinfo;
272
273 *fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
274 *lck_div = ctx.dispc_cinfo.lck_div;
275 *pck_div = ctx.dispc_cinfo.pck_div;
276
277 return 0;
278}
279
280static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
281 int *lck_div, int *pck_div)
282{
283 struct dpi_clk_calc_ctx ctx;
284 int r;
285 bool ok;
286
287 ok = dpi_dss_clk_calc(pck_req, &ctx);
288 if (!ok)
289 return -EINVAL;
290
291 r = dss_set_fck_rate(ctx.fck);
292 if (r)
293 return r;
294
295 dpi.mgr_config.clock_info = ctx.dispc_cinfo;
296
297 *fck = ctx.fck;
298 *lck_div = ctx.dispc_cinfo.lck_div;
299 *pck_div = ctx.dispc_cinfo.pck_div;
300
301 return 0;
302}
303
304static int dpi_set_mode(struct omap_overlay_manager *mgr)
305{
306 struct omap_video_timings *t = &dpi.timings;
307 int lck_div = 0, pck_div = 0;
308 unsigned long fck = 0;
309 unsigned long pck;
310 int r = 0;
311
312 if (dpi.dsidev)
313 r = dpi_set_dsi_clk(mgr->id, t->pixelclock, &fck,
314 &lck_div, &pck_div);
315 else
316 r = dpi_set_dispc_clk(t->pixelclock, &fck,
317 &lck_div, &pck_div);
318 if (r)
319 return r;
320
321 pck = fck / lck_div / pck_div;
322
323 if (pck != t->pixelclock) {
324 DSSWARN("Could not find exact pixel clock. Requested %d Hz, got %lu Hz\n",
325 t->pixelclock, pck);
326
327 t->pixelclock = pck;
328 }
329
330 dss_mgr_set_timings(mgr, t);
331
332 return 0;
333}
334
335static void dpi_config_lcd_manager(struct omap_overlay_manager *mgr)
336{
337 dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
338
339 dpi.mgr_config.stallmode = false;
340 dpi.mgr_config.fifohandcheck = false;
341
342 dpi.mgr_config.video_port_width = dpi.data_lines;
343
344 dpi.mgr_config.lcden_sig_polarity = 0;
345
346 dss_mgr_set_lcd_config(mgr, &dpi.mgr_config);
347}
348
349static int dpi_display_enable(struct omap_dss_device *dssdev)
350{
351 struct omap_dss_device *out = &dpi.output;
352 int r;
353
354 mutex_lock(&dpi.lock);
355
356 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi.vdds_dsi_reg) {
357 DSSERR("no VDSS_DSI regulator\n");
358 r = -ENODEV;
359 goto err_no_reg;
360 }
361
362 if (out == NULL || out->manager == NULL) {
363 DSSERR("failed to enable display: no output/manager\n");
364 r = -ENODEV;
365 goto err_no_out_mgr;
366 }
367
368 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) {
369 r = regulator_enable(dpi.vdds_dsi_reg);
370 if (r)
371 goto err_reg_enable;
372 }
373
374 r = dispc_runtime_get();
375 if (r)
376 goto err_get_dispc;
377
378 r = dss_dpi_select_source(out->manager->id);
379 if (r)
380 goto err_src_sel;
381
382 if (dpi.dsidev) {
383 r = dsi_runtime_get(dpi.dsidev);
384 if (r)
385 goto err_get_dsi;
386
387 r = dsi_pll_init(dpi.dsidev, 0, 1);
388 if (r)
389 goto err_dsi_pll_init;
390 }
391
392 r = dpi_set_mode(out->manager);
393 if (r)
394 goto err_set_mode;
395
396 dpi_config_lcd_manager(out->manager);
397
398 mdelay(2);
399
400 r = dss_mgr_enable(out->manager);
401 if (r)
402 goto err_mgr_enable;
403
404 mutex_unlock(&dpi.lock);
405
406 return 0;
407
408err_mgr_enable:
409err_set_mode:
410 if (dpi.dsidev)
411 dsi_pll_uninit(dpi.dsidev, true);
412err_dsi_pll_init:
413 if (dpi.dsidev)
414 dsi_runtime_put(dpi.dsidev);
415err_get_dsi:
416err_src_sel:
417 dispc_runtime_put();
418err_get_dispc:
419 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
420 regulator_disable(dpi.vdds_dsi_reg);
421err_reg_enable:
422err_no_out_mgr:
423err_no_reg:
424 mutex_unlock(&dpi.lock);
425 return r;
426}
427
428static void dpi_display_disable(struct omap_dss_device *dssdev)
429{
430 struct omap_overlay_manager *mgr = dpi.output.manager;
431
432 mutex_lock(&dpi.lock);
433
434 dss_mgr_disable(mgr);
435
436 if (dpi.dsidev) {
437 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
438 dsi_pll_uninit(dpi.dsidev, true);
439 dsi_runtime_put(dpi.dsidev);
440 }
441
442 dispc_runtime_put();
443
444 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
445 regulator_disable(dpi.vdds_dsi_reg);
446
447 mutex_unlock(&dpi.lock);
448}
449
450static void dpi_set_timings(struct omap_dss_device *dssdev,
451 struct omap_video_timings *timings)
452{
453 DSSDBG("dpi_set_timings\n");
454
455 mutex_lock(&dpi.lock);
456
457 dpi.timings = *timings;
458
459 mutex_unlock(&dpi.lock);
460}
461
462static void dpi_get_timings(struct omap_dss_device *dssdev,
463 struct omap_video_timings *timings)
464{
465 mutex_lock(&dpi.lock);
466
467 *timings = dpi.timings;
468
469 mutex_unlock(&dpi.lock);
470}
471
472static int dpi_check_timings(struct omap_dss_device *dssdev,
473 struct omap_video_timings *timings)
474{
475 struct omap_overlay_manager *mgr = dpi.output.manager;
476 int lck_div, pck_div;
477 unsigned long fck;
478 unsigned long pck;
479 struct dpi_clk_calc_ctx ctx;
480 bool ok;
481
482 if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
483 return -EINVAL;
484
485 if (timings->pixelclock == 0)
486 return -EINVAL;
487
488 if (dpi.dsidev) {
489 ok = dpi_dsi_clk_calc(timings->pixelclock, &ctx);
490 if (!ok)
491 return -EINVAL;
492
493 fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
494 } else {
495 ok = dpi_dss_clk_calc(timings->pixelclock, &ctx);
496 if (!ok)
497 return -EINVAL;
498
499 fck = ctx.fck;
500 }
501
502 lck_div = ctx.dispc_cinfo.lck_div;
503 pck_div = ctx.dispc_cinfo.pck_div;
504
505 pck = fck / lck_div / pck_div;
506
507 timings->pixelclock = pck;
508
509 return 0;
510}
511
512static void dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
513{
514 mutex_lock(&dpi.lock);
515
516 dpi.data_lines = data_lines;
517
518 mutex_unlock(&dpi.lock);
519}
520
521static int dpi_verify_dsi_pll(struct platform_device *dsidev)
522{
523 int r;
524
525 /* do initial setup with the PLL to see if it is operational */
526
527 r = dsi_runtime_get(dsidev);
528 if (r)
529 return r;
530
531 r = dsi_pll_init(dsidev, 0, 1);
532 if (r) {
533 dsi_runtime_put(dsidev);
534 return r;
535 }
536
537 dsi_pll_uninit(dsidev, true);
538 dsi_runtime_put(dsidev);
539
540 return 0;
541}
542
543static int dpi_init_regulator(void)
544{
545 struct regulator *vdds_dsi;
546
547 if (!dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
548 return 0;
549
550 if (dpi.vdds_dsi_reg)
551 return 0;
552
553 vdds_dsi = devm_regulator_get(&dpi.pdev->dev, "vdds_dsi");
554 if (IS_ERR(vdds_dsi)) {
555 if (PTR_ERR(vdds_dsi) != -EPROBE_DEFER)
556 DSSERR("can't get VDDS_DSI regulator\n");
557 return PTR_ERR(vdds_dsi);
558 }
559
560 dpi.vdds_dsi_reg = vdds_dsi;
561
562 return 0;
563}
564
565static void dpi_init_pll(void)
566{
567 struct platform_device *dsidev;
568
569 if (dpi.dsidev)
570 return;
571
572 dsidev = dpi_get_dsidev(dpi.output.dispc_channel);
573 if (!dsidev)
574 return;
575
576 if (dpi_verify_dsi_pll(dsidev)) {
577 DSSWARN("DSI PLL not operational\n");
578 return;
579 }
580
581 dpi.dsidev = dsidev;
582}
583
584/*
585 * Return a hardcoded channel for the DPI output. This should work for
586 * current use cases, but this can be later expanded to either resolve
587 * the channel in some more dynamic manner, or get the channel as a user
588 * parameter.
589 */
590static enum omap_channel dpi_get_channel(void)
591{
592 switch (omapdss_get_version()) {
593 case OMAPDSS_VER_OMAP24xx:
594 case OMAPDSS_VER_OMAP34xx_ES1:
595 case OMAPDSS_VER_OMAP34xx_ES3:
596 case OMAPDSS_VER_OMAP3630:
597 case OMAPDSS_VER_AM35xx:
598 return OMAP_DSS_CHANNEL_LCD;
599
600 case OMAPDSS_VER_OMAP4430_ES1:
601 case OMAPDSS_VER_OMAP4430_ES2:
602 case OMAPDSS_VER_OMAP4:
603 return OMAP_DSS_CHANNEL_LCD2;
604
605 case OMAPDSS_VER_OMAP5:
606 return OMAP_DSS_CHANNEL_LCD3;
607
608 default:
609 DSSWARN("unsupported DSS version\n");
610 return OMAP_DSS_CHANNEL_LCD;
611 }
612}
613
614static int dpi_connect(struct omap_dss_device *dssdev,
615 struct omap_dss_device *dst)
616{
617 struct omap_overlay_manager *mgr;
618 int r;
619
620 r = dpi_init_regulator();
621 if (r)
622 return r;
623
624 dpi_init_pll();
625
626 mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
627 if (!mgr)
628 return -ENODEV;
629
630 r = dss_mgr_connect(mgr, dssdev);
631 if (r)
632 return r;
633
634 r = omapdss_output_set_device(dssdev, dst);
635 if (r) {
636 DSSERR("failed to connect output to new device: %s\n",
637 dst->name);
638 dss_mgr_disconnect(mgr, dssdev);
639 return r;
640 }
641
642 return 0;
643}
644
645static void dpi_disconnect(struct omap_dss_device *dssdev,
646 struct omap_dss_device *dst)
647{
648 WARN_ON(dst != dssdev->dst);
649
650 if (dst != dssdev->dst)
651 return;
652
653 omapdss_output_unset_device(dssdev);
654
655 if (dssdev->manager)
656 dss_mgr_disconnect(dssdev->manager, dssdev);
657}
658
659static const struct omapdss_dpi_ops dpi_ops = {
660 .connect = dpi_connect,
661 .disconnect = dpi_disconnect,
662
663 .enable = dpi_display_enable,
664 .disable = dpi_display_disable,
665
666 .check_timings = dpi_check_timings,
667 .set_timings = dpi_set_timings,
668 .get_timings = dpi_get_timings,
669
670 .set_data_lines = dpi_set_data_lines,
671};
672
673static void dpi_init_output(struct platform_device *pdev)
674{
675 struct omap_dss_device *out = &dpi.output;
676
677 out->dev = &pdev->dev;
678 out->id = OMAP_DSS_OUTPUT_DPI;
679 out->output_type = OMAP_DISPLAY_TYPE_DPI;
680 out->name = "dpi.0";
681 out->dispc_channel = dpi_get_channel();
682 out->ops.dpi = &dpi_ops;
683 out->owner = THIS_MODULE;
684
685 omapdss_register_output(out);
686}
687
688static void __exit dpi_uninit_output(struct platform_device *pdev)
689{
690 struct omap_dss_device *out = &dpi.output;
691
692 omapdss_unregister_output(out);
693}
694
695static int omap_dpi_probe(struct platform_device *pdev)
696{
697 dpi.pdev = pdev;
698
699 mutex_init(&dpi.lock);
700
701 dpi_init_output(pdev);
702
703 return 0;
704}
705
706static int __exit omap_dpi_remove(struct platform_device *pdev)
707{
708 dpi_uninit_output(pdev);
709
710 return 0;
711}
712
713static struct platform_driver omap_dpi_driver = {
714 .probe = omap_dpi_probe,
715 .remove = __exit_p(omap_dpi_remove),
716 .driver = {
717 .name = "omapdss_dpi",
718 .owner = THIS_MODULE,
719 },
720};
721
722int __init dpi_init_platform_driver(void)
723{
724 return platform_driver_register(&omap_dpi_driver);
725}
726
727void __exit dpi_uninit_platform_driver(void)
728{
729 platform_driver_unregister(&omap_dpi_driver);
730}
731
732int __init dpi_init_port(struct platform_device *pdev, struct device_node *port)
733{
734 struct device_node *ep;
735 u32 datalines;
736 int r;
737
738 ep = omapdss_of_get_next_endpoint(port, NULL);
739 if (!ep)
740 return 0;
741
742 r = of_property_read_u32(ep, "data-lines", &datalines);
743 if (r) {
744 DSSERR("failed to parse datalines\n");
745 goto err_datalines;
746 }
747
748 dpi.data_lines = datalines;
749
750 of_node_put(ep);
751
752 dpi.pdev = pdev;
753
754 mutex_init(&dpi.lock);
755
756 dpi_init_output(pdev);
757
758 dpi.port_initialized = true;
759
760 return 0;
761
762err_datalines:
763 of_node_put(ep);
764
765 return r;
766}
767
768void __exit dpi_uninit_port(void)
769{
770 if (!dpi.port_initialized)
771 return;
772
773 dpi_uninit_output(dpi.pdev);
774}
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
deleted file mode 100644
index 8be9b04d8849..000000000000
--- a/drivers/video/omap2/dss/dsi.c
+++ /dev/null
@@ -1,5751 +0,0 @@
1/*
2 * linux/drivers/video/omap2/dss/dsi.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.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 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#define DSS_SUBSYS_NAME "DSI"
21
22#include <linux/kernel.h>
23#include <linux/io.h>
24#include <linux/clk.h>
25#include <linux/device.h>
26#include <linux/err.h>
27#include <linux/interrupt.h>
28#include <linux/delay.h>
29#include <linux/mutex.h>
30#include <linux/module.h>
31#include <linux/semaphore.h>
32#include <linux/seq_file.h>
33#include <linux/platform_device.h>
34#include <linux/regulator/consumer.h>
35#include <linux/wait.h>
36#include <linux/workqueue.h>
37#include <linux/sched.h>
38#include <linux/slab.h>
39#include <linux/debugfs.h>
40#include <linux/pm_runtime.h>
41#include <linux/of.h>
42#include <linux/of_platform.h>
43
44#include <video/omapdss.h>
45#include <video/mipi_display.h>
46
47#include "dss.h"
48#include "dss_features.h"
49
50#define DSI_CATCH_MISSING_TE
51
52struct dsi_reg { u16 module; u16 idx; };
53
54#define DSI_REG(mod, idx) ((const struct dsi_reg) { mod, idx })
55
56/* DSI Protocol Engine */
57
58#define DSI_PROTO 0
59#define DSI_PROTO_SZ 0x200
60
61#define DSI_REVISION DSI_REG(DSI_PROTO, 0x0000)
62#define DSI_SYSCONFIG DSI_REG(DSI_PROTO, 0x0010)
63#define DSI_SYSSTATUS DSI_REG(DSI_PROTO, 0x0014)
64#define DSI_IRQSTATUS DSI_REG(DSI_PROTO, 0x0018)
65#define DSI_IRQENABLE DSI_REG(DSI_PROTO, 0x001C)
66#define DSI_CTRL DSI_REG(DSI_PROTO, 0x0040)
67#define DSI_GNQ DSI_REG(DSI_PROTO, 0x0044)
68#define DSI_COMPLEXIO_CFG1 DSI_REG(DSI_PROTO, 0x0048)
69#define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(DSI_PROTO, 0x004C)
70#define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(DSI_PROTO, 0x0050)
71#define DSI_CLK_CTRL DSI_REG(DSI_PROTO, 0x0054)
72#define DSI_TIMING1 DSI_REG(DSI_PROTO, 0x0058)
73#define DSI_TIMING2 DSI_REG(DSI_PROTO, 0x005C)
74#define DSI_VM_TIMING1 DSI_REG(DSI_PROTO, 0x0060)
75#define DSI_VM_TIMING2 DSI_REG(DSI_PROTO, 0x0064)
76#define DSI_VM_TIMING3 DSI_REG(DSI_PROTO, 0x0068)
77#define DSI_CLK_TIMING DSI_REG(DSI_PROTO, 0x006C)
78#define DSI_TX_FIFO_VC_SIZE DSI_REG(DSI_PROTO, 0x0070)
79#define DSI_RX_FIFO_VC_SIZE DSI_REG(DSI_PROTO, 0x0074)
80#define DSI_COMPLEXIO_CFG2 DSI_REG(DSI_PROTO, 0x0078)
81#define DSI_RX_FIFO_VC_FULLNESS DSI_REG(DSI_PROTO, 0x007C)
82#define DSI_VM_TIMING4 DSI_REG(DSI_PROTO, 0x0080)
83#define DSI_TX_FIFO_VC_EMPTINESS DSI_REG(DSI_PROTO, 0x0084)
84#define DSI_VM_TIMING5 DSI_REG(DSI_PROTO, 0x0088)
85#define DSI_VM_TIMING6 DSI_REG(DSI_PROTO, 0x008C)
86#define DSI_VM_TIMING7 DSI_REG(DSI_PROTO, 0x0090)
87#define DSI_STOPCLK_TIMING DSI_REG(DSI_PROTO, 0x0094)
88#define DSI_VC_CTRL(n) DSI_REG(DSI_PROTO, 0x0100 + (n * 0x20))
89#define DSI_VC_TE(n) DSI_REG(DSI_PROTO, 0x0104 + (n * 0x20))
90#define DSI_VC_LONG_PACKET_HEADER(n) DSI_REG(DSI_PROTO, 0x0108 + (n * 0x20))
91#define DSI_VC_LONG_PACKET_PAYLOAD(n) DSI_REG(DSI_PROTO, 0x010C + (n * 0x20))
92#define DSI_VC_SHORT_PACKET_HEADER(n) DSI_REG(DSI_PROTO, 0x0110 + (n * 0x20))
93#define DSI_VC_IRQSTATUS(n) DSI_REG(DSI_PROTO, 0x0118 + (n * 0x20))
94#define DSI_VC_IRQENABLE(n) DSI_REG(DSI_PROTO, 0x011C + (n * 0x20))
95
96/* DSIPHY_SCP */
97
98#define DSI_PHY 1
99#define DSI_PHY_OFFSET 0x200
100#define DSI_PHY_SZ 0x40
101
102#define DSI_DSIPHY_CFG0 DSI_REG(DSI_PHY, 0x0000)
103#define DSI_DSIPHY_CFG1 DSI_REG(DSI_PHY, 0x0004)
104#define DSI_DSIPHY_CFG2 DSI_REG(DSI_PHY, 0x0008)
105#define DSI_DSIPHY_CFG5 DSI_REG(DSI_PHY, 0x0014)
106#define DSI_DSIPHY_CFG10 DSI_REG(DSI_PHY, 0x0028)
107
108/* DSI_PLL_CTRL_SCP */
109
110#define DSI_PLL 2
111#define DSI_PLL_OFFSET 0x300
112#define DSI_PLL_SZ 0x20
113
114#define DSI_PLL_CONTROL DSI_REG(DSI_PLL, 0x0000)
115#define DSI_PLL_STATUS DSI_REG(DSI_PLL, 0x0004)
116#define DSI_PLL_GO DSI_REG(DSI_PLL, 0x0008)
117#define DSI_PLL_CONFIGURATION1 DSI_REG(DSI_PLL, 0x000C)
118#define DSI_PLL_CONFIGURATION2 DSI_REG(DSI_PLL, 0x0010)
119
120#define REG_GET(dsidev, idx, start, end) \
121 FLD_GET(dsi_read_reg(dsidev, idx), start, end)
122
123#define REG_FLD_MOD(dsidev, idx, val, start, end) \
124 dsi_write_reg(dsidev, idx, FLD_MOD(dsi_read_reg(dsidev, idx), val, start, end))
125
126/* Global interrupts */
127#define DSI_IRQ_VC0 (1 << 0)
128#define DSI_IRQ_VC1 (1 << 1)
129#define DSI_IRQ_VC2 (1 << 2)
130#define DSI_IRQ_VC3 (1 << 3)
131#define DSI_IRQ_WAKEUP (1 << 4)
132#define DSI_IRQ_RESYNC (1 << 5)
133#define DSI_IRQ_PLL_LOCK (1 << 7)
134#define DSI_IRQ_PLL_UNLOCK (1 << 8)
135#define DSI_IRQ_PLL_RECALL (1 << 9)
136#define DSI_IRQ_COMPLEXIO_ERR (1 << 10)
137#define DSI_IRQ_HS_TX_TIMEOUT (1 << 14)
138#define DSI_IRQ_LP_RX_TIMEOUT (1 << 15)
139#define DSI_IRQ_TE_TRIGGER (1 << 16)
140#define DSI_IRQ_ACK_TRIGGER (1 << 17)
141#define DSI_IRQ_SYNC_LOST (1 << 18)
142#define DSI_IRQ_LDO_POWER_GOOD (1 << 19)
143#define DSI_IRQ_TA_TIMEOUT (1 << 20)
144#define DSI_IRQ_ERROR_MASK \
145 (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \
146 DSI_IRQ_TA_TIMEOUT | DSI_IRQ_SYNC_LOST)
147#define DSI_IRQ_CHANNEL_MASK 0xf
148
149/* Virtual channel interrupts */
150#define DSI_VC_IRQ_CS (1 << 0)
151#define DSI_VC_IRQ_ECC_CORR (1 << 1)
152#define DSI_VC_IRQ_PACKET_SENT (1 << 2)
153#define DSI_VC_IRQ_FIFO_TX_OVF (1 << 3)
154#define DSI_VC_IRQ_FIFO_RX_OVF (1 << 4)
155#define DSI_VC_IRQ_BTA (1 << 5)
156#define DSI_VC_IRQ_ECC_NO_CORR (1 << 6)
157#define DSI_VC_IRQ_FIFO_TX_UDF (1 << 7)
158#define DSI_VC_IRQ_PP_BUSY_CHANGE (1 << 8)
159#define DSI_VC_IRQ_ERROR_MASK \
160 (DSI_VC_IRQ_CS | DSI_VC_IRQ_ECC_CORR | DSI_VC_IRQ_FIFO_TX_OVF | \
161 DSI_VC_IRQ_FIFO_RX_OVF | DSI_VC_IRQ_ECC_NO_CORR | \
162 DSI_VC_IRQ_FIFO_TX_UDF)
163
164/* ComplexIO interrupts */
165#define DSI_CIO_IRQ_ERRSYNCESC1 (1 << 0)
166#define DSI_CIO_IRQ_ERRSYNCESC2 (1 << 1)
167#define DSI_CIO_IRQ_ERRSYNCESC3 (1 << 2)
168#define DSI_CIO_IRQ_ERRSYNCESC4 (1 << 3)
169#define DSI_CIO_IRQ_ERRSYNCESC5 (1 << 4)
170#define DSI_CIO_IRQ_ERRESC1 (1 << 5)
171#define DSI_CIO_IRQ_ERRESC2 (1 << 6)
172#define DSI_CIO_IRQ_ERRESC3 (1 << 7)
173#define DSI_CIO_IRQ_ERRESC4 (1 << 8)
174#define DSI_CIO_IRQ_ERRESC5 (1 << 9)
175#define DSI_CIO_IRQ_ERRCONTROL1 (1 << 10)
176#define DSI_CIO_IRQ_ERRCONTROL2 (1 << 11)
177#define DSI_CIO_IRQ_ERRCONTROL3 (1 << 12)
178#define DSI_CIO_IRQ_ERRCONTROL4 (1 << 13)
179#define DSI_CIO_IRQ_ERRCONTROL5 (1 << 14)
180#define DSI_CIO_IRQ_STATEULPS1 (1 << 15)
181#define DSI_CIO_IRQ_STATEULPS2 (1 << 16)
182#define DSI_CIO_IRQ_STATEULPS3 (1 << 17)
183#define DSI_CIO_IRQ_STATEULPS4 (1 << 18)
184#define DSI_CIO_IRQ_STATEULPS5 (1 << 19)
185#define DSI_CIO_IRQ_ERRCONTENTIONLP0_1 (1 << 20)
186#define DSI_CIO_IRQ_ERRCONTENTIONLP1_1 (1 << 21)
187#define DSI_CIO_IRQ_ERRCONTENTIONLP0_2 (1 << 22)
188#define DSI_CIO_IRQ_ERRCONTENTIONLP1_2 (1 << 23)
189#define DSI_CIO_IRQ_ERRCONTENTIONLP0_3 (1 << 24)
190#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25)
191#define DSI_CIO_IRQ_ERRCONTENTIONLP0_4 (1 << 26)
192#define DSI_CIO_IRQ_ERRCONTENTIONLP1_4 (1 << 27)
193#define DSI_CIO_IRQ_ERRCONTENTIONLP0_5 (1 << 28)
194#define DSI_CIO_IRQ_ERRCONTENTIONLP1_5 (1 << 29)
195#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30)
196#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31)
197#define DSI_CIO_IRQ_ERROR_MASK \
198 (DSI_CIO_IRQ_ERRSYNCESC1 | DSI_CIO_IRQ_ERRSYNCESC2 | \
199 DSI_CIO_IRQ_ERRSYNCESC3 | DSI_CIO_IRQ_ERRSYNCESC4 | \
200 DSI_CIO_IRQ_ERRSYNCESC5 | \
201 DSI_CIO_IRQ_ERRESC1 | DSI_CIO_IRQ_ERRESC2 | \
202 DSI_CIO_IRQ_ERRESC3 | DSI_CIO_IRQ_ERRESC4 | \
203 DSI_CIO_IRQ_ERRESC5 | \
204 DSI_CIO_IRQ_ERRCONTROL1 | DSI_CIO_IRQ_ERRCONTROL2 | \
205 DSI_CIO_IRQ_ERRCONTROL3 | DSI_CIO_IRQ_ERRCONTROL4 | \
206 DSI_CIO_IRQ_ERRCONTROL5 | \
207 DSI_CIO_IRQ_ERRCONTENTIONLP0_1 | DSI_CIO_IRQ_ERRCONTENTIONLP1_1 | \
208 DSI_CIO_IRQ_ERRCONTENTIONLP0_2 | DSI_CIO_IRQ_ERRCONTENTIONLP1_2 | \
209 DSI_CIO_IRQ_ERRCONTENTIONLP0_3 | DSI_CIO_IRQ_ERRCONTENTIONLP1_3 | \
210 DSI_CIO_IRQ_ERRCONTENTIONLP0_4 | DSI_CIO_IRQ_ERRCONTENTIONLP1_4 | \
211 DSI_CIO_IRQ_ERRCONTENTIONLP0_5 | DSI_CIO_IRQ_ERRCONTENTIONLP1_5)
212
213typedef void (*omap_dsi_isr_t) (void *arg, u32 mask);
214
215static int dsi_display_init_dispc(struct platform_device *dsidev,
216 struct omap_overlay_manager *mgr);
217static void dsi_display_uninit_dispc(struct platform_device *dsidev,
218 struct omap_overlay_manager *mgr);
219
220static int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel);
221
222#define DSI_MAX_NR_ISRS 2
223#define DSI_MAX_NR_LANES 5
224
225enum dsi_lane_function {
226 DSI_LANE_UNUSED = 0,
227 DSI_LANE_CLK,
228 DSI_LANE_DATA1,
229 DSI_LANE_DATA2,
230 DSI_LANE_DATA3,
231 DSI_LANE_DATA4,
232};
233
234struct dsi_lane_config {
235 enum dsi_lane_function function;
236 u8 polarity;
237};
238
239struct dsi_isr_data {
240 omap_dsi_isr_t isr;
241 void *arg;
242 u32 mask;
243};
244
245enum fifo_size {
246 DSI_FIFO_SIZE_0 = 0,
247 DSI_FIFO_SIZE_32 = 1,
248 DSI_FIFO_SIZE_64 = 2,
249 DSI_FIFO_SIZE_96 = 3,
250 DSI_FIFO_SIZE_128 = 4,
251};
252
253enum dsi_vc_source {
254 DSI_VC_SOURCE_L4 = 0,
255 DSI_VC_SOURCE_VP,
256};
257
258struct dsi_irq_stats {
259 unsigned long last_reset;
260 unsigned irq_count;
261 unsigned dsi_irqs[32];
262 unsigned vc_irqs[4][32];
263 unsigned cio_irqs[32];
264};
265
266struct dsi_isr_tables {
267 struct dsi_isr_data isr_table[DSI_MAX_NR_ISRS];
268 struct dsi_isr_data isr_table_vc[4][DSI_MAX_NR_ISRS];
269 struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS];
270};
271
272struct dsi_clk_calc_ctx {
273 struct platform_device *dsidev;
274
275 /* inputs */
276
277 const struct omap_dss_dsi_config *config;
278
279 unsigned long req_pck_min, req_pck_nom, req_pck_max;
280
281 /* outputs */
282
283 struct dsi_clock_info dsi_cinfo;
284 struct dispc_clock_info dispc_cinfo;
285
286 struct omap_video_timings dispc_vm;
287 struct omap_dss_dsi_videomode_timings dsi_vm;
288};
289
290struct dsi_data {
291 struct platform_device *pdev;
292 void __iomem *proto_base;
293 void __iomem *phy_base;
294 void __iomem *pll_base;
295
296 int module_id;
297
298 int irq;
299
300 bool is_enabled;
301
302 struct clk *dss_clk;
303 struct clk *sys_clk;
304
305 struct dispc_clock_info user_dispc_cinfo;
306 struct dsi_clock_info user_dsi_cinfo;
307
308 struct dsi_clock_info current_cinfo;
309
310 bool vdds_dsi_enabled;
311 struct regulator *vdds_dsi_reg;
312
313 struct {
314 enum dsi_vc_source source;
315 struct omap_dss_device *dssdev;
316 enum fifo_size tx_fifo_size;
317 enum fifo_size rx_fifo_size;
318 int vc_id;
319 } vc[4];
320
321 struct mutex lock;
322 struct semaphore bus_lock;
323
324 unsigned pll_locked;
325
326 spinlock_t irq_lock;
327 struct dsi_isr_tables isr_tables;
328 /* space for a copy used by the interrupt handler */
329 struct dsi_isr_tables isr_tables_copy;
330
331 int update_channel;
332#ifdef DSI_PERF_MEASURE
333 unsigned update_bytes;
334#endif
335
336 bool te_enabled;
337 bool ulps_enabled;
338
339 void (*framedone_callback)(int, void *);
340 void *framedone_data;
341
342 struct delayed_work framedone_timeout_work;
343
344#ifdef DSI_CATCH_MISSING_TE
345 struct timer_list te_timer;
346#endif
347
348 unsigned long cache_req_pck;
349 unsigned long cache_clk_freq;
350 struct dsi_clock_info cache_cinfo;
351
352 u32 errors;
353 spinlock_t errors_lock;
354#ifdef DSI_PERF_MEASURE
355 ktime_t perf_setup_time;
356 ktime_t perf_start_time;
357#endif
358 int debug_read;
359 int debug_write;
360
361#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
362 spinlock_t irq_stats_lock;
363 struct dsi_irq_stats irq_stats;
364#endif
365 /* DSI PLL Parameter Ranges */
366 unsigned long regm_max, regn_max;
367 unsigned long regm_dispc_max, regm_dsi_max;
368 unsigned long fint_min, fint_max;
369 unsigned long lpdiv_max;
370
371 unsigned num_lanes_supported;
372 unsigned line_buffer_size;
373
374 struct dsi_lane_config lanes[DSI_MAX_NR_LANES];
375 unsigned num_lanes_used;
376
377 unsigned scp_clk_refcount;
378
379 struct dss_lcd_mgr_config mgr_config;
380 struct omap_video_timings timings;
381 enum omap_dss_dsi_pixel_format pix_fmt;
382 enum omap_dss_dsi_mode mode;
383 struct omap_dss_dsi_videomode_timings vm_timings;
384
385 struct omap_dss_device output;
386};
387
388struct dsi_packet_sent_handler_data {
389 struct platform_device *dsidev;
390 struct completion *completion;
391};
392
393struct dsi_module_id_data {
394 u32 address;
395 int id;
396};
397
398static const struct of_device_id dsi_of_match[];
399
400#ifdef DSI_PERF_MEASURE
401static bool dsi_perf;
402module_param(dsi_perf, bool, 0644);
403#endif
404
405static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dsidev)
406{
407 return dev_get_drvdata(&dsidev->dev);
408}
409
410static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev)
411{
412 return to_platform_device(dssdev->dev);
413}
414
415struct platform_device *dsi_get_dsidev_from_id(int module)
416{
417 struct omap_dss_device *out;
418 enum omap_dss_output_id id;
419
420 switch (module) {
421 case 0:
422 id = OMAP_DSS_OUTPUT_DSI1;
423 break;
424 case 1:
425 id = OMAP_DSS_OUTPUT_DSI2;
426 break;
427 default:
428 return NULL;
429 }
430
431 out = omap_dss_get_output(id);
432
433 return out ? to_platform_device(out->dev) : NULL;
434}
435
436static inline void dsi_write_reg(struct platform_device *dsidev,
437 const struct dsi_reg idx, u32 val)
438{
439 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
440 void __iomem *base;
441
442 switch(idx.module) {
443 case DSI_PROTO: base = dsi->proto_base; break;
444 case DSI_PHY: base = dsi->phy_base; break;
445 case DSI_PLL: base = dsi->pll_base; break;
446 default: return;
447 }
448
449 __raw_writel(val, base + idx.idx);
450}
451
452static inline u32 dsi_read_reg(struct platform_device *dsidev,
453 const struct dsi_reg idx)
454{
455 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
456 void __iomem *base;
457
458 switch(idx.module) {
459 case DSI_PROTO: base = dsi->proto_base; break;
460 case DSI_PHY: base = dsi->phy_base; break;
461 case DSI_PLL: base = dsi->pll_base; break;
462 default: return 0;
463 }
464
465 return __raw_readl(base + idx.idx);
466}
467
468static void dsi_bus_lock(struct omap_dss_device *dssdev)
469{
470 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
471 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
472
473 down(&dsi->bus_lock);
474}
475
476static void dsi_bus_unlock(struct omap_dss_device *dssdev)
477{
478 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
479 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
480
481 up(&dsi->bus_lock);
482}
483
484static bool dsi_bus_is_locked(struct platform_device *dsidev)
485{
486 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
487
488 return dsi->bus_lock.count == 0;
489}
490
491static void dsi_completion_handler(void *data, u32 mask)
492{
493 complete((struct completion *)data);
494}
495
496static inline int wait_for_bit_change(struct platform_device *dsidev,
497 const struct dsi_reg idx, int bitnum, int value)
498{
499 unsigned long timeout;
500 ktime_t wait;
501 int t;
502
503 /* first busyloop to see if the bit changes right away */
504 t = 100;
505 while (t-- > 0) {
506 if (REG_GET(dsidev, idx, bitnum, bitnum) == value)
507 return value;
508 }
509
510 /* then loop for 500ms, sleeping for 1ms in between */
511 timeout = jiffies + msecs_to_jiffies(500);
512 while (time_before(jiffies, timeout)) {
513 if (REG_GET(dsidev, idx, bitnum, bitnum) == value)
514 return value;
515
516 wait = ns_to_ktime(1000 * 1000);
517 set_current_state(TASK_UNINTERRUPTIBLE);
518 schedule_hrtimeout(&wait, HRTIMER_MODE_REL);
519 }
520
521 return !value;
522}
523
524u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
525{
526 switch (fmt) {
527 case OMAP_DSS_DSI_FMT_RGB888:
528 case OMAP_DSS_DSI_FMT_RGB666:
529 return 24;
530 case OMAP_DSS_DSI_FMT_RGB666_PACKED:
531 return 18;
532 case OMAP_DSS_DSI_FMT_RGB565:
533 return 16;
534 default:
535 BUG();
536 return 0;
537 }
538}
539
540#ifdef DSI_PERF_MEASURE
541static void dsi_perf_mark_setup(struct platform_device *dsidev)
542{
543 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
544 dsi->perf_setup_time = ktime_get();
545}
546
547static void dsi_perf_mark_start(struct platform_device *dsidev)
548{
549 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
550 dsi->perf_start_time = ktime_get();
551}
552
553static void dsi_perf_show(struct platform_device *dsidev, const char *name)
554{
555 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
556 ktime_t t, setup_time, trans_time;
557 u32 total_bytes;
558 u32 setup_us, trans_us, total_us;
559
560 if (!dsi_perf)
561 return;
562
563 t = ktime_get();
564
565 setup_time = ktime_sub(dsi->perf_start_time, dsi->perf_setup_time);
566 setup_us = (u32)ktime_to_us(setup_time);
567 if (setup_us == 0)
568 setup_us = 1;
569
570 trans_time = ktime_sub(t, dsi->perf_start_time);
571 trans_us = (u32)ktime_to_us(trans_time);
572 if (trans_us == 0)
573 trans_us = 1;
574
575 total_us = setup_us + trans_us;
576
577 total_bytes = dsi->update_bytes;
578
579 printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
580 "%u bytes, %u kbytes/sec\n",
581 name,
582 setup_us,
583 trans_us,
584 total_us,
585 1000*1000 / total_us,
586 total_bytes,
587 total_bytes * 1000 / total_us);
588}
589#else
590static inline void dsi_perf_mark_setup(struct platform_device *dsidev)
591{
592}
593
594static inline void dsi_perf_mark_start(struct platform_device *dsidev)
595{
596}
597
598static inline void dsi_perf_show(struct platform_device *dsidev,
599 const char *name)
600{
601}
602#endif
603
604static int verbose_irq;
605
606static void print_irq_status(u32 status)
607{
608 if (status == 0)
609 return;
610
611 if (!verbose_irq && (status & ~DSI_IRQ_CHANNEL_MASK) == 0)
612 return;
613
614#define PIS(x) (status & DSI_IRQ_##x) ? (#x " ") : ""
615
616 pr_debug("DSI IRQ: 0x%x: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
617 status,
618 verbose_irq ? PIS(VC0) : "",
619 verbose_irq ? PIS(VC1) : "",
620 verbose_irq ? PIS(VC2) : "",
621 verbose_irq ? PIS(VC3) : "",
622 PIS(WAKEUP),
623 PIS(RESYNC),
624 PIS(PLL_LOCK),
625 PIS(PLL_UNLOCK),
626 PIS(PLL_RECALL),
627 PIS(COMPLEXIO_ERR),
628 PIS(HS_TX_TIMEOUT),
629 PIS(LP_RX_TIMEOUT),
630 PIS(TE_TRIGGER),
631 PIS(ACK_TRIGGER),
632 PIS(SYNC_LOST),
633 PIS(LDO_POWER_GOOD),
634 PIS(TA_TIMEOUT));
635#undef PIS
636}
637
638static void print_irq_status_vc(int channel, u32 status)
639{
640 if (status == 0)
641 return;
642
643 if (!verbose_irq && (status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
644 return;
645
646#define PIS(x) (status & DSI_VC_IRQ_##x) ? (#x " ") : ""
647
648 pr_debug("DSI VC(%d) IRQ 0x%x: %s%s%s%s%s%s%s%s%s\n",
649 channel,
650 status,
651 PIS(CS),
652 PIS(ECC_CORR),
653 PIS(ECC_NO_CORR),
654 verbose_irq ? PIS(PACKET_SENT) : "",
655 PIS(BTA),
656 PIS(FIFO_TX_OVF),
657 PIS(FIFO_RX_OVF),
658 PIS(FIFO_TX_UDF),
659 PIS(PP_BUSY_CHANGE));
660#undef PIS
661}
662
663static void print_irq_status_cio(u32 status)
664{
665 if (status == 0)
666 return;
667
668#define PIS(x) (status & DSI_CIO_IRQ_##x) ? (#x " ") : ""
669
670 pr_debug("DSI CIO IRQ 0x%x: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
671 status,
672 PIS(ERRSYNCESC1),
673 PIS(ERRSYNCESC2),
674 PIS(ERRSYNCESC3),
675 PIS(ERRESC1),
676 PIS(ERRESC2),
677 PIS(ERRESC3),
678 PIS(ERRCONTROL1),
679 PIS(ERRCONTROL2),
680 PIS(ERRCONTROL3),
681 PIS(STATEULPS1),
682 PIS(STATEULPS2),
683 PIS(STATEULPS3),
684 PIS(ERRCONTENTIONLP0_1),
685 PIS(ERRCONTENTIONLP1_1),
686 PIS(ERRCONTENTIONLP0_2),
687 PIS(ERRCONTENTIONLP1_2),
688 PIS(ERRCONTENTIONLP0_3),
689 PIS(ERRCONTENTIONLP1_3),
690 PIS(ULPSACTIVENOT_ALL0),
691 PIS(ULPSACTIVENOT_ALL1));
692#undef PIS
693}
694
695#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
696static void dsi_collect_irq_stats(struct platform_device *dsidev, u32 irqstatus,
697 u32 *vcstatus, u32 ciostatus)
698{
699 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
700 int i;
701
702 spin_lock(&dsi->irq_stats_lock);
703
704 dsi->irq_stats.irq_count++;
705 dss_collect_irq_stats(irqstatus, dsi->irq_stats.dsi_irqs);
706
707 for (i = 0; i < 4; ++i)
708 dss_collect_irq_stats(vcstatus[i], dsi->irq_stats.vc_irqs[i]);
709
710 dss_collect_irq_stats(ciostatus, dsi->irq_stats.cio_irqs);
711
712 spin_unlock(&dsi->irq_stats_lock);
713}
714#else
715#define dsi_collect_irq_stats(dsidev, irqstatus, vcstatus, ciostatus)
716#endif
717
718static int debug_irq;
719
720static void dsi_handle_irq_errors(struct platform_device *dsidev, u32 irqstatus,
721 u32 *vcstatus, u32 ciostatus)
722{
723 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
724 int i;
725
726 if (irqstatus & DSI_IRQ_ERROR_MASK) {
727 DSSERR("DSI error, irqstatus %x\n", irqstatus);
728 print_irq_status(irqstatus);
729 spin_lock(&dsi->errors_lock);
730 dsi->errors |= irqstatus & DSI_IRQ_ERROR_MASK;
731 spin_unlock(&dsi->errors_lock);
732 } else if (debug_irq) {
733 print_irq_status(irqstatus);
734 }
735
736 for (i = 0; i < 4; ++i) {
737 if (vcstatus[i] & DSI_VC_IRQ_ERROR_MASK) {
738 DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
739 i, vcstatus[i]);
740 print_irq_status_vc(i, vcstatus[i]);
741 } else if (debug_irq) {
742 print_irq_status_vc(i, vcstatus[i]);
743 }
744 }
745
746 if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) {
747 DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
748 print_irq_status_cio(ciostatus);
749 } else if (debug_irq) {
750 print_irq_status_cio(ciostatus);
751 }
752}
753
754static void dsi_call_isrs(struct dsi_isr_data *isr_array,
755 unsigned isr_array_size, u32 irqstatus)
756{
757 struct dsi_isr_data *isr_data;
758 int i;
759
760 for (i = 0; i < isr_array_size; i++) {
761 isr_data = &isr_array[i];
762 if (isr_data->isr && isr_data->mask & irqstatus)
763 isr_data->isr(isr_data->arg, irqstatus);
764 }
765}
766
767static void dsi_handle_isrs(struct dsi_isr_tables *isr_tables,
768 u32 irqstatus, u32 *vcstatus, u32 ciostatus)
769{
770 int i;
771
772 dsi_call_isrs(isr_tables->isr_table,
773 ARRAY_SIZE(isr_tables->isr_table),
774 irqstatus);
775
776 for (i = 0; i < 4; ++i) {
777 if (vcstatus[i] == 0)
778 continue;
779 dsi_call_isrs(isr_tables->isr_table_vc[i],
780 ARRAY_SIZE(isr_tables->isr_table_vc[i]),
781 vcstatus[i]);
782 }
783
784 if (ciostatus != 0)
785 dsi_call_isrs(isr_tables->isr_table_cio,
786 ARRAY_SIZE(isr_tables->isr_table_cio),
787 ciostatus);
788}
789
790static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
791{
792 struct platform_device *dsidev;
793 struct dsi_data *dsi;
794 u32 irqstatus, vcstatus[4], ciostatus;
795 int i;
796
797 dsidev = (struct platform_device *) arg;
798 dsi = dsi_get_dsidrv_data(dsidev);
799
800 if (!dsi->is_enabled)
801 return IRQ_NONE;
802
803 spin_lock(&dsi->irq_lock);
804
805 irqstatus = dsi_read_reg(dsidev, DSI_IRQSTATUS);
806
807 /* IRQ is not for us */
808 if (!irqstatus) {
809 spin_unlock(&dsi->irq_lock);
810 return IRQ_NONE;
811 }
812
813 dsi_write_reg(dsidev, DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
814 /* flush posted write */
815 dsi_read_reg(dsidev, DSI_IRQSTATUS);
816
817 for (i = 0; i < 4; ++i) {
818 if ((irqstatus & (1 << i)) == 0) {
819 vcstatus[i] = 0;
820 continue;
821 }
822
823 vcstatus[i] = dsi_read_reg(dsidev, DSI_VC_IRQSTATUS(i));
824
825 dsi_write_reg(dsidev, DSI_VC_IRQSTATUS(i), vcstatus[i]);
826 /* flush posted write */
827 dsi_read_reg(dsidev, DSI_VC_IRQSTATUS(i));
828 }
829
830 if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) {
831 ciostatus = dsi_read_reg(dsidev, DSI_COMPLEXIO_IRQ_STATUS);
832
833 dsi_write_reg(dsidev, DSI_COMPLEXIO_IRQ_STATUS, ciostatus);
834 /* flush posted write */
835 dsi_read_reg(dsidev, DSI_COMPLEXIO_IRQ_STATUS);
836 } else {
837 ciostatus = 0;
838 }
839
840#ifdef DSI_CATCH_MISSING_TE
841 if (irqstatus & DSI_IRQ_TE_TRIGGER)
842 del_timer(&dsi->te_timer);
843#endif
844
845 /* make a copy and unlock, so that isrs can unregister
846 * themselves */
847 memcpy(&dsi->isr_tables_copy, &dsi->isr_tables,
848 sizeof(dsi->isr_tables));
849
850 spin_unlock(&dsi->irq_lock);
851
852 dsi_handle_isrs(&dsi->isr_tables_copy, irqstatus, vcstatus, ciostatus);
853
854 dsi_handle_irq_errors(dsidev, irqstatus, vcstatus, ciostatus);
855
856 dsi_collect_irq_stats(dsidev, irqstatus, vcstatus, ciostatus);
857
858 return IRQ_HANDLED;
859}
860
861/* dsi->irq_lock has to be locked by the caller */
862static void _omap_dsi_configure_irqs(struct platform_device *dsidev,
863 struct dsi_isr_data *isr_array,
864 unsigned isr_array_size, u32 default_mask,
865 const struct dsi_reg enable_reg,
866 const struct dsi_reg status_reg)
867{
868 struct dsi_isr_data *isr_data;
869 u32 mask;
870 u32 old_mask;
871 int i;
872
873 mask = default_mask;
874
875 for (i = 0; i < isr_array_size; i++) {
876 isr_data = &isr_array[i];
877
878 if (isr_data->isr == NULL)
879 continue;
880
881 mask |= isr_data->mask;
882 }
883
884 old_mask = dsi_read_reg(dsidev, enable_reg);
885 /* clear the irqstatus for newly enabled irqs */
886 dsi_write_reg(dsidev, status_reg, (mask ^ old_mask) & mask);
887 dsi_write_reg(dsidev, enable_reg, mask);
888
889 /* flush posted writes */
890 dsi_read_reg(dsidev, enable_reg);
891 dsi_read_reg(dsidev, status_reg);
892}
893
894/* dsi->irq_lock has to be locked by the caller */
895static void _omap_dsi_set_irqs(struct platform_device *dsidev)
896{
897 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
898 u32 mask = DSI_IRQ_ERROR_MASK;
899#ifdef DSI_CATCH_MISSING_TE
900 mask |= DSI_IRQ_TE_TRIGGER;
901#endif
902 _omap_dsi_configure_irqs(dsidev, dsi->isr_tables.isr_table,
903 ARRAY_SIZE(dsi->isr_tables.isr_table), mask,
904 DSI_IRQENABLE, DSI_IRQSTATUS);
905}
906
907/* dsi->irq_lock has to be locked by the caller */
908static void _omap_dsi_set_irqs_vc(struct platform_device *dsidev, int vc)
909{
910 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
911
912 _omap_dsi_configure_irqs(dsidev, dsi->isr_tables.isr_table_vc[vc],
913 ARRAY_SIZE(dsi->isr_tables.isr_table_vc[vc]),
914 DSI_VC_IRQ_ERROR_MASK,
915 DSI_VC_IRQENABLE(vc), DSI_VC_IRQSTATUS(vc));
916}
917
918/* dsi->irq_lock has to be locked by the caller */
919static void _omap_dsi_set_irqs_cio(struct platform_device *dsidev)
920{
921 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
922
923 _omap_dsi_configure_irqs(dsidev, dsi->isr_tables.isr_table_cio,
924 ARRAY_SIZE(dsi->isr_tables.isr_table_cio),
925 DSI_CIO_IRQ_ERROR_MASK,
926 DSI_COMPLEXIO_IRQ_ENABLE, DSI_COMPLEXIO_IRQ_STATUS);
927}
928
929static void _dsi_initialize_irq(struct platform_device *dsidev)
930{
931 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
932 unsigned long flags;
933 int vc;
934
935 spin_lock_irqsave(&dsi->irq_lock, flags);
936
937 memset(&dsi->isr_tables, 0, sizeof(dsi->isr_tables));
938
939 _omap_dsi_set_irqs(dsidev);
940 for (vc = 0; vc < 4; ++vc)
941 _omap_dsi_set_irqs_vc(dsidev, vc);
942 _omap_dsi_set_irqs_cio(dsidev);
943
944 spin_unlock_irqrestore(&dsi->irq_lock, flags);
945}
946
947static int _dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask,
948 struct dsi_isr_data *isr_array, unsigned isr_array_size)
949{
950 struct dsi_isr_data *isr_data;
951 int free_idx;
952 int i;
953
954 BUG_ON(isr == NULL);
955
956 /* check for duplicate entry and find a free slot */
957 free_idx = -1;
958 for (i = 0; i < isr_array_size; i++) {
959 isr_data = &isr_array[i];
960
961 if (isr_data->isr == isr && isr_data->arg == arg &&
962 isr_data->mask == mask) {
963 return -EINVAL;
964 }
965
966 if (isr_data->isr == NULL && free_idx == -1)
967 free_idx = i;
968 }
969
970 if (free_idx == -1)
971 return -EBUSY;
972
973 isr_data = &isr_array[free_idx];
974 isr_data->isr = isr;
975 isr_data->arg = arg;
976 isr_data->mask = mask;
977
978 return 0;
979}
980
981static int _dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask,
982 struct dsi_isr_data *isr_array, unsigned isr_array_size)
983{
984 struct dsi_isr_data *isr_data;
985 int i;
986
987 for (i = 0; i < isr_array_size; i++) {
988 isr_data = &isr_array[i];
989 if (isr_data->isr != isr || isr_data->arg != arg ||
990 isr_data->mask != mask)
991 continue;
992
993 isr_data->isr = NULL;
994 isr_data->arg = NULL;
995 isr_data->mask = 0;
996
997 return 0;
998 }
999
1000 return -EINVAL;
1001}
1002
1003static int dsi_register_isr(struct platform_device *dsidev, omap_dsi_isr_t isr,
1004 void *arg, u32 mask)
1005{
1006 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1007 unsigned long flags;
1008 int r;
1009
1010 spin_lock_irqsave(&dsi->irq_lock, flags);
1011
1012 r = _dsi_register_isr(isr, arg, mask, dsi->isr_tables.isr_table,
1013 ARRAY_SIZE(dsi->isr_tables.isr_table));
1014
1015 if (r == 0)
1016 _omap_dsi_set_irqs(dsidev);
1017
1018 spin_unlock_irqrestore(&dsi->irq_lock, flags);
1019
1020 return r;
1021}
1022
1023static int dsi_unregister_isr(struct platform_device *dsidev,
1024 omap_dsi_isr_t isr, void *arg, u32 mask)
1025{
1026 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1027 unsigned long flags;
1028 int r;
1029
1030 spin_lock_irqsave(&dsi->irq_lock, flags);
1031
1032 r = _dsi_unregister_isr(isr, arg, mask, dsi->isr_tables.isr_table,
1033 ARRAY_SIZE(dsi->isr_tables.isr_table));
1034
1035 if (r == 0)
1036 _omap_dsi_set_irqs(dsidev);
1037
1038 spin_unlock_irqrestore(&dsi->irq_lock, flags);
1039
1040 return r;
1041}
1042
1043static int dsi_register_isr_vc(struct platform_device *dsidev, int channel,
1044 omap_dsi_isr_t isr, void *arg, u32 mask)
1045{
1046 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1047 unsigned long flags;
1048 int r;
1049
1050 spin_lock_irqsave(&dsi->irq_lock, flags);
1051
1052 r = _dsi_register_isr(isr, arg, mask,
1053 dsi->isr_tables.isr_table_vc[channel],
1054 ARRAY_SIZE(dsi->isr_tables.isr_table_vc[channel]));
1055
1056 if (r == 0)
1057 _omap_dsi_set_irqs_vc(dsidev, channel);
1058
1059 spin_unlock_irqrestore(&dsi->irq_lock, flags);
1060
1061 return r;
1062}
1063
1064static int dsi_unregister_isr_vc(struct platform_device *dsidev, int channel,
1065 omap_dsi_isr_t isr, void *arg, u32 mask)
1066{
1067 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1068 unsigned long flags;
1069 int r;
1070
1071 spin_lock_irqsave(&dsi->irq_lock, flags);
1072
1073 r = _dsi_unregister_isr(isr, arg, mask,
1074 dsi->isr_tables.isr_table_vc[channel],
1075 ARRAY_SIZE(dsi->isr_tables.isr_table_vc[channel]));
1076
1077 if (r == 0)
1078 _omap_dsi_set_irqs_vc(dsidev, channel);
1079
1080 spin_unlock_irqrestore(&dsi->irq_lock, flags);
1081
1082 return r;
1083}
1084
1085static int dsi_register_isr_cio(struct platform_device *dsidev,
1086 omap_dsi_isr_t isr, void *arg, u32 mask)
1087{
1088 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1089 unsigned long flags;
1090 int r;
1091
1092 spin_lock_irqsave(&dsi->irq_lock, flags);
1093
1094 r = _dsi_register_isr(isr, arg, mask, dsi->isr_tables.isr_table_cio,
1095 ARRAY_SIZE(dsi->isr_tables.isr_table_cio));
1096
1097 if (r == 0)
1098 _omap_dsi_set_irqs_cio(dsidev);
1099
1100 spin_unlock_irqrestore(&dsi->irq_lock, flags);
1101
1102 return r;
1103}
1104
1105static int dsi_unregister_isr_cio(struct platform_device *dsidev,
1106 omap_dsi_isr_t isr, void *arg, u32 mask)
1107{
1108 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1109 unsigned long flags;
1110 int r;
1111
1112 spin_lock_irqsave(&dsi->irq_lock, flags);
1113
1114 r = _dsi_unregister_isr(isr, arg, mask, dsi->isr_tables.isr_table_cio,
1115 ARRAY_SIZE(dsi->isr_tables.isr_table_cio));
1116
1117 if (r == 0)
1118 _omap_dsi_set_irqs_cio(dsidev);
1119
1120 spin_unlock_irqrestore(&dsi->irq_lock, flags);
1121
1122 return r;
1123}
1124
1125static u32 dsi_get_errors(struct platform_device *dsidev)
1126{
1127 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1128 unsigned long flags;
1129 u32 e;
1130 spin_lock_irqsave(&dsi->errors_lock, flags);
1131 e = dsi->errors;
1132 dsi->errors = 0;
1133 spin_unlock_irqrestore(&dsi->errors_lock, flags);
1134 return e;
1135}
1136
1137int dsi_runtime_get(struct platform_device *dsidev)
1138{
1139 int r;
1140 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1141
1142 DSSDBG("dsi_runtime_get\n");
1143
1144 r = pm_runtime_get_sync(&dsi->pdev->dev);
1145 WARN_ON(r < 0);
1146 return r < 0 ? r : 0;
1147}
1148
1149void dsi_runtime_put(struct platform_device *dsidev)
1150{
1151 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1152 int r;
1153
1154 DSSDBG("dsi_runtime_put\n");
1155
1156 r = pm_runtime_put_sync(&dsi->pdev->dev);
1157 WARN_ON(r < 0 && r != -ENOSYS);
1158}
1159
1160static int dsi_regulator_init(struct platform_device *dsidev)
1161{
1162 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1163 struct regulator *vdds_dsi;
1164
1165 if (dsi->vdds_dsi_reg != NULL)
1166 return 0;
1167
1168 vdds_dsi = devm_regulator_get(&dsi->pdev->dev, "vdd");
1169
1170 if (IS_ERR(vdds_dsi)) {
1171 if (PTR_ERR(vdds_dsi) != -EPROBE_DEFER)
1172 DSSERR("can't get DSI VDD regulator\n");
1173 return PTR_ERR(vdds_dsi);
1174 }
1175
1176 dsi->vdds_dsi_reg = vdds_dsi;
1177
1178 return 0;
1179}
1180
1181/* source clock for DSI PLL. this could also be PCLKFREE */
1182static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
1183 bool enable)
1184{
1185 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1186
1187 if (enable)
1188 clk_prepare_enable(dsi->sys_clk);
1189 else
1190 clk_disable_unprepare(dsi->sys_clk);
1191
1192 if (enable && dsi->pll_locked) {
1193 if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1)
1194 DSSERR("cannot lock PLL when enabling clocks\n");
1195 }
1196}
1197
1198static void _dsi_print_reset_status(struct platform_device *dsidev)
1199{
1200 u32 l;
1201 int b0, b1, b2;
1202
1203 /* A dummy read using the SCP interface to any DSIPHY register is
1204 * required after DSIPHY reset to complete the reset of the DSI complex
1205 * I/O. */
1206 l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
1207
1208 if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) {
1209 b0 = 28;
1210 b1 = 27;
1211 b2 = 26;
1212 } else {
1213 b0 = 24;
1214 b1 = 25;
1215 b2 = 26;
1216 }
1217
1218#define DSI_FLD_GET(fld, start, end)\
1219 FLD_GET(dsi_read_reg(dsidev, DSI_##fld), start, end)
1220
1221 pr_debug("DSI resets: PLL (%d) CIO (%d) PHY (%x%x%x, %d, %d, %d)\n",
1222 DSI_FLD_GET(PLL_STATUS, 0, 0),
1223 DSI_FLD_GET(COMPLEXIO_CFG1, 29, 29),
1224 DSI_FLD_GET(DSIPHY_CFG5, b0, b0),
1225 DSI_FLD_GET(DSIPHY_CFG5, b1, b1),
1226 DSI_FLD_GET(DSIPHY_CFG5, b2, b2),
1227 DSI_FLD_GET(DSIPHY_CFG5, 29, 29),
1228 DSI_FLD_GET(DSIPHY_CFG5, 30, 30),
1229 DSI_FLD_GET(DSIPHY_CFG5, 31, 31));
1230
1231#undef DSI_FLD_GET
1232}
1233
1234static inline int dsi_if_enable(struct platform_device *dsidev, bool enable)
1235{
1236 DSSDBG("dsi_if_enable(%d)\n", enable);
1237
1238 enable = enable ? 1 : 0;
1239 REG_FLD_MOD(dsidev, DSI_CTRL, enable, 0, 0); /* IF_EN */
1240
1241 if (wait_for_bit_change(dsidev, DSI_CTRL, 0, enable) != enable) {
1242 DSSERR("Failed to set dsi_if_enable to %d\n", enable);
1243 return -EIO;
1244 }
1245
1246 return 0;
1247}
1248
1249unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
1250{
1251 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1252
1253 return dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk;
1254}
1255
1256static unsigned long dsi_get_pll_hsdiv_dsi_rate(struct platform_device *dsidev)
1257{
1258 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1259
1260 return dsi->current_cinfo.dsi_pll_hsdiv_dsi_clk;
1261}
1262
1263static unsigned long dsi_get_txbyteclkhs(struct platform_device *dsidev)
1264{
1265 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1266
1267 return dsi->current_cinfo.clkin4ddr / 16;
1268}
1269
1270static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
1271{
1272 unsigned long r;
1273 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1274
1275 if (dss_get_dsi_clk_source(dsi->module_id) == OMAP_DSS_CLK_SRC_FCK) {
1276 /* DSI FCLK source is DSS_CLK_FCK */
1277 r = clk_get_rate(dsi->dss_clk);
1278 } else {
1279 /* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */
1280 r = dsi_get_pll_hsdiv_dsi_rate(dsidev);
1281 }
1282
1283 return r;
1284}
1285
1286static int dsi_lp_clock_calc(struct dsi_clock_info *cinfo,
1287 unsigned long lp_clk_min, unsigned long lp_clk_max)
1288{
1289 unsigned long dsi_fclk = cinfo->dsi_pll_hsdiv_dsi_clk;
1290 unsigned lp_clk_div;
1291 unsigned long lp_clk;
1292
1293 lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk_max * 2);
1294 lp_clk = dsi_fclk / 2 / lp_clk_div;
1295
1296 if (lp_clk < lp_clk_min || lp_clk > lp_clk_max)
1297 return -EINVAL;
1298
1299 cinfo->lp_clk_div = lp_clk_div;
1300 cinfo->lp_clk = lp_clk;
1301
1302 return 0;
1303}
1304
1305static int dsi_set_lp_clk_divisor(struct platform_device *dsidev)
1306{
1307 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1308 unsigned long dsi_fclk;
1309 unsigned lp_clk_div;
1310 unsigned long lp_clk;
1311
1312 lp_clk_div = dsi->user_dsi_cinfo.lp_clk_div;
1313
1314 if (lp_clk_div == 0 || lp_clk_div > dsi->lpdiv_max)
1315 return -EINVAL;
1316
1317 dsi_fclk = dsi_fclk_rate(dsidev);
1318
1319 lp_clk = dsi_fclk / 2 / lp_clk_div;
1320
1321 DSSDBG("LP_CLK_DIV %u, LP_CLK %lu\n", lp_clk_div, lp_clk);
1322 dsi->current_cinfo.lp_clk = lp_clk;
1323 dsi->current_cinfo.lp_clk_div = lp_clk_div;
1324
1325 /* LP_CLK_DIVISOR */
1326 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, lp_clk_div, 12, 0);
1327
1328 /* LP_RX_SYNCHRO_ENABLE */
1329 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, dsi_fclk > 30000000 ? 1 : 0, 21, 21);
1330
1331 return 0;
1332}
1333
1334static void dsi_enable_scp_clk(struct platform_device *dsidev)
1335{
1336 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1337
1338 if (dsi->scp_clk_refcount++ == 0)
1339 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 14, 14); /* CIO_CLK_ICG */
1340}
1341
1342static void dsi_disable_scp_clk(struct platform_device *dsidev)
1343{
1344 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1345
1346 WARN_ON(dsi->scp_clk_refcount == 0);
1347 if (--dsi->scp_clk_refcount == 0)
1348 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 14, 14); /* CIO_CLK_ICG */
1349}
1350
1351enum dsi_pll_power_state {
1352 DSI_PLL_POWER_OFF = 0x0,
1353 DSI_PLL_POWER_ON_HSCLK = 0x1,
1354 DSI_PLL_POWER_ON_ALL = 0x2,
1355 DSI_PLL_POWER_ON_DIV = 0x3,
1356};
1357
1358static int dsi_pll_power(struct platform_device *dsidev,
1359 enum dsi_pll_power_state state)
1360{
1361 int t = 0;
1362
1363 /* DSI-PLL power command 0x3 is not working */
1364 if (dss_has_feature(FEAT_DSI_PLL_PWR_BUG) &&
1365 state == DSI_PLL_POWER_ON_DIV)
1366 state = DSI_PLL_POWER_ON_ALL;
1367
1368 /* PLL_PWR_CMD */
1369 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, state, 31, 30);
1370
1371 /* PLL_PWR_STATUS */
1372 while (FLD_GET(dsi_read_reg(dsidev, DSI_CLK_CTRL), 29, 28) != state) {
1373 if (++t > 1000) {
1374 DSSERR("Failed to set DSI PLL power mode to %d\n",
1375 state);
1376 return -ENODEV;
1377 }
1378 udelay(1);
1379 }
1380
1381 return 0;
1382}
1383
1384unsigned long dsi_get_pll_clkin(struct platform_device *dsidev)
1385{
1386 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1387 return clk_get_rate(dsi->sys_clk);
1388}
1389
1390bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
1391 unsigned long out_min, dsi_hsdiv_calc_func func, void *data)
1392{
1393 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1394 int regm, regm_start, regm_stop;
1395 unsigned long out_max;
1396 unsigned long out;
1397
1398 out_min = out_min ? out_min : 1;
1399 out_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
1400
1401 regm_start = max(DIV_ROUND_UP(pll, out_max), 1ul);
1402 regm_stop = min(pll / out_min, dsi->regm_dispc_max);
1403
1404 for (regm = regm_start; regm <= regm_stop; ++regm) {
1405 out = pll / regm;
1406
1407 if (func(regm, out, data))
1408 return true;
1409 }
1410
1411 return false;
1412}
1413
1414bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
1415 unsigned long pll_min, unsigned long pll_max,
1416 dsi_pll_calc_func func, void *data)
1417{
1418 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1419 int regn, regn_start, regn_stop;
1420 int regm, regm_start, regm_stop;
1421 unsigned long fint, pll;
1422 const unsigned long pll_hw_max = 1800000000;
1423 unsigned long fint_hw_min, fint_hw_max;
1424
1425 fint_hw_min = dsi->fint_min;
1426 fint_hw_max = dsi->fint_max;
1427
1428 regn_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul);
1429 regn_stop = min(clkin / fint_hw_min, dsi->regn_max);
1430
1431 pll_max = pll_max ? pll_max : ULONG_MAX;
1432
1433 for (regn = regn_start; regn <= regn_stop; ++regn) {
1434 fint = clkin / regn;
1435
1436 regm_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2),
1437 1ul);
1438 regm_stop = min3(pll_max / fint / 2,
1439 pll_hw_max / fint / 2,
1440 dsi->regm_max);
1441
1442 for (regm = regm_start; regm <= regm_stop; ++regm) {
1443 pll = 2 * regm * fint;
1444
1445 if (func(regn, regm, fint, pll, data))
1446 return true;
1447 }
1448 }
1449
1450 return false;
1451}
1452
1453/* calculate clock rates using dividers in cinfo */
1454static int dsi_calc_clock_rates(struct platform_device *dsidev,
1455 struct dsi_clock_info *cinfo)
1456{
1457 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1458
1459 if (cinfo->regn == 0 || cinfo->regn > dsi->regn_max)
1460 return -EINVAL;
1461
1462 if (cinfo->regm == 0 || cinfo->regm > dsi->regm_max)
1463 return -EINVAL;
1464
1465 if (cinfo->regm_dispc > dsi->regm_dispc_max)
1466 return -EINVAL;
1467
1468 if (cinfo->regm_dsi > dsi->regm_dsi_max)
1469 return -EINVAL;
1470
1471 cinfo->clkin = clk_get_rate(dsi->sys_clk);
1472 cinfo->fint = cinfo->clkin / cinfo->regn;
1473
1474 if (cinfo->fint > dsi->fint_max || cinfo->fint < dsi->fint_min)
1475 return -EINVAL;
1476
1477 cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint;
1478
1479 if (cinfo->clkin4ddr > 1800 * 1000 * 1000)
1480 return -EINVAL;
1481
1482 if (cinfo->regm_dispc > 0)
1483 cinfo->dsi_pll_hsdiv_dispc_clk =
1484 cinfo->clkin4ddr / cinfo->regm_dispc;
1485 else
1486 cinfo->dsi_pll_hsdiv_dispc_clk = 0;
1487
1488 if (cinfo->regm_dsi > 0)
1489 cinfo->dsi_pll_hsdiv_dsi_clk =
1490 cinfo->clkin4ddr / cinfo->regm_dsi;
1491 else
1492 cinfo->dsi_pll_hsdiv_dsi_clk = 0;
1493
1494 return 0;
1495}
1496
1497static void dsi_pll_calc_dsi_fck(struct dsi_clock_info *cinfo)
1498{
1499 unsigned long max_dsi_fck;
1500
1501 max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK);
1502
1503 cinfo->regm_dsi = DIV_ROUND_UP(cinfo->clkin4ddr, max_dsi_fck);
1504 cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi;
1505}
1506
1507int dsi_pll_set_clock_div(struct platform_device *dsidev,
1508 struct dsi_clock_info *cinfo)
1509{
1510 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1511 int r = 0;
1512 u32 l;
1513 int f = 0;
1514 u8 regn_start, regn_end, regm_start, regm_end;
1515 u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end;
1516
1517 DSSDBG("DSI PLL clock config starts");
1518
1519 dsi->current_cinfo.clkin = cinfo->clkin;
1520 dsi->current_cinfo.fint = cinfo->fint;
1521 dsi->current_cinfo.clkin4ddr = cinfo->clkin4ddr;
1522 dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk =
1523 cinfo->dsi_pll_hsdiv_dispc_clk;
1524 dsi->current_cinfo.dsi_pll_hsdiv_dsi_clk =
1525 cinfo->dsi_pll_hsdiv_dsi_clk;
1526
1527 dsi->current_cinfo.regn = cinfo->regn;
1528 dsi->current_cinfo.regm = cinfo->regm;
1529 dsi->current_cinfo.regm_dispc = cinfo->regm_dispc;
1530 dsi->current_cinfo.regm_dsi = cinfo->regm_dsi;
1531
1532 DSSDBG("DSI Fint %ld\n", cinfo->fint);
1533
1534 DSSDBG("clkin rate %ld\n", cinfo->clkin);
1535
1536 /* DSIPHY == CLKIN4DDR */
1537 DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu = %lu\n",
1538 cinfo->regm,
1539 cinfo->regn,
1540 cinfo->clkin,
1541 cinfo->clkin4ddr);
1542
1543 DSSDBG("Data rate on 1 DSI lane %ld Mbps\n",
1544 cinfo->clkin4ddr / 1000 / 1000 / 2);
1545
1546 DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4);
1547
1548 DSSDBG("regm_dispc = %d, %s (%s) = %lu\n", cinfo->regm_dispc,
1549 dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
1550 dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
1551 cinfo->dsi_pll_hsdiv_dispc_clk);
1552 DSSDBG("regm_dsi = %d, %s (%s) = %lu\n", cinfo->regm_dsi,
1553 dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
1554 dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
1555 cinfo->dsi_pll_hsdiv_dsi_clk);
1556
1557 dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGN, &regn_start, &regn_end);
1558 dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM, &regm_start, &regm_end);
1559 dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DISPC, &regm_dispc_start,
1560 &regm_dispc_end);
1561 dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DSI, &regm_dsi_start,
1562 &regm_dsi_end);
1563
1564 /* DSI_PLL_AUTOMODE = manual */
1565 REG_FLD_MOD(dsidev, DSI_PLL_CONTROL, 0, 0, 0);
1566
1567 l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION1);
1568 l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */
1569 /* DSI_PLL_REGN */
1570 l = FLD_MOD(l, cinfo->regn - 1, regn_start, regn_end);
1571 /* DSI_PLL_REGM */
1572 l = FLD_MOD(l, cinfo->regm, regm_start, regm_end);
1573 /* DSI_CLOCK_DIV */
1574 l = FLD_MOD(l, cinfo->regm_dispc > 0 ? cinfo->regm_dispc - 1 : 0,
1575 regm_dispc_start, regm_dispc_end);
1576 /* DSIPROTO_CLOCK_DIV */
1577 l = FLD_MOD(l, cinfo->regm_dsi > 0 ? cinfo->regm_dsi - 1 : 0,
1578 regm_dsi_start, regm_dsi_end);
1579 dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION1, l);
1580
1581 BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max);
1582
1583 l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
1584
1585 if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) {
1586 f = cinfo->fint < 1000000 ? 0x3 :
1587 cinfo->fint < 1250000 ? 0x4 :
1588 cinfo->fint < 1500000 ? 0x5 :
1589 cinfo->fint < 1750000 ? 0x6 :
1590 0x7;
1591
1592 l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */
1593 } else if (dss_has_feature(FEAT_DSI_PLL_SELFREQDCO)) {
1594 f = cinfo->clkin4ddr < 1000000000 ? 0x2 : 0x4;
1595
1596 l = FLD_MOD(l, f, 4, 1); /* PLL_SELFREQDCO */
1597 }
1598
1599 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
1600 l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */
1601 l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */
1602 if (dss_has_feature(FEAT_DSI_PLL_REFSEL))
1603 l = FLD_MOD(l, 3, 22, 21); /* REF_SYSCLK = sysclk */
1604 dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l);
1605
1606 REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */
1607
1608 if (wait_for_bit_change(dsidev, DSI_PLL_GO, 0, 0) != 0) {
1609 DSSERR("dsi pll go bit not going down.\n");
1610 r = -EIO;
1611 goto err;
1612 }
1613
1614 if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1) {
1615 DSSERR("cannot lock PLL\n");
1616 r = -EIO;
1617 goto err;
1618 }
1619
1620 dsi->pll_locked = 1;
1621
1622 l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
1623 l = FLD_MOD(l, 0, 0, 0); /* DSI_PLL_IDLE */
1624 l = FLD_MOD(l, 0, 5, 5); /* DSI_PLL_PLLLPMODE */
1625 l = FLD_MOD(l, 0, 6, 6); /* DSI_PLL_LOWCURRSTBY */
1626 l = FLD_MOD(l, 0, 7, 7); /* DSI_PLL_TIGHTPHASELOCK */
1627 l = FLD_MOD(l, 0, 8, 8); /* DSI_PLL_DRIFTGUARDEN */
1628 l = FLD_MOD(l, 0, 10, 9); /* DSI_PLL_LOCKSEL */
1629 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
1630 l = FLD_MOD(l, 1, 14, 14); /* DSIPHY_CLKINEN */
1631 l = FLD_MOD(l, 0, 15, 15); /* DSI_BYPASSEN */
1632 l = FLD_MOD(l, 1, 16, 16); /* DSS_CLOCK_EN */
1633 l = FLD_MOD(l, 0, 17, 17); /* DSS_CLOCK_PWDN */
1634 l = FLD_MOD(l, 1, 18, 18); /* DSI_PROTO_CLOCK_EN */
1635 l = FLD_MOD(l, 0, 19, 19); /* DSI_PROTO_CLOCK_PWDN */
1636 l = FLD_MOD(l, 0, 20, 20); /* DSI_HSDIVBYPASS */
1637 dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l);
1638
1639 DSSDBG("PLL config done\n");
1640err:
1641 return r;
1642}
1643
1644int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
1645 bool enable_hsdiv)
1646{
1647 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1648 int r = 0;
1649 enum dsi_pll_power_state pwstate;
1650
1651 DSSDBG("PLL init\n");
1652
1653 /*
1654 * It seems that on many OMAPs we need to enable both to have a
1655 * functional HSDivider.
1656 */
1657 enable_hsclk = enable_hsdiv = true;
1658
1659 r = dsi_regulator_init(dsidev);
1660 if (r)
1661 return r;
1662
1663 dsi_enable_pll_clock(dsidev, 1);
1664 /*
1665 * Note: SCP CLK is not required on OMAP3, but it is required on OMAP4.
1666 */
1667 dsi_enable_scp_clk(dsidev);
1668
1669 if (!dsi->vdds_dsi_enabled) {
1670 r = regulator_enable(dsi->vdds_dsi_reg);
1671 if (r)
1672 goto err0;
1673 dsi->vdds_dsi_enabled = true;
1674 }
1675
1676 /* XXX PLL does not come out of reset without this... */
1677 dispc_pck_free_enable(1);
1678
1679 if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 0, 1) != 1) {
1680 DSSERR("PLL not coming out of reset.\n");
1681 r = -ENODEV;
1682 dispc_pck_free_enable(0);
1683 goto err1;
1684 }
1685
1686 /* XXX ... but if left on, we get problems when planes do not
1687 * fill the whole display. No idea about this */
1688 dispc_pck_free_enable(0);
1689
1690 if (enable_hsclk && enable_hsdiv)
1691 pwstate = DSI_PLL_POWER_ON_ALL;
1692 else if (enable_hsclk)
1693 pwstate = DSI_PLL_POWER_ON_HSCLK;
1694 else if (enable_hsdiv)
1695 pwstate = DSI_PLL_POWER_ON_DIV;
1696 else
1697 pwstate = DSI_PLL_POWER_OFF;
1698
1699 r = dsi_pll_power(dsidev, pwstate);
1700
1701 if (r)
1702 goto err1;
1703
1704 DSSDBG("PLL init done\n");
1705
1706 return 0;
1707err1:
1708 if (dsi->vdds_dsi_enabled) {
1709 regulator_disable(dsi->vdds_dsi_reg);
1710 dsi->vdds_dsi_enabled = false;
1711 }
1712err0:
1713 dsi_disable_scp_clk(dsidev);
1714 dsi_enable_pll_clock(dsidev, 0);
1715 return r;
1716}
1717
1718void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes)
1719{
1720 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1721
1722 dsi->pll_locked = 0;
1723 dsi_pll_power(dsidev, DSI_PLL_POWER_OFF);
1724 if (disconnect_lanes) {
1725 WARN_ON(!dsi->vdds_dsi_enabled);
1726 regulator_disable(dsi->vdds_dsi_reg);
1727 dsi->vdds_dsi_enabled = false;
1728 }
1729
1730 dsi_disable_scp_clk(dsidev);
1731 dsi_enable_pll_clock(dsidev, 0);
1732
1733 DSSDBG("PLL uninit done\n");
1734}
1735
1736static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
1737 struct seq_file *s)
1738{
1739 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1740 struct dsi_clock_info *cinfo = &dsi->current_cinfo;
1741 enum omap_dss_clk_source dispc_clk_src, dsi_clk_src;
1742 int dsi_module = dsi->module_id;
1743
1744 dispc_clk_src = dss_get_dispc_clk_source();
1745 dsi_clk_src = dss_get_dsi_clk_source(dsi_module);
1746
1747 if (dsi_runtime_get(dsidev))
1748 return;
1749
1750 seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1);
1751
1752 seq_printf(s, "dsi pll clkin\t%lu\n", cinfo->clkin);
1753
1754 seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn);
1755
1756 seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n",
1757 cinfo->clkin4ddr, cinfo->regm);
1758
1759 seq_printf(s, "DSI_PLL_HSDIV_DISPC (%s)\t%-16luregm_dispc %u\t(%s)\n",
1760 dss_feat_get_clk_source_name(dsi_module == 0 ?
1761 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
1762 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC),
1763 cinfo->dsi_pll_hsdiv_dispc_clk,
1764 cinfo->regm_dispc,
1765 dispc_clk_src == OMAP_DSS_CLK_SRC_FCK ?
1766 "off" : "on");
1767
1768 seq_printf(s, "DSI_PLL_HSDIV_DSI (%s)\t%-16luregm_dsi %u\t(%s)\n",
1769 dss_feat_get_clk_source_name(dsi_module == 0 ?
1770 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
1771 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI),
1772 cinfo->dsi_pll_hsdiv_dsi_clk,
1773 cinfo->regm_dsi,
1774 dsi_clk_src == OMAP_DSS_CLK_SRC_FCK ?
1775 "off" : "on");
1776
1777 seq_printf(s, "- DSI%d -\n", dsi_module + 1);
1778
1779 seq_printf(s, "dsi fclk source = %s (%s)\n",
1780 dss_get_generic_clk_source_name(dsi_clk_src),
1781 dss_feat_get_clk_source_name(dsi_clk_src));
1782
1783 seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate(dsidev));
1784
1785 seq_printf(s, "DDR_CLK\t\t%lu\n",
1786 cinfo->clkin4ddr / 4);
1787
1788 seq_printf(s, "TxByteClkHS\t%lu\n", dsi_get_txbyteclkhs(dsidev));
1789
1790 seq_printf(s, "LP_CLK\t\t%lu\n", cinfo->lp_clk);
1791
1792 dsi_runtime_put(dsidev);
1793}
1794
1795void dsi_dump_clocks(struct seq_file *s)
1796{
1797 struct platform_device *dsidev;
1798 int i;
1799
1800 for (i = 0; i < MAX_NUM_DSI; i++) {
1801 dsidev = dsi_get_dsidev_from_id(i);
1802 if (dsidev)
1803 dsi_dump_dsidev_clocks(dsidev, s);
1804 }
1805}
1806
1807#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
1808static void dsi_dump_dsidev_irqs(struct platform_device *dsidev,
1809 struct seq_file *s)
1810{
1811 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1812 unsigned long flags;
1813 struct dsi_irq_stats stats;
1814
1815 spin_lock_irqsave(&dsi->irq_stats_lock, flags);
1816
1817 stats = dsi->irq_stats;
1818 memset(&dsi->irq_stats, 0, sizeof(dsi->irq_stats));
1819 dsi->irq_stats.last_reset = jiffies;
1820
1821 spin_unlock_irqrestore(&dsi->irq_stats_lock, flags);
1822
1823 seq_printf(s, "period %u ms\n",
1824 jiffies_to_msecs(jiffies - stats.last_reset));
1825
1826 seq_printf(s, "irqs %d\n", stats.irq_count);
1827#define PIS(x) \
1828 seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]);
1829
1830 seq_printf(s, "-- DSI%d interrupts --\n", dsi->module_id + 1);
1831 PIS(VC0);
1832 PIS(VC1);
1833 PIS(VC2);
1834 PIS(VC3);
1835 PIS(WAKEUP);
1836 PIS(RESYNC);
1837 PIS(PLL_LOCK);
1838 PIS(PLL_UNLOCK);
1839 PIS(PLL_RECALL);
1840 PIS(COMPLEXIO_ERR);
1841 PIS(HS_TX_TIMEOUT);
1842 PIS(LP_RX_TIMEOUT);
1843 PIS(TE_TRIGGER);
1844 PIS(ACK_TRIGGER);
1845 PIS(SYNC_LOST);
1846 PIS(LDO_POWER_GOOD);
1847 PIS(TA_TIMEOUT);
1848#undef PIS
1849
1850#define PIS(x) \
1851 seq_printf(s, "%-20s %10d %10d %10d %10d\n", #x, \
1852 stats.vc_irqs[0][ffs(DSI_VC_IRQ_##x)-1], \
1853 stats.vc_irqs[1][ffs(DSI_VC_IRQ_##x)-1], \
1854 stats.vc_irqs[2][ffs(DSI_VC_IRQ_##x)-1], \
1855 stats.vc_irqs[3][ffs(DSI_VC_IRQ_##x)-1]);
1856
1857 seq_printf(s, "-- VC interrupts --\n");
1858 PIS(CS);
1859 PIS(ECC_CORR);
1860 PIS(PACKET_SENT);
1861 PIS(FIFO_TX_OVF);
1862 PIS(FIFO_RX_OVF);
1863 PIS(BTA);
1864 PIS(ECC_NO_CORR);
1865 PIS(FIFO_TX_UDF);
1866 PIS(PP_BUSY_CHANGE);
1867#undef PIS
1868
1869#define PIS(x) \
1870 seq_printf(s, "%-20s %10d\n", #x, \
1871 stats.cio_irqs[ffs(DSI_CIO_IRQ_##x)-1]);
1872
1873 seq_printf(s, "-- CIO interrupts --\n");
1874 PIS(ERRSYNCESC1);
1875 PIS(ERRSYNCESC2);
1876 PIS(ERRSYNCESC3);
1877 PIS(ERRESC1);
1878 PIS(ERRESC2);
1879 PIS(ERRESC3);
1880 PIS(ERRCONTROL1);
1881 PIS(ERRCONTROL2);
1882 PIS(ERRCONTROL3);
1883 PIS(STATEULPS1);
1884 PIS(STATEULPS2);
1885 PIS(STATEULPS3);
1886 PIS(ERRCONTENTIONLP0_1);
1887 PIS(ERRCONTENTIONLP1_1);
1888 PIS(ERRCONTENTIONLP0_2);
1889 PIS(ERRCONTENTIONLP1_2);
1890 PIS(ERRCONTENTIONLP0_3);
1891 PIS(ERRCONTENTIONLP1_3);
1892 PIS(ULPSACTIVENOT_ALL0);
1893 PIS(ULPSACTIVENOT_ALL1);
1894#undef PIS
1895}
1896
1897static void dsi1_dump_irqs(struct seq_file *s)
1898{
1899 struct platform_device *dsidev = dsi_get_dsidev_from_id(0);
1900
1901 dsi_dump_dsidev_irqs(dsidev, s);
1902}
1903
1904static void dsi2_dump_irqs(struct seq_file *s)
1905{
1906 struct platform_device *dsidev = dsi_get_dsidev_from_id(1);
1907
1908 dsi_dump_dsidev_irqs(dsidev, s);
1909}
1910#endif
1911
1912static void dsi_dump_dsidev_regs(struct platform_device *dsidev,
1913 struct seq_file *s)
1914{
1915#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsidev, r))
1916
1917 if (dsi_runtime_get(dsidev))
1918 return;
1919 dsi_enable_scp_clk(dsidev);
1920
1921 DUMPREG(DSI_REVISION);
1922 DUMPREG(DSI_SYSCONFIG);
1923 DUMPREG(DSI_SYSSTATUS);
1924 DUMPREG(DSI_IRQSTATUS);
1925 DUMPREG(DSI_IRQENABLE);
1926 DUMPREG(DSI_CTRL);
1927 DUMPREG(DSI_COMPLEXIO_CFG1);
1928 DUMPREG(DSI_COMPLEXIO_IRQ_STATUS);
1929 DUMPREG(DSI_COMPLEXIO_IRQ_ENABLE);
1930 DUMPREG(DSI_CLK_CTRL);
1931 DUMPREG(DSI_TIMING1);
1932 DUMPREG(DSI_TIMING2);
1933 DUMPREG(DSI_VM_TIMING1);
1934 DUMPREG(DSI_VM_TIMING2);
1935 DUMPREG(DSI_VM_TIMING3);
1936 DUMPREG(DSI_CLK_TIMING);
1937 DUMPREG(DSI_TX_FIFO_VC_SIZE);
1938 DUMPREG(DSI_RX_FIFO_VC_SIZE);
1939 DUMPREG(DSI_COMPLEXIO_CFG2);
1940 DUMPREG(DSI_RX_FIFO_VC_FULLNESS);
1941 DUMPREG(DSI_VM_TIMING4);
1942 DUMPREG(DSI_TX_FIFO_VC_EMPTINESS);
1943 DUMPREG(DSI_VM_TIMING5);
1944 DUMPREG(DSI_VM_TIMING6);
1945 DUMPREG(DSI_VM_TIMING7);
1946 DUMPREG(DSI_STOPCLK_TIMING);
1947
1948 DUMPREG(DSI_VC_CTRL(0));
1949 DUMPREG(DSI_VC_TE(0));
1950 DUMPREG(DSI_VC_LONG_PACKET_HEADER(0));
1951 DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(0));
1952 DUMPREG(DSI_VC_SHORT_PACKET_HEADER(0));
1953 DUMPREG(DSI_VC_IRQSTATUS(0));
1954 DUMPREG(DSI_VC_IRQENABLE(0));
1955
1956 DUMPREG(DSI_VC_CTRL(1));
1957 DUMPREG(DSI_VC_TE(1));
1958 DUMPREG(DSI_VC_LONG_PACKET_HEADER(1));
1959 DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(1));
1960 DUMPREG(DSI_VC_SHORT_PACKET_HEADER(1));
1961 DUMPREG(DSI_VC_IRQSTATUS(1));
1962 DUMPREG(DSI_VC_IRQENABLE(1));
1963
1964 DUMPREG(DSI_VC_CTRL(2));
1965 DUMPREG(DSI_VC_TE(2));
1966 DUMPREG(DSI_VC_LONG_PACKET_HEADER(2));
1967 DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(2));
1968 DUMPREG(DSI_VC_SHORT_PACKET_HEADER(2));
1969 DUMPREG(DSI_VC_IRQSTATUS(2));
1970 DUMPREG(DSI_VC_IRQENABLE(2));
1971
1972 DUMPREG(DSI_VC_CTRL(3));
1973 DUMPREG(DSI_VC_TE(3));
1974 DUMPREG(DSI_VC_LONG_PACKET_HEADER(3));
1975 DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(3));
1976 DUMPREG(DSI_VC_SHORT_PACKET_HEADER(3));
1977 DUMPREG(DSI_VC_IRQSTATUS(3));
1978 DUMPREG(DSI_VC_IRQENABLE(3));
1979
1980 DUMPREG(DSI_DSIPHY_CFG0);
1981 DUMPREG(DSI_DSIPHY_CFG1);
1982 DUMPREG(DSI_DSIPHY_CFG2);
1983 DUMPREG(DSI_DSIPHY_CFG5);
1984
1985 DUMPREG(DSI_PLL_CONTROL);
1986 DUMPREG(DSI_PLL_STATUS);
1987 DUMPREG(DSI_PLL_GO);
1988 DUMPREG(DSI_PLL_CONFIGURATION1);
1989 DUMPREG(DSI_PLL_CONFIGURATION2);
1990
1991 dsi_disable_scp_clk(dsidev);
1992 dsi_runtime_put(dsidev);
1993#undef DUMPREG
1994}
1995
1996static void dsi1_dump_regs(struct seq_file *s)
1997{
1998 struct platform_device *dsidev = dsi_get_dsidev_from_id(0);
1999
2000 dsi_dump_dsidev_regs(dsidev, s);
2001}
2002
2003static void dsi2_dump_regs(struct seq_file *s)
2004{
2005 struct platform_device *dsidev = dsi_get_dsidev_from_id(1);
2006
2007 dsi_dump_dsidev_regs(dsidev, s);
2008}
2009
2010enum dsi_cio_power_state {
2011 DSI_COMPLEXIO_POWER_OFF = 0x0,
2012 DSI_COMPLEXIO_POWER_ON = 0x1,
2013 DSI_COMPLEXIO_POWER_ULPS = 0x2,
2014};
2015
2016static int dsi_cio_power(struct platform_device *dsidev,
2017 enum dsi_cio_power_state state)
2018{
2019 int t = 0;
2020
2021 /* PWR_CMD */
2022 REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG1, state, 28, 27);
2023
2024 /* PWR_STATUS */
2025 while (FLD_GET(dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1),
2026 26, 25) != state) {
2027 if (++t > 1000) {
2028 DSSERR("failed to set complexio power state to "
2029 "%d\n", state);
2030 return -ENODEV;
2031 }
2032 udelay(1);
2033 }
2034
2035 return 0;
2036}
2037
2038static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
2039{
2040 int val;
2041
2042 /* line buffer on OMAP3 is 1024 x 24bits */
2043 /* XXX: for some reason using full buffer size causes
2044 * considerable TX slowdown with update sizes that fill the
2045 * whole buffer */
2046 if (!dss_has_feature(FEAT_DSI_GNQ))
2047 return 1023 * 3;
2048
2049 val = REG_GET(dsidev, DSI_GNQ, 14, 12); /* VP1_LINE_BUFFER_SIZE */
2050
2051 switch (val) {
2052 case 1:
2053 return 512 * 3; /* 512x24 bits */
2054 case 2:
2055 return 682 * 3; /* 682x24 bits */
2056 case 3:
2057 return 853 * 3; /* 853x24 bits */
2058 case 4:
2059 return 1024 * 3; /* 1024x24 bits */
2060 case 5:
2061 return 1194 * 3; /* 1194x24 bits */
2062 case 6:
2063 return 1365 * 3; /* 1365x24 bits */
2064 case 7:
2065 return 1920 * 3; /* 1920x24 bits */
2066 default:
2067 BUG();
2068 return 0;
2069 }
2070}
2071
2072static int dsi_set_lane_config(struct platform_device *dsidev)
2073{
2074 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2075 static const u8 offsets[] = { 0, 4, 8, 12, 16 };
2076 static const enum dsi_lane_function functions[] = {
2077 DSI_LANE_CLK,
2078 DSI_LANE_DATA1,
2079 DSI_LANE_DATA2,
2080 DSI_LANE_DATA3,
2081 DSI_LANE_DATA4,
2082 };
2083 u32 r;
2084 int i;
2085
2086 r = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1);
2087
2088 for (i = 0; i < dsi->num_lanes_used; ++i) {
2089 unsigned offset = offsets[i];
2090 unsigned polarity, lane_number;
2091 unsigned t;
2092
2093 for (t = 0; t < dsi->num_lanes_supported; ++t)
2094 if (dsi->lanes[t].function == functions[i])
2095 break;
2096
2097 if (t == dsi->num_lanes_supported)
2098 return -EINVAL;
2099
2100 lane_number = t;
2101 polarity = dsi->lanes[t].polarity;
2102
2103 r = FLD_MOD(r, lane_number + 1, offset + 2, offset);
2104 r = FLD_MOD(r, polarity, offset + 3, offset + 3);
2105 }
2106
2107 /* clear the unused lanes */
2108 for (; i < dsi->num_lanes_supported; ++i) {
2109 unsigned offset = offsets[i];
2110
2111 r = FLD_MOD(r, 0, offset + 2, offset);
2112 r = FLD_MOD(r, 0, offset + 3, offset + 3);
2113 }
2114
2115 dsi_write_reg(dsidev, DSI_COMPLEXIO_CFG1, r);
2116
2117 return 0;
2118}
2119
2120static inline unsigned ns2ddr(struct platform_device *dsidev, unsigned ns)
2121{
2122 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2123
2124 /* convert time in ns to ddr ticks, rounding up */
2125 unsigned long ddr_clk = dsi->current_cinfo.clkin4ddr / 4;
2126 return (ns * (ddr_clk / 1000 / 1000) + 999) / 1000;
2127}
2128
2129static inline unsigned ddr2ns(struct platform_device *dsidev, unsigned ddr)
2130{
2131 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2132
2133 unsigned long ddr_clk = dsi->current_cinfo.clkin4ddr / 4;
2134 return ddr * 1000 * 1000 / (ddr_clk / 1000);
2135}
2136
2137static void dsi_cio_timings(struct platform_device *dsidev)
2138{
2139 u32 r;
2140 u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit;
2141 u32 tlpx_half, tclk_trail, tclk_zero;
2142 u32 tclk_prepare;
2143
2144 /* calculate timings */
2145
2146 /* 1 * DDR_CLK = 2 * UI */
2147
2148 /* min 40ns + 4*UI max 85ns + 6*UI */
2149 ths_prepare = ns2ddr(dsidev, 70) + 2;
2150
2151 /* min 145ns + 10*UI */
2152 ths_prepare_ths_zero = ns2ddr(dsidev, 175) + 2;
2153
2154 /* min max(8*UI, 60ns+4*UI) */
2155 ths_trail = ns2ddr(dsidev, 60) + 5;
2156
2157 /* min 100ns */
2158 ths_exit = ns2ddr(dsidev, 145);
2159
2160 /* tlpx min 50n */
2161 tlpx_half = ns2ddr(dsidev, 25);
2162
2163 /* min 60ns */
2164 tclk_trail = ns2ddr(dsidev, 60) + 2;
2165
2166 /* min 38ns, max 95ns */
2167 tclk_prepare = ns2ddr(dsidev, 65);
2168
2169 /* min tclk-prepare + tclk-zero = 300ns */
2170 tclk_zero = ns2ddr(dsidev, 260);
2171
2172 DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n",
2173 ths_prepare, ddr2ns(dsidev, ths_prepare),
2174 ths_prepare_ths_zero, ddr2ns(dsidev, ths_prepare_ths_zero));
2175 DSSDBG("ths_trail %u (%uns), ths_exit %u (%uns)\n",
2176 ths_trail, ddr2ns(dsidev, ths_trail),
2177 ths_exit, ddr2ns(dsidev, ths_exit));
2178
2179 DSSDBG("tlpx_half %u (%uns), tclk_trail %u (%uns), "
2180 "tclk_zero %u (%uns)\n",
2181 tlpx_half, ddr2ns(dsidev, tlpx_half),
2182 tclk_trail, ddr2ns(dsidev, tclk_trail),
2183 tclk_zero, ddr2ns(dsidev, tclk_zero));
2184 DSSDBG("tclk_prepare %u (%uns)\n",
2185 tclk_prepare, ddr2ns(dsidev, tclk_prepare));
2186
2187 /* program timings */
2188
2189 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
2190 r = FLD_MOD(r, ths_prepare, 31, 24);
2191 r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16);
2192 r = FLD_MOD(r, ths_trail, 15, 8);
2193 r = FLD_MOD(r, ths_exit, 7, 0);
2194 dsi_write_reg(dsidev, DSI_DSIPHY_CFG0, r);
2195
2196 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
2197 r = FLD_MOD(r, tlpx_half, 20, 16);
2198 r = FLD_MOD(r, tclk_trail, 15, 8);
2199 r = FLD_MOD(r, tclk_zero, 7, 0);
2200
2201 if (dss_has_feature(FEAT_DSI_PHY_DCC)) {
2202 r = FLD_MOD(r, 0, 21, 21); /* DCCEN = disable */
2203 r = FLD_MOD(r, 1, 22, 22); /* CLKINP_DIVBY2EN = enable */
2204 r = FLD_MOD(r, 1, 23, 23); /* CLKINP_SEL = enable */
2205 }
2206
2207 dsi_write_reg(dsidev, DSI_DSIPHY_CFG1, r);
2208
2209 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2);
2210 r = FLD_MOD(r, tclk_prepare, 7, 0);
2211 dsi_write_reg(dsidev, DSI_DSIPHY_CFG2, r);
2212}
2213
2214/* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */
2215static void dsi_cio_enable_lane_override(struct platform_device *dsidev,
2216 unsigned mask_p, unsigned mask_n)
2217{
2218 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2219 int i;
2220 u32 l;
2221 u8 lptxscp_start = dsi->num_lanes_supported == 3 ? 22 : 26;
2222
2223 l = 0;
2224
2225 for (i = 0; i < dsi->num_lanes_supported; ++i) {
2226 unsigned p = dsi->lanes[i].polarity;
2227
2228 if (mask_p & (1 << i))
2229 l |= 1 << (i * 2 + (p ? 0 : 1));
2230
2231 if (mask_n & (1 << i))
2232 l |= 1 << (i * 2 + (p ? 1 : 0));
2233 }
2234
2235 /*
2236 * Bits in REGLPTXSCPDAT4TO0DXDY:
2237 * 17: DY0 18: DX0
2238 * 19: DY1 20: DX1
2239 * 21: DY2 22: DX2
2240 * 23: DY3 24: DX3
2241 * 25: DY4 26: DX4
2242 */
2243
2244 /* Set the lane override configuration */
2245
2246 /* REGLPTXSCPDAT4TO0DXDY */
2247 REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, l, lptxscp_start, 17);
2248
2249 /* Enable lane override */
2250
2251 /* ENLPTXSCPDAT */
2252 REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 1, 27, 27);
2253}
2254
2255static void dsi_cio_disable_lane_override(struct platform_device *dsidev)
2256{
2257 /* Disable lane override */
2258 REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 27, 27); /* ENLPTXSCPDAT */
2259 /* Reset the lane override configuration */
2260 /* REGLPTXSCPDAT4TO0DXDY */
2261 REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 22, 17);
2262}
2263
2264static int dsi_cio_wait_tx_clk_esc_reset(struct platform_device *dsidev)
2265{
2266 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2267 int t, i;
2268 bool in_use[DSI_MAX_NR_LANES];
2269 static const u8 offsets_old[] = { 28, 27, 26 };
2270 static const u8 offsets_new[] = { 24, 25, 26, 27, 28 };
2271 const u8 *offsets;
2272
2273 if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC))
2274 offsets = offsets_old;
2275 else
2276 offsets = offsets_new;
2277
2278 for (i = 0; i < dsi->num_lanes_supported; ++i)
2279 in_use[i] = dsi->lanes[i].function != DSI_LANE_UNUSED;
2280
2281 t = 100000;
2282 while (true) {
2283 u32 l;
2284 int ok;
2285
2286 l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
2287
2288 ok = 0;
2289 for (i = 0; i < dsi->num_lanes_supported; ++i) {
2290 if (!in_use[i] || (l & (1 << offsets[i])))
2291 ok++;
2292 }
2293
2294 if (ok == dsi->num_lanes_supported)
2295 break;
2296
2297 if (--t == 0) {
2298 for (i = 0; i < dsi->num_lanes_supported; ++i) {
2299 if (!in_use[i] || (l & (1 << offsets[i])))
2300 continue;
2301
2302 DSSERR("CIO TXCLKESC%d domain not coming " \
2303 "out of reset\n", i);
2304 }
2305 return -EIO;
2306 }
2307 }
2308
2309 return 0;
2310}
2311
2312/* return bitmask of enabled lanes, lane0 being the lsb */
2313static unsigned dsi_get_lane_mask(struct platform_device *dsidev)
2314{
2315 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2316 unsigned mask = 0;
2317 int i;
2318
2319 for (i = 0; i < dsi->num_lanes_supported; ++i) {
2320 if (dsi->lanes[i].function != DSI_LANE_UNUSED)
2321 mask |= 1 << i;
2322 }
2323
2324 return mask;
2325}
2326
2327static int dsi_cio_init(struct platform_device *dsidev)
2328{
2329 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2330 int r;
2331 u32 l;
2332
2333 DSSDBG("DSI CIO init starts");
2334
2335 r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
2336 if (r)
2337 return r;
2338
2339 dsi_enable_scp_clk(dsidev);
2340
2341 /* A dummy read using the SCP interface to any DSIPHY register is
2342 * required after DSIPHY reset to complete the reset of the DSI complex
2343 * I/O. */
2344 dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
2345
2346 if (wait_for_bit_change(dsidev, DSI_DSIPHY_CFG5, 30, 1) != 1) {
2347 DSSERR("CIO SCP Clock domain not coming out of reset.\n");
2348 r = -EIO;
2349 goto err_scp_clk_dom;
2350 }
2351
2352 r = dsi_set_lane_config(dsidev);
2353 if (r)
2354 goto err_scp_clk_dom;
2355
2356 /* set TX STOP MODE timer to maximum for this operation */
2357 l = dsi_read_reg(dsidev, DSI_TIMING1);
2358 l = FLD_MOD(l, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
2359 l = FLD_MOD(l, 1, 14, 14); /* STOP_STATE_X16_IO */
2360 l = FLD_MOD(l, 1, 13, 13); /* STOP_STATE_X4_IO */
2361 l = FLD_MOD(l, 0x1fff, 12, 0); /* STOP_STATE_COUNTER_IO */
2362 dsi_write_reg(dsidev, DSI_TIMING1, l);
2363
2364 if (dsi->ulps_enabled) {
2365 unsigned mask_p;
2366 int i;
2367
2368 DSSDBG("manual ulps exit\n");
2369
2370 /* ULPS is exited by Mark-1 state for 1ms, followed by
2371 * stop state. DSS HW cannot do this via the normal
2372 * ULPS exit sequence, as after reset the DSS HW thinks
2373 * that we are not in ULPS mode, and refuses to send the
2374 * sequence. So we need to send the ULPS exit sequence
2375 * manually by setting positive lines high and negative lines
2376 * low for 1ms.
2377 */
2378
2379 mask_p = 0;
2380
2381 for (i = 0; i < dsi->num_lanes_supported; ++i) {
2382 if (dsi->lanes[i].function == DSI_LANE_UNUSED)
2383 continue;
2384 mask_p |= 1 << i;
2385 }
2386
2387 dsi_cio_enable_lane_override(dsidev, mask_p, 0);
2388 }
2389
2390 r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON);
2391 if (r)
2392 goto err_cio_pwr;
2393
2394 if (wait_for_bit_change(dsidev, DSI_COMPLEXIO_CFG1, 29, 1) != 1) {
2395 DSSERR("CIO PWR clock domain not coming out of reset.\n");
2396 r = -ENODEV;
2397 goto err_cio_pwr_dom;
2398 }
2399
2400 dsi_if_enable(dsidev, true);
2401 dsi_if_enable(dsidev, false);
2402 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
2403
2404 r = dsi_cio_wait_tx_clk_esc_reset(dsidev);
2405 if (r)
2406 goto err_tx_clk_esc_rst;
2407
2408 if (dsi->ulps_enabled) {
2409 /* Keep Mark-1 state for 1ms (as per DSI spec) */
2410 ktime_t wait = ns_to_ktime(1000 * 1000);
2411 set_current_state(TASK_UNINTERRUPTIBLE);
2412 schedule_hrtimeout(&wait, HRTIMER_MODE_REL);
2413
2414 /* Disable the override. The lanes should be set to Mark-11
2415 * state by the HW */
2416 dsi_cio_disable_lane_override(dsidev);
2417 }
2418
2419 /* FORCE_TX_STOP_MODE_IO */
2420 REG_FLD_MOD(dsidev, DSI_TIMING1, 0, 15, 15);
2421
2422 dsi_cio_timings(dsidev);
2423
2424 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
2425 /* DDR_CLK_ALWAYS_ON */
2426 REG_FLD_MOD(dsidev, DSI_CLK_CTRL,
2427 dsi->vm_timings.ddr_clk_always_on, 13, 13);
2428 }
2429
2430 dsi->ulps_enabled = false;
2431
2432 DSSDBG("CIO init done\n");
2433
2434 return 0;
2435
2436err_tx_clk_esc_rst:
2437 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 20, 20); /* LP_CLK_ENABLE */
2438err_cio_pwr_dom:
2439 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);
2440err_cio_pwr:
2441 if (dsi->ulps_enabled)
2442 dsi_cio_disable_lane_override(dsidev);
2443err_scp_clk_dom:
2444 dsi_disable_scp_clk(dsidev);
2445 dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
2446 return r;
2447}
2448
2449static void dsi_cio_uninit(struct platform_device *dsidev)
2450{
2451 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2452
2453 /* DDR_CLK_ALWAYS_ON */
2454 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13);
2455
2456 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);
2457 dsi_disable_scp_clk(dsidev);
2458 dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
2459}
2460
2461static void dsi_config_tx_fifo(struct platform_device *dsidev,
2462 enum fifo_size size1, enum fifo_size size2,
2463 enum fifo_size size3, enum fifo_size size4)
2464{
2465 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2466 u32 r = 0;
2467 int add = 0;
2468 int i;
2469
2470 dsi->vc[0].tx_fifo_size = size1;
2471 dsi->vc[1].tx_fifo_size = size2;
2472 dsi->vc[2].tx_fifo_size = size3;
2473 dsi->vc[3].tx_fifo_size = size4;
2474
2475 for (i = 0; i < 4; i++) {
2476 u8 v;
2477 int size = dsi->vc[i].tx_fifo_size;
2478
2479 if (add + size > 4) {
2480 DSSERR("Illegal FIFO configuration\n");
2481 BUG();
2482 return;
2483 }
2484
2485 v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
2486 r |= v << (8 * i);
2487 /*DSSDBG("TX FIFO vc %d: size %d, add %d\n", i, size, add); */
2488 add += size;
2489 }
2490
2491 dsi_write_reg(dsidev, DSI_TX_FIFO_VC_SIZE, r);
2492}
2493
2494static void dsi_config_rx_fifo(struct platform_device *dsidev,
2495 enum fifo_size size1, enum fifo_size size2,
2496 enum fifo_size size3, enum fifo_size size4)
2497{
2498 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2499 u32 r = 0;
2500 int add = 0;
2501 int i;
2502
2503 dsi->vc[0].rx_fifo_size = size1;
2504 dsi->vc[1].rx_fifo_size = size2;
2505 dsi->vc[2].rx_fifo_size = size3;
2506 dsi->vc[3].rx_fifo_size = size4;
2507
2508 for (i = 0; i < 4; i++) {
2509 u8 v;
2510 int size = dsi->vc[i].rx_fifo_size;
2511
2512 if (add + size > 4) {
2513 DSSERR("Illegal FIFO configuration\n");
2514 BUG();
2515 return;
2516 }
2517
2518 v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
2519 r |= v << (8 * i);
2520 /*DSSDBG("RX FIFO vc %d: size %d, add %d\n", i, size, add); */
2521 add += size;
2522 }
2523
2524 dsi_write_reg(dsidev, DSI_RX_FIFO_VC_SIZE, r);
2525}
2526
2527static int dsi_force_tx_stop_mode_io(struct platform_device *dsidev)
2528{
2529 u32 r;
2530
2531 r = dsi_read_reg(dsidev, DSI_TIMING1);
2532 r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
2533 dsi_write_reg(dsidev, DSI_TIMING1, r);
2534
2535 if (wait_for_bit_change(dsidev, DSI_TIMING1, 15, 0) != 0) {
2536 DSSERR("TX_STOP bit not going down\n");
2537 return -EIO;
2538 }
2539
2540 return 0;
2541}
2542
2543static bool dsi_vc_is_enabled(struct platform_device *dsidev, int channel)
2544{
2545 return REG_GET(dsidev, DSI_VC_CTRL(channel), 0, 0);
2546}
2547
2548static void dsi_packet_sent_handler_vp(void *data, u32 mask)
2549{
2550 struct dsi_packet_sent_handler_data *vp_data =
2551 (struct dsi_packet_sent_handler_data *) data;
2552 struct dsi_data *dsi = dsi_get_dsidrv_data(vp_data->dsidev);
2553 const int channel = dsi->update_channel;
2554 u8 bit = dsi->te_enabled ? 30 : 31;
2555
2556 if (REG_GET(vp_data->dsidev, DSI_VC_TE(channel), bit, bit) == 0)
2557 complete(vp_data->completion);
2558}
2559
2560static int dsi_sync_vc_vp(struct platform_device *dsidev, int channel)
2561{
2562 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2563 DECLARE_COMPLETION_ONSTACK(completion);
2564 struct dsi_packet_sent_handler_data vp_data = { dsidev, &completion };
2565 int r = 0;
2566 u8 bit;
2567
2568 bit = dsi->te_enabled ? 30 : 31;
2569
2570 r = dsi_register_isr_vc(dsidev, channel, dsi_packet_sent_handler_vp,
2571 &vp_data, DSI_VC_IRQ_PACKET_SENT);
2572 if (r)
2573 goto err0;
2574
2575 /* Wait for completion only if TE_EN/TE_START is still set */
2576 if (REG_GET(dsidev, DSI_VC_TE(channel), bit, bit)) {
2577 if (wait_for_completion_timeout(&completion,
2578 msecs_to_jiffies(10)) == 0) {
2579 DSSERR("Failed to complete previous frame transfer\n");
2580 r = -EIO;
2581 goto err1;
2582 }
2583 }
2584
2585 dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_vp,
2586 &vp_data, DSI_VC_IRQ_PACKET_SENT);
2587
2588 return 0;
2589err1:
2590 dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_vp,
2591 &vp_data, DSI_VC_IRQ_PACKET_SENT);
2592err0:
2593 return r;
2594}
2595
2596static void dsi_packet_sent_handler_l4(void *data, u32 mask)
2597{
2598 struct dsi_packet_sent_handler_data *l4_data =
2599 (struct dsi_packet_sent_handler_data *) data;
2600 struct dsi_data *dsi = dsi_get_dsidrv_data(l4_data->dsidev);
2601 const int channel = dsi->update_channel;
2602
2603 if (REG_GET(l4_data->dsidev, DSI_VC_CTRL(channel), 5, 5) == 0)
2604 complete(l4_data->completion);
2605}
2606
2607static int dsi_sync_vc_l4(struct platform_device *dsidev, int channel)
2608{
2609 DECLARE_COMPLETION_ONSTACK(completion);
2610 struct dsi_packet_sent_handler_data l4_data = { dsidev, &completion };
2611 int r = 0;
2612
2613 r = dsi_register_isr_vc(dsidev, channel, dsi_packet_sent_handler_l4,
2614 &l4_data, DSI_VC_IRQ_PACKET_SENT);
2615 if (r)
2616 goto err0;
2617
2618 /* Wait for completion only if TX_FIFO_NOT_EMPTY is still set */
2619 if (REG_GET(dsidev, DSI_VC_CTRL(channel), 5, 5)) {
2620 if (wait_for_completion_timeout(&completion,
2621 msecs_to_jiffies(10)) == 0) {
2622 DSSERR("Failed to complete previous l4 transfer\n");
2623 r = -EIO;
2624 goto err1;
2625 }
2626 }
2627
2628 dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_l4,
2629 &l4_data, DSI_VC_IRQ_PACKET_SENT);
2630
2631 return 0;
2632err1:
2633 dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_l4,
2634 &l4_data, DSI_VC_IRQ_PACKET_SENT);
2635err0:
2636 return r;
2637}
2638
2639static int dsi_sync_vc(struct platform_device *dsidev, int channel)
2640{
2641 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2642
2643 WARN_ON(!dsi_bus_is_locked(dsidev));
2644
2645 WARN_ON(in_interrupt());
2646
2647 if (!dsi_vc_is_enabled(dsidev, channel))
2648 return 0;
2649
2650 switch (dsi->vc[channel].source) {
2651 case DSI_VC_SOURCE_VP:
2652 return dsi_sync_vc_vp(dsidev, channel);
2653 case DSI_VC_SOURCE_L4:
2654 return dsi_sync_vc_l4(dsidev, channel);
2655 default:
2656 BUG();
2657 return -EINVAL;
2658 }
2659}
2660
2661static int dsi_vc_enable(struct platform_device *dsidev, int channel,
2662 bool enable)
2663{
2664 DSSDBG("dsi_vc_enable channel %d, enable %d\n",
2665 channel, enable);
2666
2667 enable = enable ? 1 : 0;
2668
2669 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 0, 0);
2670
2671 if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel),
2672 0, enable) != enable) {
2673 DSSERR("Failed to set dsi_vc_enable to %d\n", enable);
2674 return -EIO;
2675 }
2676
2677 return 0;
2678}
2679
2680static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)
2681{
2682 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2683 u32 r;
2684
2685 DSSDBG("Initial config of virtual channel %d", channel);
2686
2687 r = dsi_read_reg(dsidev, DSI_VC_CTRL(channel));
2688
2689 if (FLD_GET(r, 15, 15)) /* VC_BUSY */
2690 DSSERR("VC(%d) busy when trying to configure it!\n",
2691 channel);
2692
2693 r = FLD_MOD(r, 0, 1, 1); /* SOURCE, 0 = L4 */
2694 r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN */
2695 r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */
2696 r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */
2697 r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
2698 r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
2699 r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */
2700 if (dss_has_feature(FEAT_DSI_VC_OCP_WIDTH))
2701 r = FLD_MOD(r, 3, 11, 10); /* OCP_WIDTH = 32 bit */
2702
2703 r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
2704 r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
2705
2706 dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r);
2707
2708 dsi->vc[channel].source = DSI_VC_SOURCE_L4;
2709}
2710
2711static int dsi_vc_config_source(struct platform_device *dsidev, int channel,
2712 enum dsi_vc_source source)
2713{
2714 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2715
2716 if (dsi->vc[channel].source == source)
2717 return 0;
2718
2719 DSSDBG("Source config of virtual channel %d", channel);
2720
2721 dsi_sync_vc(dsidev, channel);
2722
2723 dsi_vc_enable(dsidev, channel, 0);
2724
2725 /* VC_BUSY */
2726 if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel), 15, 0) != 0) {
2727 DSSERR("vc(%d) busy when trying to config for VP\n", channel);
2728 return -EIO;
2729 }
2730
2731 /* SOURCE, 0 = L4, 1 = video port */
2732 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), source, 1, 1);
2733
2734 /* DCS_CMD_ENABLE */
2735 if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) {
2736 bool enable = source == DSI_VC_SOURCE_VP;
2737 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 30, 30);
2738 }
2739
2740 dsi_vc_enable(dsidev, channel, 1);
2741
2742 dsi->vc[channel].source = source;
2743
2744 return 0;
2745}
2746
2747static void dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
2748 bool enable)
2749{
2750 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2751 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2752
2753 DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
2754
2755 WARN_ON(!dsi_bus_is_locked(dsidev));
2756
2757 dsi_vc_enable(dsidev, channel, 0);
2758 dsi_if_enable(dsidev, 0);
2759
2760 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 9, 9);
2761
2762 dsi_vc_enable(dsidev, channel, 1);
2763 dsi_if_enable(dsidev, 1);
2764
2765 dsi_force_tx_stop_mode_io(dsidev);
2766
2767 /* start the DDR clock by sending a NULL packet */
2768 if (dsi->vm_timings.ddr_clk_always_on && enable)
2769 dsi_vc_send_null(dssdev, channel);
2770}
2771
2772static void dsi_vc_flush_long_data(struct platform_device *dsidev, int channel)
2773{
2774 while (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) {
2775 u32 val;
2776 val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel));
2777 DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n",
2778 (val >> 0) & 0xff,
2779 (val >> 8) & 0xff,
2780 (val >> 16) & 0xff,
2781 (val >> 24) & 0xff);
2782 }
2783}
2784
2785static void dsi_show_rx_ack_with_err(u16 err)
2786{
2787 DSSERR("\tACK with ERROR (%#x):\n", err);
2788 if (err & (1 << 0))
2789 DSSERR("\t\tSoT Error\n");
2790 if (err & (1 << 1))
2791 DSSERR("\t\tSoT Sync Error\n");
2792 if (err & (1 << 2))
2793 DSSERR("\t\tEoT Sync Error\n");
2794 if (err & (1 << 3))
2795 DSSERR("\t\tEscape Mode Entry Command Error\n");
2796 if (err & (1 << 4))
2797 DSSERR("\t\tLP Transmit Sync Error\n");
2798 if (err & (1 << 5))
2799 DSSERR("\t\tHS Receive Timeout Error\n");
2800 if (err & (1 << 6))
2801 DSSERR("\t\tFalse Control Error\n");
2802 if (err & (1 << 7))
2803 DSSERR("\t\t(reserved7)\n");
2804 if (err & (1 << 8))
2805 DSSERR("\t\tECC Error, single-bit (corrected)\n");
2806 if (err & (1 << 9))
2807 DSSERR("\t\tECC Error, multi-bit (not corrected)\n");
2808 if (err & (1 << 10))
2809 DSSERR("\t\tChecksum Error\n");
2810 if (err & (1 << 11))
2811 DSSERR("\t\tData type not recognized\n");
2812 if (err & (1 << 12))
2813 DSSERR("\t\tInvalid VC ID\n");
2814 if (err & (1 << 13))
2815 DSSERR("\t\tInvalid Transmission Length\n");
2816 if (err & (1 << 14))
2817 DSSERR("\t\t(reserved14)\n");
2818 if (err & (1 << 15))
2819 DSSERR("\t\tDSI Protocol Violation\n");
2820}
2821
2822static u16 dsi_vc_flush_receive_data(struct platform_device *dsidev,
2823 int channel)
2824{
2825 /* RX_FIFO_NOT_EMPTY */
2826 while (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) {
2827 u32 val;
2828 u8 dt;
2829 val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel));
2830 DSSERR("\trawval %#08x\n", val);
2831 dt = FLD_GET(val, 5, 0);
2832 if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) {
2833 u16 err = FLD_GET(val, 23, 8);
2834 dsi_show_rx_ack_with_err(err);
2835 } else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE) {
2836 DSSERR("\tDCS short response, 1 byte: %#x\n",
2837 FLD_GET(val, 23, 8));
2838 } else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE) {
2839 DSSERR("\tDCS short response, 2 byte: %#x\n",
2840 FLD_GET(val, 23, 8));
2841 } else if (dt == MIPI_DSI_RX_DCS_LONG_READ_RESPONSE) {
2842 DSSERR("\tDCS long response, len %d\n",
2843 FLD_GET(val, 23, 8));
2844 dsi_vc_flush_long_data(dsidev, channel);
2845 } else {
2846 DSSERR("\tunknown datatype 0x%02x\n", dt);
2847 }
2848 }
2849 return 0;
2850}
2851
2852static int dsi_vc_send_bta(struct platform_device *dsidev, int channel)
2853{
2854 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2855
2856 if (dsi->debug_write || dsi->debug_read)
2857 DSSDBG("dsi_vc_send_bta %d\n", channel);
2858
2859 WARN_ON(!dsi_bus_is_locked(dsidev));
2860
2861 /* RX_FIFO_NOT_EMPTY */
2862 if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) {
2863 DSSERR("rx fifo not empty when sending BTA, dumping data:\n");
2864 dsi_vc_flush_receive_data(dsidev, channel);
2865 }
2866
2867 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */
2868
2869 /* flush posted write */
2870 dsi_read_reg(dsidev, DSI_VC_CTRL(channel));
2871
2872 return 0;
2873}
2874
2875static int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel)
2876{
2877 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2878 DECLARE_COMPLETION_ONSTACK(completion);
2879 int r = 0;
2880 u32 err;
2881
2882 r = dsi_register_isr_vc(dsidev, channel, dsi_completion_handler,
2883 &completion, DSI_VC_IRQ_BTA);
2884 if (r)
2885 goto err0;
2886
2887 r = dsi_register_isr(dsidev, dsi_completion_handler, &completion,
2888 DSI_IRQ_ERROR_MASK);
2889 if (r)
2890 goto err1;
2891
2892 r = dsi_vc_send_bta(dsidev, channel);
2893 if (r)
2894 goto err2;
2895
2896 if (wait_for_completion_timeout(&completion,
2897 msecs_to_jiffies(500)) == 0) {
2898 DSSERR("Failed to receive BTA\n");
2899 r = -EIO;
2900 goto err2;
2901 }
2902
2903 err = dsi_get_errors(dsidev);
2904 if (err) {
2905 DSSERR("Error while sending BTA: %x\n", err);
2906 r = -EIO;
2907 goto err2;
2908 }
2909err2:
2910 dsi_unregister_isr(dsidev, dsi_completion_handler, &completion,
2911 DSI_IRQ_ERROR_MASK);
2912err1:
2913 dsi_unregister_isr_vc(dsidev, channel, dsi_completion_handler,
2914 &completion, DSI_VC_IRQ_BTA);
2915err0:
2916 return r;
2917}
2918
2919static inline void dsi_vc_write_long_header(struct platform_device *dsidev,
2920 int channel, u8 data_type, u16 len, u8 ecc)
2921{
2922 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2923 u32 val;
2924 u8 data_id;
2925
2926 WARN_ON(!dsi_bus_is_locked(dsidev));
2927
2928 data_id = data_type | dsi->vc[channel].vc_id << 6;
2929
2930 val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) |
2931 FLD_VAL(ecc, 31, 24);
2932
2933 dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_HEADER(channel), val);
2934}
2935
2936static inline void dsi_vc_write_long_payload(struct platform_device *dsidev,
2937 int channel, u8 b1, u8 b2, u8 b3, u8 b4)
2938{
2939 u32 val;
2940
2941 val = b4 << 24 | b3 << 16 | b2 << 8 | b1 << 0;
2942
2943/* DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n",
2944 b1, b2, b3, b4, val); */
2945
2946 dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_PAYLOAD(channel), val);
2947}
2948
2949static int dsi_vc_send_long(struct platform_device *dsidev, int channel,
2950 u8 data_type, u8 *data, u16 len, u8 ecc)
2951{
2952 /*u32 val; */
2953 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2954 int i;
2955 u8 *p;
2956 int r = 0;
2957 u8 b1, b2, b3, b4;
2958
2959 if (dsi->debug_write)
2960 DSSDBG("dsi_vc_send_long, %d bytes\n", len);
2961
2962 /* len + header */
2963 if (dsi->vc[channel].tx_fifo_size * 32 * 4 < len + 4) {
2964 DSSERR("unable to send long packet: packet too long.\n");
2965 return -EINVAL;
2966 }
2967
2968 dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_L4);
2969
2970 dsi_vc_write_long_header(dsidev, channel, data_type, len, ecc);
2971
2972 p = data;
2973 for (i = 0; i < len >> 2; i++) {
2974 if (dsi->debug_write)
2975 DSSDBG("\tsending full packet %d\n", i);
2976
2977 b1 = *p++;
2978 b2 = *p++;
2979 b3 = *p++;
2980 b4 = *p++;
2981
2982 dsi_vc_write_long_payload(dsidev, channel, b1, b2, b3, b4);
2983 }
2984
2985 i = len % 4;
2986 if (i) {
2987 b1 = 0; b2 = 0; b3 = 0;
2988
2989 if (dsi->debug_write)
2990 DSSDBG("\tsending remainder bytes %d\n", i);
2991
2992 switch (i) {
2993 case 3:
2994 b1 = *p++;
2995 b2 = *p++;
2996 b3 = *p++;
2997 break;
2998 case 2:
2999 b1 = *p++;
3000 b2 = *p++;
3001 break;
3002 case 1:
3003 b1 = *p++;
3004 break;
3005 }
3006
3007 dsi_vc_write_long_payload(dsidev, channel, b1, b2, b3, 0);
3008 }
3009
3010 return r;
3011}
3012
3013static int dsi_vc_send_short(struct platform_device *dsidev, int channel,
3014 u8 data_type, u16 data, u8 ecc)
3015{
3016 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3017 u32 r;
3018 u8 data_id;
3019
3020 WARN_ON(!dsi_bus_is_locked(dsidev));
3021
3022 if (dsi->debug_write)
3023 DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n",
3024 channel,
3025 data_type, data & 0xff, (data >> 8) & 0xff);
3026
3027 dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_L4);
3028
3029 if (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(channel)), 16, 16)) {
3030 DSSERR("ERROR FIFO FULL, aborting transfer\n");
3031 return -EINVAL;
3032 }
3033
3034 data_id = data_type | dsi->vc[channel].vc_id << 6;
3035
3036 r = (data_id << 0) | (data << 8) | (ecc << 24);
3037
3038 dsi_write_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel), r);
3039
3040 return 0;
3041}
3042
3043static int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel)
3044{
3045 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3046
3047 return dsi_vc_send_long(dsidev, channel, MIPI_DSI_NULL_PACKET, NULL,
3048 0, 0);
3049}
3050
3051static int dsi_vc_write_nosync_common(struct platform_device *dsidev,
3052 int channel, u8 *data, int len, enum dss_dsi_content_type type)
3053{
3054 int r;
3055
3056 if (len == 0) {
3057 BUG_ON(type == DSS_DSI_CONTENT_DCS);
3058 r = dsi_vc_send_short(dsidev, channel,
3059 MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM, 0, 0);
3060 } else if (len == 1) {
3061 r = dsi_vc_send_short(dsidev, channel,
3062 type == DSS_DSI_CONTENT_GENERIC ?
3063 MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM :
3064 MIPI_DSI_DCS_SHORT_WRITE, data[0], 0);
3065 } else if (len == 2) {
3066 r = dsi_vc_send_short(dsidev, channel,
3067 type == DSS_DSI_CONTENT_GENERIC ?
3068 MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM :
3069 MIPI_DSI_DCS_SHORT_WRITE_PARAM,
3070 data[0] | (data[1] << 8), 0);
3071 } else {
3072 r = dsi_vc_send_long(dsidev, channel,
3073 type == DSS_DSI_CONTENT_GENERIC ?
3074 MIPI_DSI_GENERIC_LONG_WRITE :
3075 MIPI_DSI_DCS_LONG_WRITE, data, len, 0);
3076 }
3077
3078 return r;
3079}
3080
3081static int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,
3082 u8 *data, int len)
3083{
3084 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3085
3086 return dsi_vc_write_nosync_common(dsidev, channel, data, len,
3087 DSS_DSI_CONTENT_DCS);
3088}
3089
3090static int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel,
3091 u8 *data, int len)
3092{
3093 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3094
3095 return dsi_vc_write_nosync_common(dsidev, channel, data, len,
3096 DSS_DSI_CONTENT_GENERIC);
3097}
3098
3099static int dsi_vc_write_common(struct omap_dss_device *dssdev, int channel,
3100 u8 *data, int len, enum dss_dsi_content_type type)
3101{
3102 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3103 int r;
3104
3105 r = dsi_vc_write_nosync_common(dsidev, channel, data, len, type);
3106 if (r)
3107 goto err;
3108
3109 r = dsi_vc_send_bta_sync(dssdev, channel);
3110 if (r)
3111 goto err;
3112
3113 /* RX_FIFO_NOT_EMPTY */
3114 if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) {
3115 DSSERR("rx fifo not empty after write, dumping data:\n");
3116 dsi_vc_flush_receive_data(dsidev, channel);
3117 r = -EIO;
3118 goto err;
3119 }
3120
3121 return 0;
3122err:
3123 DSSERR("dsi_vc_write_common(ch %d, cmd 0x%02x, len %d) failed\n",
3124 channel, data[0], len);
3125 return r;
3126}
3127
3128static int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
3129 int len)
3130{
3131 return dsi_vc_write_common(dssdev, channel, data, len,
3132 DSS_DSI_CONTENT_DCS);
3133}
3134
3135static int dsi_vc_generic_write(struct omap_dss_device *dssdev, int channel, u8 *data,
3136 int len)
3137{
3138 return dsi_vc_write_common(dssdev, channel, data, len,
3139 DSS_DSI_CONTENT_GENERIC);
3140}
3141
3142static int dsi_vc_dcs_send_read_request(struct platform_device *dsidev,
3143 int channel, u8 dcs_cmd)
3144{
3145 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3146 int r;
3147
3148 if (dsi->debug_read)
3149 DSSDBG("dsi_vc_dcs_send_read_request(ch%d, dcs_cmd %x)\n",
3150 channel, dcs_cmd);
3151
3152 r = dsi_vc_send_short(dsidev, channel, MIPI_DSI_DCS_READ, dcs_cmd, 0);
3153 if (r) {
3154 DSSERR("dsi_vc_dcs_send_read_request(ch %d, cmd 0x%02x)"
3155 " failed\n", channel, dcs_cmd);
3156 return r;
3157 }
3158
3159 return 0;
3160}
3161
3162static int dsi_vc_generic_send_read_request(struct platform_device *dsidev,
3163 int channel, u8 *reqdata, int reqlen)
3164{
3165 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3166 u16 data;
3167 u8 data_type;
3168 int r;
3169
3170 if (dsi->debug_read)
3171 DSSDBG("dsi_vc_generic_send_read_request(ch %d, reqlen %d)\n",
3172 channel, reqlen);
3173
3174 if (reqlen == 0) {
3175 data_type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM;
3176 data = 0;
3177 } else if (reqlen == 1) {
3178 data_type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
3179 data = reqdata[0];
3180 } else if (reqlen == 2) {
3181 data_type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM;
3182 data = reqdata[0] | (reqdata[1] << 8);
3183 } else {
3184 BUG();
3185 return -EINVAL;
3186 }
3187
3188 r = dsi_vc_send_short(dsidev, channel, data_type, data, 0);
3189 if (r) {
3190 DSSERR("dsi_vc_generic_send_read_request(ch %d, reqlen %d)"
3191 " failed\n", channel, reqlen);
3192 return r;
3193 }
3194
3195 return 0;
3196}
3197
3198static int dsi_vc_read_rx_fifo(struct platform_device *dsidev, int channel,
3199 u8 *buf, int buflen, enum dss_dsi_content_type type)
3200{
3201 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3202 u32 val;
3203 u8 dt;
3204 int r;
3205
3206 /* RX_FIFO_NOT_EMPTY */
3207 if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20) == 0) {
3208 DSSERR("RX fifo empty when trying to read.\n");
3209 r = -EIO;
3210 goto err;
3211 }
3212
3213 val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel));
3214 if (dsi->debug_read)
3215 DSSDBG("\theader: %08x\n", val);
3216 dt = FLD_GET(val, 5, 0);
3217 if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) {
3218 u16 err = FLD_GET(val, 23, 8);
3219 dsi_show_rx_ack_with_err(err);
3220 r = -EIO;
3221 goto err;
3222
3223 } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ?
3224 MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE :
3225 MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE)) {
3226 u8 data = FLD_GET(val, 15, 8);
3227 if (dsi->debug_read)
3228 DSSDBG("\t%s short response, 1 byte: %02x\n",
3229 type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" :
3230 "DCS", data);
3231
3232 if (buflen < 1) {
3233 r = -EIO;
3234 goto err;
3235 }
3236
3237 buf[0] = data;
3238
3239 return 1;
3240 } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ?
3241 MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE :
3242 MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE)) {
3243 u16 data = FLD_GET(val, 23, 8);
3244 if (dsi->debug_read)
3245 DSSDBG("\t%s short response, 2 byte: %04x\n",
3246 type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" :
3247 "DCS", data);
3248
3249 if (buflen < 2) {
3250 r = -EIO;
3251 goto err;
3252 }
3253
3254 buf[0] = data & 0xff;
3255 buf[1] = (data >> 8) & 0xff;
3256
3257 return 2;
3258 } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ?
3259 MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE :
3260 MIPI_DSI_RX_DCS_LONG_READ_RESPONSE)) {
3261 int w;
3262 int len = FLD_GET(val, 23, 8);
3263 if (dsi->debug_read)
3264 DSSDBG("\t%s long response, len %d\n",
3265 type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" :
3266 "DCS", len);
3267
3268 if (len > buflen) {
3269 r = -EIO;
3270 goto err;
3271 }
3272
3273 /* two byte checksum ends the packet, not included in len */
3274 for (w = 0; w < len + 2;) {
3275 int b;
3276 val = dsi_read_reg(dsidev,
3277 DSI_VC_SHORT_PACKET_HEADER(channel));
3278 if (dsi->debug_read)
3279 DSSDBG("\t\t%02x %02x %02x %02x\n",
3280 (val >> 0) & 0xff,
3281 (val >> 8) & 0xff,
3282 (val >> 16) & 0xff,
3283 (val >> 24) & 0xff);
3284
3285 for (b = 0; b < 4; ++b) {
3286 if (w < len)
3287 buf[w] = (val >> (b * 8)) & 0xff;
3288 /* we discard the 2 byte checksum */
3289 ++w;
3290 }
3291 }
3292
3293 return len;
3294 } else {
3295 DSSERR("\tunknown datatype 0x%02x\n", dt);
3296 r = -EIO;
3297 goto err;
3298 }
3299
3300err:
3301 DSSERR("dsi_vc_read_rx_fifo(ch %d type %s) failed\n", channel,
3302 type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : "DCS");
3303
3304 return r;
3305}
3306
3307static int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
3308 u8 *buf, int buflen)
3309{
3310 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3311 int r;
3312
3313 r = dsi_vc_dcs_send_read_request(dsidev, channel, dcs_cmd);
3314 if (r)
3315 goto err;
3316
3317 r = dsi_vc_send_bta_sync(dssdev, channel);
3318 if (r)
3319 goto err;
3320
3321 r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen,
3322 DSS_DSI_CONTENT_DCS);
3323 if (r < 0)
3324 goto err;
3325
3326 if (r != buflen) {
3327 r = -EIO;
3328 goto err;
3329 }
3330
3331 return 0;
3332err:
3333 DSSERR("dsi_vc_dcs_read(ch %d, cmd 0x%02x) failed\n", channel, dcs_cmd);
3334 return r;
3335}
3336
3337static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int channel,
3338 u8 *reqdata, int reqlen, u8 *buf, int buflen)
3339{
3340 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3341 int r;
3342
3343 r = dsi_vc_generic_send_read_request(dsidev, channel, reqdata, reqlen);
3344 if (r)
3345 return r;
3346
3347 r = dsi_vc_send_bta_sync(dssdev, channel);
3348 if (r)
3349 return r;
3350
3351 r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen,
3352 DSS_DSI_CONTENT_GENERIC);
3353 if (r < 0)
3354 return r;
3355
3356 if (r != buflen) {
3357 r = -EIO;
3358 return r;
3359 }
3360
3361 return 0;
3362}
3363
3364static int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel,
3365 u16 len)
3366{
3367 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3368
3369 return dsi_vc_send_short(dsidev, channel,
3370 MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, len, 0);
3371}
3372
3373static int dsi_enter_ulps(struct platform_device *dsidev)
3374{
3375 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3376 DECLARE_COMPLETION_ONSTACK(completion);
3377 int r, i;
3378 unsigned mask;
3379
3380 DSSDBG("Entering ULPS");
3381
3382 WARN_ON(!dsi_bus_is_locked(dsidev));
3383
3384 WARN_ON(dsi->ulps_enabled);
3385
3386 if (dsi->ulps_enabled)
3387 return 0;
3388
3389 /* DDR_CLK_ALWAYS_ON */
3390 if (REG_GET(dsidev, DSI_CLK_CTRL, 13, 13)) {
3391 dsi_if_enable(dsidev, 0);
3392 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13);
3393 dsi_if_enable(dsidev, 1);
3394 }
3395
3396 dsi_sync_vc(dsidev, 0);
3397 dsi_sync_vc(dsidev, 1);
3398 dsi_sync_vc(dsidev, 2);
3399 dsi_sync_vc(dsidev, 3);
3400
3401 dsi_force_tx_stop_mode_io(dsidev);
3402
3403 dsi_vc_enable(dsidev, 0, false);
3404 dsi_vc_enable(dsidev, 1, false);
3405 dsi_vc_enable(dsidev, 2, false);
3406 dsi_vc_enable(dsidev, 3, false);
3407
3408 if (REG_GET(dsidev, DSI_COMPLEXIO_CFG2, 16, 16)) { /* HS_BUSY */
3409 DSSERR("HS busy when enabling ULPS\n");
3410 return -EIO;
3411 }
3412
3413 if (REG_GET(dsidev, DSI_COMPLEXIO_CFG2, 17, 17)) { /* LP_BUSY */
3414 DSSERR("LP busy when enabling ULPS\n");
3415 return -EIO;
3416 }
3417
3418 r = dsi_register_isr_cio(dsidev, dsi_completion_handler, &completion,
3419 DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
3420 if (r)
3421 return r;
3422
3423 mask = 0;
3424
3425 for (i = 0; i < dsi->num_lanes_supported; ++i) {
3426 if (dsi->lanes[i].function == DSI_LANE_UNUSED)
3427 continue;
3428 mask |= 1 << i;
3429 }
3430 /* Assert TxRequestEsc for data lanes and TxUlpsClk for clk lane */
3431 /* LANEx_ULPS_SIG2 */
3432 REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, mask, 9, 5);
3433
3434 /* flush posted write and wait for SCP interface to finish the write */
3435 dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2);
3436
3437 if (wait_for_completion_timeout(&completion,
3438 msecs_to_jiffies(1000)) == 0) {
3439 DSSERR("ULPS enable timeout\n");
3440 r = -EIO;
3441 goto err;
3442 }
3443
3444 dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion,
3445 DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
3446
3447 /* Reset LANEx_ULPS_SIG2 */
3448 REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, 0, 9, 5);
3449
3450 /* flush posted write and wait for SCP interface to finish the write */
3451 dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2);
3452
3453 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS);
3454
3455 dsi_if_enable(dsidev, false);
3456
3457 dsi->ulps_enabled = true;
3458
3459 return 0;
3460
3461err:
3462 dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion,
3463 DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
3464 return r;
3465}
3466
3467static void dsi_set_lp_rx_timeout(struct platform_device *dsidev,
3468 unsigned ticks, bool x4, bool x16)
3469{
3470 unsigned long fck;
3471 unsigned long total_ticks;
3472 u32 r;
3473
3474 BUG_ON(ticks > 0x1fff);
3475
3476 /* ticks in DSI_FCK */
3477 fck = dsi_fclk_rate(dsidev);
3478
3479 r = dsi_read_reg(dsidev, DSI_TIMING2);
3480 r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */
3481 r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* LP_RX_TO_X16 */
3482 r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* LP_RX_TO_X4 */
3483 r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */
3484 dsi_write_reg(dsidev, DSI_TIMING2, r);
3485
3486 total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1);
3487
3488 DSSDBG("LP_RX_TO %lu ticks (%#x%s%s) = %lu ns\n",
3489 total_ticks,
3490 ticks, x4 ? " x4" : "", x16 ? " x16" : "",
3491 (total_ticks * 1000) / (fck / 1000 / 1000));
3492}
3493
3494static void dsi_set_ta_timeout(struct platform_device *dsidev, unsigned ticks,
3495 bool x8, bool x16)
3496{
3497 unsigned long fck;
3498 unsigned long total_ticks;
3499 u32 r;
3500
3501 BUG_ON(ticks > 0x1fff);
3502
3503 /* ticks in DSI_FCK */
3504 fck = dsi_fclk_rate(dsidev);
3505
3506 r = dsi_read_reg(dsidev, DSI_TIMING1);
3507 r = FLD_MOD(r, 1, 31, 31); /* TA_TO */
3508 r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* TA_TO_X16 */
3509 r = FLD_MOD(r, x8 ? 1 : 0, 29, 29); /* TA_TO_X8 */
3510 r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */
3511 dsi_write_reg(dsidev, DSI_TIMING1, r);
3512
3513 total_ticks = ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1);
3514
3515 DSSDBG("TA_TO %lu ticks (%#x%s%s) = %lu ns\n",
3516 total_ticks,
3517 ticks, x8 ? " x8" : "", x16 ? " x16" : "",
3518 (total_ticks * 1000) / (fck / 1000 / 1000));
3519}
3520
3521static void dsi_set_stop_state_counter(struct platform_device *dsidev,
3522 unsigned ticks, bool x4, bool x16)
3523{
3524 unsigned long fck;
3525 unsigned long total_ticks;
3526 u32 r;
3527
3528 BUG_ON(ticks > 0x1fff);
3529
3530 /* ticks in DSI_FCK */
3531 fck = dsi_fclk_rate(dsidev);
3532
3533 r = dsi_read_reg(dsidev, DSI_TIMING1);
3534 r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
3535 r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* STOP_STATE_X16_IO */
3536 r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* STOP_STATE_X4_IO */
3537 r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */
3538 dsi_write_reg(dsidev, DSI_TIMING1, r);
3539
3540 total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1);
3541
3542 DSSDBG("STOP_STATE_COUNTER %lu ticks (%#x%s%s) = %lu ns\n",
3543 total_ticks,
3544 ticks, x4 ? " x4" : "", x16 ? " x16" : "",
3545 (total_ticks * 1000) / (fck / 1000 / 1000));
3546}
3547
3548static void dsi_set_hs_tx_timeout(struct platform_device *dsidev,
3549 unsigned ticks, bool x4, bool x16)
3550{
3551 unsigned long fck;
3552 unsigned long total_ticks;
3553 u32 r;
3554
3555 BUG_ON(ticks > 0x1fff);
3556
3557 /* ticks in TxByteClkHS */
3558 fck = dsi_get_txbyteclkhs(dsidev);
3559
3560 r = dsi_read_reg(dsidev, DSI_TIMING2);
3561 r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */
3562 r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* HS_TX_TO_X16 */
3563 r = FLD_MOD(r, x4 ? 1 : 0, 29, 29); /* HS_TX_TO_X8 (4 really) */
3564 r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */
3565 dsi_write_reg(dsidev, DSI_TIMING2, r);
3566
3567 total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1);
3568
3569 DSSDBG("HS_TX_TO %lu ticks (%#x%s%s) = %lu ns\n",
3570 total_ticks,
3571 ticks, x4 ? " x4" : "", x16 ? " x16" : "",
3572 (total_ticks * 1000) / (fck / 1000 / 1000));
3573}
3574
3575static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev)
3576{
3577 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3578 int num_line_buffers;
3579
3580 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
3581 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
3582 struct omap_video_timings *timings = &dsi->timings;
3583 /*
3584 * Don't use line buffers if width is greater than the video
3585 * port's line buffer size
3586 */
3587 if (dsi->line_buffer_size <= timings->x_res * bpp / 8)
3588 num_line_buffers = 0;
3589 else
3590 num_line_buffers = 2;
3591 } else {
3592 /* Use maximum number of line buffers in command mode */
3593 num_line_buffers = 2;
3594 }
3595
3596 /* LINE_BUFFER */
3597 REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12);
3598}
3599
3600static void dsi_config_vp_sync_events(struct platform_device *dsidev)
3601{
3602 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3603 bool sync_end;
3604 u32 r;
3605
3606 if (dsi->vm_timings.trans_mode == OMAP_DSS_DSI_PULSE_MODE)
3607 sync_end = true;
3608 else
3609 sync_end = false;
3610
3611 r = dsi_read_reg(dsidev, DSI_CTRL);
3612 r = FLD_MOD(r, 1, 9, 9); /* VP_DE_POL */
3613 r = FLD_MOD(r, 1, 10, 10); /* VP_HSYNC_POL */
3614 r = FLD_MOD(r, 1, 11, 11); /* VP_VSYNC_POL */
3615 r = FLD_MOD(r, 1, 15, 15); /* VP_VSYNC_START */
3616 r = FLD_MOD(r, sync_end, 16, 16); /* VP_VSYNC_END */
3617 r = FLD_MOD(r, 1, 17, 17); /* VP_HSYNC_START */
3618 r = FLD_MOD(r, sync_end, 18, 18); /* VP_HSYNC_END */
3619 dsi_write_reg(dsidev, DSI_CTRL, r);
3620}
3621
3622static void dsi_config_blanking_modes(struct platform_device *dsidev)
3623{
3624 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3625 int blanking_mode = dsi->vm_timings.blanking_mode;
3626 int hfp_blanking_mode = dsi->vm_timings.hfp_blanking_mode;
3627 int hbp_blanking_mode = dsi->vm_timings.hbp_blanking_mode;
3628 int hsa_blanking_mode = dsi->vm_timings.hsa_blanking_mode;
3629 u32 r;
3630
3631 /*
3632 * 0 = TX FIFO packets sent or LPS in corresponding blanking periods
3633 * 1 = Long blanking packets are sent in corresponding blanking periods
3634 */
3635 r = dsi_read_reg(dsidev, DSI_CTRL);
3636 r = FLD_MOD(r, blanking_mode, 20, 20); /* BLANKING_MODE */
3637 r = FLD_MOD(r, hfp_blanking_mode, 21, 21); /* HFP_BLANKING */
3638 r = FLD_MOD(r, hbp_blanking_mode, 22, 22); /* HBP_BLANKING */
3639 r = FLD_MOD(r, hsa_blanking_mode, 23, 23); /* HSA_BLANKING */
3640 dsi_write_reg(dsidev, DSI_CTRL, r);
3641}
3642
3643/*
3644 * According to section 'HS Command Mode Interleaving' in OMAP TRM, Scenario 3
3645 * results in maximum transition time for data and clock lanes to enter and
3646 * exit HS mode. Hence, this is the scenario where the least amount of command
3647 * mode data can be interleaved. We program the minimum amount of TXBYTECLKHS
3648 * clock cycles that can be used to interleave command mode data in HS so that
3649 * all scenarios are satisfied.
3650 */
3651static int dsi_compute_interleave_hs(int blank, bool ddr_alwon, int enter_hs,
3652 int exit_hs, int exiths_clk, int ddr_pre, int ddr_post)
3653{
3654 int transition;
3655
3656 /*
3657 * If DDR_CLK_ALWAYS_ON is set, we need to consider HS mode transition
3658 * time of data lanes only, if it isn't set, we need to consider HS
3659 * transition time of both data and clock lanes. HS transition time
3660 * of Scenario 3 is considered.
3661 */
3662 if (ddr_alwon) {
3663 transition = enter_hs + exit_hs + max(enter_hs, 2) + 1;
3664 } else {
3665 int trans1, trans2;
3666 trans1 = ddr_pre + enter_hs + exit_hs + max(enter_hs, 2) + 1;
3667 trans2 = ddr_pre + enter_hs + exiths_clk + ddr_post + ddr_pre +
3668 enter_hs + 1;
3669 transition = max(trans1, trans2);
3670 }
3671
3672 return blank > transition ? blank - transition : 0;
3673}
3674
3675/*
3676 * According to section 'LP Command Mode Interleaving' in OMAP TRM, Scenario 1
3677 * results in maximum transition time for data lanes to enter and exit LP mode.
3678 * Hence, this is the scenario where the least amount of command mode data can
3679 * be interleaved. We program the minimum amount of bytes that can be
3680 * interleaved in LP so that all scenarios are satisfied.
3681 */
3682static int dsi_compute_interleave_lp(int blank, int enter_hs, int exit_hs,
3683 int lp_clk_div, int tdsi_fclk)
3684{
3685 int trans_lp; /* time required for a LP transition, in TXBYTECLKHS */
3686 int tlp_avail; /* time left for interleaving commands, in CLKIN4DDR */
3687 int ttxclkesc; /* period of LP transmit escape clock, in CLKIN4DDR */
3688 int thsbyte_clk = 16; /* Period of TXBYTECLKHS clock, in CLKIN4DDR */
3689 int lp_inter; /* cmd mode data that can be interleaved, in bytes */
3690
3691 /* maximum LP transition time according to Scenario 1 */
3692 trans_lp = exit_hs + max(enter_hs, 2) + 1;
3693
3694 /* CLKIN4DDR = 16 * TXBYTECLKHS */
3695 tlp_avail = thsbyte_clk * (blank - trans_lp);
3696
3697 ttxclkesc = tdsi_fclk * lp_clk_div;
3698
3699 lp_inter = ((tlp_avail - 8 * thsbyte_clk - 5 * tdsi_fclk) / ttxclkesc -
3700 26) / 16;
3701
3702 return max(lp_inter, 0);
3703}
3704
3705static void dsi_config_cmd_mode_interleaving(struct platform_device *dsidev)
3706{
3707 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3708 int blanking_mode;
3709 int hfp_blanking_mode, hbp_blanking_mode, hsa_blanking_mode;
3710 int hsa, hfp, hbp, width_bytes, bllp, lp_clk_div;
3711 int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat;
3712 int tclk_trail, ths_exit, exiths_clk;
3713 bool ddr_alwon;
3714 struct omap_video_timings *timings = &dsi->timings;
3715 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
3716 int ndl = dsi->num_lanes_used - 1;
3717 int dsi_fclk_hsdiv = dsi->user_dsi_cinfo.regm_dsi + 1;
3718 int hsa_interleave_hs = 0, hsa_interleave_lp = 0;
3719 int hfp_interleave_hs = 0, hfp_interleave_lp = 0;
3720 int hbp_interleave_hs = 0, hbp_interleave_lp = 0;
3721 int bl_interleave_hs = 0, bl_interleave_lp = 0;
3722 u32 r;
3723
3724 r = dsi_read_reg(dsidev, DSI_CTRL);
3725 blanking_mode = FLD_GET(r, 20, 20);
3726 hfp_blanking_mode = FLD_GET(r, 21, 21);
3727 hbp_blanking_mode = FLD_GET(r, 22, 22);
3728 hsa_blanking_mode = FLD_GET(r, 23, 23);
3729
3730 r = dsi_read_reg(dsidev, DSI_VM_TIMING1);
3731 hbp = FLD_GET(r, 11, 0);
3732 hfp = FLD_GET(r, 23, 12);
3733 hsa = FLD_GET(r, 31, 24);
3734
3735 r = dsi_read_reg(dsidev, DSI_CLK_TIMING);
3736 ddr_clk_post = FLD_GET(r, 7, 0);
3737 ddr_clk_pre = FLD_GET(r, 15, 8);
3738
3739 r = dsi_read_reg(dsidev, DSI_VM_TIMING7);
3740 exit_hs_mode_lat = FLD_GET(r, 15, 0);
3741 enter_hs_mode_lat = FLD_GET(r, 31, 16);
3742
3743 r = dsi_read_reg(dsidev, DSI_CLK_CTRL);
3744 lp_clk_div = FLD_GET(r, 12, 0);
3745 ddr_alwon = FLD_GET(r, 13, 13);
3746
3747 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
3748 ths_exit = FLD_GET(r, 7, 0);
3749
3750 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
3751 tclk_trail = FLD_GET(r, 15, 8);
3752
3753 exiths_clk = ths_exit + tclk_trail;
3754
3755 width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8);
3756 bllp = hbp + hfp + hsa + DIV_ROUND_UP(width_bytes + 6, ndl);
3757
3758 if (!hsa_blanking_mode) {
3759 hsa_interleave_hs = dsi_compute_interleave_hs(hsa, ddr_alwon,
3760 enter_hs_mode_lat, exit_hs_mode_lat,
3761 exiths_clk, ddr_clk_pre, ddr_clk_post);
3762 hsa_interleave_lp = dsi_compute_interleave_lp(hsa,
3763 enter_hs_mode_lat, exit_hs_mode_lat,
3764 lp_clk_div, dsi_fclk_hsdiv);
3765 }
3766
3767 if (!hfp_blanking_mode) {
3768 hfp_interleave_hs = dsi_compute_interleave_hs(hfp, ddr_alwon,
3769 enter_hs_mode_lat, exit_hs_mode_lat,
3770 exiths_clk, ddr_clk_pre, ddr_clk_post);
3771 hfp_interleave_lp = dsi_compute_interleave_lp(hfp,
3772 enter_hs_mode_lat, exit_hs_mode_lat,
3773 lp_clk_div, dsi_fclk_hsdiv);
3774 }
3775
3776 if (!hbp_blanking_mode) {
3777 hbp_interleave_hs = dsi_compute_interleave_hs(hbp, ddr_alwon,
3778 enter_hs_mode_lat, exit_hs_mode_lat,
3779 exiths_clk, ddr_clk_pre, ddr_clk_post);
3780
3781 hbp_interleave_lp = dsi_compute_interleave_lp(hbp,
3782 enter_hs_mode_lat, exit_hs_mode_lat,
3783 lp_clk_div, dsi_fclk_hsdiv);
3784 }
3785
3786 if (!blanking_mode) {
3787 bl_interleave_hs = dsi_compute_interleave_hs(bllp, ddr_alwon,
3788 enter_hs_mode_lat, exit_hs_mode_lat,
3789 exiths_clk, ddr_clk_pre, ddr_clk_post);
3790
3791 bl_interleave_lp = dsi_compute_interleave_lp(bllp,
3792 enter_hs_mode_lat, exit_hs_mode_lat,
3793 lp_clk_div, dsi_fclk_hsdiv);
3794 }
3795
3796 DSSDBG("DSI HS interleaving(TXBYTECLKHS) HSA %d, HFP %d, HBP %d, BLLP %d\n",
3797 hsa_interleave_hs, hfp_interleave_hs, hbp_interleave_hs,
3798 bl_interleave_hs);
3799
3800 DSSDBG("DSI LP interleaving(bytes) HSA %d, HFP %d, HBP %d, BLLP %d\n",
3801 hsa_interleave_lp, hfp_interleave_lp, hbp_interleave_lp,
3802 bl_interleave_lp);
3803
3804 r = dsi_read_reg(dsidev, DSI_VM_TIMING4);
3805 r = FLD_MOD(r, hsa_interleave_hs, 23, 16);
3806 r = FLD_MOD(r, hfp_interleave_hs, 15, 8);
3807 r = FLD_MOD(r, hbp_interleave_hs, 7, 0);
3808 dsi_write_reg(dsidev, DSI_VM_TIMING4, r);
3809
3810 r = dsi_read_reg(dsidev, DSI_VM_TIMING5);
3811 r = FLD_MOD(r, hsa_interleave_lp, 23, 16);
3812 r = FLD_MOD(r, hfp_interleave_lp, 15, 8);
3813 r = FLD_MOD(r, hbp_interleave_lp, 7, 0);
3814 dsi_write_reg(dsidev, DSI_VM_TIMING5, r);
3815
3816 r = dsi_read_reg(dsidev, DSI_VM_TIMING6);
3817 r = FLD_MOD(r, bl_interleave_hs, 31, 15);
3818 r = FLD_MOD(r, bl_interleave_lp, 16, 0);
3819 dsi_write_reg(dsidev, DSI_VM_TIMING6, r);
3820}
3821
3822static int dsi_proto_config(struct platform_device *dsidev)
3823{
3824 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3825 u32 r;
3826 int buswidth = 0;
3827
3828 dsi_config_tx_fifo(dsidev, DSI_FIFO_SIZE_32,
3829 DSI_FIFO_SIZE_32,
3830 DSI_FIFO_SIZE_32,
3831 DSI_FIFO_SIZE_32);
3832
3833 dsi_config_rx_fifo(dsidev, DSI_FIFO_SIZE_32,
3834 DSI_FIFO_SIZE_32,
3835 DSI_FIFO_SIZE_32,
3836 DSI_FIFO_SIZE_32);
3837
3838 /* XXX what values for the timeouts? */
3839 dsi_set_stop_state_counter(dsidev, 0x1000, false, false);
3840 dsi_set_ta_timeout(dsidev, 0x1fff, true, true);
3841 dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true);
3842 dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true);
3843
3844 switch (dsi_get_pixel_size(dsi->pix_fmt)) {
3845 case 16:
3846 buswidth = 0;
3847 break;
3848 case 18:
3849 buswidth = 1;
3850 break;
3851 case 24:
3852 buswidth = 2;
3853 break;
3854 default:
3855 BUG();
3856 return -EINVAL;
3857 }
3858
3859 r = dsi_read_reg(dsidev, DSI_CTRL);
3860 r = FLD_MOD(r, 1, 1, 1); /* CS_RX_EN */
3861 r = FLD_MOD(r, 1, 2, 2); /* ECC_RX_EN */
3862 r = FLD_MOD(r, 1, 3, 3); /* TX_FIFO_ARBITRATION */
3863 r = FLD_MOD(r, 1, 4, 4); /* VP_CLK_RATIO, always 1, see errata*/
3864 r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */
3865 r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */
3866 r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */
3867 r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */
3868 if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) {
3869 r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */
3870 /* DCS_CMD_CODE, 1=start, 0=continue */
3871 r = FLD_MOD(r, 0, 25, 25);
3872 }
3873
3874 dsi_write_reg(dsidev, DSI_CTRL, r);
3875
3876 dsi_config_vp_num_line_buffers(dsidev);
3877
3878 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
3879 dsi_config_vp_sync_events(dsidev);
3880 dsi_config_blanking_modes(dsidev);
3881 dsi_config_cmd_mode_interleaving(dsidev);
3882 }
3883
3884 dsi_vc_initial_config(dsidev, 0);
3885 dsi_vc_initial_config(dsidev, 1);
3886 dsi_vc_initial_config(dsidev, 2);
3887 dsi_vc_initial_config(dsidev, 3);
3888
3889 return 0;
3890}
3891
3892static void dsi_proto_timings(struct platform_device *dsidev)
3893{
3894 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3895 unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
3896 unsigned tclk_pre, tclk_post;
3897 unsigned ths_prepare, ths_prepare_ths_zero, ths_zero;
3898 unsigned ths_trail, ths_exit;
3899 unsigned ddr_clk_pre, ddr_clk_post;
3900 unsigned enter_hs_mode_lat, exit_hs_mode_lat;
3901 unsigned ths_eot;
3902 int ndl = dsi->num_lanes_used - 1;
3903 u32 r;
3904
3905 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
3906 ths_prepare = FLD_GET(r, 31, 24);
3907 ths_prepare_ths_zero = FLD_GET(r, 23, 16);
3908 ths_zero = ths_prepare_ths_zero - ths_prepare;
3909 ths_trail = FLD_GET(r, 15, 8);
3910 ths_exit = FLD_GET(r, 7, 0);
3911
3912 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
3913 tlpx = FLD_GET(r, 20, 16) * 2;
3914 tclk_trail = FLD_GET(r, 15, 8);
3915 tclk_zero = FLD_GET(r, 7, 0);
3916
3917 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2);
3918 tclk_prepare = FLD_GET(r, 7, 0);
3919
3920 /* min 8*UI */
3921 tclk_pre = 20;
3922 /* min 60ns + 52*UI */
3923 tclk_post = ns2ddr(dsidev, 60) + 26;
3924
3925 ths_eot = DIV_ROUND_UP(4, ndl);
3926
3927 ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare,
3928 4);
3929 ddr_clk_post = DIV_ROUND_UP(tclk_post + ths_trail, 4) + ths_eot;
3930
3931 BUG_ON(ddr_clk_pre == 0 || ddr_clk_pre > 255);
3932 BUG_ON(ddr_clk_post == 0 || ddr_clk_post > 255);
3933
3934 r = dsi_read_reg(dsidev, DSI_CLK_TIMING);
3935 r = FLD_MOD(r, ddr_clk_pre, 15, 8);
3936 r = FLD_MOD(r, ddr_clk_post, 7, 0);
3937 dsi_write_reg(dsidev, DSI_CLK_TIMING, r);
3938
3939 DSSDBG("ddr_clk_pre %u, ddr_clk_post %u\n",
3940 ddr_clk_pre,
3941 ddr_clk_post);
3942
3943 enter_hs_mode_lat = 1 + DIV_ROUND_UP(tlpx, 4) +
3944 DIV_ROUND_UP(ths_prepare, 4) +
3945 DIV_ROUND_UP(ths_zero + 3, 4);
3946
3947 exit_hs_mode_lat = DIV_ROUND_UP(ths_trail + ths_exit, 4) + 1 + ths_eot;
3948
3949 r = FLD_VAL(enter_hs_mode_lat, 31, 16) |
3950 FLD_VAL(exit_hs_mode_lat, 15, 0);
3951 dsi_write_reg(dsidev, DSI_VM_TIMING7, r);
3952
3953 DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
3954 enter_hs_mode_lat, exit_hs_mode_lat);
3955
3956 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
3957 /* TODO: Implement a video mode check_timings function */
3958 int hsa = dsi->vm_timings.hsa;
3959 int hfp = dsi->vm_timings.hfp;
3960 int hbp = dsi->vm_timings.hbp;
3961 int vsa = dsi->vm_timings.vsa;
3962 int vfp = dsi->vm_timings.vfp;
3963 int vbp = dsi->vm_timings.vbp;
3964 int window_sync = dsi->vm_timings.window_sync;
3965 bool hsync_end;
3966 struct omap_video_timings *timings = &dsi->timings;
3967 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
3968 int tl, t_he, width_bytes;
3969
3970 hsync_end = dsi->vm_timings.trans_mode == OMAP_DSS_DSI_PULSE_MODE;
3971 t_he = hsync_end ?
3972 ((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0;
3973
3974 width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8);
3975
3976 /* TL = t_HS + HSA + t_HE + HFP + ceil((WC + 6) / NDL) + HBP */
3977 tl = DIV_ROUND_UP(4, ndl) + (hsync_end ? hsa : 0) + t_he + hfp +
3978 DIV_ROUND_UP(width_bytes + 6, ndl) + hbp;
3979
3980 DSSDBG("HBP: %d, HFP: %d, HSA: %d, TL: %d TXBYTECLKHS\n", hbp,
3981 hfp, hsync_end ? hsa : 0, tl);
3982 DSSDBG("VBP: %d, VFP: %d, VSA: %d, VACT: %d lines\n", vbp, vfp,
3983 vsa, timings->y_res);
3984
3985 r = dsi_read_reg(dsidev, DSI_VM_TIMING1);
3986 r = FLD_MOD(r, hbp, 11, 0); /* HBP */
3987 r = FLD_MOD(r, hfp, 23, 12); /* HFP */
3988 r = FLD_MOD(r, hsync_end ? hsa : 0, 31, 24); /* HSA */
3989 dsi_write_reg(dsidev, DSI_VM_TIMING1, r);
3990
3991 r = dsi_read_reg(dsidev, DSI_VM_TIMING2);
3992 r = FLD_MOD(r, vbp, 7, 0); /* VBP */
3993 r = FLD_MOD(r, vfp, 15, 8); /* VFP */
3994 r = FLD_MOD(r, vsa, 23, 16); /* VSA */
3995 r = FLD_MOD(r, window_sync, 27, 24); /* WINDOW_SYNC */
3996 dsi_write_reg(dsidev, DSI_VM_TIMING2, r);
3997
3998 r = dsi_read_reg(dsidev, DSI_VM_TIMING3);
3999 r = FLD_MOD(r, timings->y_res, 14, 0); /* VACT */
4000 r = FLD_MOD(r, tl, 31, 16); /* TL */
4001 dsi_write_reg(dsidev, DSI_VM_TIMING3, r);
4002 }
4003}
4004
4005static int dsi_configure_pins(struct omap_dss_device *dssdev,
4006 const struct omap_dsi_pin_config *pin_cfg)
4007{
4008 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4009 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4010 int num_pins;
4011 const int *pins;
4012 struct dsi_lane_config lanes[DSI_MAX_NR_LANES];
4013 int num_lanes;
4014 int i;
4015
4016 static const enum dsi_lane_function functions[] = {
4017 DSI_LANE_CLK,
4018 DSI_LANE_DATA1,
4019 DSI_LANE_DATA2,
4020 DSI_LANE_DATA3,
4021 DSI_LANE_DATA4,
4022 };
4023
4024 num_pins = pin_cfg->num_pins;
4025 pins = pin_cfg->pins;
4026
4027 if (num_pins < 4 || num_pins > dsi->num_lanes_supported * 2
4028 || num_pins % 2 != 0)
4029 return -EINVAL;
4030
4031 for (i = 0; i < DSI_MAX_NR_LANES; ++i)
4032 lanes[i].function = DSI_LANE_UNUSED;
4033
4034 num_lanes = 0;
4035
4036 for (i = 0; i < num_pins; i += 2) {
4037 u8 lane, pol;
4038 int dx, dy;
4039
4040 dx = pins[i];
4041 dy = pins[i + 1];
4042
4043 if (dx < 0 || dx >= dsi->num_lanes_supported * 2)
4044 return -EINVAL;
4045
4046 if (dy < 0 || dy >= dsi->num_lanes_supported * 2)
4047 return -EINVAL;
4048
4049 if (dx & 1) {
4050 if (dy != dx - 1)
4051 return -EINVAL;
4052 pol = 1;
4053 } else {
4054 if (dy != dx + 1)
4055 return -EINVAL;
4056 pol = 0;
4057 }
4058
4059 lane = dx / 2;
4060
4061 lanes[lane].function = functions[i / 2];
4062 lanes[lane].polarity = pol;
4063 num_lanes++;
4064 }
4065
4066 memcpy(dsi->lanes, lanes, sizeof(dsi->lanes));
4067 dsi->num_lanes_used = num_lanes;
4068
4069 return 0;
4070}
4071
4072static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
4073{
4074 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4075 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4076 struct omap_overlay_manager *mgr = dsi->output.manager;
4077 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
4078 struct omap_dss_device *out = &dsi->output;
4079 u8 data_type;
4080 u16 word_count;
4081 int r;
4082
4083 if (out == NULL || out->manager == NULL) {
4084 DSSERR("failed to enable display: no output/manager\n");
4085 return -ENODEV;
4086 }
4087
4088 r = dsi_display_init_dispc(dsidev, mgr);
4089 if (r)
4090 goto err_init_dispc;
4091
4092 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
4093 switch (dsi->pix_fmt) {
4094 case OMAP_DSS_DSI_FMT_RGB888:
4095 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
4096 break;
4097 case OMAP_DSS_DSI_FMT_RGB666:
4098 data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
4099 break;
4100 case OMAP_DSS_DSI_FMT_RGB666_PACKED:
4101 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18;
4102 break;
4103 case OMAP_DSS_DSI_FMT_RGB565:
4104 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16;
4105 break;
4106 default:
4107 r = -EINVAL;
4108 goto err_pix_fmt;
4109 }
4110
4111 dsi_if_enable(dsidev, false);
4112 dsi_vc_enable(dsidev, channel, false);
4113
4114 /* MODE, 1 = video mode */
4115 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);
4116
4117 word_count = DIV_ROUND_UP(dsi->timings.x_res * bpp, 8);
4118
4119 dsi_vc_write_long_header(dsidev, channel, data_type,
4120 word_count, 0);
4121
4122 dsi_vc_enable(dsidev, channel, true);
4123 dsi_if_enable(dsidev, true);
4124 }
4125
4126 r = dss_mgr_enable(mgr);
4127 if (r)
4128 goto err_mgr_enable;
4129
4130 return 0;
4131
4132err_mgr_enable:
4133 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
4134 dsi_if_enable(dsidev, false);
4135 dsi_vc_enable(dsidev, channel, false);
4136 }
4137err_pix_fmt:
4138 dsi_display_uninit_dispc(dsidev, mgr);
4139err_init_dispc:
4140 return r;
4141}
4142
4143static void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
4144{
4145 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4146 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4147 struct omap_overlay_manager *mgr = dsi->output.manager;
4148
4149 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
4150 dsi_if_enable(dsidev, false);
4151 dsi_vc_enable(dsidev, channel, false);
4152
4153 /* MODE, 0 = command mode */
4154 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4);
4155
4156 dsi_vc_enable(dsidev, channel, true);
4157 dsi_if_enable(dsidev, true);
4158 }
4159
4160 dss_mgr_disable(mgr);
4161
4162 dsi_display_uninit_dispc(dsidev, mgr);
4163}
4164
4165static void dsi_update_screen_dispc(struct platform_device *dsidev)
4166{
4167 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4168 struct omap_overlay_manager *mgr = dsi->output.manager;
4169 unsigned bytespp;
4170 unsigned bytespl;
4171 unsigned bytespf;
4172 unsigned total_len;
4173 unsigned packet_payload;
4174 unsigned packet_len;
4175 u32 l;
4176 int r;
4177 const unsigned channel = dsi->update_channel;
4178 const unsigned line_buf_size = dsi->line_buffer_size;
4179 u16 w = dsi->timings.x_res;
4180 u16 h = dsi->timings.y_res;
4181
4182 DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h);
4183
4184 dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP);
4185
4186 bytespp = dsi_get_pixel_size(dsi->pix_fmt) / 8;
4187 bytespl = w * bytespp;
4188 bytespf = bytespl * h;
4189
4190 /* NOTE: packet_payload has to be equal to N * bytespl, where N is
4191 * number of lines in a packet. See errata about VP_CLK_RATIO */
4192
4193 if (bytespf < line_buf_size)
4194 packet_payload = bytespf;
4195 else
4196 packet_payload = (line_buf_size) / bytespl * bytespl;
4197
4198 packet_len = packet_payload + 1; /* 1 byte for DCS cmd */
4199 total_len = (bytespf / packet_payload) * packet_len;
4200
4201 if (bytespf % packet_payload)
4202 total_len += (bytespf % packet_payload) + 1;
4203
4204 l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
4205 dsi_write_reg(dsidev, DSI_VC_TE(channel), l);
4206
4207 dsi_vc_write_long_header(dsidev, channel, MIPI_DSI_DCS_LONG_WRITE,
4208 packet_len, 0);
4209
4210 if (dsi->te_enabled)
4211 l = FLD_MOD(l, 1, 30, 30); /* TE_EN */
4212 else
4213 l = FLD_MOD(l, 1, 31, 31); /* TE_START */
4214 dsi_write_reg(dsidev, DSI_VC_TE(channel), l);
4215
4216 /* We put SIDLEMODE to no-idle for the duration of the transfer,
4217 * because DSS interrupts are not capable of waking up the CPU and the
4218 * framedone interrupt could be delayed for quite a long time. I think
4219 * the same goes for any DSS interrupts, but for some reason I have not
4220 * seen the problem anywhere else than here.
4221 */
4222 dispc_disable_sidle();
4223
4224 dsi_perf_mark_start(dsidev);
4225
4226 r = schedule_delayed_work(&dsi->framedone_timeout_work,
4227 msecs_to_jiffies(250));
4228 BUG_ON(r == 0);
4229
4230 dss_mgr_set_timings(mgr, &dsi->timings);
4231
4232 dss_mgr_start_update(mgr);
4233
4234 if (dsi->te_enabled) {
4235 /* disable LP_RX_TO, so that we can receive TE. Time to wait
4236 * for TE is longer than the timer allows */
4237 REG_FLD_MOD(dsidev, DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
4238
4239 dsi_vc_send_bta(dsidev, channel);
4240
4241#ifdef DSI_CATCH_MISSING_TE
4242 mod_timer(&dsi->te_timer, jiffies + msecs_to_jiffies(250));
4243#endif
4244 }
4245}
4246
4247#ifdef DSI_CATCH_MISSING_TE
4248static void dsi_te_timeout(unsigned long arg)
4249{
4250 DSSERR("TE not received for 250ms!\n");
4251}
4252#endif
4253
4254static void dsi_handle_framedone(struct platform_device *dsidev, int error)
4255{
4256 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4257
4258 /* SIDLEMODE back to smart-idle */
4259 dispc_enable_sidle();
4260
4261 if (dsi->te_enabled) {
4262 /* enable LP_RX_TO again after the TE */
4263 REG_FLD_MOD(dsidev, DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
4264 }
4265
4266 dsi->framedone_callback(error, dsi->framedone_data);
4267
4268 if (!error)
4269 dsi_perf_show(dsidev, "DISPC");
4270}
4271
4272static void dsi_framedone_timeout_work_callback(struct work_struct *work)
4273{
4274 struct dsi_data *dsi = container_of(work, struct dsi_data,
4275 framedone_timeout_work.work);
4276 /* XXX While extremely unlikely, we could get FRAMEDONE interrupt after
4277 * 250ms which would conflict with this timeout work. What should be
4278 * done is first cancel the transfer on the HW, and then cancel the
4279 * possibly scheduled framedone work. However, cancelling the transfer
4280 * on the HW is buggy, and would probably require resetting the whole
4281 * DSI */
4282
4283 DSSERR("Framedone not received for 250ms!\n");
4284
4285 dsi_handle_framedone(dsi->pdev, -ETIMEDOUT);
4286}
4287
4288static void dsi_framedone_irq_callback(void *data)
4289{
4290 struct platform_device *dsidev = (struct platform_device *) data;
4291 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4292
4293 /* Note: We get FRAMEDONE when DISPC has finished sending pixels and
4294 * turns itself off. However, DSI still has the pixels in its buffers,
4295 * and is sending the data.
4296 */
4297
4298 cancel_delayed_work(&dsi->framedone_timeout_work);
4299
4300 dsi_handle_framedone(dsidev, 0);
4301}
4302
4303static int dsi_update(struct omap_dss_device *dssdev, int channel,
4304 void (*callback)(int, void *), void *data)
4305{
4306 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4307 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4308 u16 dw, dh;
4309
4310 dsi_perf_mark_setup(dsidev);
4311
4312 dsi->update_channel = channel;
4313
4314 dsi->framedone_callback = callback;
4315 dsi->framedone_data = data;
4316
4317 dw = dsi->timings.x_res;
4318 dh = dsi->timings.y_res;
4319
4320#ifdef DSI_PERF_MEASURE
4321 dsi->update_bytes = dw * dh *
4322 dsi_get_pixel_size(dsi->pix_fmt) / 8;
4323#endif
4324 dsi_update_screen_dispc(dsidev);
4325
4326 return 0;
4327}
4328
4329/* Display funcs */
4330
4331static int dsi_configure_dispc_clocks(struct platform_device *dsidev)
4332{
4333 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4334 struct dispc_clock_info dispc_cinfo;
4335 int r;
4336 unsigned long fck;
4337
4338 fck = dsi_get_pll_hsdiv_dispc_rate(dsidev);
4339
4340 dispc_cinfo.lck_div = dsi->user_dispc_cinfo.lck_div;
4341 dispc_cinfo.pck_div = dsi->user_dispc_cinfo.pck_div;
4342
4343 r = dispc_calc_clock_rates(fck, &dispc_cinfo);
4344 if (r) {
4345 DSSERR("Failed to calc dispc clocks\n");
4346 return r;
4347 }
4348
4349 dsi->mgr_config.clock_info = dispc_cinfo;
4350
4351 return 0;
4352}
4353
4354static int dsi_display_init_dispc(struct platform_device *dsidev,
4355 struct omap_overlay_manager *mgr)
4356{
4357 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4358 int r;
4359
4360 dss_select_lcd_clk_source(mgr->id, dsi->module_id == 0 ?
4361 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
4362 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC);
4363
4364 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
4365 r = dss_mgr_register_framedone_handler(mgr,
4366 dsi_framedone_irq_callback, dsidev);
4367 if (r) {
4368 DSSERR("can't register FRAMEDONE handler\n");
4369 goto err;
4370 }
4371
4372 dsi->mgr_config.stallmode = true;
4373 dsi->mgr_config.fifohandcheck = true;
4374 } else {
4375 dsi->mgr_config.stallmode = false;
4376 dsi->mgr_config.fifohandcheck = false;
4377 }
4378
4379 /*
4380 * override interlace, logic level and edge related parameters in
4381 * omap_video_timings with default values
4382 */
4383 dsi->timings.interlace = false;
4384 dsi->timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
4385 dsi->timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
4386 dsi->timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
4387 dsi->timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
4388 dsi->timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
4389
4390 dss_mgr_set_timings(mgr, &dsi->timings);
4391
4392 r = dsi_configure_dispc_clocks(dsidev);
4393 if (r)
4394 goto err1;
4395
4396 dsi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
4397 dsi->mgr_config.video_port_width =
4398 dsi_get_pixel_size(dsi->pix_fmt);
4399 dsi->mgr_config.lcden_sig_polarity = 0;
4400
4401 dss_mgr_set_lcd_config(mgr, &dsi->mgr_config);
4402
4403 return 0;
4404err1:
4405 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
4406 dss_mgr_unregister_framedone_handler(mgr,
4407 dsi_framedone_irq_callback, dsidev);
4408err:
4409 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
4410 return r;
4411}
4412
4413static void dsi_display_uninit_dispc(struct platform_device *dsidev,
4414 struct omap_overlay_manager *mgr)
4415{
4416 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4417
4418 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
4419 dss_mgr_unregister_framedone_handler(mgr,
4420 dsi_framedone_irq_callback, dsidev);
4421
4422 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
4423}
4424
4425static int dsi_configure_dsi_clocks(struct platform_device *dsidev)
4426{
4427 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4428 struct dsi_clock_info cinfo;
4429 int r;
4430
4431 cinfo = dsi->user_dsi_cinfo;
4432
4433 r = dsi_calc_clock_rates(dsidev, &cinfo);
4434 if (r) {
4435 DSSERR("Failed to calc dsi clocks\n");
4436 return r;
4437 }
4438
4439 r = dsi_pll_set_clock_div(dsidev, &cinfo);
4440 if (r) {
4441 DSSERR("Failed to set dsi clocks\n");
4442 return r;
4443 }
4444
4445 return 0;
4446}
4447
4448static int dsi_display_init_dsi(struct platform_device *dsidev)
4449{
4450 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4451 int r;
4452
4453 r = dsi_pll_init(dsidev, true, true);
4454 if (r)
4455 goto err0;
4456
4457 r = dsi_configure_dsi_clocks(dsidev);
4458 if (r)
4459 goto err1;
4460
4461 dss_select_dsi_clk_source(dsi->module_id, dsi->module_id == 0 ?
4462 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
4463 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI);
4464
4465 DSSDBG("PLL OK\n");
4466
4467 r = dsi_cio_init(dsidev);
4468 if (r)
4469 goto err2;
4470
4471 _dsi_print_reset_status(dsidev);
4472
4473 dsi_proto_timings(dsidev);
4474 dsi_set_lp_clk_divisor(dsidev);
4475
4476 if (1)
4477 _dsi_print_reset_status(dsidev);
4478
4479 r = dsi_proto_config(dsidev);
4480 if (r)
4481 goto err3;
4482
4483 /* enable interface */
4484 dsi_vc_enable(dsidev, 0, 1);
4485 dsi_vc_enable(dsidev, 1, 1);
4486 dsi_vc_enable(dsidev, 2, 1);
4487 dsi_vc_enable(dsidev, 3, 1);
4488 dsi_if_enable(dsidev, 1);
4489 dsi_force_tx_stop_mode_io(dsidev);
4490
4491 return 0;
4492err3:
4493 dsi_cio_uninit(dsidev);
4494err2:
4495 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
4496err1:
4497 dsi_pll_uninit(dsidev, true);
4498err0:
4499 return r;
4500}
4501
4502static void dsi_display_uninit_dsi(struct platform_device *dsidev,
4503 bool disconnect_lanes, bool enter_ulps)
4504{
4505 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4506
4507 if (enter_ulps && !dsi->ulps_enabled)
4508 dsi_enter_ulps(dsidev);
4509
4510 /* disable interface */
4511 dsi_if_enable(dsidev, 0);
4512 dsi_vc_enable(dsidev, 0, 0);
4513 dsi_vc_enable(dsidev, 1, 0);
4514 dsi_vc_enable(dsidev, 2, 0);
4515 dsi_vc_enable(dsidev, 3, 0);
4516
4517 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
4518 dsi_cio_uninit(dsidev);
4519 dsi_pll_uninit(dsidev, disconnect_lanes);
4520}
4521
4522static int dsi_display_enable(struct omap_dss_device *dssdev)
4523{
4524 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4525 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4526 int r = 0;
4527
4528 DSSDBG("dsi_display_enable\n");
4529
4530 WARN_ON(!dsi_bus_is_locked(dsidev));
4531
4532 mutex_lock(&dsi->lock);
4533
4534 r = dsi_runtime_get(dsidev);
4535 if (r)
4536 goto err_get_dsi;
4537
4538 dsi_enable_pll_clock(dsidev, 1);
4539
4540 _dsi_initialize_irq(dsidev);
4541
4542 r = dsi_display_init_dsi(dsidev);
4543 if (r)
4544 goto err_init_dsi;
4545
4546 mutex_unlock(&dsi->lock);
4547
4548 return 0;
4549
4550err_init_dsi:
4551 dsi_enable_pll_clock(dsidev, 0);
4552 dsi_runtime_put(dsidev);
4553err_get_dsi:
4554 mutex_unlock(&dsi->lock);
4555 DSSDBG("dsi_display_enable FAILED\n");
4556 return r;
4557}
4558
4559static void dsi_display_disable(struct omap_dss_device *dssdev,
4560 bool disconnect_lanes, bool enter_ulps)
4561{
4562 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4563 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4564
4565 DSSDBG("dsi_display_disable\n");
4566
4567 WARN_ON(!dsi_bus_is_locked(dsidev));
4568
4569 mutex_lock(&dsi->lock);
4570
4571 dsi_sync_vc(dsidev, 0);
4572 dsi_sync_vc(dsidev, 1);
4573 dsi_sync_vc(dsidev, 2);
4574 dsi_sync_vc(dsidev, 3);
4575
4576 dsi_display_uninit_dsi(dsidev, disconnect_lanes, enter_ulps);
4577
4578 dsi_runtime_put(dsidev);
4579 dsi_enable_pll_clock(dsidev, 0);
4580
4581 mutex_unlock(&dsi->lock);
4582}
4583
4584static int dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
4585{
4586 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4587 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4588
4589 dsi->te_enabled = enable;
4590 return 0;
4591}
4592
4593#ifdef PRINT_VERBOSE_VM_TIMINGS
4594static void print_dsi_vm(const char *str,
4595 const struct omap_dss_dsi_videomode_timings *t)
4596{
4597 unsigned long byteclk = t->hsclk / 4;
4598 int bl, wc, pps, tot;
4599
4600 wc = DIV_ROUND_UP(t->hact * t->bitspp, 8);
4601 pps = DIV_ROUND_UP(wc + 6, t->ndl); /* pixel packet size */
4602 bl = t->hss + t->hsa + t->hse + t->hbp + t->hfp;
4603 tot = bl + pps;
4604
4605#define TO_DSI_T(x) ((u32)div64_u64((u64)x * 1000000000llu, byteclk))
4606
4607 pr_debug("%s bck %lu, %u/%u/%u/%u/%u/%u = %u+%u = %u, "
4608 "%u/%u/%u/%u/%u/%u = %u + %u = %u\n",
4609 str,
4610 byteclk,
4611 t->hss, t->hsa, t->hse, t->hbp, pps, t->hfp,
4612 bl, pps, tot,
4613 TO_DSI_T(t->hss),
4614 TO_DSI_T(t->hsa),
4615 TO_DSI_T(t->hse),
4616 TO_DSI_T(t->hbp),
4617 TO_DSI_T(pps),
4618 TO_DSI_T(t->hfp),
4619
4620 TO_DSI_T(bl),
4621 TO_DSI_T(pps),
4622
4623 TO_DSI_T(tot));
4624#undef TO_DSI_T
4625}
4626
4627static void print_dispc_vm(const char *str, const struct omap_video_timings *t)
4628{
4629 unsigned long pck = t->pixelclock;
4630 int hact, bl, tot;
4631
4632 hact = t->x_res;
4633 bl = t->hsw + t->hbp + t->hfp;
4634 tot = hact + bl;
4635
4636#define TO_DISPC_T(x) ((u32)div64_u64((u64)x * 1000000000llu, pck))
4637
4638 pr_debug("%s pck %lu, %u/%u/%u/%u = %u+%u = %u, "
4639 "%u/%u/%u/%u = %u + %u = %u\n",
4640 str,
4641 pck,
4642 t->hsw, t->hbp, hact, t->hfp,
4643 bl, hact, tot,
4644 TO_DISPC_T(t->hsw),
4645 TO_DISPC_T(t->hbp),
4646 TO_DISPC_T(hact),
4647 TO_DISPC_T(t->hfp),
4648 TO_DISPC_T(bl),
4649 TO_DISPC_T(hact),
4650 TO_DISPC_T(tot));
4651#undef TO_DISPC_T
4652}
4653
4654/* note: this is not quite accurate */
4655static void print_dsi_dispc_vm(const char *str,
4656 const struct omap_dss_dsi_videomode_timings *t)
4657{
4658 struct omap_video_timings vm = { 0 };
4659 unsigned long byteclk = t->hsclk / 4;
4660 unsigned long pck;
4661 u64 dsi_tput;
4662 int dsi_hact, dsi_htot;
4663
4664 dsi_tput = (u64)byteclk * t->ndl * 8;
4665 pck = (u32)div64_u64(dsi_tput, t->bitspp);
4666 dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(t->hact * t->bitspp, 8) + 6, t->ndl);
4667 dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfp;
4668
4669 vm.pixelclock = pck;
4670 vm.hsw = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk);
4671 vm.hbp = div64_u64((u64)t->hbp * pck, byteclk);
4672 vm.hfp = div64_u64((u64)t->hfp * pck, byteclk);
4673 vm.x_res = t->hact;
4674
4675 print_dispc_vm(str, &vm);
4676}
4677#endif /* PRINT_VERBOSE_VM_TIMINGS */
4678
4679static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
4680 unsigned long pck, void *data)
4681{
4682 struct dsi_clk_calc_ctx *ctx = data;
4683 struct omap_video_timings *t = &ctx->dispc_vm;
4684
4685 ctx->dispc_cinfo.lck_div = lckd;
4686 ctx->dispc_cinfo.pck_div = pckd;
4687 ctx->dispc_cinfo.lck = lck;
4688 ctx->dispc_cinfo.pck = pck;
4689
4690 *t = *ctx->config->timings;
4691 t->pixelclock = pck;
4692 t->x_res = ctx->config->timings->x_res;
4693 t->y_res = ctx->config->timings->y_res;
4694 t->hsw = t->hfp = t->hbp = t->vsw = 1;
4695 t->vfp = t->vbp = 0;
4696
4697 return true;
4698}
4699
4700static bool dsi_cm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
4701 void *data)
4702{
4703 struct dsi_clk_calc_ctx *ctx = data;
4704
4705 ctx->dsi_cinfo.regm_dispc = regm_dispc;
4706 ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
4707
4708 return dispc_div_calc(dispc, ctx->req_pck_min, ctx->req_pck_max,
4709 dsi_cm_calc_dispc_cb, ctx);
4710}
4711
4712static bool dsi_cm_calc_pll_cb(int regn, int regm, unsigned long fint,
4713 unsigned long pll, void *data)
4714{
4715 struct dsi_clk_calc_ctx *ctx = data;
4716
4717 ctx->dsi_cinfo.regn = regn;
4718 ctx->dsi_cinfo.regm = regm;
4719 ctx->dsi_cinfo.fint = fint;
4720 ctx->dsi_cinfo.clkin4ddr = pll;
4721
4722 return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min,
4723 dsi_cm_calc_hsdiv_cb, ctx);
4724}
4725
4726static bool dsi_cm_calc(struct dsi_data *dsi,
4727 const struct omap_dss_dsi_config *cfg,
4728 struct dsi_clk_calc_ctx *ctx)
4729{
4730 unsigned long clkin;
4731 int bitspp, ndl;
4732 unsigned long pll_min, pll_max;
4733 unsigned long pck, txbyteclk;
4734
4735 clkin = clk_get_rate(dsi->sys_clk);
4736 bitspp = dsi_get_pixel_size(cfg->pixel_format);
4737 ndl = dsi->num_lanes_used - 1;
4738
4739 /*
4740 * Here we should calculate minimum txbyteclk to be able to send the
4741 * frame in time, and also to handle TE. That's not very simple, though,
4742 * especially as we go to LP between each pixel packet due to HW
4743 * "feature". So let's just estimate very roughly and multiply by 1.5.
4744 */
4745 pck = cfg->timings->pixelclock;
4746 pck = pck * 3 / 2;
4747 txbyteclk = pck * bitspp / 8 / ndl;
4748
4749 memset(ctx, 0, sizeof(*ctx));
4750 ctx->dsidev = dsi->pdev;
4751 ctx->config = cfg;
4752 ctx->req_pck_min = pck;
4753 ctx->req_pck_nom = pck;
4754 ctx->req_pck_max = pck * 3 / 2;
4755 ctx->dsi_cinfo.clkin = clkin;
4756
4757 pll_min = max(cfg->hs_clk_min * 4, txbyteclk * 4 * 4);
4758 pll_max = cfg->hs_clk_max * 4;
4759
4760 return dsi_pll_calc(dsi->pdev, clkin,
4761 pll_min, pll_max,
4762 dsi_cm_calc_pll_cb, ctx);
4763}
4764
4765static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx)
4766{
4767 struct dsi_data *dsi = dsi_get_dsidrv_data(ctx->dsidev);
4768 const struct omap_dss_dsi_config *cfg = ctx->config;
4769 int bitspp = dsi_get_pixel_size(cfg->pixel_format);
4770 int ndl = dsi->num_lanes_used - 1;
4771 unsigned long hsclk = ctx->dsi_cinfo.clkin4ddr / 4;
4772 unsigned long byteclk = hsclk / 4;
4773
4774 unsigned long dispc_pck, req_pck_min, req_pck_nom, req_pck_max;
4775 int xres;
4776 int panel_htot, panel_hbl; /* pixels */
4777 int dispc_htot, dispc_hbl; /* pixels */
4778 int dsi_htot, dsi_hact, dsi_hbl, hss, hse; /* byteclks */
4779 int hfp, hsa, hbp;
4780 const struct omap_video_timings *req_vm;
4781 struct omap_video_timings *dispc_vm;
4782 struct omap_dss_dsi_videomode_timings *dsi_vm;
4783 u64 dsi_tput, dispc_tput;
4784
4785 dsi_tput = (u64)byteclk * ndl * 8;
4786
4787 req_vm = cfg->timings;
4788 req_pck_min = ctx->req_pck_min;
4789 req_pck_max = ctx->req_pck_max;
4790 req_pck_nom = ctx->req_pck_nom;
4791
4792 dispc_pck = ctx->dispc_cinfo.pck;
4793 dispc_tput = (u64)dispc_pck * bitspp;
4794
4795 xres = req_vm->x_res;
4796
4797 panel_hbl = req_vm->hfp + req_vm->hbp + req_vm->hsw;
4798 panel_htot = xres + panel_hbl;
4799
4800 dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(xres * bitspp, 8) + 6, ndl);
4801
4802 /*
4803 * When there are no line buffers, DISPC and DSI must have the
4804 * same tput. Otherwise DISPC tput needs to be higher than DSI's.
4805 */
4806 if (dsi->line_buffer_size < xres * bitspp / 8) {
4807 if (dispc_tput != dsi_tput)
4808 return false;
4809 } else {
4810 if (dispc_tput < dsi_tput)
4811 return false;
4812 }
4813
4814 /* DSI tput must be over the min requirement */
4815 if (dsi_tput < (u64)bitspp * req_pck_min)
4816 return false;
4817
4818 /* When non-burst mode, DSI tput must be below max requirement. */
4819 if (cfg->trans_mode != OMAP_DSS_DSI_BURST_MODE) {
4820 if (dsi_tput > (u64)bitspp * req_pck_max)
4821 return false;
4822 }
4823
4824 hss = DIV_ROUND_UP(4, ndl);
4825
4826 if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) {
4827 if (ndl == 3 && req_vm->hsw == 0)
4828 hse = 1;
4829 else
4830 hse = DIV_ROUND_UP(4, ndl);
4831 } else {
4832 hse = 0;
4833 }
4834
4835 /* DSI htot to match the panel's nominal pck */
4836 dsi_htot = div64_u64((u64)panel_htot * byteclk, req_pck_nom);
4837
4838 /* fail if there would be no time for blanking */
4839 if (dsi_htot < hss + hse + dsi_hact)
4840 return false;
4841
4842 /* total DSI blanking needed to achieve panel's TL */
4843 dsi_hbl = dsi_htot - dsi_hact;
4844
4845 /* DISPC htot to match the DSI TL */
4846 dispc_htot = div64_u64((u64)dsi_htot * dispc_pck, byteclk);
4847
4848 /* verify that the DSI and DISPC TLs are the same */
4849 if ((u64)dsi_htot * dispc_pck != (u64)dispc_htot * byteclk)
4850 return false;
4851
4852 dispc_hbl = dispc_htot - xres;
4853
4854 /* setup DSI videomode */
4855
4856 dsi_vm = &ctx->dsi_vm;
4857 memset(dsi_vm, 0, sizeof(*dsi_vm));
4858
4859 dsi_vm->hsclk = hsclk;
4860
4861 dsi_vm->ndl = ndl;
4862 dsi_vm->bitspp = bitspp;
4863
4864 if (cfg->trans_mode != OMAP_DSS_DSI_PULSE_MODE) {
4865 hsa = 0;
4866 } else if (ndl == 3 && req_vm->hsw == 0) {
4867 hsa = 0;
4868 } else {
4869 hsa = div64_u64((u64)req_vm->hsw * byteclk, req_pck_nom);
4870 hsa = max(hsa - hse, 1);
4871 }
4872
4873 hbp = div64_u64((u64)req_vm->hbp * byteclk, req_pck_nom);
4874 hbp = max(hbp, 1);
4875
4876 hfp = dsi_hbl - (hss + hsa + hse + hbp);
4877 if (hfp < 1) {
4878 int t;
4879 /* we need to take cycles from hbp */
4880
4881 t = 1 - hfp;
4882 hbp = max(hbp - t, 1);
4883 hfp = dsi_hbl - (hss + hsa + hse + hbp);
4884
4885 if (hfp < 1 && hsa > 0) {
4886 /* we need to take cycles from hsa */
4887 t = 1 - hfp;
4888 hsa = max(hsa - t, 1);
4889 hfp = dsi_hbl - (hss + hsa + hse + hbp);
4890 }
4891 }
4892
4893 if (hfp < 1)
4894 return false;
4895
4896 dsi_vm->hss = hss;
4897 dsi_vm->hsa = hsa;
4898 dsi_vm->hse = hse;
4899 dsi_vm->hbp = hbp;
4900 dsi_vm->hact = xres;
4901 dsi_vm->hfp = hfp;
4902
4903 dsi_vm->vsa = req_vm->vsw;
4904 dsi_vm->vbp = req_vm->vbp;
4905 dsi_vm->vact = req_vm->y_res;
4906 dsi_vm->vfp = req_vm->vfp;
4907
4908 dsi_vm->trans_mode = cfg->trans_mode;
4909
4910 dsi_vm->blanking_mode = 0;
4911 dsi_vm->hsa_blanking_mode = 1;
4912 dsi_vm->hfp_blanking_mode = 1;
4913 dsi_vm->hbp_blanking_mode = 1;
4914
4915 dsi_vm->ddr_clk_always_on = cfg->ddr_clk_always_on;
4916 dsi_vm->window_sync = 4;
4917
4918 /* setup DISPC videomode */
4919
4920 dispc_vm = &ctx->dispc_vm;
4921 *dispc_vm = *req_vm;
4922 dispc_vm->pixelclock = dispc_pck;
4923
4924 if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) {
4925 hsa = div64_u64((u64)req_vm->hsw * dispc_pck,
4926 req_pck_nom);
4927 hsa = max(hsa, 1);
4928 } else {
4929 hsa = 1;
4930 }
4931
4932 hbp = div64_u64((u64)req_vm->hbp * dispc_pck, req_pck_nom);
4933 hbp = max(hbp, 1);
4934
4935 hfp = dispc_hbl - hsa - hbp;
4936 if (hfp < 1) {
4937 int t;
4938 /* we need to take cycles from hbp */
4939
4940 t = 1 - hfp;
4941 hbp = max(hbp - t, 1);
4942 hfp = dispc_hbl - hsa - hbp;
4943
4944 if (hfp < 1) {
4945 /* we need to take cycles from hsa */
4946 t = 1 - hfp;
4947 hsa = max(hsa - t, 1);
4948 hfp = dispc_hbl - hsa - hbp;
4949 }
4950 }
4951
4952 if (hfp < 1)
4953 return false;
4954
4955 dispc_vm->hfp = hfp;
4956 dispc_vm->hsw = hsa;
4957 dispc_vm->hbp = hbp;
4958
4959 return true;
4960}
4961
4962
4963static bool dsi_vm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
4964 unsigned long pck, void *data)
4965{
4966 struct dsi_clk_calc_ctx *ctx = data;
4967
4968 ctx->dispc_cinfo.lck_div = lckd;
4969 ctx->dispc_cinfo.pck_div = pckd;
4970 ctx->dispc_cinfo.lck = lck;
4971 ctx->dispc_cinfo.pck = pck;
4972
4973 if (dsi_vm_calc_blanking(ctx) == false)
4974 return false;
4975
4976#ifdef PRINT_VERBOSE_VM_TIMINGS
4977 print_dispc_vm("dispc", &ctx->dispc_vm);
4978 print_dsi_vm("dsi ", &ctx->dsi_vm);
4979 print_dispc_vm("req ", ctx->config->timings);
4980 print_dsi_dispc_vm("act ", &ctx->dsi_vm);
4981#endif
4982
4983 return true;
4984}
4985
4986static bool dsi_vm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
4987 void *data)
4988{
4989 struct dsi_clk_calc_ctx *ctx = data;
4990 unsigned long pck_max;
4991
4992 ctx->dsi_cinfo.regm_dispc = regm_dispc;
4993 ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
4994
4995 /*
4996 * In burst mode we can let the dispc pck be arbitrarily high, but it
4997 * limits our scaling abilities. So for now, don't aim too high.
4998 */
4999
5000 if (ctx->config->trans_mode == OMAP_DSS_DSI_BURST_MODE)
5001 pck_max = ctx->req_pck_max + 10000000;
5002 else
5003 pck_max = ctx->req_pck_max;
5004
5005 return dispc_div_calc(dispc, ctx->req_pck_min, pck_max,
5006 dsi_vm_calc_dispc_cb, ctx);
5007}
5008
5009static bool dsi_vm_calc_pll_cb(int regn, int regm, unsigned long fint,
5010 unsigned long pll, void *data)
5011{
5012 struct dsi_clk_calc_ctx *ctx = data;
5013
5014 ctx->dsi_cinfo.regn = regn;
5015 ctx->dsi_cinfo.regm = regm;
5016 ctx->dsi_cinfo.fint = fint;
5017 ctx->dsi_cinfo.clkin4ddr = pll;
5018
5019 return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min,
5020 dsi_vm_calc_hsdiv_cb, ctx);
5021}
5022
5023static bool dsi_vm_calc(struct dsi_data *dsi,
5024 const struct omap_dss_dsi_config *cfg,
5025 struct dsi_clk_calc_ctx *ctx)
5026{
5027 const struct omap_video_timings *t = cfg->timings;
5028 unsigned long clkin;
5029 unsigned long pll_min;
5030 unsigned long pll_max;
5031 int ndl = dsi->num_lanes_used - 1;
5032 int bitspp = dsi_get_pixel_size(cfg->pixel_format);
5033 unsigned long byteclk_min;
5034
5035 clkin = clk_get_rate(dsi->sys_clk);
5036
5037 memset(ctx, 0, sizeof(*ctx));
5038 ctx->dsidev = dsi->pdev;
5039 ctx->config = cfg;
5040
5041 ctx->dsi_cinfo.clkin = clkin;
5042
5043 /* these limits should come from the panel driver */
5044 ctx->req_pck_min = t->pixelclock - 1000;
5045 ctx->req_pck_nom = t->pixelclock;
5046 ctx->req_pck_max = t->pixelclock + 1000;
5047
5048 byteclk_min = div64_u64((u64)ctx->req_pck_min * bitspp, ndl * 8);
5049 pll_min = max(cfg->hs_clk_min * 4, byteclk_min * 4 * 4);
5050
5051 if (cfg->trans_mode == OMAP_DSS_DSI_BURST_MODE) {
5052 pll_max = cfg->hs_clk_max * 4;
5053 } else {
5054 unsigned long byteclk_max;
5055 byteclk_max = div64_u64((u64)ctx->req_pck_max * bitspp,
5056 ndl * 8);
5057
5058 pll_max = byteclk_max * 4 * 4;
5059 }
5060
5061 return dsi_pll_calc(dsi->pdev, clkin,
5062 pll_min, pll_max,
5063 dsi_vm_calc_pll_cb, ctx);
5064}
5065
5066static int dsi_set_config(struct omap_dss_device *dssdev,
5067 const struct omap_dss_dsi_config *config)
5068{
5069 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
5070 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5071 struct dsi_clk_calc_ctx ctx;
5072 bool ok;
5073 int r;
5074
5075 mutex_lock(&dsi->lock);
5076
5077 dsi->pix_fmt = config->pixel_format;
5078 dsi->mode = config->mode;
5079
5080 if (config->mode == OMAP_DSS_DSI_VIDEO_MODE)
5081 ok = dsi_vm_calc(dsi, config, &ctx);
5082 else
5083 ok = dsi_cm_calc(dsi, config, &ctx);
5084
5085 if (!ok) {
5086 DSSERR("failed to find suitable DSI clock settings\n");
5087 r = -EINVAL;
5088 goto err;
5089 }
5090
5091 dsi_pll_calc_dsi_fck(&ctx.dsi_cinfo);
5092
5093 r = dsi_lp_clock_calc(&ctx.dsi_cinfo, config->lp_clk_min,
5094 config->lp_clk_max);
5095 if (r) {
5096 DSSERR("failed to find suitable DSI LP clock settings\n");
5097 goto err;
5098 }
5099
5100 dsi->user_dsi_cinfo = ctx.dsi_cinfo;
5101 dsi->user_dispc_cinfo = ctx.dispc_cinfo;
5102
5103 dsi->timings = ctx.dispc_vm;
5104 dsi->vm_timings = ctx.dsi_vm;
5105
5106 mutex_unlock(&dsi->lock);
5107
5108 return 0;
5109err:
5110 mutex_unlock(&dsi->lock);
5111
5112 return r;
5113}
5114
5115/*
5116 * Return a hardcoded channel for the DSI output. This should work for
5117 * current use cases, but this can be later expanded to either resolve
5118 * the channel in some more dynamic manner, or get the channel as a user
5119 * parameter.
5120 */
5121static enum omap_channel dsi_get_channel(int module_id)
5122{
5123 switch (omapdss_get_version()) {
5124 case OMAPDSS_VER_OMAP24xx:
5125 DSSWARN("DSI not supported\n");
5126 return OMAP_DSS_CHANNEL_LCD;
5127
5128 case OMAPDSS_VER_OMAP34xx_ES1:
5129 case OMAPDSS_VER_OMAP34xx_ES3:
5130 case OMAPDSS_VER_OMAP3630:
5131 case OMAPDSS_VER_AM35xx:
5132 return OMAP_DSS_CHANNEL_LCD;
5133
5134 case OMAPDSS_VER_OMAP4430_ES1:
5135 case OMAPDSS_VER_OMAP4430_ES2:
5136 case OMAPDSS_VER_OMAP4:
5137 switch (module_id) {
5138 case 0:
5139 return OMAP_DSS_CHANNEL_LCD;
5140 case 1:
5141 return OMAP_DSS_CHANNEL_LCD2;
5142 default:
5143 DSSWARN("unsupported module id\n");
5144 return OMAP_DSS_CHANNEL_LCD;
5145 }
5146
5147 case OMAPDSS_VER_OMAP5:
5148 switch (module_id) {
5149 case 0:
5150 return OMAP_DSS_CHANNEL_LCD;
5151 case 1:
5152 return OMAP_DSS_CHANNEL_LCD3;
5153 default:
5154 DSSWARN("unsupported module id\n");
5155 return OMAP_DSS_CHANNEL_LCD;
5156 }
5157
5158 default:
5159 DSSWARN("unsupported DSS version\n");
5160 return OMAP_DSS_CHANNEL_LCD;
5161 }
5162}
5163
5164static int dsi_request_vc(struct omap_dss_device *dssdev, int *channel)
5165{
5166 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
5167 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5168 int i;
5169
5170 for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) {
5171 if (!dsi->vc[i].dssdev) {
5172 dsi->vc[i].dssdev = dssdev;
5173 *channel = i;
5174 return 0;
5175 }
5176 }
5177
5178 DSSERR("cannot get VC for display %s", dssdev->name);
5179 return -ENOSPC;
5180}
5181
5182static int dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id)
5183{
5184 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
5185 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5186
5187 if (vc_id < 0 || vc_id > 3) {
5188 DSSERR("VC ID out of range\n");
5189 return -EINVAL;
5190 }
5191
5192 if (channel < 0 || channel > 3) {
5193 DSSERR("Virtual Channel out of range\n");
5194 return -EINVAL;
5195 }
5196
5197 if (dsi->vc[channel].dssdev != dssdev) {
5198 DSSERR("Virtual Channel not allocated to display %s\n",
5199 dssdev->name);
5200 return -EINVAL;
5201 }
5202
5203 dsi->vc[channel].vc_id = vc_id;
5204
5205 return 0;
5206}
5207
5208static void dsi_release_vc(struct omap_dss_device *dssdev, int channel)
5209{
5210 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
5211 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5212
5213 if ((channel >= 0 && channel <= 3) &&
5214 dsi->vc[channel].dssdev == dssdev) {
5215 dsi->vc[channel].dssdev = NULL;
5216 dsi->vc[channel].vc_id = 0;
5217 }
5218}
5219
5220void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev)
5221{
5222 if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 7, 1) != 1)
5223 DSSERR("%s (%s) not active\n",
5224 dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
5225 dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC));
5226}
5227
5228void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev)
5229{
5230 if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 8, 1) != 1)
5231 DSSERR("%s (%s) not active\n",
5232 dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
5233 dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI));
5234}
5235
5236static void dsi_calc_clock_param_ranges(struct platform_device *dsidev)
5237{
5238 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5239
5240 dsi->regn_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGN);
5241 dsi->regm_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM);
5242 dsi->regm_dispc_max =
5243 dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DISPC);
5244 dsi->regm_dsi_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DSI);
5245 dsi->fint_min = dss_feat_get_param_min(FEAT_PARAM_DSIPLL_FINT);
5246 dsi->fint_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_FINT);
5247 dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV);
5248}
5249
5250static int dsi_get_clocks(struct platform_device *dsidev)
5251{
5252 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5253 struct clk *clk;
5254
5255 clk = devm_clk_get(&dsidev->dev, "fck");
5256 if (IS_ERR(clk)) {
5257 DSSERR("can't get fck\n");
5258 return PTR_ERR(clk);
5259 }
5260
5261 dsi->dss_clk = clk;
5262
5263 clk = devm_clk_get(&dsidev->dev, "sys_clk");
5264 if (IS_ERR(clk)) {
5265 DSSERR("can't get sys_clk\n");
5266 return PTR_ERR(clk);
5267 }
5268
5269 dsi->sys_clk = clk;
5270
5271 return 0;
5272}
5273
5274static int dsi_connect(struct omap_dss_device *dssdev,
5275 struct omap_dss_device *dst)
5276{
5277 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
5278 struct omap_overlay_manager *mgr;
5279 int r;
5280
5281 r = dsi_regulator_init(dsidev);
5282 if (r)
5283 return r;
5284
5285 mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
5286 if (!mgr)
5287 return -ENODEV;
5288
5289 r = dss_mgr_connect(mgr, dssdev);
5290 if (r)
5291 return r;
5292
5293 r = omapdss_output_set_device(dssdev, dst);
5294 if (r) {
5295 DSSERR("failed to connect output to new device: %s\n",
5296 dssdev->name);
5297 dss_mgr_disconnect(mgr, dssdev);
5298 return r;
5299 }
5300
5301 return 0;
5302}
5303
5304static void dsi_disconnect(struct omap_dss_device *dssdev,
5305 struct omap_dss_device *dst)
5306{
5307 WARN_ON(dst != dssdev->dst);
5308
5309 if (dst != dssdev->dst)
5310 return;
5311
5312 omapdss_output_unset_device(dssdev);
5313
5314 if (dssdev->manager)
5315 dss_mgr_disconnect(dssdev->manager, dssdev);
5316}
5317
5318static const struct omapdss_dsi_ops dsi_ops = {
5319 .connect = dsi_connect,
5320 .disconnect = dsi_disconnect,
5321
5322 .bus_lock = dsi_bus_lock,
5323 .bus_unlock = dsi_bus_unlock,
5324
5325 .enable = dsi_display_enable,
5326 .disable = dsi_display_disable,
5327
5328 .enable_hs = dsi_vc_enable_hs,
5329
5330 .configure_pins = dsi_configure_pins,
5331 .set_config = dsi_set_config,
5332
5333 .enable_video_output = dsi_enable_video_output,
5334 .disable_video_output = dsi_disable_video_output,
5335
5336 .update = dsi_update,
5337
5338 .enable_te = dsi_enable_te,
5339
5340 .request_vc = dsi_request_vc,
5341 .set_vc_id = dsi_set_vc_id,
5342 .release_vc = dsi_release_vc,
5343
5344 .dcs_write = dsi_vc_dcs_write,
5345 .dcs_write_nosync = dsi_vc_dcs_write_nosync,
5346 .dcs_read = dsi_vc_dcs_read,
5347
5348 .gen_write = dsi_vc_generic_write,
5349 .gen_write_nosync = dsi_vc_generic_write_nosync,
5350 .gen_read = dsi_vc_generic_read,
5351
5352 .bta_sync = dsi_vc_send_bta_sync,
5353
5354 .set_max_rx_packet_size = dsi_vc_set_max_rx_packet_size,
5355};
5356
5357static void dsi_init_output(struct platform_device *dsidev)
5358{
5359 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5360 struct omap_dss_device *out = &dsi->output;
5361
5362 out->dev = &dsidev->dev;
5363 out->id = dsi->module_id == 0 ?
5364 OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
5365
5366 out->output_type = OMAP_DISPLAY_TYPE_DSI;
5367 out->name = dsi->module_id == 0 ? "dsi.0" : "dsi.1";
5368 out->dispc_channel = dsi_get_channel(dsi->module_id);
5369 out->ops.dsi = &dsi_ops;
5370 out->owner = THIS_MODULE;
5371
5372 omapdss_register_output(out);
5373}
5374
5375static void dsi_uninit_output(struct platform_device *dsidev)
5376{
5377 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5378 struct omap_dss_device *out = &dsi->output;
5379
5380 omapdss_unregister_output(out);
5381}
5382
5383static int dsi_probe_of(struct platform_device *pdev)
5384{
5385 struct device_node *node = pdev->dev.of_node;
5386 struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
5387 struct property *prop;
5388 u32 lane_arr[10];
5389 int len, num_pins;
5390 int r, i;
5391 struct device_node *ep;
5392 struct omap_dsi_pin_config pin_cfg;
5393
5394 ep = omapdss_of_get_first_endpoint(node);
5395 if (!ep)
5396 return 0;
5397
5398 prop = of_find_property(ep, "lanes", &len);
5399 if (prop == NULL) {
5400 dev_err(&pdev->dev, "failed to find lane data\n");
5401 r = -EINVAL;
5402 goto err;
5403 }
5404
5405 num_pins = len / sizeof(u32);
5406
5407 if (num_pins < 4 || num_pins % 2 != 0 ||
5408 num_pins > dsi->num_lanes_supported * 2) {
5409 dev_err(&pdev->dev, "bad number of lanes\n");
5410 r = -EINVAL;
5411 goto err;
5412 }
5413
5414 r = of_property_read_u32_array(ep, "lanes", lane_arr, num_pins);
5415 if (r) {
5416 dev_err(&pdev->dev, "failed to read lane data\n");
5417 goto err;
5418 }
5419
5420 pin_cfg.num_pins = num_pins;
5421 for (i = 0; i < num_pins; ++i)
5422 pin_cfg.pins[i] = (int)lane_arr[i];
5423
5424 r = dsi_configure_pins(&dsi->output, &pin_cfg);
5425 if (r) {
5426 dev_err(&pdev->dev, "failed to configure pins");
5427 goto err;
5428 }
5429
5430 of_node_put(ep);
5431
5432 return 0;
5433
5434err:
5435 of_node_put(ep);
5436 return r;
5437}
5438
5439/* DSI1 HW IP initialisation */
5440static int omap_dsihw_probe(struct platform_device *dsidev)
5441{
5442 u32 rev;
5443 int r, i;
5444 struct dsi_data *dsi;
5445 struct resource *dsi_mem;
5446 struct resource *res;
5447 struct resource temp_res;
5448
5449 dsi = devm_kzalloc(&dsidev->dev, sizeof(*dsi), GFP_KERNEL);
5450 if (!dsi)
5451 return -ENOMEM;
5452
5453 dsi->pdev = dsidev;
5454 dev_set_drvdata(&dsidev->dev, dsi);
5455
5456 spin_lock_init(&dsi->irq_lock);
5457 spin_lock_init(&dsi->errors_lock);
5458 dsi->errors = 0;
5459
5460#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
5461 spin_lock_init(&dsi->irq_stats_lock);
5462 dsi->irq_stats.last_reset = jiffies;
5463#endif
5464
5465 mutex_init(&dsi->lock);
5466 sema_init(&dsi->bus_lock, 1);
5467
5468 INIT_DEFERRABLE_WORK(&dsi->framedone_timeout_work,
5469 dsi_framedone_timeout_work_callback);
5470
5471#ifdef DSI_CATCH_MISSING_TE
5472 init_timer(&dsi->te_timer);
5473 dsi->te_timer.function = dsi_te_timeout;
5474 dsi->te_timer.data = 0;
5475#endif
5476
5477 res = platform_get_resource_byname(dsidev, IORESOURCE_MEM, "proto");
5478 if (!res) {
5479 res = platform_get_resource(dsidev, IORESOURCE_MEM, 0);
5480 if (!res) {
5481 DSSERR("can't get IORESOURCE_MEM DSI\n");
5482 return -EINVAL;
5483 }
5484
5485 temp_res.start = res->start;
5486 temp_res.end = temp_res.start + DSI_PROTO_SZ - 1;
5487 res = &temp_res;
5488 }
5489
5490 dsi_mem = res;
5491
5492 dsi->proto_base = devm_ioremap(&dsidev->dev, res->start,
5493 resource_size(res));
5494 if (!dsi->proto_base) {
5495 DSSERR("can't ioremap DSI protocol engine\n");
5496 return -ENOMEM;
5497 }
5498
5499 res = platform_get_resource_byname(dsidev, IORESOURCE_MEM, "phy");
5500 if (!res) {
5501 res = platform_get_resource(dsidev, IORESOURCE_MEM, 0);
5502 if (!res) {
5503 DSSERR("can't get IORESOURCE_MEM DSI\n");
5504 return -EINVAL;
5505 }
5506
5507 temp_res.start = res->start + DSI_PHY_OFFSET;
5508 temp_res.end = temp_res.start + DSI_PHY_SZ - 1;
5509 res = &temp_res;
5510 }
5511
5512 dsi->phy_base = devm_ioremap(&dsidev->dev, res->start,
5513 resource_size(res));
5514 if (!dsi->proto_base) {
5515 DSSERR("can't ioremap DSI PHY\n");
5516 return -ENOMEM;
5517 }
5518
5519 res = platform_get_resource_byname(dsidev, IORESOURCE_MEM, "pll");
5520 if (!res) {
5521 res = platform_get_resource(dsidev, IORESOURCE_MEM, 0);
5522 if (!res) {
5523 DSSERR("can't get IORESOURCE_MEM DSI\n");
5524 return -EINVAL;
5525 }
5526
5527 temp_res.start = res->start + DSI_PLL_OFFSET;
5528 temp_res.end = temp_res.start + DSI_PLL_SZ - 1;
5529 res = &temp_res;
5530 }
5531
5532 dsi->pll_base = devm_ioremap(&dsidev->dev, res->start,
5533 resource_size(res));
5534 if (!dsi->proto_base) {
5535 DSSERR("can't ioremap DSI PLL\n");
5536 return -ENOMEM;
5537 }
5538
5539 dsi->irq = platform_get_irq(dsi->pdev, 0);
5540 if (dsi->irq < 0) {
5541 DSSERR("platform_get_irq failed\n");
5542 return -ENODEV;
5543 }
5544
5545 r = devm_request_irq(&dsidev->dev, dsi->irq, omap_dsi_irq_handler,
5546 IRQF_SHARED, dev_name(&dsidev->dev), dsi->pdev);
5547 if (r < 0) {
5548 DSSERR("request_irq failed\n");
5549 return r;
5550 }
5551
5552 if (dsidev->dev.of_node) {
5553 const struct of_device_id *match;
5554 const struct dsi_module_id_data *d;
5555
5556 match = of_match_node(dsi_of_match, dsidev->dev.of_node);
5557 if (!match) {
5558 DSSERR("unsupported DSI module\n");
5559 return -ENODEV;
5560 }
5561
5562 d = match->data;
5563
5564 while (d->address != 0 && d->address != dsi_mem->start)
5565 d++;
5566
5567 if (d->address == 0) {
5568 DSSERR("unsupported DSI module\n");
5569 return -ENODEV;
5570 }
5571
5572 dsi->module_id = d->id;
5573 } else {
5574 dsi->module_id = dsidev->id;
5575 }
5576
5577 /* DSI VCs initialization */
5578 for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) {
5579 dsi->vc[i].source = DSI_VC_SOURCE_L4;
5580 dsi->vc[i].dssdev = NULL;
5581 dsi->vc[i].vc_id = 0;
5582 }
5583
5584 dsi_calc_clock_param_ranges(dsidev);
5585
5586 r = dsi_get_clocks(dsidev);
5587 if (r)
5588 return r;
5589
5590 pm_runtime_enable(&dsidev->dev);
5591
5592 r = dsi_runtime_get(dsidev);
5593 if (r)
5594 goto err_runtime_get;
5595
5596 rev = dsi_read_reg(dsidev, DSI_REVISION);
5597 dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n",
5598 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
5599
5600 /* DSI on OMAP3 doesn't have register DSI_GNQ, set number
5601 * of data to 3 by default */
5602 if (dss_has_feature(FEAT_DSI_GNQ))
5603 /* NB_DATA_LANES */
5604 dsi->num_lanes_supported = 1 + REG_GET(dsidev, DSI_GNQ, 11, 9);
5605 else
5606 dsi->num_lanes_supported = 3;
5607
5608 dsi->line_buffer_size = dsi_get_line_buf_size(dsidev);
5609
5610 dsi_init_output(dsidev);
5611
5612 if (dsidev->dev.of_node) {
5613 r = dsi_probe_of(dsidev);
5614 if (r) {
5615 DSSERR("Invalid DSI DT data\n");
5616 goto err_probe_of;
5617 }
5618
5619 r = of_platform_populate(dsidev->dev.of_node, NULL, NULL,
5620 &dsidev->dev);
5621 if (r)
5622 DSSERR("Failed to populate DSI child devices: %d\n", r);
5623 }
5624
5625 dsi_runtime_put(dsidev);
5626
5627 if (dsi->module_id == 0)
5628 dss_debugfs_create_file("dsi1_regs", dsi1_dump_regs);
5629 else if (dsi->module_id == 1)
5630 dss_debugfs_create_file("dsi2_regs", dsi2_dump_regs);
5631
5632#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
5633 if (dsi->module_id == 0)
5634 dss_debugfs_create_file("dsi1_irqs", dsi1_dump_irqs);
5635 else if (dsi->module_id == 1)
5636 dss_debugfs_create_file("dsi2_irqs", dsi2_dump_irqs);
5637#endif
5638
5639 return 0;
5640
5641err_probe_of:
5642 dsi_uninit_output(dsidev);
5643 dsi_runtime_put(dsidev);
5644
5645err_runtime_get:
5646 pm_runtime_disable(&dsidev->dev);
5647 return r;
5648}
5649
5650static int dsi_unregister_child(struct device *dev, void *data)
5651{
5652 struct platform_device *pdev = to_platform_device(dev);
5653 platform_device_unregister(pdev);
5654 return 0;
5655}
5656
5657static int __exit omap_dsihw_remove(struct platform_device *dsidev)
5658{
5659 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5660
5661 device_for_each_child(&dsidev->dev, NULL, dsi_unregister_child);
5662
5663 WARN_ON(dsi->scp_clk_refcount > 0);
5664
5665 dsi_uninit_output(dsidev);
5666
5667 pm_runtime_disable(&dsidev->dev);
5668
5669 if (dsi->vdds_dsi_reg != NULL && dsi->vdds_dsi_enabled) {
5670 regulator_disable(dsi->vdds_dsi_reg);
5671 dsi->vdds_dsi_enabled = false;
5672 }
5673
5674 return 0;
5675}
5676
5677static int dsi_runtime_suspend(struct device *dev)
5678{
5679 struct platform_device *pdev = to_platform_device(dev);
5680 struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
5681
5682 dsi->is_enabled = false;
5683 /* ensure the irq handler sees the is_enabled value */
5684 smp_wmb();
5685 /* wait for current handler to finish before turning the DSI off */
5686 synchronize_irq(dsi->irq);
5687
5688 dispc_runtime_put();
5689
5690 return 0;
5691}
5692
5693static int dsi_runtime_resume(struct device *dev)
5694{
5695 struct platform_device *pdev = to_platform_device(dev);
5696 struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
5697 int r;
5698
5699 r = dispc_runtime_get();
5700 if (r)
5701 return r;
5702
5703 dsi->is_enabled = true;
5704 /* ensure the irq handler sees the is_enabled value */
5705 smp_wmb();
5706
5707 return 0;
5708}
5709
5710static const struct dev_pm_ops dsi_pm_ops = {
5711 .runtime_suspend = dsi_runtime_suspend,
5712 .runtime_resume = dsi_runtime_resume,
5713};
5714
5715static const struct dsi_module_id_data dsi_of_data_omap3[] = {
5716 { .address = 0x4804fc00, .id = 0, },
5717 { },
5718};
5719
5720static const struct dsi_module_id_data dsi_of_data_omap4[] = {
5721 { .address = 0x58004000, .id = 0, },
5722 { .address = 0x58005000, .id = 1, },
5723 { },
5724};
5725
5726static const struct of_device_id dsi_of_match[] = {
5727 { .compatible = "ti,omap3-dsi", .data = dsi_of_data_omap3, },
5728 { .compatible = "ti,omap4-dsi", .data = dsi_of_data_omap4, },
5729 {},
5730};
5731
5732static struct platform_driver omap_dsihw_driver = {
5733 .probe = omap_dsihw_probe,
5734 .remove = __exit_p(omap_dsihw_remove),
5735 .driver = {
5736 .name = "omapdss_dsi",
5737 .owner = THIS_MODULE,
5738 .pm = &dsi_pm_ops,
5739 .of_match_table = dsi_of_match,
5740 },
5741};
5742
5743int __init dsi_init_platform_driver(void)
5744{
5745 return platform_driver_register(&omap_dsihw_driver);
5746}
5747
5748void __exit dsi_uninit_platform_driver(void)
5749{
5750 platform_driver_unregister(&omap_dsihw_driver);
5751}
diff --git a/drivers/video/omap2/dss/dss-of.c b/drivers/video/omap2/dss/dss-of.c
deleted file mode 100644
index a4b20aaf6142..000000000000
--- a/drivers/video/omap2/dss/dss-of.c
+++ /dev/null
@@ -1,159 +0,0 @@
1/*
2 * Copyright (C) 2013 Texas Instruments
3 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 */
14
15#include <linux/device.h>
16#include <linux/err.h>
17#include <linux/module.h>
18#include <linux/of.h>
19#include <linux/seq_file.h>
20
21#include <video/omapdss.h>
22
23struct device_node *
24omapdss_of_get_next_port(const struct device_node *parent,
25 struct device_node *prev)
26{
27 struct device_node *port = NULL;
28
29 if (!parent)
30 return NULL;
31
32 if (!prev) {
33 struct device_node *ports;
34 /*
35 * It's the first call, we have to find a port subnode
36 * within this node or within an optional 'ports' node.
37 */
38 ports = of_get_child_by_name(parent, "ports");
39 if (ports)
40 parent = ports;
41
42 port = of_get_child_by_name(parent, "port");
43
44 /* release the 'ports' node */
45 of_node_put(ports);
46 } else {
47 struct device_node *ports;
48
49 ports = of_get_parent(prev);
50 if (!ports)
51 return NULL;
52
53 do {
54 port = of_get_next_child(ports, prev);
55 if (!port) {
56 of_node_put(ports);
57 return NULL;
58 }
59 prev = port;
60 } while (of_node_cmp(port->name, "port") != 0);
61 }
62
63 return port;
64}
65EXPORT_SYMBOL_GPL(omapdss_of_get_next_port);
66
67struct device_node *
68omapdss_of_get_next_endpoint(const struct device_node *parent,
69 struct device_node *prev)
70{
71 struct device_node *ep = NULL;
72
73 if (!parent)
74 return NULL;
75
76 do {
77 ep = of_get_next_child(parent, prev);
78 if (!ep)
79 return NULL;
80 prev = ep;
81 } while (of_node_cmp(ep->name, "endpoint") != 0);
82
83 return ep;
84}
85EXPORT_SYMBOL_GPL(omapdss_of_get_next_endpoint);
86
87static struct device_node *
88omapdss_of_get_remote_device_node(const struct device_node *node)
89{
90 struct device_node *np;
91 int i;
92
93 np = of_parse_phandle(node, "remote-endpoint", 0);
94
95 if (!np)
96 return NULL;
97
98 np = of_get_next_parent(np);
99
100 for (i = 0; i < 3 && np; ++i) {
101 struct property *prop;
102
103 prop = of_find_property(np, "compatible", NULL);
104
105 if (prop)
106 return np;
107
108 np = of_get_next_parent(np);
109 }
110
111 return NULL;
112}
113
114struct device_node *
115omapdss_of_get_first_endpoint(const struct device_node *parent)
116{
117 struct device_node *port, *ep;
118
119 port = omapdss_of_get_next_port(parent, NULL);
120
121 if (!port)
122 return NULL;
123
124 ep = omapdss_of_get_next_endpoint(port, NULL);
125
126 of_node_put(port);
127
128 return ep;
129}
130EXPORT_SYMBOL_GPL(omapdss_of_get_first_endpoint);
131
132struct omap_dss_device *
133omapdss_of_find_source_for_first_ep(struct device_node *node)
134{
135 struct device_node *ep;
136 struct device_node *src_node;
137 struct omap_dss_device *src;
138
139 ep = omapdss_of_get_first_endpoint(node);
140 if (!ep)
141 return ERR_PTR(-EINVAL);
142
143 src_node = omapdss_of_get_remote_device_node(ep);
144
145 of_node_put(ep);
146
147 if (!src_node)
148 return ERR_PTR(-EINVAL);
149
150 src = omap_dss_find_output_by_node(src_node);
151
152 of_node_put(src_node);
153
154 if (!src)
155 return ERR_PTR(-EPROBE_DEFER);
156
157 return src;
158}
159EXPORT_SYMBOL_GPL(omapdss_of_find_source_for_first_ep);
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
deleted file mode 100644
index d55266c0e029..000000000000
--- a/drivers/video/omap2/dss/dss.c
+++ /dev/null
@@ -1,972 +0,0 @@
1/*
2 * linux/drivers/video/omap2/dss/dss.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
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#define DSS_SUBSYS_NAME "DSS"
24
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/io.h>
28#include <linux/export.h>
29#include <linux/err.h>
30#include <linux/delay.h>
31#include <linux/seq_file.h>
32#include <linux/clk.h>
33#include <linux/platform_device.h>
34#include <linux/pm_runtime.h>
35#include <linux/gfp.h>
36#include <linux/sizes.h>
37#include <linux/of.h>
38
39#include <video/omapdss.h>
40
41#include "dss.h"
42#include "dss_features.h"
43
44#define DSS_SZ_REGS SZ_512
45
46struct dss_reg {
47 u16 idx;
48};
49
50#define DSS_REG(idx) ((const struct dss_reg) { idx })
51
52#define DSS_REVISION DSS_REG(0x0000)
53#define DSS_SYSCONFIG DSS_REG(0x0010)
54#define DSS_SYSSTATUS DSS_REG(0x0014)
55#define DSS_CONTROL DSS_REG(0x0040)
56#define DSS_SDI_CONTROL DSS_REG(0x0044)
57#define DSS_PLL_CONTROL DSS_REG(0x0048)
58#define DSS_SDI_STATUS DSS_REG(0x005C)
59
60#define REG_GET(idx, start, end) \
61 FLD_GET(dss_read_reg(idx), start, end)
62
63#define REG_FLD_MOD(idx, val, start, end) \
64 dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
65
66static int dss_runtime_get(void);
67static void dss_runtime_put(void);
68
69struct dss_features {
70 u8 fck_div_max;
71 u8 dss_fck_multiplier;
72 const char *parent_clk_name;
73 int (*dpi_select_source)(enum omap_channel channel);
74};
75
76static struct {
77 struct platform_device *pdev;
78 void __iomem *base;
79
80 struct clk *parent_clk;
81 struct clk *dss_clk;
82 unsigned long dss_clk_rate;
83
84 unsigned long cache_req_pck;
85 unsigned long cache_prate;
86 struct dispc_clock_info cache_dispc_cinfo;
87
88 enum omap_dss_clk_source dsi_clk_source[MAX_NUM_DSI];
89 enum omap_dss_clk_source dispc_clk_source;
90 enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
91
92 bool ctx_valid;
93 u32 ctx[DSS_SZ_REGS / sizeof(u32)];
94
95 const struct dss_features *feat;
96} dss;
97
98static const char * const dss_generic_clk_source_names[] = {
99 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC",
100 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI",
101 [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK",
102 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DSI_PLL2_HSDIV_DISPC",
103 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DSI_PLL2_HSDIV_DSI",
104};
105
106static inline void dss_write_reg(const struct dss_reg idx, u32 val)
107{
108 __raw_writel(val, dss.base + idx.idx);
109}
110
111static inline u32 dss_read_reg(const struct dss_reg idx)
112{
113 return __raw_readl(dss.base + idx.idx);
114}
115
116#define SR(reg) \
117 dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
118#define RR(reg) \
119 dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
120
121static void dss_save_context(void)
122{
123 DSSDBG("dss_save_context\n");
124
125 SR(CONTROL);
126
127 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
128 OMAP_DISPLAY_TYPE_SDI) {
129 SR(SDI_CONTROL);
130 SR(PLL_CONTROL);
131 }
132
133 dss.ctx_valid = true;
134
135 DSSDBG("context saved\n");
136}
137
138static void dss_restore_context(void)
139{
140 DSSDBG("dss_restore_context\n");
141
142 if (!dss.ctx_valid)
143 return;
144
145 RR(CONTROL);
146
147 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
148 OMAP_DISPLAY_TYPE_SDI) {
149 RR(SDI_CONTROL);
150 RR(PLL_CONTROL);
151 }
152
153 DSSDBG("context restored\n");
154}
155
156#undef SR
157#undef RR
158
159void dss_sdi_init(int datapairs)
160{
161 u32 l;
162
163 BUG_ON(datapairs > 3 || datapairs < 1);
164
165 l = dss_read_reg(DSS_SDI_CONTROL);
166 l = FLD_MOD(l, 0xf, 19, 15); /* SDI_PDIV */
167 l = FLD_MOD(l, datapairs-1, 3, 2); /* SDI_PRSEL */
168 l = FLD_MOD(l, 2, 1, 0); /* SDI_BWSEL */
169 dss_write_reg(DSS_SDI_CONTROL, l);
170
171 l = dss_read_reg(DSS_PLL_CONTROL);
172 l = FLD_MOD(l, 0x7, 25, 22); /* SDI_PLL_FREQSEL */
173 l = FLD_MOD(l, 0xb, 16, 11); /* SDI_PLL_REGN */
174 l = FLD_MOD(l, 0xb4, 10, 1); /* SDI_PLL_REGM */
175 dss_write_reg(DSS_PLL_CONTROL, l);
176}
177
178int dss_sdi_enable(void)
179{
180 unsigned long timeout;
181
182 dispc_pck_free_enable(1);
183
184 /* Reset SDI PLL */
185 REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */
186 udelay(1); /* wait 2x PCLK */
187
188 /* Lock SDI PLL */
189 REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */
190
191 /* Waiting for PLL lock request to complete */
192 timeout = jiffies + msecs_to_jiffies(500);
193 while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6)) {
194 if (time_after_eq(jiffies, timeout)) {
195 DSSERR("PLL lock request timed out\n");
196 goto err1;
197 }
198 }
199
200 /* Clearing PLL_GO bit */
201 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28);
202
203 /* Waiting for PLL to lock */
204 timeout = jiffies + msecs_to_jiffies(500);
205 while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5))) {
206 if (time_after_eq(jiffies, timeout)) {
207 DSSERR("PLL lock timed out\n");
208 goto err1;
209 }
210 }
211
212 dispc_lcd_enable_signal(1);
213
214 /* Waiting for SDI reset to complete */
215 timeout = jiffies + msecs_to_jiffies(500);
216 while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2))) {
217 if (time_after_eq(jiffies, timeout)) {
218 DSSERR("SDI reset timed out\n");
219 goto err2;
220 }
221 }
222
223 return 0;
224
225 err2:
226 dispc_lcd_enable_signal(0);
227 err1:
228 /* Reset SDI PLL */
229 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
230
231 dispc_pck_free_enable(0);
232
233 return -ETIMEDOUT;
234}
235
236void dss_sdi_disable(void)
237{
238 dispc_lcd_enable_signal(0);
239
240 dispc_pck_free_enable(0);
241
242 /* Reset SDI PLL */
243 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
244}
245
246const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
247{
248 return dss_generic_clk_source_names[clk_src];
249}
250
251void dss_dump_clocks(struct seq_file *s)
252{
253 const char *fclk_name, *fclk_real_name;
254 unsigned long fclk_rate;
255
256 if (dss_runtime_get())
257 return;
258
259 seq_printf(s, "- DSS -\n");
260
261 fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
262 fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
263 fclk_rate = clk_get_rate(dss.dss_clk);
264
265 seq_printf(s, "%s (%s) = %lu\n",
266 fclk_name, fclk_real_name,
267 fclk_rate);
268
269 dss_runtime_put();
270}
271
272static void dss_dump_regs(struct seq_file *s)
273{
274#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
275
276 if (dss_runtime_get())
277 return;
278
279 DUMPREG(DSS_REVISION);
280 DUMPREG(DSS_SYSCONFIG);
281 DUMPREG(DSS_SYSSTATUS);
282 DUMPREG(DSS_CONTROL);
283
284 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
285 OMAP_DISPLAY_TYPE_SDI) {
286 DUMPREG(DSS_SDI_CONTROL);
287 DUMPREG(DSS_PLL_CONTROL);
288 DUMPREG(DSS_SDI_STATUS);
289 }
290
291 dss_runtime_put();
292#undef DUMPREG
293}
294
295static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
296{
297 struct platform_device *dsidev;
298 int b;
299 u8 start, end;
300
301 switch (clk_src) {
302 case OMAP_DSS_CLK_SRC_FCK:
303 b = 0;
304 break;
305 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
306 b = 1;
307 dsidev = dsi_get_dsidev_from_id(0);
308 dsi_wait_pll_hsdiv_dispc_active(dsidev);
309 break;
310 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
311 b = 2;
312 dsidev = dsi_get_dsidev_from_id(1);
313 dsi_wait_pll_hsdiv_dispc_active(dsidev);
314 break;
315 default:
316 BUG();
317 return;
318 }
319
320 dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end);
321
322 REG_FLD_MOD(DSS_CONTROL, b, start, end); /* DISPC_CLK_SWITCH */
323
324 dss.dispc_clk_source = clk_src;
325}
326
327void dss_select_dsi_clk_source(int dsi_module,
328 enum omap_dss_clk_source clk_src)
329{
330 struct platform_device *dsidev;
331 int b, pos;
332
333 switch (clk_src) {
334 case OMAP_DSS_CLK_SRC_FCK:
335 b = 0;
336 break;
337 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI:
338 BUG_ON(dsi_module != 0);
339 b = 1;
340 dsidev = dsi_get_dsidev_from_id(0);
341 dsi_wait_pll_hsdiv_dsi_active(dsidev);
342 break;
343 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI:
344 BUG_ON(dsi_module != 1);
345 b = 1;
346 dsidev = dsi_get_dsidev_from_id(1);
347 dsi_wait_pll_hsdiv_dsi_active(dsidev);
348 break;
349 default:
350 BUG();
351 return;
352 }
353
354 pos = dsi_module == 0 ? 1 : 10;
355 REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* DSIx_CLK_SWITCH */
356
357 dss.dsi_clk_source[dsi_module] = clk_src;
358}
359
360void dss_select_lcd_clk_source(enum omap_channel channel,
361 enum omap_dss_clk_source clk_src)
362{
363 struct platform_device *dsidev;
364 int b, ix, pos;
365
366 if (!dss_has_feature(FEAT_LCD_CLK_SRC)) {
367 dss_select_dispc_clk_source(clk_src);
368 return;
369 }
370
371 switch (clk_src) {
372 case OMAP_DSS_CLK_SRC_FCK:
373 b = 0;
374 break;
375 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
376 BUG_ON(channel != OMAP_DSS_CHANNEL_LCD);
377 b = 1;
378 dsidev = dsi_get_dsidev_from_id(0);
379 dsi_wait_pll_hsdiv_dispc_active(dsidev);
380 break;
381 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
382 BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2 &&
383 channel != OMAP_DSS_CHANNEL_LCD3);
384 b = 1;
385 dsidev = dsi_get_dsidev_from_id(1);
386 dsi_wait_pll_hsdiv_dispc_active(dsidev);
387 break;
388 default:
389 BUG();
390 return;
391 }
392
393 pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
394 (channel == OMAP_DSS_CHANNEL_LCD2 ? 12 : 19);
395 REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* LCDx_CLK_SWITCH */
396
397 ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
398 (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2);
399 dss.lcd_clk_source[ix] = clk_src;
400}
401
402enum omap_dss_clk_source dss_get_dispc_clk_source(void)
403{
404 return dss.dispc_clk_source;
405}
406
407enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module)
408{
409 return dss.dsi_clk_source[dsi_module];
410}
411
412enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
413{
414 if (dss_has_feature(FEAT_LCD_CLK_SRC)) {
415 int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
416 (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2);
417 return dss.lcd_clk_source[ix];
418 } else {
419 /* LCD_CLK source is the same as DISPC_FCLK source for
420 * OMAP2 and OMAP3 */
421 return dss.dispc_clk_source;
422 }
423}
424
425bool dss_div_calc(unsigned long pck, unsigned long fck_min,
426 dss_div_calc_func func, void *data)
427{
428 int fckd, fckd_start, fckd_stop;
429 unsigned long fck;
430 unsigned long fck_hw_max;
431 unsigned long fckd_hw_max;
432 unsigned long prate;
433 unsigned m;
434
435 fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
436
437 if (dss.parent_clk == NULL) {
438 unsigned pckd;
439
440 pckd = fck_hw_max / pck;
441
442 fck = pck * pckd;
443
444 fck = clk_round_rate(dss.dss_clk, fck);
445
446 return func(fck, data);
447 }
448
449 fckd_hw_max = dss.feat->fck_div_max;
450
451 m = dss.feat->dss_fck_multiplier;
452 prate = clk_get_rate(dss.parent_clk);
453
454 fck_min = fck_min ? fck_min : 1;
455
456 fckd_start = min(prate * m / fck_min, fckd_hw_max);
457 fckd_stop = max(DIV_ROUND_UP(prate * m, fck_hw_max), 1ul);
458
459 for (fckd = fckd_start; fckd >= fckd_stop; --fckd) {
460 fck = DIV_ROUND_UP(prate, fckd) * m;
461
462 if (func(fck, data))
463 return true;
464 }
465
466 return false;
467}
468
469int dss_set_fck_rate(unsigned long rate)
470{
471 int r;
472
473 DSSDBG("set fck to %lu\n", rate);
474
475 r = clk_set_rate(dss.dss_clk, rate);
476 if (r)
477 return r;
478
479 dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
480
481 WARN_ONCE(dss.dss_clk_rate != rate,
482 "clk rate mismatch: %lu != %lu", dss.dss_clk_rate,
483 rate);
484
485 return 0;
486}
487
488unsigned long dss_get_dispc_clk_rate(void)
489{
490 return dss.dss_clk_rate;
491}
492
493static int dss_setup_default_clock(void)
494{
495 unsigned long max_dss_fck, prate;
496 unsigned long fck;
497 unsigned fck_div;
498 int r;
499
500 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
501
502 if (dss.parent_clk == NULL) {
503 fck = clk_round_rate(dss.dss_clk, max_dss_fck);
504 } else {
505 prate = clk_get_rate(dss.parent_clk);
506
507 fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier,
508 max_dss_fck);
509 fck = DIV_ROUND_UP(prate, fck_div) * dss.feat->dss_fck_multiplier;
510 }
511
512 r = dss_set_fck_rate(fck);
513 if (r)
514 return r;
515
516 return 0;
517}
518
519void dss_set_venc_output(enum omap_dss_venc_type type)
520{
521 int l = 0;
522
523 if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
524 l = 0;
525 else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
526 l = 1;
527 else
528 BUG();
529
530 /* venc out selection. 0 = comp, 1 = svideo */
531 REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
532}
533
534void dss_set_dac_pwrdn_bgz(bool enable)
535{
536 REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
537}
538
539void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src)
540{
541 enum omap_display_type dp;
542 dp = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
543
544 /* Complain about invalid selections */
545 WARN_ON((src == DSS_VENC_TV_CLK) && !(dp & OMAP_DISPLAY_TYPE_VENC));
546 WARN_ON((src == DSS_HDMI_M_PCLK) && !(dp & OMAP_DISPLAY_TYPE_HDMI));
547
548 /* Select only if we have options */
549 if ((dp & OMAP_DISPLAY_TYPE_VENC) && (dp & OMAP_DISPLAY_TYPE_HDMI))
550 REG_FLD_MOD(DSS_CONTROL, src, 15, 15); /* VENC_HDMI_SWITCH */
551}
552
553enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
554{
555 enum omap_display_type displays;
556
557 displays = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
558 if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0)
559 return DSS_VENC_TV_CLK;
560
561 if ((displays & OMAP_DISPLAY_TYPE_VENC) == 0)
562 return DSS_HDMI_M_PCLK;
563
564 return REG_GET(DSS_CONTROL, 15, 15);
565}
566
567static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel)
568{
569 if (channel != OMAP_DSS_CHANNEL_LCD)
570 return -EINVAL;
571
572 return 0;
573}
574
575static int dss_dpi_select_source_omap4(enum omap_channel channel)
576{
577 int val;
578
579 switch (channel) {
580 case OMAP_DSS_CHANNEL_LCD2:
581 val = 0;
582 break;
583 case OMAP_DSS_CHANNEL_DIGIT:
584 val = 1;
585 break;
586 default:
587 return -EINVAL;
588 }
589
590 REG_FLD_MOD(DSS_CONTROL, val, 17, 17);
591
592 return 0;
593}
594
595static int dss_dpi_select_source_omap5(enum omap_channel channel)
596{
597 int val;
598
599 switch (channel) {
600 case OMAP_DSS_CHANNEL_LCD:
601 val = 1;
602 break;
603 case OMAP_DSS_CHANNEL_LCD2:
604 val = 2;
605 break;
606 case OMAP_DSS_CHANNEL_LCD3:
607 val = 3;
608 break;
609 case OMAP_DSS_CHANNEL_DIGIT:
610 val = 0;
611 break;
612 default:
613 return -EINVAL;
614 }
615
616 REG_FLD_MOD(DSS_CONTROL, val, 17, 16);
617
618 return 0;
619}
620
621int dss_dpi_select_source(enum omap_channel channel)
622{
623 return dss.feat->dpi_select_source(channel);
624}
625
626static int dss_get_clocks(void)
627{
628 struct clk *clk;
629
630 clk = devm_clk_get(&dss.pdev->dev, "fck");
631 if (IS_ERR(clk)) {
632 DSSERR("can't get clock fck\n");
633 return PTR_ERR(clk);
634 }
635
636 dss.dss_clk = clk;
637
638 if (dss.feat->parent_clk_name) {
639 clk = clk_get(NULL, dss.feat->parent_clk_name);
640 if (IS_ERR(clk)) {
641 DSSERR("Failed to get %s\n", dss.feat->parent_clk_name);
642 return PTR_ERR(clk);
643 }
644 } else {
645 clk = NULL;
646 }
647
648 dss.parent_clk = clk;
649
650 return 0;
651}
652
653static void dss_put_clocks(void)
654{
655 if (dss.parent_clk)
656 clk_put(dss.parent_clk);
657}
658
659static int dss_runtime_get(void)
660{
661 int r;
662
663 DSSDBG("dss_runtime_get\n");
664
665 r = pm_runtime_get_sync(&dss.pdev->dev);
666 WARN_ON(r < 0);
667 return r < 0 ? r : 0;
668}
669
670static void dss_runtime_put(void)
671{
672 int r;
673
674 DSSDBG("dss_runtime_put\n");
675
676 r = pm_runtime_put_sync(&dss.pdev->dev);
677 WARN_ON(r < 0 && r != -ENOSYS && r != -EBUSY);
678}
679
680/* DEBUGFS */
681#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
682void dss_debug_dump_clocks(struct seq_file *s)
683{
684 dss_dump_clocks(s);
685 dispc_dump_clocks(s);
686#ifdef CONFIG_OMAP2_DSS_DSI
687 dsi_dump_clocks(s);
688#endif
689}
690#endif
691
692static const struct dss_features omap24xx_dss_feats __initconst = {
693 /*
694 * fck div max is really 16, but the divider range has gaps. The range
695 * from 1 to 6 has no gaps, so let's use that as a max.
696 */
697 .fck_div_max = 6,
698 .dss_fck_multiplier = 2,
699 .parent_clk_name = "core_ck",
700 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
701};
702
703static const struct dss_features omap34xx_dss_feats __initconst = {
704 .fck_div_max = 16,
705 .dss_fck_multiplier = 2,
706 .parent_clk_name = "dpll4_ck",
707 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
708};
709
710static const struct dss_features omap3630_dss_feats __initconst = {
711 .fck_div_max = 32,
712 .dss_fck_multiplier = 1,
713 .parent_clk_name = "dpll4_ck",
714 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
715};
716
717static const struct dss_features omap44xx_dss_feats __initconst = {
718 .fck_div_max = 32,
719 .dss_fck_multiplier = 1,
720 .parent_clk_name = "dpll_per_x2_ck",
721 .dpi_select_source = &dss_dpi_select_source_omap4,
722};
723
724static const struct dss_features omap54xx_dss_feats __initconst = {
725 .fck_div_max = 64,
726 .dss_fck_multiplier = 1,
727 .parent_clk_name = "dpll_per_x2_ck",
728 .dpi_select_source = &dss_dpi_select_source_omap5,
729};
730
731static int __init dss_init_features(struct platform_device *pdev)
732{
733 const struct dss_features *src;
734 struct dss_features *dst;
735
736 dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
737 if (!dst) {
738 dev_err(&pdev->dev, "Failed to allocate local DSS Features\n");
739 return -ENOMEM;
740 }
741
742 switch (omapdss_get_version()) {
743 case OMAPDSS_VER_OMAP24xx:
744 src = &omap24xx_dss_feats;
745 break;
746
747 case OMAPDSS_VER_OMAP34xx_ES1:
748 case OMAPDSS_VER_OMAP34xx_ES3:
749 case OMAPDSS_VER_AM35xx:
750 src = &omap34xx_dss_feats;
751 break;
752
753 case OMAPDSS_VER_OMAP3630:
754 src = &omap3630_dss_feats;
755 break;
756
757 case OMAPDSS_VER_OMAP4430_ES1:
758 case OMAPDSS_VER_OMAP4430_ES2:
759 case OMAPDSS_VER_OMAP4:
760 src = &omap44xx_dss_feats;
761 break;
762
763 case OMAPDSS_VER_OMAP5:
764 src = &omap54xx_dss_feats;
765 break;
766
767 default:
768 return -ENODEV;
769 }
770
771 memcpy(dst, src, sizeof(*dst));
772 dss.feat = dst;
773
774 return 0;
775}
776
777static int __init dss_init_ports(struct platform_device *pdev)
778{
779 struct device_node *parent = pdev->dev.of_node;
780 struct device_node *port;
781 int r;
782
783 if (parent == NULL)
784 return 0;
785
786 port = omapdss_of_get_next_port(parent, NULL);
787 if (!port) {
788#ifdef CONFIG_OMAP2_DSS_DPI
789 dpi_init_port(pdev, parent);
790#endif
791 return 0;
792 }
793
794 do {
795 u32 reg;
796
797 r = of_property_read_u32(port, "reg", &reg);
798 if (r)
799 reg = 0;
800
801#ifdef CONFIG_OMAP2_DSS_DPI
802 if (reg == 0)
803 dpi_init_port(pdev, port);
804#endif
805
806#ifdef CONFIG_OMAP2_DSS_SDI
807 if (reg == 1)
808 sdi_init_port(pdev, port);
809#endif
810
811 } while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
812
813 return 0;
814}
815
816static void dss_uninit_ports(void)
817{
818#ifdef CONFIG_OMAP2_DSS_DPI
819 dpi_uninit_port();
820#endif
821
822#ifdef CONFIG_OMAP2_DSS_SDI
823 sdi_uninit_port();
824#endif
825}
826
827/* DSS HW IP initialisation */
828static int __init omap_dsshw_probe(struct platform_device *pdev)
829{
830 struct resource *dss_mem;
831 u32 rev;
832 int r;
833
834 dss.pdev = pdev;
835
836 r = dss_init_features(dss.pdev);
837 if (r)
838 return r;
839
840 dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
841 if (!dss_mem) {
842 DSSERR("can't get IORESOURCE_MEM DSS\n");
843 return -EINVAL;
844 }
845
846 dss.base = devm_ioremap(&pdev->dev, dss_mem->start,
847 resource_size(dss_mem));
848 if (!dss.base) {
849 DSSERR("can't ioremap DSS\n");
850 return -ENOMEM;
851 }
852
853 r = dss_get_clocks();
854 if (r)
855 return r;
856
857 r = dss_setup_default_clock();
858 if (r)
859 goto err_setup_clocks;
860
861 pm_runtime_enable(&pdev->dev);
862
863 r = dss_runtime_get();
864 if (r)
865 goto err_runtime_get;
866
867 dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
868
869 /* Select DPLL */
870 REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
871
872 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
873
874#ifdef CONFIG_OMAP2_DSS_VENC
875 REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
876 REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
877 REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
878#endif
879 dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
880 dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
881 dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
882 dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
883 dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
884
885 dss_init_ports(pdev);
886
887 rev = dss_read_reg(DSS_REVISION);
888 printk(KERN_INFO "OMAP DSS rev %d.%d\n",
889 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
890
891 dss_runtime_put();
892
893 dss_debugfs_create_file("dss", dss_dump_regs);
894
895 return 0;
896
897err_runtime_get:
898 pm_runtime_disable(&pdev->dev);
899err_setup_clocks:
900 dss_put_clocks();
901 return r;
902}
903
904static int __exit omap_dsshw_remove(struct platform_device *pdev)
905{
906 dss_uninit_ports();
907
908 pm_runtime_disable(&pdev->dev);
909
910 dss_put_clocks();
911
912 return 0;
913}
914
915static int dss_runtime_suspend(struct device *dev)
916{
917 dss_save_context();
918 dss_set_min_bus_tput(dev, 0);
919 return 0;
920}
921
922static int dss_runtime_resume(struct device *dev)
923{
924 int r;
925 /*
926 * Set an arbitrarily high tput request to ensure OPP100.
927 * What we should really do is to make a request to stay in OPP100,
928 * without any tput requirements, but that is not currently possible
929 * via the PM layer.
930 */
931
932 r = dss_set_min_bus_tput(dev, 1000000000);
933 if (r)
934 return r;
935
936 dss_restore_context();
937 return 0;
938}
939
940static const struct dev_pm_ops dss_pm_ops = {
941 .runtime_suspend = dss_runtime_suspend,
942 .runtime_resume = dss_runtime_resume,
943};
944
945static const struct of_device_id dss_of_match[] = {
946 { .compatible = "ti,omap2-dss", },
947 { .compatible = "ti,omap3-dss", },
948 { .compatible = "ti,omap4-dss", },
949 {},
950};
951
952MODULE_DEVICE_TABLE(of, dss_of_match);
953
954static struct platform_driver omap_dsshw_driver = {
955 .remove = __exit_p(omap_dsshw_remove),
956 .driver = {
957 .name = "omapdss_dss",
958 .owner = THIS_MODULE,
959 .pm = &dss_pm_ops,
960 .of_match_table = dss_of_match,
961 },
962};
963
964int __init dss_init_platform_driver(void)
965{
966 return platform_driver_probe(&omap_dsshw_driver, omap_dsshw_probe);
967}
968
969void dss_uninit_platform_driver(void)
970{
971 platform_driver_unregister(&omap_dsshw_driver);
972}
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
deleted file mode 100644
index 560078fcb198..000000000000
--- a/drivers/video/omap2/dss/dss.h
+++ /dev/null
@@ -1,438 +0,0 @@
1/*
2 * linux/drivers/video/omap2/dss/dss.h
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
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#ifndef __OMAP2_DSS_H
24#define __OMAP2_DSS_H
25
26#include <linux/interrupt.h>
27
28#ifdef pr_fmt
29#undef pr_fmt
30#endif
31
32#ifdef DSS_SUBSYS_NAME
33#define pr_fmt(fmt) DSS_SUBSYS_NAME ": " fmt
34#else
35#define pr_fmt(fmt) fmt
36#endif
37
38#define DSSDBG(format, ...) \
39 pr_debug(format, ## __VA_ARGS__)
40
41#ifdef DSS_SUBSYS_NAME
42#define DSSERR(format, ...) \
43 printk(KERN_ERR "omapdss " DSS_SUBSYS_NAME " error: " format, \
44 ## __VA_ARGS__)
45#else
46#define DSSERR(format, ...) \
47 printk(KERN_ERR "omapdss error: " format, ## __VA_ARGS__)
48#endif
49
50#ifdef DSS_SUBSYS_NAME
51#define DSSINFO(format, ...) \
52 printk(KERN_INFO "omapdss " DSS_SUBSYS_NAME ": " format, \
53 ## __VA_ARGS__)
54#else
55#define DSSINFO(format, ...) \
56 printk(KERN_INFO "omapdss: " format, ## __VA_ARGS__)
57#endif
58
59#ifdef DSS_SUBSYS_NAME
60#define DSSWARN(format, ...) \
61 printk(KERN_WARNING "omapdss " DSS_SUBSYS_NAME ": " format, \
62 ## __VA_ARGS__)
63#else
64#define DSSWARN(format, ...) \
65 printk(KERN_WARNING "omapdss: " format, ## __VA_ARGS__)
66#endif
67
68/* OMAP TRM gives bitfields as start:end, where start is the higher bit
69 number. For example 7:0 */
70#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
71#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
72#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end))
73#define FLD_MOD(orig, val, start, end) \
74 (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
75
76enum dss_io_pad_mode {
77 DSS_IO_PAD_MODE_RESET,
78 DSS_IO_PAD_MODE_RFBI,
79 DSS_IO_PAD_MODE_BYPASS,
80};
81
82enum dss_hdmi_venc_clk_source_select {
83 DSS_VENC_TV_CLK = 0,
84 DSS_HDMI_M_PCLK = 1,
85};
86
87enum dss_dsi_content_type {
88 DSS_DSI_CONTENT_DCS,
89 DSS_DSI_CONTENT_GENERIC,
90};
91
92enum dss_writeback_channel {
93 DSS_WB_LCD1_MGR = 0,
94 DSS_WB_LCD2_MGR = 1,
95 DSS_WB_TV_MGR = 2,
96 DSS_WB_OVL0 = 3,
97 DSS_WB_OVL1 = 4,
98 DSS_WB_OVL2 = 5,
99 DSS_WB_OVL3 = 6,
100 DSS_WB_LCD3_MGR = 7,
101};
102
103struct dispc_clock_info {
104 /* rates that we get with dividers below */
105 unsigned long lck;
106 unsigned long pck;
107
108 /* dividers */
109 u16 lck_div;
110 u16 pck_div;
111};
112
113struct dsi_clock_info {
114 /* rates that we get with dividers below */
115 unsigned long fint;
116 unsigned long clkin4ddr;
117 unsigned long clkin;
118 unsigned long dsi_pll_hsdiv_dispc_clk; /* OMAP3: DSI1_PLL_CLK
119 * OMAP4: PLLx_CLK1 */
120 unsigned long dsi_pll_hsdiv_dsi_clk; /* OMAP3: DSI2_PLL_CLK
121 * OMAP4: PLLx_CLK2 */
122 unsigned long lp_clk;
123
124 /* dividers */
125 u16 regn;
126 u16 regm;
127 u16 regm_dispc; /* OMAP3: REGM3
128 * OMAP4: REGM4 */
129 u16 regm_dsi; /* OMAP3: REGM4
130 * OMAP4: REGM5 */
131 u16 lp_clk_div;
132};
133
134struct dss_lcd_mgr_config {
135 enum dss_io_pad_mode io_pad_mode;
136
137 bool stallmode;
138 bool fifohandcheck;
139
140 struct dispc_clock_info clock_info;
141
142 int video_port_width;
143
144 int lcden_sig_polarity;
145};
146
147struct seq_file;
148struct platform_device;
149
150/* core */
151struct platform_device *dss_get_core_pdev(void);
152int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask);
153void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
154int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
155int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *));
156
157/* display */
158int dss_suspend_all_devices(void);
159int dss_resume_all_devices(void);
160void dss_disable_all_devices(void);
161
162int display_init_sysfs(struct platform_device *pdev);
163void display_uninit_sysfs(struct platform_device *pdev);
164
165/* manager */
166int dss_init_overlay_managers(void);
167void dss_uninit_overlay_managers(void);
168int dss_init_overlay_managers_sysfs(struct platform_device *pdev);
169void dss_uninit_overlay_managers_sysfs(struct platform_device *pdev);
170int dss_mgr_simple_check(struct omap_overlay_manager *mgr,
171 const struct omap_overlay_manager_info *info);
172int dss_mgr_check_timings(struct omap_overlay_manager *mgr,
173 const struct omap_video_timings *timings);
174int dss_mgr_check(struct omap_overlay_manager *mgr,
175 struct omap_overlay_manager_info *info,
176 const struct omap_video_timings *mgr_timings,
177 const struct dss_lcd_mgr_config *config,
178 struct omap_overlay_info **overlay_infos);
179
180static inline bool dss_mgr_is_lcd(enum omap_channel id)
181{
182 if (id == OMAP_DSS_CHANNEL_LCD || id == OMAP_DSS_CHANNEL_LCD2 ||
183 id == OMAP_DSS_CHANNEL_LCD3)
184 return true;
185 else
186 return false;
187}
188
189int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
190 struct platform_device *pdev);
191void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr);
192
193/* overlay */
194void dss_init_overlays(struct platform_device *pdev);
195void dss_uninit_overlays(struct platform_device *pdev);
196void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
197int dss_ovl_simple_check(struct omap_overlay *ovl,
198 const struct omap_overlay_info *info);
199int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info,
200 const struct omap_video_timings *mgr_timings);
201bool dss_ovl_use_replication(struct dss_lcd_mgr_config config,
202 enum omap_color_mode mode);
203int dss_overlay_kobj_init(struct omap_overlay *ovl,
204 struct platform_device *pdev);
205void dss_overlay_kobj_uninit(struct omap_overlay *ovl);
206
207/* DSS */
208int dss_init_platform_driver(void) __init;
209void dss_uninit_platform_driver(void);
210
211unsigned long dss_get_dispc_clk_rate(void);
212int dss_dpi_select_source(enum omap_channel channel);
213void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
214enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
215const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
216void dss_dump_clocks(struct seq_file *s);
217
218#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
219void dss_debug_dump_clocks(struct seq_file *s);
220#endif
221
222void dss_sdi_init(int datapairs);
223int dss_sdi_enable(void);
224void dss_sdi_disable(void);
225
226void dss_select_dsi_clk_source(int dsi_module,
227 enum omap_dss_clk_source clk_src);
228void dss_select_lcd_clk_source(enum omap_channel channel,
229 enum omap_dss_clk_source clk_src);
230enum omap_dss_clk_source dss_get_dispc_clk_source(void);
231enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module);
232enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel);
233
234void dss_set_venc_output(enum omap_dss_venc_type type);
235void dss_set_dac_pwrdn_bgz(bool enable);
236
237int dss_set_fck_rate(unsigned long rate);
238
239typedef bool (*dss_div_calc_func)(unsigned long fck, void *data);
240bool dss_div_calc(unsigned long pck, unsigned long fck_min,
241 dss_div_calc_func func, void *data);
242
243/* SDI */
244int sdi_init_platform_driver(void) __init;
245void sdi_uninit_platform_driver(void) __exit;
246
247int sdi_init_port(struct platform_device *pdev, struct device_node *port) __init;
248void sdi_uninit_port(void) __exit;
249
250/* DSI */
251
252typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint,
253 unsigned long pll, void *data);
254typedef bool (*dsi_hsdiv_calc_func)(int regm_dispc, unsigned long dispc,
255 void *data);
256
257#ifdef CONFIG_OMAP2_DSS_DSI
258
259struct dentry;
260struct file_operations;
261
262int dsi_init_platform_driver(void) __init;
263void dsi_uninit_platform_driver(void) __exit;
264
265int dsi_runtime_get(struct platform_device *dsidev);
266void dsi_runtime_put(struct platform_device *dsidev);
267
268void dsi_dump_clocks(struct seq_file *s);
269
270void dsi_irq_handler(void);
271u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt);
272
273unsigned long dsi_get_pll_clkin(struct platform_device *dsidev);
274
275bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
276 unsigned long out_min, dsi_hsdiv_calc_func func, void *data);
277bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
278 unsigned long pll_min, unsigned long pll_max,
279 dsi_pll_calc_func func, void *data);
280
281unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
282int dsi_pll_set_clock_div(struct platform_device *dsidev,
283 struct dsi_clock_info *cinfo);
284int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
285 bool enable_hsdiv);
286void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes);
287void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev);
288void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev);
289struct platform_device *dsi_get_dsidev_from_id(int module);
290#else
291static inline int dsi_runtime_get(struct platform_device *dsidev)
292{
293 return 0;
294}
295static inline void dsi_runtime_put(struct platform_device *dsidev)
296{
297}
298static inline u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
299{
300 WARN("%s: DSI not compiled in, returning pixel_size as 0\n", __func__);
301 return 0;
302}
303static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
304{
305 WARN("%s: DSI not compiled in, returning rate as 0\n", __func__);
306 return 0;
307}
308static inline int dsi_pll_set_clock_div(struct platform_device *dsidev,
309 struct dsi_clock_info *cinfo)
310{
311 WARN("%s: DSI not compiled in\n", __func__);
312 return -ENODEV;
313}
314static inline int dsi_pll_init(struct platform_device *dsidev,
315 bool enable_hsclk, bool enable_hsdiv)
316{
317 WARN("%s: DSI not compiled in\n", __func__);
318 return -ENODEV;
319}
320static inline void dsi_pll_uninit(struct platform_device *dsidev,
321 bool disconnect_lanes)
322{
323}
324static inline void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev)
325{
326}
327static inline void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev)
328{
329}
330static inline struct platform_device *dsi_get_dsidev_from_id(int module)
331{
332 return NULL;
333}
334
335static inline unsigned long dsi_get_pll_clkin(struct platform_device *dsidev)
336{
337 return 0;
338}
339
340static inline bool dsi_hsdiv_calc(struct platform_device *dsidev,
341 unsigned long pll, unsigned long out_min,
342 dsi_hsdiv_calc_func func, void *data)
343{
344 return false;
345}
346
347static inline bool dsi_pll_calc(struct platform_device *dsidev,
348 unsigned long clkin,
349 unsigned long pll_min, unsigned long pll_max,
350 dsi_pll_calc_func func, void *data)
351{
352 return false;
353}
354
355#endif
356
357/* DPI */
358int dpi_init_platform_driver(void) __init;
359void dpi_uninit_platform_driver(void) __exit;
360
361int dpi_init_port(struct platform_device *pdev, struct device_node *port) __init;
362void dpi_uninit_port(void) __exit;
363
364/* DISPC */
365int dispc_init_platform_driver(void) __init;
366void dispc_uninit_platform_driver(void) __exit;
367void dispc_dump_clocks(struct seq_file *s);
368
369void dispc_enable_sidle(void);
370void dispc_disable_sidle(void);
371
372void dispc_lcd_enable_signal(bool enable);
373void dispc_pck_free_enable(bool enable);
374void dispc_enable_fifomerge(bool enable);
375void dispc_enable_gamma_table(bool enable);
376void dispc_set_loadmode(enum omap_dss_load_mode mode);
377
378typedef bool (*dispc_div_calc_func)(int lckd, int pckd, unsigned long lck,
379 unsigned long pck, void *data);
380bool dispc_div_calc(unsigned long dispc,
381 unsigned long pck_min, unsigned long pck_max,
382 dispc_div_calc_func func, void *data);
383
384bool dispc_mgr_timings_ok(enum omap_channel channel,
385 const struct omap_video_timings *timings);
386unsigned long dispc_fclk_rate(void);
387int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
388 struct dispc_clock_info *cinfo);
389
390
391void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
392void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
393 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
394 bool manual_update);
395
396unsigned long dispc_mgr_lclk_rate(enum omap_channel channel);
397unsigned long dispc_mgr_pclk_rate(enum omap_channel channel);
398unsigned long dispc_core_clk_rate(void);
399void dispc_mgr_set_clock_div(enum omap_channel channel,
400 const struct dispc_clock_info *cinfo);
401int dispc_mgr_get_clock_div(enum omap_channel channel,
402 struct dispc_clock_info *cinfo);
403void dispc_set_tv_pclk(unsigned long pclk);
404
405u32 dispc_wb_get_framedone_irq(void);
406bool dispc_wb_go_busy(void);
407void dispc_wb_go(void);
408void dispc_wb_enable(bool enable);
409bool dispc_wb_is_enabled(void);
410void dispc_wb_set_channel_in(enum dss_writeback_channel channel);
411int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
412 bool mem_to_mem, const struct omap_video_timings *timings);
413
414/* VENC */
415int venc_init_platform_driver(void) __init;
416void venc_uninit_platform_driver(void) __exit;
417
418/* HDMI */
419int hdmi4_init_platform_driver(void) __init;
420void hdmi4_uninit_platform_driver(void) __exit;
421
422/* RFBI */
423int rfbi_init_platform_driver(void) __init;
424void rfbi_uninit_platform_driver(void) __exit;
425
426
427#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
428static inline void dss_collect_irq_stats(u32 irqstatus, unsigned *irq_arr)
429{
430 int b;
431 for (b = 0; b < 32; ++b) {
432 if (irqstatus & (1 << b))
433 irq_arr[b]++;
434 }
435}
436#endif
437
438#endif
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
deleted file mode 100644
index 7f8969191dc6..000000000000
--- a/drivers/video/omap2/dss/dss_features.c
+++ /dev/null
@@ -1,935 +0,0 @@
1/*
2 * linux/drivers/video/omap2/dss/dss_features.c
3 *
4 * Copyright (C) 2010 Texas Instruments
5 * Author: Archit Taneja <archit@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 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/types.h>
23#include <linux/err.h>
24#include <linux/slab.h>
25
26#include <video/omapdss.h>
27
28#include "dss.h"
29#include "dss_features.h"
30
31/* Defines a generic omap register field */
32struct dss_reg_field {
33 u8 start, end;
34};
35
36struct dss_param_range {
37 int min, max;
38};
39
40struct omap_dss_features {
41 const struct dss_reg_field *reg_fields;
42 const int num_reg_fields;
43
44 const enum dss_feat_id *features;
45 const int num_features;
46
47 const int num_mgrs;
48 const int num_ovls;
49 const int num_wbs;
50 const enum omap_display_type *supported_displays;
51 const enum omap_dss_output_id *supported_outputs;
52 const enum omap_color_mode *supported_color_modes;
53 const enum omap_overlay_caps *overlay_caps;
54 const char * const *clksrc_names;
55 const struct dss_param_range *dss_params;
56
57 const enum omap_dss_rotation_type supported_rotation_types;
58
59 const u32 buffer_size_unit;
60 const u32 burst_size_unit;
61};
62
63/* This struct is assigned to one of the below during initialization */
64static const struct omap_dss_features *omap_current_dss_features;
65
66static const struct dss_reg_field omap2_dss_reg_fields[] = {
67 [FEAT_REG_FIRHINC] = { 11, 0 },
68 [FEAT_REG_FIRVINC] = { 27, 16 },
69 [FEAT_REG_FIFOLOWTHRESHOLD] = { 8, 0 },
70 [FEAT_REG_FIFOHIGHTHRESHOLD] = { 24, 16 },
71 [FEAT_REG_FIFOSIZE] = { 8, 0 },
72 [FEAT_REG_HORIZONTALACCU] = { 9, 0 },
73 [FEAT_REG_VERTICALACCU] = { 25, 16 },
74 [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 },
75 [FEAT_REG_DSIPLL_REGN] = { 0, 0 },
76 [FEAT_REG_DSIPLL_REGM] = { 0, 0 },
77 [FEAT_REG_DSIPLL_REGM_DISPC] = { 0, 0 },
78 [FEAT_REG_DSIPLL_REGM_DSI] = { 0, 0 },
79};
80
81static const struct dss_reg_field omap3_dss_reg_fields[] = {
82 [FEAT_REG_FIRHINC] = { 12, 0 },
83 [FEAT_REG_FIRVINC] = { 28, 16 },
84 [FEAT_REG_FIFOLOWTHRESHOLD] = { 11, 0 },
85 [FEAT_REG_FIFOHIGHTHRESHOLD] = { 27, 16 },
86 [FEAT_REG_FIFOSIZE] = { 10, 0 },
87 [FEAT_REG_HORIZONTALACCU] = { 9, 0 },
88 [FEAT_REG_VERTICALACCU] = { 25, 16 },
89 [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 },
90 [FEAT_REG_DSIPLL_REGN] = { 7, 1 },
91 [FEAT_REG_DSIPLL_REGM] = { 18, 8 },
92 [FEAT_REG_DSIPLL_REGM_DISPC] = { 22, 19 },
93 [FEAT_REG_DSIPLL_REGM_DSI] = { 26, 23 },
94};
95
96static const struct dss_reg_field omap4_dss_reg_fields[] = {
97 [FEAT_REG_FIRHINC] = { 12, 0 },
98 [FEAT_REG_FIRVINC] = { 28, 16 },
99 [FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 },
100 [FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 },
101 [FEAT_REG_FIFOSIZE] = { 15, 0 },
102 [FEAT_REG_HORIZONTALACCU] = { 10, 0 },
103 [FEAT_REG_VERTICALACCU] = { 26, 16 },
104 [FEAT_REG_DISPC_CLK_SWITCH] = { 9, 8 },
105 [FEAT_REG_DSIPLL_REGN] = { 8, 1 },
106 [FEAT_REG_DSIPLL_REGM] = { 20, 9 },
107 [FEAT_REG_DSIPLL_REGM_DISPC] = { 25, 21 },
108 [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 },
109};
110
111static const struct dss_reg_field omap5_dss_reg_fields[] = {
112 [FEAT_REG_FIRHINC] = { 12, 0 },
113 [FEAT_REG_FIRVINC] = { 28, 16 },
114 [FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 },
115 [FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 },
116 [FEAT_REG_FIFOSIZE] = { 15, 0 },
117 [FEAT_REG_HORIZONTALACCU] = { 10, 0 },
118 [FEAT_REG_VERTICALACCU] = { 26, 16 },
119 [FEAT_REG_DISPC_CLK_SWITCH] = { 9, 7 },
120 [FEAT_REG_DSIPLL_REGN] = { 8, 1 },
121 [FEAT_REG_DSIPLL_REGM] = { 20, 9 },
122 [FEAT_REG_DSIPLL_REGM_DISPC] = { 25, 21 },
123 [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 },
124};
125
126static const enum omap_display_type omap2_dss_supported_displays[] = {
127 /* OMAP_DSS_CHANNEL_LCD */
128 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI,
129
130 /* OMAP_DSS_CHANNEL_DIGIT */
131 OMAP_DISPLAY_TYPE_VENC,
132};
133
134static const enum omap_display_type omap3430_dss_supported_displays[] = {
135 /* OMAP_DSS_CHANNEL_LCD */
136 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
137 OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI,
138
139 /* OMAP_DSS_CHANNEL_DIGIT */
140 OMAP_DISPLAY_TYPE_VENC,
141};
142
143static const enum omap_display_type omap3630_dss_supported_displays[] = {
144 /* OMAP_DSS_CHANNEL_LCD */
145 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
146 OMAP_DISPLAY_TYPE_DSI,
147
148 /* OMAP_DSS_CHANNEL_DIGIT */
149 OMAP_DISPLAY_TYPE_VENC,
150};
151
152static const enum omap_display_type omap4_dss_supported_displays[] = {
153 /* OMAP_DSS_CHANNEL_LCD */
154 OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI,
155
156 /* OMAP_DSS_CHANNEL_DIGIT */
157 OMAP_DISPLAY_TYPE_VENC | OMAP_DISPLAY_TYPE_HDMI,
158
159 /* OMAP_DSS_CHANNEL_LCD2 */
160 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
161 OMAP_DISPLAY_TYPE_DSI,
162};
163
164static const enum omap_display_type omap5_dss_supported_displays[] = {
165 /* OMAP_DSS_CHANNEL_LCD */
166 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
167 OMAP_DISPLAY_TYPE_DSI,
168
169 /* OMAP_DSS_CHANNEL_DIGIT */
170 OMAP_DISPLAY_TYPE_HDMI | OMAP_DISPLAY_TYPE_DPI,
171
172 /* OMAP_DSS_CHANNEL_LCD2 */
173 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
174 OMAP_DISPLAY_TYPE_DSI,
175};
176
177static const enum omap_dss_output_id omap2_dss_supported_outputs[] = {
178 /* OMAP_DSS_CHANNEL_LCD */
179 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI,
180
181 /* OMAP_DSS_CHANNEL_DIGIT */
182 OMAP_DSS_OUTPUT_VENC,
183};
184
185static const enum omap_dss_output_id omap3430_dss_supported_outputs[] = {
186 /* OMAP_DSS_CHANNEL_LCD */
187 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
188 OMAP_DSS_OUTPUT_SDI | OMAP_DSS_OUTPUT_DSI1,
189
190 /* OMAP_DSS_CHANNEL_DIGIT */
191 OMAP_DSS_OUTPUT_VENC,
192};
193
194static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = {
195 /* OMAP_DSS_CHANNEL_LCD */
196 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
197 OMAP_DSS_OUTPUT_DSI1,
198
199 /* OMAP_DSS_CHANNEL_DIGIT */
200 OMAP_DSS_OUTPUT_VENC,
201};
202
203static const enum omap_dss_output_id omap4_dss_supported_outputs[] = {
204 /* OMAP_DSS_CHANNEL_LCD */
205 OMAP_DSS_OUTPUT_DBI | OMAP_DSS_OUTPUT_DSI1,
206
207 /* OMAP_DSS_CHANNEL_DIGIT */
208 OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI,
209
210 /* OMAP_DSS_CHANNEL_LCD2 */
211 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
212 OMAP_DSS_OUTPUT_DSI2,
213};
214
215static const enum omap_dss_output_id omap5_dss_supported_outputs[] = {
216 /* OMAP_DSS_CHANNEL_LCD */
217 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
218 OMAP_DSS_OUTPUT_DSI1 | OMAP_DSS_OUTPUT_DSI2,
219
220 /* OMAP_DSS_CHANNEL_DIGIT */
221 OMAP_DSS_OUTPUT_HDMI | OMAP_DSS_OUTPUT_DPI,
222
223 /* OMAP_DSS_CHANNEL_LCD2 */
224 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
225 OMAP_DSS_OUTPUT_DSI1,
226
227 /* OMAP_DSS_CHANNEL_LCD3 */
228 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
229 OMAP_DSS_OUTPUT_DSI2,
230};
231
232static const enum omap_color_mode omap2_dss_supported_color_modes[] = {
233 /* OMAP_DSS_GFX */
234 OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
235 OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
236 OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
237 OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P,
238
239 /* OMAP_DSS_VIDEO1 */
240 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
241 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
242 OMAP_DSS_COLOR_UYVY,
243
244 /* OMAP_DSS_VIDEO2 */
245 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
246 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
247 OMAP_DSS_COLOR_UYVY,
248};
249
250static const enum omap_color_mode omap3_dss_supported_color_modes[] = {
251 /* OMAP_DSS_GFX */
252 OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
253 OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
254 OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
255 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
256 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
257 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
258
259 /* OMAP_DSS_VIDEO1 */
260 OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P |
261 OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
262 OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY,
263
264 /* OMAP_DSS_VIDEO2 */
265 OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
266 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
267 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
268 OMAP_DSS_COLOR_UYVY | OMAP_DSS_COLOR_ARGB32 |
269 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
270};
271
272static const enum omap_color_mode omap4_dss_supported_color_modes[] = {
273 /* OMAP_DSS_GFX */
274 OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
275 OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
276 OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
277 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
278 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
279 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 |
280 OMAP_DSS_COLOR_ARGB16_1555 | OMAP_DSS_COLOR_RGBX16 |
281 OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_XRGB16_1555,
282
283 /* OMAP_DSS_VIDEO1 */
284 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
285 OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
286 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
287 OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
288 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
289 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
290 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
291 OMAP_DSS_COLOR_RGBX32,
292
293 /* OMAP_DSS_VIDEO2 */
294 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
295 OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
296 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
297 OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
298 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
299 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
300 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
301 OMAP_DSS_COLOR_RGBX32,
302
303 /* OMAP_DSS_VIDEO3 */
304 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
305 OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
306 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
307 OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
308 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
309 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
310 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
311 OMAP_DSS_COLOR_RGBX32,
312
313 /* OMAP_DSS_WB */
314 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
315 OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
316 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
317 OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
318 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
319 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
320 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
321 OMAP_DSS_COLOR_RGBX32,
322};
323
324static const enum omap_overlay_caps omap2_dss_overlay_caps[] = {
325 /* OMAP_DSS_GFX */
326 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
327
328 /* OMAP_DSS_VIDEO1 */
329 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
330 OMAP_DSS_OVL_CAP_REPLICATION,
331
332 /* OMAP_DSS_VIDEO2 */
333 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
334 OMAP_DSS_OVL_CAP_REPLICATION,
335};
336
337static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = {
338 /* OMAP_DSS_GFX */
339 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_POS |
340 OMAP_DSS_OVL_CAP_REPLICATION,
341
342 /* OMAP_DSS_VIDEO1 */
343 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
344 OMAP_DSS_OVL_CAP_REPLICATION,
345
346 /* OMAP_DSS_VIDEO2 */
347 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
348 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
349};
350
351static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = {
352 /* OMAP_DSS_GFX */
353 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
354 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
355
356 /* OMAP_DSS_VIDEO1 */
357 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
358 OMAP_DSS_OVL_CAP_REPLICATION,
359
360 /* OMAP_DSS_VIDEO2 */
361 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
362 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_POS |
363 OMAP_DSS_OVL_CAP_REPLICATION,
364};
365
366static const enum omap_overlay_caps omap4_dss_overlay_caps[] = {
367 /* OMAP_DSS_GFX */
368 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
369 OMAP_DSS_OVL_CAP_ZORDER | OMAP_DSS_OVL_CAP_POS |
370 OMAP_DSS_OVL_CAP_REPLICATION,
371
372 /* OMAP_DSS_VIDEO1 */
373 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
374 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
375 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
376
377 /* OMAP_DSS_VIDEO2 */
378 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
379 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
380 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
381
382 /* OMAP_DSS_VIDEO3 */
383 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
384 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
385 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
386};
387
388static const char * const omap2_dss_clk_source_names[] = {
389 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "N/A",
390 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "N/A",
391 [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCLK1",
392};
393
394static const char * const omap3_dss_clk_source_names[] = {
395 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI1_PLL_FCLK",
396 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI2_PLL_FCLK",
397 [OMAP_DSS_CLK_SRC_FCK] = "DSS1_ALWON_FCLK",
398};
399
400static const char * const omap4_dss_clk_source_names[] = {
401 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "PLL1_CLK1",
402 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "PLL1_CLK2",
403 [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCLK",
404 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "PLL2_CLK1",
405 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "PLL2_CLK2",
406};
407
408static const char * const omap5_dss_clk_source_names[] = {
409 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DPLL_DSI1_A_CLK1",
410 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DPLL_DSI1_A_CLK2",
411 [OMAP_DSS_CLK_SRC_FCK] = "DSS_CLK",
412 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DPLL_DSI1_C_CLK1",
413 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DPLL_DSI1_C_CLK2",
414};
415
416static const struct dss_param_range omap2_dss_param_range[] = {
417 [FEAT_PARAM_DSS_FCK] = { 0, 133000000 },
418 [FEAT_PARAM_DSS_PCD] = { 2, 255 },
419 [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 },
420 [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 },
421 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, 0 },
422 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, 0 },
423 [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 },
424 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 },
425 [FEAT_PARAM_DOWNSCALE] = { 1, 2 },
426 /*
427 * Assuming the line width buffer to be 768 pixels as OMAP2 DISPC
428 * scaler cannot scale a image with width more than 768.
429 */
430 [FEAT_PARAM_LINEWIDTH] = { 1, 768 },
431};
432
433static const struct dss_param_range omap3_dss_param_range[] = {
434 [FEAT_PARAM_DSS_FCK] = { 0, 173000000 },
435 [FEAT_PARAM_DSS_PCD] = { 1, 255 },
436 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 7) - 1 },
437 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 11) - 1 },
438 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 4) - 1 },
439 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 },
440 [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 },
441 [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1},
442 [FEAT_PARAM_DSI_FCK] = { 0, 173000000 },
443 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
444 [FEAT_PARAM_LINEWIDTH] = { 1, 1024 },
445};
446
447static const struct dss_param_range omap4_dss_param_range[] = {
448 [FEAT_PARAM_DSS_FCK] = { 0, 186000000 },
449 [FEAT_PARAM_DSS_PCD] = { 1, 255 },
450 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 },
451 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 },
452 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 },
453 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 },
454 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 },
455 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
456 [FEAT_PARAM_DSI_FCK] = { 0, 170000000 },
457 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
458 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
459};
460
461static const struct dss_param_range omap5_dss_param_range[] = {
462 [FEAT_PARAM_DSS_FCK] = { 0, 209250000 },
463 [FEAT_PARAM_DSS_PCD] = { 1, 255 },
464 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 },
465 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 },
466 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 },
467 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 },
468 [FEAT_PARAM_DSIPLL_FINT] = { 150000, 52000000 },
469 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
470 [FEAT_PARAM_DSI_FCK] = { 0, 209250000 },
471 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
472 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
473};
474
475static const enum dss_feat_id omap2_dss_feat_list[] = {
476 FEAT_LCDENABLEPOL,
477 FEAT_LCDENABLESIGNAL,
478 FEAT_PCKFREEENABLE,
479 FEAT_FUNCGATED,
480 FEAT_ROWREPEATENABLE,
481 FEAT_RESIZECONF,
482};
483
484static const enum dss_feat_id omap3430_dss_feat_list[] = {
485 FEAT_LCDENABLEPOL,
486 FEAT_LCDENABLESIGNAL,
487 FEAT_PCKFREEENABLE,
488 FEAT_FUNCGATED,
489 FEAT_LINEBUFFERSPLIT,
490 FEAT_ROWREPEATENABLE,
491 FEAT_RESIZECONF,
492 FEAT_DSI_PLL_FREQSEL,
493 FEAT_DSI_REVERSE_TXCLKESC,
494 FEAT_VENC_REQUIRES_TV_DAC_CLK,
495 FEAT_CPR,
496 FEAT_PRELOAD,
497 FEAT_FIR_COEF_V,
498 FEAT_ALPHA_FIXED_ZORDER,
499 FEAT_FIFO_MERGE,
500 FEAT_OMAP3_DSI_FIFO_BUG,
501 FEAT_DPI_USES_VDDS_DSI,
502};
503
504static const enum dss_feat_id am35xx_dss_feat_list[] = {
505 FEAT_LCDENABLEPOL,
506 FEAT_LCDENABLESIGNAL,
507 FEAT_PCKFREEENABLE,
508 FEAT_FUNCGATED,
509 FEAT_LINEBUFFERSPLIT,
510 FEAT_ROWREPEATENABLE,
511 FEAT_RESIZECONF,
512 FEAT_DSI_PLL_FREQSEL,
513 FEAT_DSI_REVERSE_TXCLKESC,
514 FEAT_VENC_REQUIRES_TV_DAC_CLK,
515 FEAT_CPR,
516 FEAT_PRELOAD,
517 FEAT_FIR_COEF_V,
518 FEAT_ALPHA_FIXED_ZORDER,
519 FEAT_FIFO_MERGE,
520 FEAT_OMAP3_DSI_FIFO_BUG,
521};
522
523static const enum dss_feat_id omap3630_dss_feat_list[] = {
524 FEAT_LCDENABLEPOL,
525 FEAT_LCDENABLESIGNAL,
526 FEAT_PCKFREEENABLE,
527 FEAT_FUNCGATED,
528 FEAT_LINEBUFFERSPLIT,
529 FEAT_ROWREPEATENABLE,
530 FEAT_RESIZECONF,
531 FEAT_DSI_PLL_PWR_BUG,
532 FEAT_DSI_PLL_FREQSEL,
533 FEAT_CPR,
534 FEAT_PRELOAD,
535 FEAT_FIR_COEF_V,
536 FEAT_ALPHA_FIXED_ZORDER,
537 FEAT_FIFO_MERGE,
538 FEAT_OMAP3_DSI_FIFO_BUG,
539 FEAT_DPI_USES_VDDS_DSI,
540};
541
542static const enum dss_feat_id omap4430_es1_0_dss_feat_list[] = {
543 FEAT_MGR_LCD2,
544 FEAT_CORE_CLK_DIV,
545 FEAT_LCD_CLK_SRC,
546 FEAT_DSI_DCS_CMD_CONFIG_VC,
547 FEAT_DSI_VC_OCP_WIDTH,
548 FEAT_DSI_GNQ,
549 FEAT_HANDLE_UV_SEPARATE,
550 FEAT_ATTR2,
551 FEAT_CPR,
552 FEAT_PRELOAD,
553 FEAT_FIR_COEF_V,
554 FEAT_ALPHA_FREE_ZORDER,
555 FEAT_FIFO_MERGE,
556 FEAT_BURST_2D,
557};
558
559static const enum dss_feat_id omap4430_es2_0_1_2_dss_feat_list[] = {
560 FEAT_MGR_LCD2,
561 FEAT_CORE_CLK_DIV,
562 FEAT_LCD_CLK_SRC,
563 FEAT_DSI_DCS_CMD_CONFIG_VC,
564 FEAT_DSI_VC_OCP_WIDTH,
565 FEAT_DSI_GNQ,
566 FEAT_HDMI_CTS_SWMODE,
567 FEAT_HANDLE_UV_SEPARATE,
568 FEAT_ATTR2,
569 FEAT_CPR,
570 FEAT_PRELOAD,
571 FEAT_FIR_COEF_V,
572 FEAT_ALPHA_FREE_ZORDER,
573 FEAT_FIFO_MERGE,
574 FEAT_BURST_2D,
575};
576
577static const enum dss_feat_id omap4_dss_feat_list[] = {
578 FEAT_MGR_LCD2,
579 FEAT_CORE_CLK_DIV,
580 FEAT_LCD_CLK_SRC,
581 FEAT_DSI_DCS_CMD_CONFIG_VC,
582 FEAT_DSI_VC_OCP_WIDTH,
583 FEAT_DSI_GNQ,
584 FEAT_HDMI_CTS_SWMODE,
585 FEAT_HDMI_AUDIO_USE_MCLK,
586 FEAT_HANDLE_UV_SEPARATE,
587 FEAT_ATTR2,
588 FEAT_CPR,
589 FEAT_PRELOAD,
590 FEAT_FIR_COEF_V,
591 FEAT_ALPHA_FREE_ZORDER,
592 FEAT_FIFO_MERGE,
593 FEAT_BURST_2D,
594};
595
596static const enum dss_feat_id omap5_dss_feat_list[] = {
597 FEAT_MGR_LCD2,
598 FEAT_CORE_CLK_DIV,
599 FEAT_LCD_CLK_SRC,
600 FEAT_DSI_DCS_CMD_CONFIG_VC,
601 FEAT_DSI_VC_OCP_WIDTH,
602 FEAT_DSI_GNQ,
603 FEAT_HDMI_CTS_SWMODE,
604 FEAT_HDMI_AUDIO_USE_MCLK,
605 FEAT_HANDLE_UV_SEPARATE,
606 FEAT_ATTR2,
607 FEAT_CPR,
608 FEAT_PRELOAD,
609 FEAT_FIR_COEF_V,
610 FEAT_ALPHA_FREE_ZORDER,
611 FEAT_FIFO_MERGE,
612 FEAT_BURST_2D,
613 FEAT_DSI_PLL_SELFREQDCO,
614 FEAT_DSI_PLL_REFSEL,
615 FEAT_DSI_PHY_DCC,
616 FEAT_MFLAG,
617};
618
619/* OMAP2 DSS Features */
620static const struct omap_dss_features omap2_dss_features = {
621 .reg_fields = omap2_dss_reg_fields,
622 .num_reg_fields = ARRAY_SIZE(omap2_dss_reg_fields),
623
624 .features = omap2_dss_feat_list,
625 .num_features = ARRAY_SIZE(omap2_dss_feat_list),
626
627 .num_mgrs = 2,
628 .num_ovls = 3,
629 .supported_displays = omap2_dss_supported_displays,
630 .supported_outputs = omap2_dss_supported_outputs,
631 .supported_color_modes = omap2_dss_supported_color_modes,
632 .overlay_caps = omap2_dss_overlay_caps,
633 .clksrc_names = omap2_dss_clk_source_names,
634 .dss_params = omap2_dss_param_range,
635 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
636 .buffer_size_unit = 1,
637 .burst_size_unit = 8,
638};
639
640/* OMAP3 DSS Features */
641static const struct omap_dss_features omap3430_dss_features = {
642 .reg_fields = omap3_dss_reg_fields,
643 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
644
645 .features = omap3430_dss_feat_list,
646 .num_features = ARRAY_SIZE(omap3430_dss_feat_list),
647
648 .num_mgrs = 2,
649 .num_ovls = 3,
650 .supported_displays = omap3430_dss_supported_displays,
651 .supported_outputs = omap3430_dss_supported_outputs,
652 .supported_color_modes = omap3_dss_supported_color_modes,
653 .overlay_caps = omap3430_dss_overlay_caps,
654 .clksrc_names = omap3_dss_clk_source_names,
655 .dss_params = omap3_dss_param_range,
656 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
657 .buffer_size_unit = 1,
658 .burst_size_unit = 8,
659};
660
661/*
662 * AM35xx DSS Features. This is basically OMAP3 DSS Features without the
663 * vdds_dsi regulator.
664 */
665static const struct omap_dss_features am35xx_dss_features = {
666 .reg_fields = omap3_dss_reg_fields,
667 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
668
669 .features = am35xx_dss_feat_list,
670 .num_features = ARRAY_SIZE(am35xx_dss_feat_list),
671
672 .num_mgrs = 2,
673 .num_ovls = 3,
674 .supported_displays = omap3430_dss_supported_displays,
675 .supported_outputs = omap3430_dss_supported_outputs,
676 .supported_color_modes = omap3_dss_supported_color_modes,
677 .overlay_caps = omap3430_dss_overlay_caps,
678 .clksrc_names = omap3_dss_clk_source_names,
679 .dss_params = omap3_dss_param_range,
680 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
681 .buffer_size_unit = 1,
682 .burst_size_unit = 8,
683};
684
685static const struct omap_dss_features omap3630_dss_features = {
686 .reg_fields = omap3_dss_reg_fields,
687 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
688
689 .features = omap3630_dss_feat_list,
690 .num_features = ARRAY_SIZE(omap3630_dss_feat_list),
691
692 .num_mgrs = 2,
693 .num_ovls = 3,
694 .supported_displays = omap3630_dss_supported_displays,
695 .supported_outputs = omap3630_dss_supported_outputs,
696 .supported_color_modes = omap3_dss_supported_color_modes,
697 .overlay_caps = omap3630_dss_overlay_caps,
698 .clksrc_names = omap3_dss_clk_source_names,
699 .dss_params = omap3_dss_param_range,
700 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
701 .buffer_size_unit = 1,
702 .burst_size_unit = 8,
703};
704
705/* OMAP4 DSS Features */
706/* For OMAP4430 ES 1.0 revision */
707static const struct omap_dss_features omap4430_es1_0_dss_features = {
708 .reg_fields = omap4_dss_reg_fields,
709 .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
710
711 .features = omap4430_es1_0_dss_feat_list,
712 .num_features = ARRAY_SIZE(omap4430_es1_0_dss_feat_list),
713
714 .num_mgrs = 3,
715 .num_ovls = 4,
716 .num_wbs = 1,
717 .supported_displays = omap4_dss_supported_displays,
718 .supported_outputs = omap4_dss_supported_outputs,
719 .supported_color_modes = omap4_dss_supported_color_modes,
720 .overlay_caps = omap4_dss_overlay_caps,
721 .clksrc_names = omap4_dss_clk_source_names,
722 .dss_params = omap4_dss_param_range,
723 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
724 .buffer_size_unit = 16,
725 .burst_size_unit = 16,
726};
727
728/* For OMAP4430 ES 2.0, 2.1 and 2.2 revisions */
729static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = {
730 .reg_fields = omap4_dss_reg_fields,
731 .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
732
733 .features = omap4430_es2_0_1_2_dss_feat_list,
734 .num_features = ARRAY_SIZE(omap4430_es2_0_1_2_dss_feat_list),
735
736 .num_mgrs = 3,
737 .num_ovls = 4,
738 .num_wbs = 1,
739 .supported_displays = omap4_dss_supported_displays,
740 .supported_outputs = omap4_dss_supported_outputs,
741 .supported_color_modes = omap4_dss_supported_color_modes,
742 .overlay_caps = omap4_dss_overlay_caps,
743 .clksrc_names = omap4_dss_clk_source_names,
744 .dss_params = omap4_dss_param_range,
745 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
746 .buffer_size_unit = 16,
747 .burst_size_unit = 16,
748};
749
750/* For all the other OMAP4 versions */
751static const struct omap_dss_features omap4_dss_features = {
752 .reg_fields = omap4_dss_reg_fields,
753 .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
754
755 .features = omap4_dss_feat_list,
756 .num_features = ARRAY_SIZE(omap4_dss_feat_list),
757
758 .num_mgrs = 3,
759 .num_ovls = 4,
760 .num_wbs = 1,
761 .supported_displays = omap4_dss_supported_displays,
762 .supported_outputs = omap4_dss_supported_outputs,
763 .supported_color_modes = omap4_dss_supported_color_modes,
764 .overlay_caps = omap4_dss_overlay_caps,
765 .clksrc_names = omap4_dss_clk_source_names,
766 .dss_params = omap4_dss_param_range,
767 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
768 .buffer_size_unit = 16,
769 .burst_size_unit = 16,
770};
771
772/* OMAP5 DSS Features */
773static const struct omap_dss_features omap5_dss_features = {
774 .reg_fields = omap5_dss_reg_fields,
775 .num_reg_fields = ARRAY_SIZE(omap5_dss_reg_fields),
776
777 .features = omap5_dss_feat_list,
778 .num_features = ARRAY_SIZE(omap5_dss_feat_list),
779
780 .num_mgrs = 3,
781 .num_ovls = 4,
782 .supported_displays = omap5_dss_supported_displays,
783 .supported_outputs = omap5_dss_supported_outputs,
784 .supported_color_modes = omap4_dss_supported_color_modes,
785 .overlay_caps = omap4_dss_overlay_caps,
786 .clksrc_names = omap5_dss_clk_source_names,
787 .dss_params = omap5_dss_param_range,
788 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
789 .buffer_size_unit = 16,
790 .burst_size_unit = 16,
791};
792
793/* Functions returning values related to a DSS feature */
794int dss_feat_get_num_mgrs(void)
795{
796 return omap_current_dss_features->num_mgrs;
797}
798EXPORT_SYMBOL(dss_feat_get_num_mgrs);
799
800int dss_feat_get_num_ovls(void)
801{
802 return omap_current_dss_features->num_ovls;
803}
804EXPORT_SYMBOL(dss_feat_get_num_ovls);
805
806int dss_feat_get_num_wbs(void)
807{
808 return omap_current_dss_features->num_wbs;
809}
810
811unsigned long dss_feat_get_param_min(enum dss_range_param param)
812{
813 return omap_current_dss_features->dss_params[param].min;
814}
815
816unsigned long dss_feat_get_param_max(enum dss_range_param param)
817{
818 return omap_current_dss_features->dss_params[param].max;
819}
820
821enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel)
822{
823 return omap_current_dss_features->supported_displays[channel];
824}
825EXPORT_SYMBOL(dss_feat_get_supported_displays);
826
827enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel)
828{
829 return omap_current_dss_features->supported_outputs[channel];
830}
831EXPORT_SYMBOL(dss_feat_get_supported_outputs);
832
833enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
834{
835 return omap_current_dss_features->supported_color_modes[plane];
836}
837EXPORT_SYMBOL(dss_feat_get_supported_color_modes);
838
839enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane)
840{
841 return omap_current_dss_features->overlay_caps[plane];
842}
843
844bool dss_feat_color_mode_supported(enum omap_plane plane,
845 enum omap_color_mode color_mode)
846{
847 return omap_current_dss_features->supported_color_modes[plane] &
848 color_mode;
849}
850
851const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id)
852{
853 return omap_current_dss_features->clksrc_names[id];
854}
855
856u32 dss_feat_get_buffer_size_unit(void)
857{
858 return omap_current_dss_features->buffer_size_unit;
859}
860
861u32 dss_feat_get_burst_size_unit(void)
862{
863 return omap_current_dss_features->burst_size_unit;
864}
865
866/* DSS has_feature check */
867bool dss_has_feature(enum dss_feat_id id)
868{
869 int i;
870 const enum dss_feat_id *features = omap_current_dss_features->features;
871 const int num_features = omap_current_dss_features->num_features;
872
873 for (i = 0; i < num_features; i++) {
874 if (features[i] == id)
875 return true;
876 }
877
878 return false;
879}
880
881void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end)
882{
883 if (id >= omap_current_dss_features->num_reg_fields)
884 BUG();
885
886 *start = omap_current_dss_features->reg_fields[id].start;
887 *end = omap_current_dss_features->reg_fields[id].end;
888}
889
890bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type)
891{
892 return omap_current_dss_features->supported_rotation_types & rot_type;
893}
894
895void dss_features_init(enum omapdss_version version)
896{
897 switch (version) {
898 case OMAPDSS_VER_OMAP24xx:
899 omap_current_dss_features = &omap2_dss_features;
900 break;
901
902 case OMAPDSS_VER_OMAP34xx_ES1:
903 case OMAPDSS_VER_OMAP34xx_ES3:
904 omap_current_dss_features = &omap3430_dss_features;
905 break;
906
907 case OMAPDSS_VER_OMAP3630:
908 omap_current_dss_features = &omap3630_dss_features;
909 break;
910
911 case OMAPDSS_VER_OMAP4430_ES1:
912 omap_current_dss_features = &omap4430_es1_0_dss_features;
913 break;
914
915 case OMAPDSS_VER_OMAP4430_ES2:
916 omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;
917 break;
918
919 case OMAPDSS_VER_OMAP4:
920 omap_current_dss_features = &omap4_dss_features;
921 break;
922
923 case OMAPDSS_VER_OMAP5:
924 omap_current_dss_features = &omap5_dss_features;
925 break;
926
927 case OMAPDSS_VER_AM35xx:
928 omap_current_dss_features = &am35xx_dss_features;
929 break;
930
931 default:
932 DSSWARN("Unsupported OMAP version");
933 break;
934 }
935}
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
deleted file mode 100644
index e3ef3b714896..000000000000
--- a/drivers/video/omap2/dss/dss_features.h
+++ /dev/null
@@ -1,117 +0,0 @@
1/*
2 * linux/drivers/video/omap2/dss/dss_features.h
3 *
4 * Copyright (C) 2010 Texas Instruments
5 * Author: Archit Taneja <archit@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 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#ifndef __OMAP2_DSS_FEATURES_H
21#define __OMAP2_DSS_FEATURES_H
22
23#define MAX_DSS_MANAGERS 4
24#define MAX_DSS_OVERLAYS 4
25#define MAX_DSS_LCD_MANAGERS 3
26#define MAX_NUM_DSI 2
27
28/* DSS has feature id */
29enum dss_feat_id {
30 FEAT_LCDENABLEPOL,
31 FEAT_LCDENABLESIGNAL,
32 FEAT_PCKFREEENABLE,
33 FEAT_FUNCGATED,
34 FEAT_MGR_LCD2,
35 FEAT_MGR_LCD3,
36 FEAT_LINEBUFFERSPLIT,
37 FEAT_ROWREPEATENABLE,
38 FEAT_RESIZECONF,
39 /* Independent core clk divider */
40 FEAT_CORE_CLK_DIV,
41 FEAT_LCD_CLK_SRC,
42 /* DSI-PLL power command 0x3 is not working */
43 FEAT_DSI_PLL_PWR_BUG,
44 FEAT_DSI_PLL_FREQSEL,
45 FEAT_DSI_DCS_CMD_CONFIG_VC,
46 FEAT_DSI_VC_OCP_WIDTH,
47 FEAT_DSI_REVERSE_TXCLKESC,
48 FEAT_DSI_GNQ,
49 FEAT_DPI_USES_VDDS_DSI,
50 FEAT_HDMI_CTS_SWMODE,
51 FEAT_HDMI_AUDIO_USE_MCLK,
52 FEAT_HANDLE_UV_SEPARATE,
53 FEAT_ATTR2,
54 FEAT_VENC_REQUIRES_TV_DAC_CLK,
55 FEAT_CPR,
56 FEAT_PRELOAD,
57 FEAT_FIR_COEF_V,
58 FEAT_ALPHA_FIXED_ZORDER,
59 FEAT_ALPHA_FREE_ZORDER,
60 FEAT_FIFO_MERGE,
61 /* An unknown HW bug causing the normal FIFO thresholds not to work */
62 FEAT_OMAP3_DSI_FIFO_BUG,
63 FEAT_BURST_2D,
64 FEAT_DSI_PLL_SELFREQDCO,
65 FEAT_DSI_PLL_REFSEL,
66 FEAT_DSI_PHY_DCC,
67 FEAT_MFLAG,
68};
69
70/* DSS register field id */
71enum dss_feat_reg_field {
72 FEAT_REG_FIRHINC,
73 FEAT_REG_FIRVINC,
74 FEAT_REG_FIFOHIGHTHRESHOLD,
75 FEAT_REG_FIFOLOWTHRESHOLD,
76 FEAT_REG_FIFOSIZE,
77 FEAT_REG_HORIZONTALACCU,
78 FEAT_REG_VERTICALACCU,
79 FEAT_REG_DISPC_CLK_SWITCH,
80 FEAT_REG_DSIPLL_REGN,
81 FEAT_REG_DSIPLL_REGM,
82 FEAT_REG_DSIPLL_REGM_DISPC,
83 FEAT_REG_DSIPLL_REGM_DSI,
84};
85
86enum dss_range_param {
87 FEAT_PARAM_DSS_FCK,
88 FEAT_PARAM_DSS_PCD,
89 FEAT_PARAM_DSIPLL_REGN,
90 FEAT_PARAM_DSIPLL_REGM,
91 FEAT_PARAM_DSIPLL_REGM_DISPC,
92 FEAT_PARAM_DSIPLL_REGM_DSI,
93 FEAT_PARAM_DSIPLL_FINT,
94 FEAT_PARAM_DSIPLL_LPDIV,
95 FEAT_PARAM_DSI_FCK,
96 FEAT_PARAM_DOWNSCALE,
97 FEAT_PARAM_LINEWIDTH,
98};
99
100/* DSS Feature Functions */
101int dss_feat_get_num_wbs(void);
102unsigned long dss_feat_get_param_min(enum dss_range_param param);
103unsigned long dss_feat_get_param_max(enum dss_range_param param);
104enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane);
105bool dss_feat_color_mode_supported(enum omap_plane plane,
106 enum omap_color_mode color_mode);
107const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id);
108
109u32 dss_feat_get_buffer_size_unit(void); /* in bytes */
110u32 dss_feat_get_burst_size_unit(void); /* in bytes */
111
112bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type);
113
114bool dss_has_feature(enum dss_feat_id id);
115void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
116void dss_features_init(enum omapdss_version version);
117#endif
diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/hdmi.h
deleted file mode 100644
index e25681ff5a70..000000000000
--- a/drivers/video/omap2/dss/hdmi.h
+++ /dev/null
@@ -1,444 +0,0 @@
1/*
2 * HDMI driver definition for TI OMAP4 Processor.
3 *
4 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef _HDMI_H
20#define _HDMI_H
21
22#include <linux/delay.h>
23#include <linux/io.h>
24#include <linux/platform_device.h>
25#include <video/omapdss.h>
26
27#include "dss.h"
28
29/* HDMI Wrapper */
30
31#define HDMI_WP_REVISION 0x0
32#define HDMI_WP_SYSCONFIG 0x10
33#define HDMI_WP_IRQSTATUS_RAW 0x24
34#define HDMI_WP_IRQSTATUS 0x28
35#define HDMI_WP_IRQENABLE_SET 0x2C
36#define HDMI_WP_IRQENABLE_CLR 0x30
37#define HDMI_WP_IRQWAKEEN 0x34
38#define HDMI_WP_PWR_CTRL 0x40
39#define HDMI_WP_DEBOUNCE 0x44
40#define HDMI_WP_VIDEO_CFG 0x50
41#define HDMI_WP_VIDEO_SIZE 0x60
42#define HDMI_WP_VIDEO_TIMING_H 0x68
43#define HDMI_WP_VIDEO_TIMING_V 0x6C
44#define HDMI_WP_CLK 0x70
45#define HDMI_WP_AUDIO_CFG 0x80
46#define HDMI_WP_AUDIO_CFG2 0x84
47#define HDMI_WP_AUDIO_CTRL 0x88
48#define HDMI_WP_AUDIO_DATA 0x8C
49
50/* HDMI WP IRQ flags */
51#define HDMI_IRQ_CORE (1 << 0)
52#define HDMI_IRQ_OCP_TIMEOUT (1 << 4)
53#define HDMI_IRQ_AUDIO_FIFO_UNDERFLOW (1 << 8)
54#define HDMI_IRQ_AUDIO_FIFO_OVERFLOW (1 << 9)
55#define HDMI_IRQ_AUDIO_FIFO_SAMPLE_REQ (1 << 10)
56#define HDMI_IRQ_VIDEO_VSYNC (1 << 16)
57#define HDMI_IRQ_VIDEO_FRAME_DONE (1 << 17)
58#define HDMI_IRQ_PHY_LINE5V_ASSERT (1 << 24)
59#define HDMI_IRQ_LINK_CONNECT (1 << 25)
60#define HDMI_IRQ_LINK_DISCONNECT (1 << 26)
61#define HDMI_IRQ_PLL_LOCK (1 << 29)
62#define HDMI_IRQ_PLL_UNLOCK (1 << 30)
63#define HDMI_IRQ_PLL_RECAL (1 << 31)
64
65/* HDMI PLL */
66
67#define PLLCTRL_PLL_CONTROL 0x0
68#define PLLCTRL_PLL_STATUS 0x4
69#define PLLCTRL_PLL_GO 0x8
70#define PLLCTRL_CFG1 0xC
71#define PLLCTRL_CFG2 0x10
72#define PLLCTRL_CFG3 0x14
73#define PLLCTRL_SSC_CFG1 0x18
74#define PLLCTRL_SSC_CFG2 0x1C
75#define PLLCTRL_CFG4 0x20
76
77/* HDMI PHY */
78
79#define HDMI_TXPHY_TX_CTRL 0x0
80#define HDMI_TXPHY_DIGITAL_CTRL 0x4
81#define HDMI_TXPHY_POWER_CTRL 0x8
82#define HDMI_TXPHY_PAD_CFG_CTRL 0xC
83
84enum hdmi_pll_pwr {
85 HDMI_PLLPWRCMD_ALLOFF = 0,
86 HDMI_PLLPWRCMD_PLLONLY = 1,
87 HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2,
88 HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3
89};
90
91enum hdmi_phy_pwr {
92 HDMI_PHYPWRCMD_OFF = 0,
93 HDMI_PHYPWRCMD_LDOON = 1,
94 HDMI_PHYPWRCMD_TXON = 2
95};
96
97enum hdmi_core_hdmi_dvi {
98 HDMI_DVI = 0,
99 HDMI_HDMI = 1
100};
101
102enum hdmi_clk_refsel {
103 HDMI_REFSEL_PCLK = 0,
104 HDMI_REFSEL_REF1 = 1,
105 HDMI_REFSEL_REF2 = 2,
106 HDMI_REFSEL_SYSCLK = 3
107};
108
109enum hdmi_packing_mode {
110 HDMI_PACK_10b_RGB_YUV444 = 0,
111 HDMI_PACK_24b_RGB_YUV444_YUV422 = 1,
112 HDMI_PACK_20b_YUV422 = 2,
113 HDMI_PACK_ALREADYPACKED = 7
114};
115
116enum hdmi_stereo_channels {
117 HDMI_AUDIO_STEREO_NOCHANNELS = 0,
118 HDMI_AUDIO_STEREO_ONECHANNEL = 1,
119 HDMI_AUDIO_STEREO_TWOCHANNELS = 2,
120 HDMI_AUDIO_STEREO_THREECHANNELS = 3,
121 HDMI_AUDIO_STEREO_FOURCHANNELS = 4
122};
123
124enum hdmi_audio_type {
125 HDMI_AUDIO_TYPE_LPCM = 0,
126 HDMI_AUDIO_TYPE_IEC = 1
127};
128
129enum hdmi_audio_justify {
130 HDMI_AUDIO_JUSTIFY_LEFT = 0,
131 HDMI_AUDIO_JUSTIFY_RIGHT = 1
132};
133
134enum hdmi_audio_sample_order {
135 HDMI_AUDIO_SAMPLE_RIGHT_FIRST = 0,
136 HDMI_AUDIO_SAMPLE_LEFT_FIRST = 1
137};
138
139enum hdmi_audio_samples_perword {
140 HDMI_AUDIO_ONEWORD_ONESAMPLE = 0,
141 HDMI_AUDIO_ONEWORD_TWOSAMPLES = 1
142};
143
144enum hdmi_audio_sample_size {
145 HDMI_AUDIO_SAMPLE_16BITS = 0,
146 HDMI_AUDIO_SAMPLE_24BITS = 1
147};
148
149enum hdmi_audio_transf_mode {
150 HDMI_AUDIO_TRANSF_DMA = 0,
151 HDMI_AUDIO_TRANSF_IRQ = 1
152};
153
154enum hdmi_audio_blk_strt_end_sig {
155 HDMI_AUDIO_BLOCK_SIG_STARTEND_ON = 0,
156 HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF = 1
157};
158
159enum hdmi_core_audio_layout {
160 HDMI_AUDIO_LAYOUT_2CH = 0,
161 HDMI_AUDIO_LAYOUT_8CH = 1
162};
163
164enum hdmi_core_cts_mode {
165 HDMI_AUDIO_CTS_MODE_HW = 0,
166 HDMI_AUDIO_CTS_MODE_SW = 1
167};
168
169enum hdmi_audio_mclk_mode {
170 HDMI_AUDIO_MCLK_128FS = 0,
171 HDMI_AUDIO_MCLK_256FS = 1,
172 HDMI_AUDIO_MCLK_384FS = 2,
173 HDMI_AUDIO_MCLK_512FS = 3,
174 HDMI_AUDIO_MCLK_768FS = 4,
175 HDMI_AUDIO_MCLK_1024FS = 5,
176 HDMI_AUDIO_MCLK_1152FS = 6,
177 HDMI_AUDIO_MCLK_192FS = 7
178};
179
180/* INFOFRAME_AVI_ and INFOFRAME_AUDIO_ definitions */
181enum hdmi_core_infoframe {
182 HDMI_INFOFRAME_AVI_DB1Y_RGB = 0,
183 HDMI_INFOFRAME_AVI_DB1Y_YUV422 = 1,
184 HDMI_INFOFRAME_AVI_DB1Y_YUV444 = 2,
185 HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF = 0,
186 HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_ON = 1,
187 HDMI_INFOFRAME_AVI_DB1B_NO = 0,
188 HDMI_INFOFRAME_AVI_DB1B_VERT = 1,
189 HDMI_INFOFRAME_AVI_DB1B_HORI = 2,
190 HDMI_INFOFRAME_AVI_DB1B_VERTHORI = 3,
191 HDMI_INFOFRAME_AVI_DB1S_0 = 0,
192 HDMI_INFOFRAME_AVI_DB1S_1 = 1,
193 HDMI_INFOFRAME_AVI_DB1S_2 = 2,
194 HDMI_INFOFRAME_AVI_DB2C_NO = 0,
195 HDMI_INFOFRAME_AVI_DB2C_ITU601 = 1,
196 HDMI_INFOFRAME_AVI_DB2C_ITU709 = 2,
197 HDMI_INFOFRAME_AVI_DB2C_EC_EXTENDED = 3,
198 HDMI_INFOFRAME_AVI_DB2M_NO = 0,
199 HDMI_INFOFRAME_AVI_DB2M_43 = 1,
200 HDMI_INFOFRAME_AVI_DB2M_169 = 2,
201 HDMI_INFOFRAME_AVI_DB2R_SAME = 8,
202 HDMI_INFOFRAME_AVI_DB2R_43 = 9,
203 HDMI_INFOFRAME_AVI_DB2R_169 = 10,
204 HDMI_INFOFRAME_AVI_DB2R_149 = 11,
205 HDMI_INFOFRAME_AVI_DB3ITC_NO = 0,
206 HDMI_INFOFRAME_AVI_DB3ITC_YES = 1,
207 HDMI_INFOFRAME_AVI_DB3EC_XVYUV601 = 0,
208 HDMI_INFOFRAME_AVI_DB3EC_XVYUV709 = 1,
209 HDMI_INFOFRAME_AVI_DB3Q_DEFAULT = 0,
210 HDMI_INFOFRAME_AVI_DB3Q_LR = 1,
211 HDMI_INFOFRAME_AVI_DB3Q_FR = 2,
212 HDMI_INFOFRAME_AVI_DB3SC_NO = 0,
213 HDMI_INFOFRAME_AVI_DB3SC_HORI = 1,
214 HDMI_INFOFRAME_AVI_DB3SC_VERT = 2,
215 HDMI_INFOFRAME_AVI_DB3SC_HORIVERT = 3,
216 HDMI_INFOFRAME_AVI_DB5PR_NO = 0,
217 HDMI_INFOFRAME_AVI_DB5PR_2 = 1,
218 HDMI_INFOFRAME_AVI_DB5PR_3 = 2,
219 HDMI_INFOFRAME_AVI_DB5PR_4 = 3,
220 HDMI_INFOFRAME_AVI_DB5PR_5 = 4,
221 HDMI_INFOFRAME_AVI_DB5PR_6 = 5,
222 HDMI_INFOFRAME_AVI_DB5PR_7 = 6,
223 HDMI_INFOFRAME_AVI_DB5PR_8 = 7,
224 HDMI_INFOFRAME_AVI_DB5PR_9 = 8,
225 HDMI_INFOFRAME_AVI_DB5PR_10 = 9,
226};
227
228struct hdmi_cm {
229 int code;
230 int mode;
231};
232
233struct hdmi_video_format {
234 enum hdmi_packing_mode packing_mode;
235 u32 y_res; /* Line per panel */
236 u32 x_res; /* pixel per line */
237};
238
239struct hdmi_config {
240 struct omap_video_timings timings;
241 struct hdmi_cm cm;
242};
243
244/* HDMI PLL structure */
245struct hdmi_pll_info {
246 u16 regn;
247 u16 regm;
248 u32 regmf;
249 u16 regm2;
250 u16 regsd;
251 u16 dcofreq;
252 enum hdmi_clk_refsel refsel;
253};
254
255struct hdmi_audio_format {
256 enum hdmi_stereo_channels stereo_channels;
257 u8 active_chnnls_msk;
258 enum hdmi_audio_type type;
259 enum hdmi_audio_justify justification;
260 enum hdmi_audio_sample_order sample_order;
261 enum hdmi_audio_samples_perword samples_per_word;
262 enum hdmi_audio_sample_size sample_size;
263 enum hdmi_audio_blk_strt_end_sig en_sig_blk_strt_end;
264};
265
266struct hdmi_audio_dma {
267 u8 transfer_size;
268 u8 block_size;
269 enum hdmi_audio_transf_mode mode;
270 u16 fifo_threshold;
271};
272
273struct hdmi_core_audio_i2s_config {
274 u8 in_length_bits;
275 u8 justification;
276 u8 sck_edge_mode;
277 u8 vbit;
278 u8 direction;
279 u8 shift;
280 u8 active_sds;
281};
282
283struct hdmi_core_audio_config {
284 struct hdmi_core_audio_i2s_config i2s_cfg;
285 struct snd_aes_iec958 *iec60958_cfg;
286 bool fs_override;
287 u32 n;
288 u32 cts;
289 u32 aud_par_busclk;
290 enum hdmi_core_audio_layout layout;
291 enum hdmi_core_cts_mode cts_mode;
292 bool use_mclk;
293 enum hdmi_audio_mclk_mode mclk_mode;
294 bool en_acr_pkt;
295 bool en_dsd_audio;
296 bool en_parallel_aud_input;
297 bool en_spdif;
298};
299
300/*
301 * Refer to section 8.2 in HDMI 1.3 specification for
302 * details about infoframe databytes
303 */
304struct hdmi_core_infoframe_avi {
305 /* Y0, Y1 rgb,yCbCr */
306 u8 db1_format;
307 /* A0 Active information Present */
308 u8 db1_active_info;
309 /* B0, B1 Bar info data valid */
310 u8 db1_bar_info_dv;
311 /* S0, S1 scan information */
312 u8 db1_scan_info;
313 /* C0, C1 colorimetry */
314 u8 db2_colorimetry;
315 /* M0, M1 Aspect ratio (4:3, 16:9) */
316 u8 db2_aspect_ratio;
317 /* R0...R3 Active format aspect ratio */
318 u8 db2_active_fmt_ar;
319 /* ITC IT content. */
320 u8 db3_itc;
321 /* EC0, EC1, EC2 Extended colorimetry */
322 u8 db3_ec;
323 /* Q1, Q0 Quantization range */
324 u8 db3_q_range;
325 /* SC1, SC0 Non-uniform picture scaling */
326 u8 db3_nup_scaling;
327 /* VIC0..6 Video format identification */
328 u8 db4_videocode;
329 /* PR0..PR3 Pixel repetition factor */
330 u8 db5_pixel_repeat;
331 /* Line number end of top bar */
332 u16 db6_7_line_eoftop;
333 /* Line number start of bottom bar */
334 u16 db8_9_line_sofbottom;
335 /* Pixel number end of left bar */
336 u16 db10_11_pixel_eofleft;
337 /* Pixel number start of right bar */
338 u16 db12_13_pixel_sofright;
339};
340
341struct hdmi_wp_data {
342 void __iomem *base;
343};
344
345struct hdmi_pll_data {
346 void __iomem *base;
347
348 struct hdmi_pll_info info;
349};
350
351struct hdmi_phy_data {
352 void __iomem *base;
353
354 int irq;
355};
356
357struct hdmi_core_data {
358 void __iomem *base;
359
360 struct hdmi_core_infoframe_avi avi_cfg;
361};
362
363static inline void hdmi_write_reg(void __iomem *base_addr, const u16 idx,
364 u32 val)
365{
366 __raw_writel(val, base_addr + idx);
367}
368
369static inline u32 hdmi_read_reg(void __iomem *base_addr, const u16 idx)
370{
371 return __raw_readl(base_addr + idx);
372}
373
374#define REG_FLD_MOD(base, idx, val, start, end) \
375 hdmi_write_reg(base, idx, FLD_MOD(hdmi_read_reg(base, idx),\
376 val, start, end))
377#define REG_GET(base, idx, start, end) \
378 FLD_GET(hdmi_read_reg(base, idx), start, end)
379
380static inline int hdmi_wait_for_bit_change(void __iomem *base_addr,
381 const u32 idx, int b2, int b1, u32 val)
382{
383 u32 t = 0, v;
384 while (val != (v = REG_GET(base_addr, idx, b2, b1))) {
385 if (t++ > 10000)
386 return v;
387 udelay(1);
388 }
389 return v;
390}
391
392/* HDMI wrapper funcs */
393int hdmi_wp_video_start(struct hdmi_wp_data *wp);
394void hdmi_wp_video_stop(struct hdmi_wp_data *wp);
395void hdmi_wp_dump(struct hdmi_wp_data *wp, struct seq_file *s);
396u32 hdmi_wp_get_irqstatus(struct hdmi_wp_data *wp);
397void hdmi_wp_set_irqstatus(struct hdmi_wp_data *wp, u32 irqstatus);
398void hdmi_wp_set_irqenable(struct hdmi_wp_data *wp, u32 mask);
399void hdmi_wp_clear_irqenable(struct hdmi_wp_data *wp, u32 mask);
400int hdmi_wp_set_phy_pwr(struct hdmi_wp_data *wp, enum hdmi_phy_pwr val);
401int hdmi_wp_set_pll_pwr(struct hdmi_wp_data *wp, enum hdmi_pll_pwr val);
402void hdmi_wp_video_config_format(struct hdmi_wp_data *wp,
403 struct hdmi_video_format *video_fmt);
404void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp,
405 struct omap_video_timings *timings);
406void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
407 struct omap_video_timings *timings);
408void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
409 struct omap_video_timings *timings, struct hdmi_config *param);
410int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp);
411
412/* HDMI PLL funcs */
413int hdmi_pll_enable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp);
414void hdmi_pll_disable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp);
415void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s);
416void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy);
417int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll);
418
419/* HDMI PHY funcs */
420int hdmi_phy_enable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp,
421 struct hdmi_config *cfg);
422void hdmi_phy_disable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp);
423void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s);
424int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy);
425
426/* HDMI common funcs */
427const struct hdmi_config *hdmi_default_timing(void);
428const struct hdmi_config *hdmi_get_timings(int mode, int code);
429struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing);
430
431#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
432int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts);
433int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable);
434int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable);
435void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,
436 struct hdmi_audio_format *aud_fmt);
437void hdmi_wp_audio_config_dma(struct hdmi_wp_data *wp,
438 struct hdmi_audio_dma *aud_dma);
439static inline bool hdmi_mode_has_audio(int mode)
440{
441 return mode == HDMI_HDMI ? true : false;
442}
443#endif
444#endif
diff --git a/drivers/video/omap2/dss/hdmi4.c b/drivers/video/omap2/dss/hdmi4.c
deleted file mode 100644
index f5f7944a1fd1..000000000000
--- a/drivers/video/omap2/dss/hdmi4.c
+++ /dev/null
@@ -1,703 +0,0 @@
1/*
2 * HDMI interface DSS driver for TI's OMAP4 family of SoCs.
3 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
4 * Authors: Yong Zhi
5 * Mythri pk <mythripk@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 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#define DSS_SUBSYS_NAME "HDMI"
21
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/err.h>
25#include <linux/io.h>
26#include <linux/interrupt.h>
27#include <linux/mutex.h>
28#include <linux/delay.h>
29#include <linux/string.h>
30#include <linux/platform_device.h>
31#include <linux/pm_runtime.h>
32#include <linux/clk.h>
33#include <linux/gpio.h>
34#include <linux/regulator/consumer.h>
35#include <video/omapdss.h>
36
37#include "hdmi4_core.h"
38#include "dss.h"
39#include "dss_features.h"
40
41static struct {
42 struct mutex lock;
43 struct platform_device *pdev;
44
45 struct hdmi_wp_data wp;
46 struct hdmi_pll_data pll;
47 struct hdmi_phy_data phy;
48 struct hdmi_core_data core;
49
50 struct hdmi_config cfg;
51
52 struct clk *sys_clk;
53 struct regulator *vdda_hdmi_dac_reg;
54
55 bool core_enabled;
56
57 struct omap_dss_device output;
58} hdmi;
59
60static int hdmi_runtime_get(void)
61{
62 int r;
63
64 DSSDBG("hdmi_runtime_get\n");
65
66 r = pm_runtime_get_sync(&hdmi.pdev->dev);
67 WARN_ON(r < 0);
68 if (r < 0)
69 return r;
70
71 return 0;
72}
73
74static void hdmi_runtime_put(void)
75{
76 int r;
77
78 DSSDBG("hdmi_runtime_put\n");
79
80 r = pm_runtime_put_sync(&hdmi.pdev->dev);
81 WARN_ON(r < 0 && r != -ENOSYS);
82}
83
84static int hdmi_init_regulator(void)
85{
86 struct regulator *reg;
87
88 if (hdmi.vdda_hdmi_dac_reg != NULL)
89 return 0;
90
91 reg = devm_regulator_get(&hdmi.pdev->dev, "vdda");
92
93 if (IS_ERR(reg)) {
94 if (PTR_ERR(reg) != -EPROBE_DEFER)
95 DSSERR("can't get VDDA regulator\n");
96 return PTR_ERR(reg);
97 }
98
99 hdmi.vdda_hdmi_dac_reg = reg;
100
101 return 0;
102}
103
104static int hdmi_power_on_core(struct omap_dss_device *dssdev)
105{
106 int r;
107
108 r = regulator_enable(hdmi.vdda_hdmi_dac_reg);
109 if (r)
110 return r;
111
112 r = hdmi_runtime_get();
113 if (r)
114 goto err_runtime_get;
115
116 /* Make selection of HDMI in DSS */
117 dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
118
119 hdmi.core_enabled = true;
120
121 return 0;
122
123err_runtime_get:
124 regulator_disable(hdmi.vdda_hdmi_dac_reg);
125
126 return r;
127}
128
129static void hdmi_power_off_core(struct omap_dss_device *dssdev)
130{
131 hdmi.core_enabled = false;
132
133 hdmi_runtime_put();
134 regulator_disable(hdmi.vdda_hdmi_dac_reg);
135}
136
137static int hdmi_power_on_full(struct omap_dss_device *dssdev)
138{
139 int r;
140 struct omap_video_timings *p;
141 struct omap_overlay_manager *mgr = hdmi.output.manager;
142 unsigned long phy;
143
144 r = hdmi_power_on_core(dssdev);
145 if (r)
146 return r;
147
148 p = &hdmi.cfg.timings;
149
150 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
151
152 /* the functions below use kHz pixel clock. TODO: change to Hz */
153 phy = p->pixelclock / 1000;
154
155 hdmi_pll_compute(&hdmi.pll, clk_get_rate(hdmi.sys_clk), phy);
156
157 /* config the PLL and PHY hdmi_set_pll_pwrfirst */
158 r = hdmi_pll_enable(&hdmi.pll, &hdmi.wp);
159 if (r) {
160 DSSDBG("Failed to lock PLL\n");
161 goto err_pll_enable;
162 }
163
164 r = hdmi_phy_enable(&hdmi.phy, &hdmi.wp, &hdmi.cfg);
165 if (r) {
166 DSSDBG("Failed to start PHY\n");
167 goto err_phy_enable;
168 }
169
170 hdmi4_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg);
171
172 /* bypass TV gamma table */
173 dispc_enable_gamma_table(0);
174
175 /* tv size */
176 dss_mgr_set_timings(mgr, p);
177
178 r = hdmi_wp_video_start(&hdmi.wp);
179 if (r)
180 goto err_vid_enable;
181
182 r = dss_mgr_enable(mgr);
183 if (r)
184 goto err_mgr_enable;
185
186 return 0;
187
188err_mgr_enable:
189 hdmi_wp_video_stop(&hdmi.wp);
190err_vid_enable:
191 hdmi_phy_disable(&hdmi.phy, &hdmi.wp);
192err_phy_enable:
193 hdmi_pll_disable(&hdmi.pll, &hdmi.wp);
194err_pll_enable:
195 hdmi_power_off_core(dssdev);
196 return -EIO;
197}
198
199static void hdmi_power_off_full(struct omap_dss_device *dssdev)
200{
201 struct omap_overlay_manager *mgr = hdmi.output.manager;
202
203 dss_mgr_disable(mgr);
204
205 hdmi_wp_video_stop(&hdmi.wp);
206 hdmi_phy_disable(&hdmi.phy, &hdmi.wp);
207 hdmi_pll_disable(&hdmi.pll, &hdmi.wp);
208
209 hdmi_power_off_core(dssdev);
210}
211
212static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
213 struct omap_video_timings *timings)
214{
215 struct omap_dss_device *out = &hdmi.output;
216
217 if (!dispc_mgr_timings_ok(out->dispc_channel, timings))
218 return -EINVAL;
219
220 return 0;
221}
222
223static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
224 struct omap_video_timings *timings)
225{
226 struct hdmi_cm cm;
227 const struct hdmi_config *t;
228
229 mutex_lock(&hdmi.lock);
230
231 cm = hdmi_get_code(timings);
232 hdmi.cfg.cm = cm;
233
234 t = hdmi_get_timings(cm.mode, cm.code);
235 if (t != NULL) {
236 hdmi.cfg = *t;
237
238 dispc_set_tv_pclk(t->timings.pixelclock);
239 } else {
240 hdmi.cfg.timings = *timings;
241 hdmi.cfg.cm.code = 0;
242 hdmi.cfg.cm.mode = HDMI_DVI;
243
244 dispc_set_tv_pclk(timings->pixelclock);
245 }
246
247 DSSDBG("using mode: %s, code %d\n", hdmi.cfg.cm.mode == HDMI_DVI ?
248 "DVI" : "HDMI", hdmi.cfg.cm.code);
249
250 mutex_unlock(&hdmi.lock);
251}
252
253static void hdmi_display_get_timings(struct omap_dss_device *dssdev,
254 struct omap_video_timings *timings)
255{
256 const struct hdmi_config *cfg;
257 struct hdmi_cm cm = hdmi.cfg.cm;
258
259 cfg = hdmi_get_timings(cm.mode, cm.code);
260 if (cfg == NULL)
261 cfg = hdmi_default_timing();
262
263 memcpy(timings, &cfg->timings, sizeof(cfg->timings));
264}
265
266static void hdmi_dump_regs(struct seq_file *s)
267{
268 mutex_lock(&hdmi.lock);
269
270 if (hdmi_runtime_get()) {
271 mutex_unlock(&hdmi.lock);
272 return;
273 }
274
275 hdmi_wp_dump(&hdmi.wp, s);
276 hdmi_pll_dump(&hdmi.pll, s);
277 hdmi_phy_dump(&hdmi.phy, s);
278 hdmi4_core_dump(&hdmi.core, s);
279
280 hdmi_runtime_put();
281 mutex_unlock(&hdmi.lock);
282}
283
284static int read_edid(u8 *buf, int len)
285{
286 int r;
287
288 mutex_lock(&hdmi.lock);
289
290 r = hdmi_runtime_get();
291 BUG_ON(r);
292
293 r = hdmi4_read_edid(&hdmi.core, buf, len);
294
295 hdmi_runtime_put();
296 mutex_unlock(&hdmi.lock);
297
298 return r;
299}
300
301static int hdmi_display_enable(struct omap_dss_device *dssdev)
302{
303 struct omap_dss_device *out = &hdmi.output;
304 int r = 0;
305
306 DSSDBG("ENTER hdmi_display_enable\n");
307
308 mutex_lock(&hdmi.lock);
309
310 if (out == NULL || out->manager == NULL) {
311 DSSERR("failed to enable display: no output/manager\n");
312 r = -ENODEV;
313 goto err0;
314 }
315
316 r = hdmi_power_on_full(dssdev);
317 if (r) {
318 DSSERR("failed to power on device\n");
319 goto err0;
320 }
321
322 mutex_unlock(&hdmi.lock);
323 return 0;
324
325err0:
326 mutex_unlock(&hdmi.lock);
327 return r;
328}
329
330static void hdmi_display_disable(struct omap_dss_device *dssdev)
331{
332 DSSDBG("Enter hdmi_display_disable\n");
333
334 mutex_lock(&hdmi.lock);
335
336 hdmi_power_off_full(dssdev);
337
338 mutex_unlock(&hdmi.lock);
339}
340
341static int hdmi_core_enable(struct omap_dss_device *dssdev)
342{
343 int r = 0;
344
345 DSSDBG("ENTER omapdss_hdmi_core_enable\n");
346
347 mutex_lock(&hdmi.lock);
348
349 r = hdmi_power_on_core(dssdev);
350 if (r) {
351 DSSERR("failed to power on device\n");
352 goto err0;
353 }
354
355 mutex_unlock(&hdmi.lock);
356 return 0;
357
358err0:
359 mutex_unlock(&hdmi.lock);
360 return r;
361}
362
363static void hdmi_core_disable(struct omap_dss_device *dssdev)
364{
365 DSSDBG("Enter omapdss_hdmi_core_disable\n");
366
367 mutex_lock(&hdmi.lock);
368
369 hdmi_power_off_core(dssdev);
370
371 mutex_unlock(&hdmi.lock);
372}
373
374static int hdmi_get_clocks(struct platform_device *pdev)
375{
376 struct clk *clk;
377
378 clk = devm_clk_get(&pdev->dev, "sys_clk");
379 if (IS_ERR(clk)) {
380 DSSERR("can't get sys_clk\n");
381 return PTR_ERR(clk);
382 }
383
384 hdmi.sys_clk = clk;
385
386 return 0;
387}
388
389static int hdmi_connect(struct omap_dss_device *dssdev,
390 struct omap_dss_device *dst)
391{
392 struct omap_overlay_manager *mgr;
393 int r;
394
395 r = hdmi_init_regulator();
396 if (r)
397 return r;
398
399 mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
400 if (!mgr)
401 return -ENODEV;
402
403 r = dss_mgr_connect(mgr, dssdev);
404 if (r)
405 return r;
406
407 r = omapdss_output_set_device(dssdev, dst);
408 if (r) {
409 DSSERR("failed to connect output to new device: %s\n",
410 dst->name);
411 dss_mgr_disconnect(mgr, dssdev);
412 return r;
413 }
414
415 return 0;
416}
417
418static void hdmi_disconnect(struct omap_dss_device *dssdev,
419 struct omap_dss_device *dst)
420{
421 WARN_ON(dst != dssdev->dst);
422
423 if (dst != dssdev->dst)
424 return;
425
426 omapdss_output_unset_device(dssdev);
427
428 if (dssdev->manager)
429 dss_mgr_disconnect(dssdev->manager, dssdev);
430}
431
432static int hdmi_read_edid(struct omap_dss_device *dssdev,
433 u8 *edid, int len)
434{
435 bool need_enable;
436 int r;
437
438 need_enable = hdmi.core_enabled == false;
439
440 if (need_enable) {
441 r = hdmi_core_enable(dssdev);
442 if (r)
443 return r;
444 }
445
446 r = read_edid(edid, len);
447
448 if (need_enable)
449 hdmi_core_disable(dssdev);
450
451 return r;
452}
453
454#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
455static int hdmi_audio_enable(struct omap_dss_device *dssdev)
456{
457 int r;
458
459 mutex_lock(&hdmi.lock);
460
461 if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) {
462 r = -EPERM;
463 goto err;
464 }
465
466 r = hdmi_wp_audio_enable(&hdmi.wp, true);
467 if (r)
468 goto err;
469
470 mutex_unlock(&hdmi.lock);
471 return 0;
472
473err:
474 mutex_unlock(&hdmi.lock);
475 return r;
476}
477
478static void hdmi_audio_disable(struct omap_dss_device *dssdev)
479{
480 hdmi_wp_audio_enable(&hdmi.wp, false);
481}
482
483static int hdmi_audio_start(struct omap_dss_device *dssdev)
484{
485 return hdmi4_audio_start(&hdmi.core, &hdmi.wp);
486}
487
488static void hdmi_audio_stop(struct omap_dss_device *dssdev)
489{
490 hdmi4_audio_stop(&hdmi.core, &hdmi.wp);
491}
492
493static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
494{
495 bool r;
496
497 mutex_lock(&hdmi.lock);
498
499 r = hdmi_mode_has_audio(hdmi.cfg.cm.mode);
500
501 mutex_unlock(&hdmi.lock);
502 return r;
503}
504
505static int hdmi_audio_config(struct omap_dss_device *dssdev,
506 struct omap_dss_audio *audio)
507{
508 int r;
509 u32 pclk = hdmi.cfg.timings.pixelclock;
510
511 mutex_lock(&hdmi.lock);
512
513 if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) {
514 r = -EPERM;
515 goto err;
516 }
517
518 r = hdmi4_audio_config(&hdmi.core, &hdmi.wp, audio, pclk);
519 if (r)
520 goto err;
521
522 mutex_unlock(&hdmi.lock);
523 return 0;
524
525err:
526 mutex_unlock(&hdmi.lock);
527 return r;
528}
529#else
530static int hdmi_audio_enable(struct omap_dss_device *dssdev)
531{
532 return -EPERM;
533}
534
535static void hdmi_audio_disable(struct omap_dss_device *dssdev)
536{
537}
538
539static int hdmi_audio_start(struct omap_dss_device *dssdev)
540{
541 return -EPERM;
542}
543
544static void hdmi_audio_stop(struct omap_dss_device *dssdev)
545{
546}
547
548static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
549{
550 return false;
551}
552
553static int hdmi_audio_config(struct omap_dss_device *dssdev,
554 struct omap_dss_audio *audio)
555{
556 return -EPERM;
557}
558#endif
559
560static const struct omapdss_hdmi_ops hdmi_ops = {
561 .connect = hdmi_connect,
562 .disconnect = hdmi_disconnect,
563
564 .enable = hdmi_display_enable,
565 .disable = hdmi_display_disable,
566
567 .check_timings = hdmi_display_check_timing,
568 .set_timings = hdmi_display_set_timing,
569 .get_timings = hdmi_display_get_timings,
570
571 .read_edid = hdmi_read_edid,
572
573 .audio_enable = hdmi_audio_enable,
574 .audio_disable = hdmi_audio_disable,
575 .audio_start = hdmi_audio_start,
576 .audio_stop = hdmi_audio_stop,
577 .audio_supported = hdmi_audio_supported,
578 .audio_config = hdmi_audio_config,
579};
580
581static void hdmi_init_output(struct platform_device *pdev)
582{
583 struct omap_dss_device *out = &hdmi.output;
584
585 out->dev = &pdev->dev;
586 out->id = OMAP_DSS_OUTPUT_HDMI;
587 out->output_type = OMAP_DISPLAY_TYPE_HDMI;
588 out->name = "hdmi.0";
589 out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
590 out->ops.hdmi = &hdmi_ops;
591 out->owner = THIS_MODULE;
592
593 omapdss_register_output(out);
594}
595
596static void __exit hdmi_uninit_output(struct platform_device *pdev)
597{
598 struct omap_dss_device *out = &hdmi.output;
599
600 omapdss_unregister_output(out);
601}
602
603/* HDMI HW IP initialisation */
604static int omapdss_hdmihw_probe(struct platform_device *pdev)
605{
606 int r;
607
608 hdmi.pdev = pdev;
609
610 mutex_init(&hdmi.lock);
611
612 r = hdmi_wp_init(pdev, &hdmi.wp);
613 if (r)
614 return r;
615
616 r = hdmi_pll_init(pdev, &hdmi.pll);
617 if (r)
618 return r;
619
620 r = hdmi_phy_init(pdev, &hdmi.phy);
621 if (r)
622 return r;
623
624 r = hdmi4_core_init(pdev, &hdmi.core);
625 if (r)
626 return r;
627
628 r = hdmi_get_clocks(pdev);
629 if (r) {
630 DSSERR("can't get clocks\n");
631 return r;
632 }
633
634 pm_runtime_enable(&pdev->dev);
635
636 hdmi_init_output(pdev);
637
638 dss_debugfs_create_file("hdmi", hdmi_dump_regs);
639
640 return 0;
641}
642
643static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
644{
645 hdmi_uninit_output(pdev);
646
647 pm_runtime_disable(&pdev->dev);
648
649 return 0;
650}
651
652static int hdmi_runtime_suspend(struct device *dev)
653{
654 clk_disable_unprepare(hdmi.sys_clk);
655
656 dispc_runtime_put();
657
658 return 0;
659}
660
661static int hdmi_runtime_resume(struct device *dev)
662{
663 int r;
664
665 r = dispc_runtime_get();
666 if (r < 0)
667 return r;
668
669 clk_prepare_enable(hdmi.sys_clk);
670
671 return 0;
672}
673
674static const struct dev_pm_ops hdmi_pm_ops = {
675 .runtime_suspend = hdmi_runtime_suspend,
676 .runtime_resume = hdmi_runtime_resume,
677};
678
679static const struct of_device_id hdmi_of_match[] = {
680 { .compatible = "ti,omap4-hdmi", },
681 {},
682};
683
684static struct platform_driver omapdss_hdmihw_driver = {
685 .probe = omapdss_hdmihw_probe,
686 .remove = __exit_p(omapdss_hdmihw_remove),
687 .driver = {
688 .name = "omapdss_hdmi",
689 .owner = THIS_MODULE,
690 .pm = &hdmi_pm_ops,
691 .of_match_table = hdmi_of_match,
692 },
693};
694
695int __init hdmi4_init_platform_driver(void)
696{
697 return platform_driver_register(&omapdss_hdmihw_driver);
698}
699
700void __exit hdmi4_uninit_platform_driver(void)
701{
702 platform_driver_unregister(&omapdss_hdmihw_driver);
703}
diff --git a/drivers/video/omap2/dss/hdmi4_core.c b/drivers/video/omap2/dss/hdmi4_core.c
deleted file mode 100644
index 2eb04dcf807c..000000000000
--- a/drivers/video/omap2/dss/hdmi4_core.c
+++ /dev/null
@@ -1,1036 +0,0 @@
1/*
2 * ti_hdmi_4xxx_ip.c
3 *
4 * HDMI TI81xx, TI38xx, TI OMAP4 etc IP driver Library
5 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
6 * Authors: Yong Zhi
7 * Mythri pk <mythripk@ti.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published by
11 * the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#define DSS_SUBSYS_NAME "HDMICORE"
23
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/err.h>
27#include <linux/io.h>
28#include <linux/interrupt.h>
29#include <linux/mutex.h>
30#include <linux/delay.h>
31#include <linux/platform_device.h>
32#include <linux/string.h>
33#include <linux/seq_file.h>
34#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
35#include <sound/asound.h>
36#include <sound/asoundef.h>
37#endif
38
39#include "hdmi4_core.h"
40#include "dss_features.h"
41
42#define HDMI_CORE_AV 0x500
43
44static inline void __iomem *hdmi_av_base(struct hdmi_core_data *core)
45{
46 return core->base + HDMI_CORE_AV;
47}
48
49static int hdmi_core_ddc_init(struct hdmi_core_data *core)
50{
51 void __iomem *base = core->base;
52
53 /* Turn on CLK for DDC */
54 REG_FLD_MOD(base, HDMI_CORE_AV_DPD, 0x7, 2, 0);
55
56 /* IN_PROG */
57 if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 1) {
58 /* Abort transaction */
59 REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xf, 3, 0);
60 /* IN_PROG */
61 if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
62 4, 4, 0) != 0) {
63 DSSERR("Timeout aborting DDC transaction\n");
64 return -ETIMEDOUT;
65 }
66 }
67
68 /* Clk SCL Devices */
69 REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xA, 3, 0);
70
71 /* HDMI_CORE_DDC_STATUS_IN_PROG */
72 if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
73 4, 4, 0) != 0) {
74 DSSERR("Timeout starting SCL clock\n");
75 return -ETIMEDOUT;
76 }
77
78 /* Clear FIFO */
79 REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x9, 3, 0);
80
81 /* HDMI_CORE_DDC_STATUS_IN_PROG */
82 if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
83 4, 4, 0) != 0) {
84 DSSERR("Timeout clearing DDC fifo\n");
85 return -ETIMEDOUT;
86 }
87
88 return 0;
89}
90
91static int hdmi_core_ddc_edid(struct hdmi_core_data *core,
92 u8 *pedid, int ext)
93{
94 void __iomem *base = core->base;
95 u32 i;
96 char checksum;
97 u32 offset = 0;
98
99 /* HDMI_CORE_DDC_STATUS_IN_PROG */
100 if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
101 4, 4, 0) != 0) {
102 DSSERR("Timeout waiting DDC to be ready\n");
103 return -ETIMEDOUT;
104 }
105
106 if (ext % 2 != 0)
107 offset = 0x80;
108
109 /* Load Segment Address Register */
110 REG_FLD_MOD(base, HDMI_CORE_DDC_SEGM, ext / 2, 7, 0);
111
112 /* Load Slave Address Register */
113 REG_FLD_MOD(base, HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1);
114
115 /* Load Offset Address Register */
116 REG_FLD_MOD(base, HDMI_CORE_DDC_OFFSET, offset, 7, 0);
117
118 /* Load Byte Count */
119 REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT1, 0x80, 7, 0);
120 REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT2, 0x0, 1, 0);
121
122 /* Set DDC_CMD */
123 if (ext)
124 REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x4, 3, 0);
125 else
126 REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x2, 3, 0);
127
128 /* HDMI_CORE_DDC_STATUS_BUS_LOW */
129 if (REG_GET(base, HDMI_CORE_DDC_STATUS, 6, 6) == 1) {
130 DSSERR("I2C Bus Low?\n");
131 return -EIO;
132 }
133 /* HDMI_CORE_DDC_STATUS_NO_ACK */
134 if (REG_GET(base, HDMI_CORE_DDC_STATUS, 5, 5) == 1) {
135 DSSERR("I2C No Ack\n");
136 return -EIO;
137 }
138
139 for (i = 0; i < 0x80; ++i) {
140 int t;
141
142 /* IN_PROG */
143 if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 0) {
144 DSSERR("operation stopped when reading edid\n");
145 return -EIO;
146 }
147
148 t = 0;
149 /* FIFO_EMPTY */
150 while (REG_GET(base, HDMI_CORE_DDC_STATUS, 2, 2) == 1) {
151 if (t++ > 10000) {
152 DSSERR("timeout reading edid\n");
153 return -ETIMEDOUT;
154 }
155 udelay(1);
156 }
157
158 pedid[i] = REG_GET(base, HDMI_CORE_DDC_DATA, 7, 0);
159 }
160
161 checksum = 0;
162 for (i = 0; i < 0x80; ++i)
163 checksum += pedid[i];
164
165 if (checksum != 0) {
166 DSSERR("E-EDID checksum failed!!\n");
167 return -EIO;
168 }
169
170 return 0;
171}
172
173int hdmi4_read_edid(struct hdmi_core_data *core, u8 *edid, int len)
174{
175 int r, l;
176
177 if (len < 128)
178 return -EINVAL;
179
180 r = hdmi_core_ddc_init(core);
181 if (r)
182 return r;
183
184 r = hdmi_core_ddc_edid(core, edid, 0);
185 if (r)
186 return r;
187
188 l = 128;
189
190 if (len >= 128 * 2 && edid[0x7e] > 0) {
191 r = hdmi_core_ddc_edid(core, edid + 0x80, 1);
192 if (r)
193 return r;
194 l += 128;
195 }
196
197 return l;
198}
199
200static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
201 struct hdmi_core_infoframe_avi *avi_cfg,
202 struct hdmi_core_packet_enable_repeat *repeat_cfg)
203{
204 DSSDBG("Enter hdmi_core_init\n");
205
206 /* video core */
207 video_cfg->ip_bus_width = HDMI_INPUT_8BIT;
208 video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT;
209 video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE;
210 video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE;
211 video_cfg->hdmi_dvi = HDMI_DVI;
212 video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK;
213
214 /* info frame */
215 avi_cfg->db1_format = 0;
216 avi_cfg->db1_active_info = 0;
217 avi_cfg->db1_bar_info_dv = 0;
218 avi_cfg->db1_scan_info = 0;
219 avi_cfg->db2_colorimetry = 0;
220 avi_cfg->db2_aspect_ratio = 0;
221 avi_cfg->db2_active_fmt_ar = 0;
222 avi_cfg->db3_itc = 0;
223 avi_cfg->db3_ec = 0;
224 avi_cfg->db3_q_range = 0;
225 avi_cfg->db3_nup_scaling = 0;
226 avi_cfg->db4_videocode = 0;
227 avi_cfg->db5_pixel_repeat = 0;
228 avi_cfg->db6_7_line_eoftop = 0;
229 avi_cfg->db8_9_line_sofbottom = 0;
230 avi_cfg->db10_11_pixel_eofleft = 0;
231 avi_cfg->db12_13_pixel_sofright = 0;
232
233 /* packet enable and repeat */
234 repeat_cfg->audio_pkt = 0;
235 repeat_cfg->audio_pkt_repeat = 0;
236 repeat_cfg->avi_infoframe = 0;
237 repeat_cfg->avi_infoframe_repeat = 0;
238 repeat_cfg->gen_cntrl_pkt = 0;
239 repeat_cfg->gen_cntrl_pkt_repeat = 0;
240 repeat_cfg->generic_pkt = 0;
241 repeat_cfg->generic_pkt_repeat = 0;
242}
243
244static void hdmi_core_powerdown_disable(struct hdmi_core_data *core)
245{
246 DSSDBG("Enter hdmi_core_powerdown_disable\n");
247 REG_FLD_MOD(core->base, HDMI_CORE_SYS_SYS_CTRL1, 0x0, 0, 0);
248}
249
250static void hdmi_core_swreset_release(struct hdmi_core_data *core)
251{
252 DSSDBG("Enter hdmi_core_swreset_release\n");
253 REG_FLD_MOD(core->base, HDMI_CORE_SYS_SRST, 0x0, 0, 0);
254}
255
256static void hdmi_core_swreset_assert(struct hdmi_core_data *core)
257{
258 DSSDBG("Enter hdmi_core_swreset_assert\n");
259 REG_FLD_MOD(core->base, HDMI_CORE_SYS_SRST, 0x1, 0, 0);
260}
261
262/* HDMI_CORE_VIDEO_CONFIG */
263static void hdmi_core_video_config(struct hdmi_core_data *core,
264 struct hdmi_core_video_config *cfg)
265{
266 u32 r = 0;
267 void __iomem *core_sys_base = core->base;
268 void __iomem *core_av_base = hdmi_av_base(core);
269
270 /* sys_ctrl1 default configuration not tunable */
271 r = hdmi_read_reg(core_sys_base, HDMI_CORE_SYS_SYS_CTRL1);
272 r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_VEN_FOLLOWVSYNC, 5, 5);
273 r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_HEN_FOLLOWHSYNC, 4, 4);
274 r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_BSEL_24BITBUS, 2, 2);
275 r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_EDGE_RISINGEDGE, 1, 1);
276 hdmi_write_reg(core_sys_base, HDMI_CORE_SYS_SYS_CTRL1, r);
277
278 REG_FLD_MOD(core_sys_base,
279 HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6);
280
281 /* Vid_Mode */
282 r = hdmi_read_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE);
283
284 /* dither truncation configuration */
285 if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) {
286 r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6);
287 r = FLD_MOD(r, 1, 5, 5);
288 } else {
289 r = FLD_MOD(r, cfg->op_dither_truc, 7, 6);
290 r = FLD_MOD(r, 0, 5, 5);
291 }
292 hdmi_write_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE, r);
293
294 /* HDMI_Ctrl */
295 r = hdmi_read_reg(core_av_base, HDMI_CORE_AV_HDMI_CTRL);
296 r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6);
297 r = FLD_MOD(r, cfg->pkt_mode, 5, 3);
298 r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0);
299 hdmi_write_reg(core_av_base, HDMI_CORE_AV_HDMI_CTRL, r);
300
301 /* TMDS_CTRL */
302 REG_FLD_MOD(core_sys_base,
303 HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5);
304}
305
306static void hdmi_core_aux_infoframe_avi_config(struct hdmi_core_data *core)
307{
308 u32 val;
309 char sum = 0, checksum = 0;
310 void __iomem *av_base = hdmi_av_base(core);
311 struct hdmi_core_infoframe_avi info_avi = core->avi_cfg;
312
313 sum += 0x82 + 0x002 + 0x00D;
314 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_TYPE, 0x082);
315 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_VERS, 0x002);
316 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_LEN, 0x00D);
317
318 val = (info_avi.db1_format << 5) |
319 (info_avi.db1_active_info << 4) |
320 (info_avi.db1_bar_info_dv << 2) |
321 (info_avi.db1_scan_info);
322 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(0), val);
323 sum += val;
324
325 val = (info_avi.db2_colorimetry << 6) |
326 (info_avi.db2_aspect_ratio << 4) |
327 (info_avi.db2_active_fmt_ar);
328 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(1), val);
329 sum += val;
330
331 val = (info_avi.db3_itc << 7) |
332 (info_avi.db3_ec << 4) |
333 (info_avi.db3_q_range << 2) |
334 (info_avi.db3_nup_scaling);
335 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(2), val);
336 sum += val;
337
338 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(3),
339 info_avi.db4_videocode);
340 sum += info_avi.db4_videocode;
341
342 val = info_avi.db5_pixel_repeat;
343 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(4), val);
344 sum += val;
345
346 val = info_avi.db6_7_line_eoftop & 0x00FF;
347 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(5), val);
348 sum += val;
349
350 val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF);
351 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(6), val);
352 sum += val;
353
354 val = info_avi.db8_9_line_sofbottom & 0x00FF;
355 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(7), val);
356 sum += val;
357
358 val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF);
359 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(8), val);
360 sum += val;
361
362 val = info_avi.db10_11_pixel_eofleft & 0x00FF;
363 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(9), val);
364 sum += val;
365
366 val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF);
367 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(10), val);
368 sum += val;
369
370 val = info_avi.db12_13_pixel_sofright & 0x00FF;
371 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(11), val);
372 sum += val;
373
374 val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF);
375 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(12), val);
376 sum += val;
377
378 checksum = 0x100 - sum;
379 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_CHSUM, checksum);
380}
381
382static void hdmi_core_av_packet_config(struct hdmi_core_data *core,
383 struct hdmi_core_packet_enable_repeat repeat_cfg)
384{
385 /* enable/repeat the infoframe */
386 hdmi_write_reg(hdmi_av_base(core), HDMI_CORE_AV_PB_CTRL1,
387 (repeat_cfg.audio_pkt << 5) |
388 (repeat_cfg.audio_pkt_repeat << 4) |
389 (repeat_cfg.avi_infoframe << 1) |
390 (repeat_cfg.avi_infoframe_repeat));
391
392 /* enable/repeat the packet */
393 hdmi_write_reg(hdmi_av_base(core), HDMI_CORE_AV_PB_CTRL2,
394 (repeat_cfg.gen_cntrl_pkt << 3) |
395 (repeat_cfg.gen_cntrl_pkt_repeat << 2) |
396 (repeat_cfg.generic_pkt << 1) |
397 (repeat_cfg.generic_pkt_repeat));
398}
399
400void hdmi4_configure(struct hdmi_core_data *core,
401 struct hdmi_wp_data *wp, struct hdmi_config *cfg)
402{
403 /* HDMI */
404 struct omap_video_timings video_timing;
405 struct hdmi_video_format video_format;
406 /* HDMI core */
407 struct hdmi_core_infoframe_avi *avi_cfg = &core->avi_cfg;
408 struct hdmi_core_video_config v_core_cfg;
409 struct hdmi_core_packet_enable_repeat repeat_cfg;
410
411 hdmi_core_init(&v_core_cfg, avi_cfg, &repeat_cfg);
412
413 hdmi_wp_init_vid_fmt_timings(&video_format, &video_timing, cfg);
414
415 hdmi_wp_video_config_timing(wp, &video_timing);
416
417 /* video config */
418 video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422;
419
420 hdmi_wp_video_config_format(wp, &video_format);
421
422 hdmi_wp_video_config_interface(wp, &video_timing);
423
424 /*
425 * configure core video part
426 * set software reset in the core
427 */
428 hdmi_core_swreset_assert(core);
429
430 /* power down off */
431 hdmi_core_powerdown_disable(core);
432
433 v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL;
434 v_core_cfg.hdmi_dvi = cfg->cm.mode;
435
436 hdmi_core_video_config(core, &v_core_cfg);
437
438 /* release software reset in the core */
439 hdmi_core_swreset_release(core);
440
441 /*
442 * configure packet
443 * info frame video see doc CEA861-D page 65
444 */
445 avi_cfg->db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB;
446 avi_cfg->db1_active_info =
447 HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF;
448 avi_cfg->db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO;
449 avi_cfg->db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0;
450 avi_cfg->db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO;
451 avi_cfg->db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO;
452 avi_cfg->db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME;
453 avi_cfg->db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO;
454 avi_cfg->db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601;
455 avi_cfg->db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT;
456 avi_cfg->db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO;
457 avi_cfg->db4_videocode = cfg->cm.code;
458 avi_cfg->db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO;
459 avi_cfg->db6_7_line_eoftop = 0;
460 avi_cfg->db8_9_line_sofbottom = 0;
461 avi_cfg->db10_11_pixel_eofleft = 0;
462 avi_cfg->db12_13_pixel_sofright = 0;
463
464 hdmi_core_aux_infoframe_avi_config(core);
465
466 /* enable/repeat the infoframe */
467 repeat_cfg.avi_infoframe = HDMI_PACKETENABLE;
468 repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON;
469 /* wakeup */
470 repeat_cfg.audio_pkt = HDMI_PACKETENABLE;
471 repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON;
472 hdmi_core_av_packet_config(core, repeat_cfg);
473}
474
475void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s)
476{
477 int i;
478
479#define CORE_REG(i, name) name(i)
480#define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\
481 hdmi_read_reg(core->base, r))
482#define DUMPCOREAV(r) seq_printf(s, "%-35s %08x\n", #r,\
483 hdmi_read_reg(hdmi_av_base(core), r))
484#define DUMPCOREAV2(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \
485 (i < 10) ? 32 - (int)strlen(#r) : 31 - (int)strlen(#r), " ", \
486 hdmi_read_reg(hdmi_av_base(core), CORE_REG(i, r)))
487
488 DUMPCORE(HDMI_CORE_SYS_VND_IDL);
489 DUMPCORE(HDMI_CORE_SYS_DEV_IDL);
490 DUMPCORE(HDMI_CORE_SYS_DEV_IDH);
491 DUMPCORE(HDMI_CORE_SYS_DEV_REV);
492 DUMPCORE(HDMI_CORE_SYS_SRST);
493 DUMPCORE(HDMI_CORE_SYS_SYS_CTRL1);
494 DUMPCORE(HDMI_CORE_SYS_SYS_STAT);
495 DUMPCORE(HDMI_CORE_SYS_SYS_CTRL3);
496 DUMPCORE(HDMI_CORE_SYS_DE_DLY);
497 DUMPCORE(HDMI_CORE_SYS_DE_CTRL);
498 DUMPCORE(HDMI_CORE_SYS_DE_TOP);
499 DUMPCORE(HDMI_CORE_SYS_DE_CNTL);
500 DUMPCORE(HDMI_CORE_SYS_DE_CNTH);
501 DUMPCORE(HDMI_CORE_SYS_DE_LINL);
502 DUMPCORE(HDMI_CORE_SYS_DE_LINH_1);
503 DUMPCORE(HDMI_CORE_SYS_HRES_L);
504 DUMPCORE(HDMI_CORE_SYS_HRES_H);
505 DUMPCORE(HDMI_CORE_SYS_VRES_L);
506 DUMPCORE(HDMI_CORE_SYS_VRES_H);
507 DUMPCORE(HDMI_CORE_SYS_IADJUST);
508 DUMPCORE(HDMI_CORE_SYS_POLDETECT);
509 DUMPCORE(HDMI_CORE_SYS_HWIDTH1);
510 DUMPCORE(HDMI_CORE_SYS_HWIDTH2);
511 DUMPCORE(HDMI_CORE_SYS_VWIDTH);
512 DUMPCORE(HDMI_CORE_SYS_VID_CTRL);
513 DUMPCORE(HDMI_CORE_SYS_VID_ACEN);
514 DUMPCORE(HDMI_CORE_SYS_VID_MODE);
515 DUMPCORE(HDMI_CORE_SYS_VID_BLANK1);
516 DUMPCORE(HDMI_CORE_SYS_VID_BLANK3);
517 DUMPCORE(HDMI_CORE_SYS_VID_BLANK1);
518 DUMPCORE(HDMI_CORE_SYS_DC_HEADER);
519 DUMPCORE(HDMI_CORE_SYS_VID_DITHER);
520 DUMPCORE(HDMI_CORE_SYS_RGB2XVYCC_CT);
521 DUMPCORE(HDMI_CORE_SYS_R2Y_COEFF_LOW);
522 DUMPCORE(HDMI_CORE_SYS_R2Y_COEFF_UP);
523 DUMPCORE(HDMI_CORE_SYS_G2Y_COEFF_LOW);
524 DUMPCORE(HDMI_CORE_SYS_G2Y_COEFF_UP);
525 DUMPCORE(HDMI_CORE_SYS_B2Y_COEFF_LOW);
526 DUMPCORE(HDMI_CORE_SYS_B2Y_COEFF_UP);
527 DUMPCORE(HDMI_CORE_SYS_R2CB_COEFF_LOW);
528 DUMPCORE(HDMI_CORE_SYS_R2CB_COEFF_UP);
529 DUMPCORE(HDMI_CORE_SYS_G2CB_COEFF_LOW);
530 DUMPCORE(HDMI_CORE_SYS_G2CB_COEFF_UP);
531 DUMPCORE(HDMI_CORE_SYS_B2CB_COEFF_LOW);
532 DUMPCORE(HDMI_CORE_SYS_B2CB_COEFF_UP);
533 DUMPCORE(HDMI_CORE_SYS_R2CR_COEFF_LOW);
534 DUMPCORE(HDMI_CORE_SYS_R2CR_COEFF_UP);
535 DUMPCORE(HDMI_CORE_SYS_G2CR_COEFF_LOW);
536 DUMPCORE(HDMI_CORE_SYS_G2CR_COEFF_UP);
537 DUMPCORE(HDMI_CORE_SYS_B2CR_COEFF_LOW);
538 DUMPCORE(HDMI_CORE_SYS_B2CR_COEFF_UP);
539 DUMPCORE(HDMI_CORE_SYS_RGB_OFFSET_LOW);
540 DUMPCORE(HDMI_CORE_SYS_RGB_OFFSET_UP);
541 DUMPCORE(HDMI_CORE_SYS_Y_OFFSET_LOW);
542 DUMPCORE(HDMI_CORE_SYS_Y_OFFSET_UP);
543 DUMPCORE(HDMI_CORE_SYS_CBCR_OFFSET_LOW);
544 DUMPCORE(HDMI_CORE_SYS_CBCR_OFFSET_UP);
545 DUMPCORE(HDMI_CORE_SYS_INTR_STATE);
546 DUMPCORE(HDMI_CORE_SYS_INTR1);
547 DUMPCORE(HDMI_CORE_SYS_INTR2);
548 DUMPCORE(HDMI_CORE_SYS_INTR3);
549 DUMPCORE(HDMI_CORE_SYS_INTR4);
550 DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK1);
551 DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK2);
552 DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK3);
553 DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK4);
554 DUMPCORE(HDMI_CORE_SYS_INTR_CTRL);
555 DUMPCORE(HDMI_CORE_SYS_TMDS_CTRL);
556
557 DUMPCORE(HDMI_CORE_DDC_ADDR);
558 DUMPCORE(HDMI_CORE_DDC_SEGM);
559 DUMPCORE(HDMI_CORE_DDC_OFFSET);
560 DUMPCORE(HDMI_CORE_DDC_COUNT1);
561 DUMPCORE(HDMI_CORE_DDC_COUNT2);
562 DUMPCORE(HDMI_CORE_DDC_STATUS);
563 DUMPCORE(HDMI_CORE_DDC_CMD);
564 DUMPCORE(HDMI_CORE_DDC_DATA);
565
566 DUMPCOREAV(HDMI_CORE_AV_ACR_CTRL);
567 DUMPCOREAV(HDMI_CORE_AV_FREQ_SVAL);
568 DUMPCOREAV(HDMI_CORE_AV_N_SVAL1);
569 DUMPCOREAV(HDMI_CORE_AV_N_SVAL2);
570 DUMPCOREAV(HDMI_CORE_AV_N_SVAL3);
571 DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL1);
572 DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL2);
573 DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL3);
574 DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL1);
575 DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL2);
576 DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL3);
577 DUMPCOREAV(HDMI_CORE_AV_AUD_MODE);
578 DUMPCOREAV(HDMI_CORE_AV_SPDIF_CTRL);
579 DUMPCOREAV(HDMI_CORE_AV_HW_SPDIF_FS);
580 DUMPCOREAV(HDMI_CORE_AV_SWAP_I2S);
581 DUMPCOREAV(HDMI_CORE_AV_SPDIF_ERTH);
582 DUMPCOREAV(HDMI_CORE_AV_I2S_IN_MAP);
583 DUMPCOREAV(HDMI_CORE_AV_I2S_IN_CTRL);
584 DUMPCOREAV(HDMI_CORE_AV_I2S_CHST0);
585 DUMPCOREAV(HDMI_CORE_AV_I2S_CHST1);
586 DUMPCOREAV(HDMI_CORE_AV_I2S_CHST2);
587 DUMPCOREAV(HDMI_CORE_AV_I2S_CHST4);
588 DUMPCOREAV(HDMI_CORE_AV_I2S_CHST5);
589 DUMPCOREAV(HDMI_CORE_AV_ASRC);
590 DUMPCOREAV(HDMI_CORE_AV_I2S_IN_LEN);
591 DUMPCOREAV(HDMI_CORE_AV_HDMI_CTRL);
592 DUMPCOREAV(HDMI_CORE_AV_AUDO_TXSTAT);
593 DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_1);
594 DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_2);
595 DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_3);
596 DUMPCOREAV(HDMI_CORE_AV_TEST_TXCTRL);
597 DUMPCOREAV(HDMI_CORE_AV_DPD);
598 DUMPCOREAV(HDMI_CORE_AV_PB_CTRL1);
599 DUMPCOREAV(HDMI_CORE_AV_PB_CTRL2);
600 DUMPCOREAV(HDMI_CORE_AV_AVI_TYPE);
601 DUMPCOREAV(HDMI_CORE_AV_AVI_VERS);
602 DUMPCOREAV(HDMI_CORE_AV_AVI_LEN);
603 DUMPCOREAV(HDMI_CORE_AV_AVI_CHSUM);
604
605 for (i = 0; i < HDMI_CORE_AV_AVI_DBYTE_NELEMS; i++)
606 DUMPCOREAV2(i, HDMI_CORE_AV_AVI_DBYTE);
607
608 DUMPCOREAV(HDMI_CORE_AV_SPD_TYPE);
609 DUMPCOREAV(HDMI_CORE_AV_SPD_VERS);
610 DUMPCOREAV(HDMI_CORE_AV_SPD_LEN);
611 DUMPCOREAV(HDMI_CORE_AV_SPD_CHSUM);
612
613 for (i = 0; i < HDMI_CORE_AV_SPD_DBYTE_NELEMS; i++)
614 DUMPCOREAV2(i, HDMI_CORE_AV_SPD_DBYTE);
615
616 DUMPCOREAV(HDMI_CORE_AV_AUDIO_TYPE);
617 DUMPCOREAV(HDMI_CORE_AV_AUDIO_VERS);
618 DUMPCOREAV(HDMI_CORE_AV_AUDIO_LEN);
619 DUMPCOREAV(HDMI_CORE_AV_AUDIO_CHSUM);
620
621 for (i = 0; i < HDMI_CORE_AV_AUD_DBYTE_NELEMS; i++)
622 DUMPCOREAV2(i, HDMI_CORE_AV_AUD_DBYTE);
623
624 DUMPCOREAV(HDMI_CORE_AV_MPEG_TYPE);
625 DUMPCOREAV(HDMI_CORE_AV_MPEG_VERS);
626 DUMPCOREAV(HDMI_CORE_AV_MPEG_LEN);
627 DUMPCOREAV(HDMI_CORE_AV_MPEG_CHSUM);
628
629 for (i = 0; i < HDMI_CORE_AV_MPEG_DBYTE_NELEMS; i++)
630 DUMPCOREAV2(i, HDMI_CORE_AV_MPEG_DBYTE);
631
632 for (i = 0; i < HDMI_CORE_AV_GEN_DBYTE_NELEMS; i++)
633 DUMPCOREAV2(i, HDMI_CORE_AV_GEN_DBYTE);
634
635 DUMPCOREAV(HDMI_CORE_AV_CP_BYTE1);
636
637 for (i = 0; i < HDMI_CORE_AV_GEN2_DBYTE_NELEMS; i++)
638 DUMPCOREAV2(i, HDMI_CORE_AV_GEN2_DBYTE);
639
640 DUMPCOREAV(HDMI_CORE_AV_CEC_ADDR_ID);
641}
642
643#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
644static void hdmi_core_audio_config(struct hdmi_core_data *core,
645 struct hdmi_core_audio_config *cfg)
646{
647 u32 r;
648 void __iomem *av_base = hdmi_av_base(core);
649
650 /*
651 * Parameters for generation of Audio Clock Recovery packets
652 */
653 REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0);
654 REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0);
655 REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0);
656
657 if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) {
658 REG_FLD_MOD(av_base, HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0);
659 REG_FLD_MOD(av_base,
660 HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0);
661 REG_FLD_MOD(av_base,
662 HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0);
663 } else {
664 REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_1,
665 cfg->aud_par_busclk, 7, 0);
666 REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_2,
667 (cfg->aud_par_busclk >> 8), 7, 0);
668 REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_3,
669 (cfg->aud_par_busclk >> 16), 7, 0);
670 }
671
672 /* Set ACR clock divisor */
673 REG_FLD_MOD(av_base,
674 HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0);
675
676 r = hdmi_read_reg(av_base, HDMI_CORE_AV_ACR_CTRL);
677 /*
678 * Use TMDS clock for ACR packets. For devices that use
679 * the MCLK, this is the first part of the MCLK initialization.
680 */
681 r = FLD_MOD(r, 0, 2, 2);
682
683 r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1);
684 r = FLD_MOD(r, cfg->cts_mode, 0, 0);
685 hdmi_write_reg(av_base, HDMI_CORE_AV_ACR_CTRL, r);
686
687 /* For devices using MCLK, this completes its initialization. */
688 if (cfg->use_mclk)
689 REG_FLD_MOD(av_base, HDMI_CORE_AV_ACR_CTRL, 1, 2, 2);
690
691 /* Override of SPDIF sample frequency with value in I2S_CHST4 */
692 REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL,
693 cfg->fs_override, 1, 1);
694
695 /*
696 * Set IEC-60958-3 channel status word. It is passed to the IP
697 * just as it is received. The user of the driver is responsible
698 * for its contents.
699 */
700 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST0,
701 cfg->iec60958_cfg->status[0]);
702 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST1,
703 cfg->iec60958_cfg->status[1]);
704 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST2,
705 cfg->iec60958_cfg->status[2]);
706 /* yes, this is correct: status[3] goes to CHST4 register */
707 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST4,
708 cfg->iec60958_cfg->status[3]);
709 /* yes, this is correct: status[4] goes to CHST5 register */
710 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST5,
711 cfg->iec60958_cfg->status[4]);
712
713 /* set I2S parameters */
714 r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL);
715 r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6);
716 r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4);
717 r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2);
718 r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1);
719 r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0);
720 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL, r);
721
722 REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_IN_LEN,
723 cfg->i2s_cfg.in_length_bits, 3, 0);
724
725 /* Audio channels and mode parameters */
726 REG_FLD_MOD(av_base, HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1);
727 r = hdmi_read_reg(av_base, HDMI_CORE_AV_AUD_MODE);
728 r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4);
729 r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3);
730 r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2);
731 r = FLD_MOD(r, cfg->en_spdif, 1, 1);
732 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_MODE, r);
733
734 /* Audio channel mappings */
735 /* TODO: Make channel mapping dynamic. For now, map channels
736 * in the ALSA order: FL/FR/RL/RR/C/LFE/SL/SR. Remapping is needed as
737 * HDMI speaker order is different. See CEA-861 Section 6.6.2.
738 */
739 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_MAP, 0x78);
740 REG_FLD_MOD(av_base, HDMI_CORE_AV_SWAP_I2S, 1, 5, 5);
741}
742
743static void hdmi_core_audio_infoframe_cfg(struct hdmi_core_data *core,
744 struct snd_cea_861_aud_if *info_aud)
745{
746 u8 sum = 0, checksum = 0;
747 void __iomem *av_base = hdmi_av_base(core);
748
749 /*
750 * Set audio info frame type, version and length as
751 * described in HDMI 1.4a Section 8.2.2 specification.
752 * Checksum calculation is defined in Section 5.3.5.
753 */
754 hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_TYPE, 0x84);
755 hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_VERS, 0x01);
756 hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_LEN, 0x0a);
757 sum += 0x84 + 0x001 + 0x00a;
758
759 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(0),
760 info_aud->db1_ct_cc);
761 sum += info_aud->db1_ct_cc;
762
763 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(1),
764 info_aud->db2_sf_ss);
765 sum += info_aud->db2_sf_ss;
766
767 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), info_aud->db3);
768 sum += info_aud->db3;
769
770 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), info_aud->db4_ca);
771 sum += info_aud->db4_ca;
772
773 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(4),
774 info_aud->db5_dminh_lsv);
775 sum += info_aud->db5_dminh_lsv;
776
777 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(5), 0x00);
778 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(6), 0x00);
779 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(7), 0x00);
780 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(8), 0x00);
781 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(9), 0x00);
782
783 checksum = 0x100 - sum;
784 hdmi_write_reg(av_base,
785 HDMI_CORE_AV_AUDIO_CHSUM, checksum);
786
787 /*
788 * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing
789 * is available.
790 */
791}
792
793int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
794 struct omap_dss_audio *audio, u32 pclk)
795{
796 struct hdmi_audio_format audio_format;
797 struct hdmi_audio_dma audio_dma;
798 struct hdmi_core_audio_config acore;
799 int err, n, cts, channel_count;
800 unsigned int fs_nr;
801 bool word_length_16b = false;
802
803 if (!audio || !audio->iec || !audio->cea || !core)
804 return -EINVAL;
805
806 acore.iec60958_cfg = audio->iec;
807 /*
808 * In the IEC-60958 status word, check if the audio sample word length
809 * is 16-bit as several optimizations can be performed in such case.
810 */
811 if (!(audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24))
812 if (audio->iec->status[4] & IEC958_AES4_CON_WORDLEN_20_16)
813 word_length_16b = true;
814
815 /* I2S configuration. See Phillips' specification */
816 if (word_length_16b)
817 acore.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT;
818 else
819 acore.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
820 /*
821 * The I2S input word length is twice the lenght given in the IEC-60958
822 * status word. If the word size is greater than
823 * 20 bits, increment by one.
824 */
825 acore.i2s_cfg.in_length_bits = audio->iec->status[4]
826 & IEC958_AES4_CON_WORDLEN;
827 if (audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24)
828 acore.i2s_cfg.in_length_bits++;
829 acore.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING;
830 acore.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM;
831 acore.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST;
832 acore.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT;
833
834 /* convert sample frequency to a number */
835 switch (audio->iec->status[3] & IEC958_AES3_CON_FS) {
836 case IEC958_AES3_CON_FS_32000:
837 fs_nr = 32000;
838 break;
839 case IEC958_AES3_CON_FS_44100:
840 fs_nr = 44100;
841 break;
842 case IEC958_AES3_CON_FS_48000:
843 fs_nr = 48000;
844 break;
845 case IEC958_AES3_CON_FS_88200:
846 fs_nr = 88200;
847 break;
848 case IEC958_AES3_CON_FS_96000:
849 fs_nr = 96000;
850 break;
851 case IEC958_AES3_CON_FS_176400:
852 fs_nr = 176400;
853 break;
854 case IEC958_AES3_CON_FS_192000:
855 fs_nr = 192000;
856 break;
857 default:
858 return -EINVAL;
859 }
860
861 err = hdmi_compute_acr(pclk, fs_nr, &n, &cts);
862
863 /* Audio clock regeneration settings */
864 acore.n = n;
865 acore.cts = cts;
866 if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) {
867 acore.aud_par_busclk = 0;
868 acore.cts_mode = HDMI_AUDIO_CTS_MODE_SW;
869 acore.use_mclk = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK);
870 } else {
871 acore.aud_par_busclk = (((128 * 31) - 1) << 8);
872 acore.cts_mode = HDMI_AUDIO_CTS_MODE_HW;
873 acore.use_mclk = true;
874 }
875
876 if (acore.use_mclk)
877 acore.mclk_mode = HDMI_AUDIO_MCLK_128FS;
878
879 /* Audio channels settings */
880 channel_count = (audio->cea->db1_ct_cc &
881 CEA861_AUDIO_INFOFRAME_DB1CC) + 1;
882
883 switch (channel_count) {
884 case 2:
885 audio_format.active_chnnls_msk = 0x03;
886 break;
887 case 3:
888 audio_format.active_chnnls_msk = 0x07;
889 break;
890 case 4:
891 audio_format.active_chnnls_msk = 0x0f;
892 break;
893 case 5:
894 audio_format.active_chnnls_msk = 0x1f;
895 break;
896 case 6:
897 audio_format.active_chnnls_msk = 0x3f;
898 break;
899 case 7:
900 audio_format.active_chnnls_msk = 0x7f;
901 break;
902 case 8:
903 audio_format.active_chnnls_msk = 0xff;
904 break;
905 default:
906 return -EINVAL;
907 }
908
909 /*
910 * the HDMI IP needs to enable four stereo channels when transmitting
911 * more than 2 audio channels
912 */
913 if (channel_count == 2) {
914 audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL;
915 acore.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN;
916 acore.layout = HDMI_AUDIO_LAYOUT_2CH;
917 } else {
918 audio_format.stereo_channels = HDMI_AUDIO_STEREO_FOURCHANNELS;
919 acore.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN |
920 HDMI_AUDIO_I2S_SD1_EN | HDMI_AUDIO_I2S_SD2_EN |
921 HDMI_AUDIO_I2S_SD3_EN;
922 acore.layout = HDMI_AUDIO_LAYOUT_8CH;
923 }
924
925 acore.en_spdif = false;
926 /* use sample frequency from channel status word */
927 acore.fs_override = true;
928 /* enable ACR packets */
929 acore.en_acr_pkt = true;
930 /* disable direct streaming digital audio */
931 acore.en_dsd_audio = false;
932 /* use parallel audio interface */
933 acore.en_parallel_aud_input = true;
934
935 /* DMA settings */
936 if (word_length_16b)
937 audio_dma.transfer_size = 0x10;
938 else
939 audio_dma.transfer_size = 0x20;
940 audio_dma.block_size = 0xC0;
941 audio_dma.mode = HDMI_AUDIO_TRANSF_DMA;
942 audio_dma.fifo_threshold = 0x20; /* in number of samples */
943
944 /* audio FIFO format settings */
945 if (word_length_16b) {
946 audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES;
947 audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS;
948 audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT;
949 } else {
950 audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_ONESAMPLE;
951 audio_format.sample_size = HDMI_AUDIO_SAMPLE_24BITS;
952 audio_format.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
953 }
954 audio_format.type = HDMI_AUDIO_TYPE_LPCM;
955 audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST;
956 /* disable start/stop signals of IEC 60958 blocks */
957 audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_ON;
958
959 /* configure DMA and audio FIFO format*/
960 hdmi_wp_audio_config_dma(wp, &audio_dma);
961 hdmi_wp_audio_config_format(wp, &audio_format);
962
963 /* configure the core*/
964 hdmi_core_audio_config(core, &acore);
965
966 /* configure CEA 861 audio infoframe*/
967 hdmi_core_audio_infoframe_cfg(core, audio->cea);
968
969 return 0;
970}
971
972int hdmi4_audio_start(struct hdmi_core_data *core, struct hdmi_wp_data *wp)
973{
974 REG_FLD_MOD(hdmi_av_base(core),
975 HDMI_CORE_AV_AUD_MODE, true, 0, 0);
976
977 hdmi_wp_audio_core_req_enable(wp, true);
978
979 return 0;
980}
981
982void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp)
983{
984 REG_FLD_MOD(hdmi_av_base(core),
985 HDMI_CORE_AV_AUD_MODE, false, 0, 0);
986
987 hdmi_wp_audio_core_req_enable(wp, false);
988}
989
990int hdmi4_audio_get_dma_port(u32 *offset, u32 *size)
991{
992 if (!offset || !size)
993 return -EINVAL;
994 *offset = HDMI_WP_AUDIO_DATA;
995 *size = 4;
996 return 0;
997}
998
999#endif
1000
1001#define CORE_OFFSET 0x400
1002#define CORE_SIZE 0xc00
1003
1004int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core)
1005{
1006 struct resource *res;
1007 struct resource temp_res;
1008
1009 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
1010 if (!res) {
1011 DSSDBG("can't get CORE mem resource by name\n");
1012 /*
1013 * if hwmod/DT doesn't have the memory resource information
1014 * split into HDMI sub blocks by name, we try again by getting
1015 * the platform's first resource. this code will be removed when
1016 * the driver can get the mem resources by name
1017 */
1018 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1019 if (!res) {
1020 DSSERR("can't get CORE mem resource\n");
1021 return -EINVAL;
1022 }
1023
1024 temp_res.start = res->start + CORE_OFFSET;
1025 temp_res.end = temp_res.start + CORE_SIZE - 1;
1026 res = &temp_res;
1027 }
1028
1029 core->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
1030 if (!core->base) {
1031 DSSERR("can't ioremap CORE\n");
1032 return -ENOMEM;
1033 }
1034
1035 return 0;
1036}
diff --git a/drivers/video/omap2/dss/hdmi4_core.h b/drivers/video/omap2/dss/hdmi4_core.h
deleted file mode 100644
index bb646896fa82..000000000000
--- a/drivers/video/omap2/dss/hdmi4_core.h
+++ /dev/null
@@ -1,276 +0,0 @@
1/*
2 * HDMI header definition for OMAP4 HDMI core IP
3 *
4 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef _HDMI4_CORE_H_
20#define _HDMI4_CORE_H_
21
22#include "hdmi.h"
23
24/* OMAP4 HDMI IP Core System */
25
26#define HDMI_CORE_SYS_VND_IDL 0x0
27#define HDMI_CORE_SYS_DEV_IDL 0x8
28#define HDMI_CORE_SYS_DEV_IDH 0xC
29#define HDMI_CORE_SYS_DEV_REV 0x10
30#define HDMI_CORE_SYS_SRST 0x14
31#define HDMI_CORE_SYS_SYS_CTRL1 0x20
32#define HDMI_CORE_SYS_SYS_STAT 0x24
33#define HDMI_CORE_SYS_SYS_CTRL3 0x28
34#define HDMI_CORE_SYS_DCTL 0x34
35#define HDMI_CORE_SYS_DE_DLY 0xC8
36#define HDMI_CORE_SYS_DE_CTRL 0xCC
37#define HDMI_CORE_SYS_DE_TOP 0xD0
38#define HDMI_CORE_SYS_DE_CNTL 0xD8
39#define HDMI_CORE_SYS_DE_CNTH 0xDC
40#define HDMI_CORE_SYS_DE_LINL 0xE0
41#define HDMI_CORE_SYS_DE_LINH_1 0xE4
42#define HDMI_CORE_SYS_HRES_L 0xE8
43#define HDMI_CORE_SYS_HRES_H 0xEC
44#define HDMI_CORE_SYS_VRES_L 0xF0
45#define HDMI_CORE_SYS_VRES_H 0xF4
46#define HDMI_CORE_SYS_IADJUST 0xF8
47#define HDMI_CORE_SYS_POLDETECT 0xFC
48#define HDMI_CORE_SYS_HWIDTH1 0x110
49#define HDMI_CORE_SYS_HWIDTH2 0x114
50#define HDMI_CORE_SYS_VWIDTH 0x11C
51#define HDMI_CORE_SYS_VID_CTRL 0x120
52#define HDMI_CORE_SYS_VID_ACEN 0x124
53#define HDMI_CORE_SYS_VID_MODE 0x128
54#define HDMI_CORE_SYS_VID_BLANK1 0x12C
55#define HDMI_CORE_SYS_VID_BLANK2 0x130
56#define HDMI_CORE_SYS_VID_BLANK3 0x134
57#define HDMI_CORE_SYS_DC_HEADER 0x138
58#define HDMI_CORE_SYS_VID_DITHER 0x13C
59#define HDMI_CORE_SYS_RGB2XVYCC_CT 0x140
60#define HDMI_CORE_SYS_R2Y_COEFF_LOW 0x144
61#define HDMI_CORE_SYS_R2Y_COEFF_UP 0x148
62#define HDMI_CORE_SYS_G2Y_COEFF_LOW 0x14C
63#define HDMI_CORE_SYS_G2Y_COEFF_UP 0x150
64#define HDMI_CORE_SYS_B2Y_COEFF_LOW 0x154
65#define HDMI_CORE_SYS_B2Y_COEFF_UP 0x158
66#define HDMI_CORE_SYS_R2CB_COEFF_LOW 0x15C
67#define HDMI_CORE_SYS_R2CB_COEFF_UP 0x160
68#define HDMI_CORE_SYS_G2CB_COEFF_LOW 0x164
69#define HDMI_CORE_SYS_G2CB_COEFF_UP 0x168
70#define HDMI_CORE_SYS_B2CB_COEFF_LOW 0x16C
71#define HDMI_CORE_SYS_B2CB_COEFF_UP 0x170
72#define HDMI_CORE_SYS_R2CR_COEFF_LOW 0x174
73#define HDMI_CORE_SYS_R2CR_COEFF_UP 0x178
74#define HDMI_CORE_SYS_G2CR_COEFF_LOW 0x17C
75#define HDMI_CORE_SYS_G2CR_COEFF_UP 0x180
76#define HDMI_CORE_SYS_B2CR_COEFF_LOW 0x184
77#define HDMI_CORE_SYS_B2CR_COEFF_UP 0x188
78#define HDMI_CORE_SYS_RGB_OFFSET_LOW 0x18C
79#define HDMI_CORE_SYS_RGB_OFFSET_UP 0x190
80#define HDMI_CORE_SYS_Y_OFFSET_LOW 0x194
81#define HDMI_CORE_SYS_Y_OFFSET_UP 0x198
82#define HDMI_CORE_SYS_CBCR_OFFSET_LOW 0x19C
83#define HDMI_CORE_SYS_CBCR_OFFSET_UP 0x1A0
84#define HDMI_CORE_SYS_INTR_STATE 0x1C0
85#define HDMI_CORE_SYS_INTR1 0x1C4
86#define HDMI_CORE_SYS_INTR2 0x1C8
87#define HDMI_CORE_SYS_INTR3 0x1CC
88#define HDMI_CORE_SYS_INTR4 0x1D0
89#define HDMI_CORE_SYS_INTR_UNMASK1 0x1D4
90#define HDMI_CORE_SYS_INTR_UNMASK2 0x1D8
91#define HDMI_CORE_SYS_INTR_UNMASK3 0x1DC
92#define HDMI_CORE_SYS_INTR_UNMASK4 0x1E0
93#define HDMI_CORE_SYS_INTR_CTRL 0x1E4
94#define HDMI_CORE_SYS_TMDS_CTRL 0x208
95
96/* value definitions for HDMI_CORE_SYS_SYS_CTRL1 fields */
97#define HDMI_CORE_SYS_SYS_CTRL1_VEN_FOLLOWVSYNC 0x1
98#define HDMI_CORE_SYS_SYS_CTRL1_HEN_FOLLOWHSYNC 0x1
99#define HDMI_CORE_SYS_SYS_CTRL1_BSEL_24BITBUS 0x1
100#define HDMI_CORE_SYS_SYS_CTRL1_EDGE_RISINGEDGE 0x1
101
102/* HDMI DDC E-DID */
103#define HDMI_CORE_DDC_ADDR 0x3B4
104#define HDMI_CORE_DDC_SEGM 0x3B8
105#define HDMI_CORE_DDC_OFFSET 0x3BC
106#define HDMI_CORE_DDC_COUNT1 0x3C0
107#define HDMI_CORE_DDC_COUNT2 0x3C4
108#define HDMI_CORE_DDC_STATUS 0x3C8
109#define HDMI_CORE_DDC_CMD 0x3CC
110#define HDMI_CORE_DDC_DATA 0x3D0
111
112/* HDMI IP Core Audio Video */
113
114#define HDMI_CORE_AV_ACR_CTRL 0x4
115#define HDMI_CORE_AV_FREQ_SVAL 0x8
116#define HDMI_CORE_AV_N_SVAL1 0xC
117#define HDMI_CORE_AV_N_SVAL2 0x10
118#define HDMI_CORE_AV_N_SVAL3 0x14
119#define HDMI_CORE_AV_CTS_SVAL1 0x18
120#define HDMI_CORE_AV_CTS_SVAL2 0x1C
121#define HDMI_CORE_AV_CTS_SVAL3 0x20
122#define HDMI_CORE_AV_CTS_HVAL1 0x24
123#define HDMI_CORE_AV_CTS_HVAL2 0x28
124#define HDMI_CORE_AV_CTS_HVAL3 0x2C
125#define HDMI_CORE_AV_AUD_MODE 0x50
126#define HDMI_CORE_AV_SPDIF_CTRL 0x54
127#define HDMI_CORE_AV_HW_SPDIF_FS 0x60
128#define HDMI_CORE_AV_SWAP_I2S 0x64
129#define HDMI_CORE_AV_SPDIF_ERTH 0x6C
130#define HDMI_CORE_AV_I2S_IN_MAP 0x70
131#define HDMI_CORE_AV_I2S_IN_CTRL 0x74
132#define HDMI_CORE_AV_I2S_CHST0 0x78
133#define HDMI_CORE_AV_I2S_CHST1 0x7C
134#define HDMI_CORE_AV_I2S_CHST2 0x80
135#define HDMI_CORE_AV_I2S_CHST4 0x84
136#define HDMI_CORE_AV_I2S_CHST5 0x88
137#define HDMI_CORE_AV_ASRC 0x8C
138#define HDMI_CORE_AV_I2S_IN_LEN 0x90
139#define HDMI_CORE_AV_HDMI_CTRL 0xBC
140#define HDMI_CORE_AV_AUDO_TXSTAT 0xC0
141#define HDMI_CORE_AV_AUD_PAR_BUSCLK_1 0xCC
142#define HDMI_CORE_AV_AUD_PAR_BUSCLK_2 0xD0
143#define HDMI_CORE_AV_AUD_PAR_BUSCLK_3 0xD4
144#define HDMI_CORE_AV_TEST_TXCTRL 0xF0
145#define HDMI_CORE_AV_DPD 0xF4
146#define HDMI_CORE_AV_PB_CTRL1 0xF8
147#define HDMI_CORE_AV_PB_CTRL2 0xFC
148#define HDMI_CORE_AV_AVI_TYPE 0x100
149#define HDMI_CORE_AV_AVI_VERS 0x104
150#define HDMI_CORE_AV_AVI_LEN 0x108
151#define HDMI_CORE_AV_AVI_CHSUM 0x10C
152#define HDMI_CORE_AV_AVI_DBYTE(n) (n * 4 + 0x110)
153#define HDMI_CORE_AV_SPD_TYPE 0x180
154#define HDMI_CORE_AV_SPD_VERS 0x184
155#define HDMI_CORE_AV_SPD_LEN 0x188
156#define HDMI_CORE_AV_SPD_CHSUM 0x18C
157#define HDMI_CORE_AV_SPD_DBYTE(n) (n * 4 + 0x190)
158#define HDMI_CORE_AV_AUDIO_TYPE 0x200
159#define HDMI_CORE_AV_AUDIO_VERS 0x204
160#define HDMI_CORE_AV_AUDIO_LEN 0x208
161#define HDMI_CORE_AV_AUDIO_CHSUM 0x20C
162#define HDMI_CORE_AV_AUD_DBYTE(n) (n * 4 + 0x210)
163#define HDMI_CORE_AV_MPEG_TYPE 0x280
164#define HDMI_CORE_AV_MPEG_VERS 0x284
165#define HDMI_CORE_AV_MPEG_LEN 0x288
166#define HDMI_CORE_AV_MPEG_CHSUM 0x28C
167#define HDMI_CORE_AV_MPEG_DBYTE(n) (n * 4 + 0x290)
168#define HDMI_CORE_AV_GEN_DBYTE(n) (n * 4 + 0x300)
169#define HDMI_CORE_AV_CP_BYTE1 0x37C
170#define HDMI_CORE_AV_GEN2_DBYTE(n) (n * 4 + 0x380)
171#define HDMI_CORE_AV_CEC_ADDR_ID 0x3FC
172
173#define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4
174#define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4
175#define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4
176#define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4
177
178#define HDMI_CORE_AV_AVI_DBYTE_NELEMS 15
179#define HDMI_CORE_AV_SPD_DBYTE_NELEMS 27
180#define HDMI_CORE_AV_AUD_DBYTE_NELEMS 10
181#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS 27
182#define HDMI_CORE_AV_GEN_DBYTE_NELEMS 31
183#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS 31
184
185enum hdmi_core_inputbus_width {
186 HDMI_INPUT_8BIT = 0,
187 HDMI_INPUT_10BIT = 1,
188 HDMI_INPUT_12BIT = 2
189};
190
191enum hdmi_core_dither_trunc {
192 HDMI_OUTPUTTRUNCATION_8BIT = 0,
193 HDMI_OUTPUTTRUNCATION_10BIT = 1,
194 HDMI_OUTPUTTRUNCATION_12BIT = 2,
195 HDMI_OUTPUTDITHER_8BIT = 3,
196 HDMI_OUTPUTDITHER_10BIT = 4,
197 HDMI_OUTPUTDITHER_12BIT = 5
198};
199
200enum hdmi_core_deepcolor_ed {
201 HDMI_DEEPCOLORPACKECTDISABLE = 0,
202 HDMI_DEEPCOLORPACKECTENABLE = 1
203};
204
205enum hdmi_core_packet_mode {
206 HDMI_PACKETMODERESERVEDVALUE = 0,
207 HDMI_PACKETMODE24BITPERPIXEL = 4,
208 HDMI_PACKETMODE30BITPERPIXEL = 5,
209 HDMI_PACKETMODE36BITPERPIXEL = 6,
210 HDMI_PACKETMODE48BITPERPIXEL = 7
211};
212
213enum hdmi_core_tclkselclkmult {
214 HDMI_FPLL05IDCK = 0,
215 HDMI_FPLL10IDCK = 1,
216 HDMI_FPLL20IDCK = 2,
217 HDMI_FPLL40IDCK = 3
218};
219
220enum hdmi_core_packet_ctrl {
221 HDMI_PACKETENABLE = 1,
222 HDMI_PACKETDISABLE = 0,
223 HDMI_PACKETREPEATON = 1,
224 HDMI_PACKETREPEATOFF = 0
225};
226
227enum hdmi_audio_i2s_config {
228 HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST = 0,
229 HDMI_AUDIO_I2S_LSB_SHIFTED_FIRST = 1,
230 HDMI_AUDIO_I2S_SCK_EDGE_FALLING = 0,
231 HDMI_AUDIO_I2S_SCK_EDGE_RISING = 1,
232 HDMI_AUDIO_I2S_VBIT_FOR_PCM = 0,
233 HDMI_AUDIO_I2S_VBIT_FOR_COMPRESSED = 1,
234 HDMI_AUDIO_I2S_FIRST_BIT_SHIFT = 0,
235 HDMI_AUDIO_I2S_FIRST_BIT_NO_SHIFT = 1,
236 HDMI_AUDIO_I2S_SD0_EN = 1,
237 HDMI_AUDIO_I2S_SD1_EN = 1 << 1,
238 HDMI_AUDIO_I2S_SD2_EN = 1 << 2,
239 HDMI_AUDIO_I2S_SD3_EN = 1 << 3,
240};
241
242struct hdmi_core_video_config {
243 enum hdmi_core_inputbus_width ip_bus_width;
244 enum hdmi_core_dither_trunc op_dither_truc;
245 enum hdmi_core_deepcolor_ed deep_color_pkt;
246 enum hdmi_core_packet_mode pkt_mode;
247 enum hdmi_core_hdmi_dvi hdmi_dvi;
248 enum hdmi_core_tclkselclkmult tclk_sel_clkmult;
249};
250
251struct hdmi_core_packet_enable_repeat {
252 u32 audio_pkt;
253 u32 audio_pkt_repeat;
254 u32 avi_infoframe;
255 u32 avi_infoframe_repeat;
256 u32 gen_cntrl_pkt;
257 u32 gen_cntrl_pkt_repeat;
258 u32 generic_pkt;
259 u32 generic_pkt_repeat;
260};
261
262int hdmi4_read_edid(struct hdmi_core_data *core, u8 *edid, int len);
263void hdmi4_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
264 struct hdmi_config *cfg);
265void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s);
266int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core);
267
268#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
269int hdmi4_audio_start(struct hdmi_core_data *core, struct hdmi_wp_data *wp);
270void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp);
271int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
272 struct omap_dss_audio *audio, u32 pclk);
273int hdmi4_audio_get_dma_port(u32 *offset, u32 *size);
274#endif
275
276#endif
diff --git a/drivers/video/omap2/dss/hdmi_common.c b/drivers/video/omap2/dss/hdmi_common.c
deleted file mode 100644
index 0b12a3f62fe1..000000000000
--- a/drivers/video/omap2/dss/hdmi_common.c
+++ /dev/null
@@ -1,425 +0,0 @@
1
2/*
3 * Logic for the below structure :
4 * user enters the CEA or VESA timings by specifying the HDMI/DVI code.
5 * There is a correspondence between CEA/VESA timing and code, please
6 * refer to section 6.3 in HDMI 1.3 specification for timing code.
7 *
8 * In the below structure, cea_vesa_timings corresponds to all OMAP4
9 * supported CEA and VESA timing values.code_cea corresponds to the CEA
10 * code, It is used to get the timing from cea_vesa_timing array.Similarly
11 * with code_vesa. Code_index is used for back mapping, that is once EDID
12 * is read from the TV, EDID is parsed to find the timing values and then
13 * map it to corresponding CEA or VESA index.
14 */
15
16#define DSS_SUBSYS_NAME "HDMI"
17
18#include <linux/kernel.h>
19#include <linux/err.h>
20#include <video/omapdss.h>
21
22#include "hdmi.h"
23
24static const struct hdmi_config cea_timings[] = {
25 {
26 { 640, 480, 25200000, 96, 16, 48, 2, 10, 33,
27 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
28 false, },
29 { 1, HDMI_HDMI },
30 },
31 {
32 { 720, 480, 27027000, 62, 16, 60, 6, 9, 30,
33 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
34 false, },
35 { 2, HDMI_HDMI },
36 },
37 {
38 { 1280, 720, 74250000, 40, 110, 220, 5, 5, 20,
39 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
40 false, },
41 { 4, HDMI_HDMI },
42 },
43 {
44 { 1920, 540, 74250000, 44, 88, 148, 5, 2, 15,
45 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
46 true, },
47 { 5, HDMI_HDMI },
48 },
49 {
50 { 1440, 240, 27027000, 124, 38, 114, 3, 4, 15,
51 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
52 true, },
53 { 6, HDMI_HDMI },
54 },
55 {
56 { 1920, 1080, 148500000, 44, 88, 148, 5, 4, 36,
57 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
58 false, },
59 { 16, HDMI_HDMI },
60 },
61 {
62 { 720, 576, 27000000, 64, 12, 68, 5, 5, 39,
63 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
64 false, },
65 { 17, HDMI_HDMI },
66 },
67 {
68 { 1280, 720, 74250000, 40, 440, 220, 5, 5, 20,
69 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
70 false, },
71 { 19, HDMI_HDMI },
72 },
73 {
74 { 1920, 540, 74250000, 44, 528, 148, 5, 2, 15,
75 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
76 true, },
77 { 20, HDMI_HDMI },
78 },
79 {
80 { 1440, 288, 27000000, 126, 24, 138, 3, 2, 19,
81 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
82 true, },
83 { 21, HDMI_HDMI },
84 },
85 {
86 { 1440, 576, 54000000, 128, 24, 136, 5, 5, 39,
87 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
88 false, },
89 { 29, HDMI_HDMI },
90 },
91 {
92 { 1920, 1080, 148500000, 44, 528, 148, 5, 4, 36,
93 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
94 false, },
95 { 31, HDMI_HDMI },
96 },
97 {
98 { 1920, 1080, 74250000, 44, 638, 148, 5, 4, 36,
99 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
100 false, },
101 { 32, HDMI_HDMI },
102 },
103 {
104 { 2880, 480, 108108000, 248, 64, 240, 6, 9, 30,
105 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
106 false, },
107 { 35, HDMI_HDMI },
108 },
109 {
110 { 2880, 576, 108000000, 256, 48, 272, 5, 5, 39,
111 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
112 false, },
113 { 37, HDMI_HDMI },
114 },
115};
116
117static const struct hdmi_config vesa_timings[] = {
118/* VESA From Here */
119 {
120 { 640, 480, 25175000, 96, 16, 48, 2, 11, 31,
121 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
122 false, },
123 { 4, HDMI_DVI },
124 },
125 {
126 { 800, 600, 40000000, 128, 40, 88, 4, 1, 23,
127 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
128 false, },
129 { 9, HDMI_DVI },
130 },
131 {
132 { 848, 480, 33750000, 112, 16, 112, 8, 6, 23,
133 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
134 false, },
135 { 0xE, HDMI_DVI },
136 },
137 {
138 { 1280, 768, 79500000, 128, 64, 192, 7, 3, 20,
139 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
140 false, },
141 { 0x17, HDMI_DVI },
142 },
143 {
144 { 1280, 800, 83500000, 128, 72, 200, 6, 3, 22,
145 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
146 false, },
147 { 0x1C, HDMI_DVI },
148 },
149 {
150 { 1360, 768, 85500000, 112, 64, 256, 6, 3, 18,
151 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
152 false, },
153 { 0x27, HDMI_DVI },
154 },
155 {
156 { 1280, 960, 108000000, 112, 96, 312, 3, 1, 36,
157 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
158 false, },
159 { 0x20, HDMI_DVI },
160 },
161 {
162 { 1280, 1024, 108000000, 112, 48, 248, 3, 1, 38,
163 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
164 false, },
165 { 0x23, HDMI_DVI },
166 },
167 {
168 { 1024, 768, 65000000, 136, 24, 160, 6, 3, 29,
169 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
170 false, },
171 { 0x10, HDMI_DVI },
172 },
173 {
174 { 1400, 1050, 121750000, 144, 88, 232, 4, 3, 32,
175 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
176 false, },
177 { 0x2A, HDMI_DVI },
178 },
179 {
180 { 1440, 900, 106500000, 152, 80, 232, 6, 3, 25,
181 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
182 false, },
183 { 0x2F, HDMI_DVI },
184 },
185 {
186 { 1680, 1050, 146250000, 176 , 104, 280, 6, 3, 30,
187 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
188 false, },
189 { 0x3A, HDMI_DVI },
190 },
191 {
192 { 1366, 768, 85500000, 143, 70, 213, 3, 3, 24,
193 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
194 false, },
195 { 0x51, HDMI_DVI },
196 },
197 {
198 { 1920, 1080, 148500000, 44, 148, 80, 5, 4, 36,
199 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
200 false, },
201 { 0x52, HDMI_DVI },
202 },
203 {
204 { 1280, 768, 68250000, 32, 48, 80, 7, 3, 12,
205 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
206 false, },
207 { 0x16, HDMI_DVI },
208 },
209 {
210 { 1400, 1050, 101000000, 32, 48, 80, 4, 3, 23,
211 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
212 false, },
213 { 0x29, HDMI_DVI },
214 },
215 {
216 { 1680, 1050, 119000000, 32, 48, 80, 6, 3, 21,
217 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
218 false, },
219 { 0x39, HDMI_DVI },
220 },
221 {
222 { 1280, 800, 79500000, 32, 48, 80, 6, 3, 14,
223 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
224 false, },
225 { 0x1B, HDMI_DVI },
226 },
227 {
228 { 1280, 720, 74250000, 40, 110, 220, 5, 5, 20,
229 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
230 false, },
231 { 0x55, HDMI_DVI },
232 },
233 {
234 { 1920, 1200, 154000000, 32, 48, 80, 6, 3, 26,
235 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
236 false, },
237 { 0x44, HDMI_DVI },
238 },
239};
240
241const struct hdmi_config *hdmi_default_timing(void)
242{
243 return &vesa_timings[0];
244}
245
246static const struct hdmi_config *hdmi_find_timing(int code,
247 const struct hdmi_config *timings_arr, int len)
248{
249 int i;
250
251 for (i = 0; i < len; i++) {
252 if (timings_arr[i].cm.code == code)
253 return &timings_arr[i];
254 }
255
256 return NULL;
257}
258
259const struct hdmi_config *hdmi_get_timings(int mode, int code)
260{
261 const struct hdmi_config *arr;
262 int len;
263
264 if (mode == HDMI_DVI) {
265 arr = vesa_timings;
266 len = ARRAY_SIZE(vesa_timings);
267 } else {
268 arr = cea_timings;
269 len = ARRAY_SIZE(cea_timings);
270 }
271
272 return hdmi_find_timing(code, arr, len);
273}
274
275static bool hdmi_timings_compare(struct omap_video_timings *timing1,
276 const struct omap_video_timings *timing2)
277{
278 int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;
279
280 if ((DIV_ROUND_CLOSEST(timing2->pixelclock, 1000000) ==
281 DIV_ROUND_CLOSEST(timing1->pixelclock, 1000000)) &&
282 (timing2->x_res == timing1->x_res) &&
283 (timing2->y_res == timing1->y_res)) {
284
285 timing2_hsync = timing2->hfp + timing2->hsw + timing2->hbp;
286 timing1_hsync = timing1->hfp + timing1->hsw + timing1->hbp;
287 timing2_vsync = timing2->vfp + timing2->vsw + timing2->vbp;
288 timing1_vsync = timing1->vfp + timing1->vsw + timing1->vbp;
289
290 DSSDBG("timing1_hsync = %d timing1_vsync = %d"\
291 "timing2_hsync = %d timing2_vsync = %d\n",
292 timing1_hsync, timing1_vsync,
293 timing2_hsync, timing2_vsync);
294
295 if ((timing1_hsync == timing2_hsync) &&
296 (timing1_vsync == timing2_vsync)) {
297 return true;
298 }
299 }
300 return false;
301}
302
303struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
304{
305 int i;
306 struct hdmi_cm cm = {-1};
307 DSSDBG("hdmi_get_code\n");
308
309 for (i = 0; i < ARRAY_SIZE(cea_timings); i++) {
310 if (hdmi_timings_compare(timing, &cea_timings[i].timings)) {
311 cm = cea_timings[i].cm;
312 goto end;
313 }
314 }
315 for (i = 0; i < ARRAY_SIZE(vesa_timings); i++) {
316 if (hdmi_timings_compare(timing, &vesa_timings[i].timings)) {
317 cm = vesa_timings[i].cm;
318 goto end;
319 }
320 }
321
322end:
323 return cm;
324}
325
326#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
327int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts)
328{
329 u32 deep_color;
330 bool deep_color_correct = false;
331
332 if (n == NULL || cts == NULL)
333 return -EINVAL;
334
335 /* TODO: When implemented, query deep color mode here. */
336 deep_color = 100;
337
338 /*
339 * When using deep color, the default N value (as in the HDMI
340 * specification) yields to an non-integer CTS. Hence, we
341 * modify it while keeping the restrictions described in
342 * section 7.2.1 of the HDMI 1.4a specification.
343 */
344 switch (sample_freq) {
345 case 32000:
346 case 48000:
347 case 96000:
348 case 192000:
349 if (deep_color == 125)
350 if (pclk == 27027000 || pclk == 74250000)
351 deep_color_correct = true;
352 if (deep_color == 150)
353 if (pclk == 27027000)
354 deep_color_correct = true;
355 break;
356 case 44100:
357 case 88200:
358 case 176400:
359 if (deep_color == 125)
360 if (pclk == 27027000)
361 deep_color_correct = true;
362 break;
363 default:
364 return -EINVAL;
365 }
366
367 if (deep_color_correct) {
368 switch (sample_freq) {
369 case 32000:
370 *n = 8192;
371 break;
372 case 44100:
373 *n = 12544;
374 break;
375 case 48000:
376 *n = 8192;
377 break;
378 case 88200:
379 *n = 25088;
380 break;
381 case 96000:
382 *n = 16384;
383 break;
384 case 176400:
385 *n = 50176;
386 break;
387 case 192000:
388 *n = 32768;
389 break;
390 default:
391 return -EINVAL;
392 }
393 } else {
394 switch (sample_freq) {
395 case 32000:
396 *n = 4096;
397 break;
398 case 44100:
399 *n = 6272;
400 break;
401 case 48000:
402 *n = 6144;
403 break;
404 case 88200:
405 *n = 12544;
406 break;
407 case 96000:
408 *n = 12288;
409 break;
410 case 176400:
411 *n = 25088;
412 break;
413 case 192000:
414 *n = 24576;
415 break;
416 default:
417 return -EINVAL;
418 }
419 }
420 /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
421 *cts = (pclk/1000) * (*n / 128) * deep_color / (sample_freq / 10);
422
423 return 0;
424}
425#endif
diff --git a/drivers/video/omap2/dss/hdmi_phy.c b/drivers/video/omap2/dss/hdmi_phy.c
deleted file mode 100644
index dd376ce8da01..000000000000
--- a/drivers/video/omap2/dss/hdmi_phy.c
+++ /dev/null
@@ -1,160 +0,0 @@
1/*
2 * HDMI PHY
3 *
4 * Copyright (C) 2013 Texas Instruments Incorporated
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 */
10
11#include <linux/kernel.h>
12#include <linux/err.h>
13#include <linux/io.h>
14#include <linux/platform_device.h>
15#include <video/omapdss.h>
16
17#include "dss.h"
18#include "hdmi.h"
19
20void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s)
21{
22#define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\
23 hdmi_read_reg(phy->base, r))
24
25 DUMPPHY(HDMI_TXPHY_TX_CTRL);
26 DUMPPHY(HDMI_TXPHY_DIGITAL_CTRL);
27 DUMPPHY(HDMI_TXPHY_POWER_CTRL);
28 DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL);
29}
30
31static irqreturn_t hdmi_irq_handler(int irq, void *data)
32{
33 struct hdmi_wp_data *wp = data;
34 u32 irqstatus;
35
36 irqstatus = hdmi_wp_get_irqstatus(wp);
37 hdmi_wp_set_irqstatus(wp, irqstatus);
38
39 if ((irqstatus & HDMI_IRQ_LINK_CONNECT) &&
40 irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
41 /*
42 * If we get both connect and disconnect interrupts at the same
43 * time, turn off the PHY, clear interrupts, and restart, which
44 * raises connect interrupt if a cable is connected, or nothing
45 * if cable is not connected.
46 */
47 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);
48
49 hdmi_wp_set_irqstatus(wp, HDMI_IRQ_LINK_CONNECT |
50 HDMI_IRQ_LINK_DISCONNECT);
51
52 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
53 } else if (irqstatus & HDMI_IRQ_LINK_CONNECT) {
54 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_TXON);
55 } else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
56 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
57 }
58
59 return IRQ_HANDLED;
60}
61
62int hdmi_phy_enable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp,
63 struct hdmi_config *cfg)
64{
65 u16 r = 0;
66 u32 irqstatus;
67
68 hdmi_wp_clear_irqenable(wp, 0xffffffff);
69
70 irqstatus = hdmi_wp_get_irqstatus(wp);
71 hdmi_wp_set_irqstatus(wp, irqstatus);
72
73 r = hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
74 if (r)
75 return r;
76
77 /*
78 * Read address 0 in order to get the SCP reset done completed
79 * Dummy access performed to make sure reset is done
80 */
81 hdmi_read_reg(phy->base, HDMI_TXPHY_TX_CTRL);
82
83 /*
84 * Write to phy address 0 to configure the clock
85 * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field
86 */
87 REG_FLD_MOD(phy->base, HDMI_TXPHY_TX_CTRL, 0x1, 31, 30);
88
89 /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */
90 hdmi_write_reg(phy->base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000);
91
92 /* Setup max LDO voltage */
93 REG_FLD_MOD(phy->base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0);
94
95 /* Write to phy address 3 to change the polarity control */
96 REG_FLD_MOD(phy->base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
97
98 r = request_threaded_irq(phy->irq, NULL, hdmi_irq_handler,
99 IRQF_ONESHOT, "OMAP HDMI", wp);
100 if (r) {
101 DSSERR("HDMI IRQ request failed\n");
102 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);
103 return r;
104 }
105
106 hdmi_wp_set_irqenable(wp,
107 HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
108
109 return 0;
110}
111
112void hdmi_phy_disable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp)
113{
114 free_irq(phy->irq, wp);
115
116 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);
117}
118
119#define PHY_OFFSET 0x300
120#define PHY_SIZE 0x100
121
122int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy)
123{
124 struct resource *res;
125 struct resource temp_res;
126
127 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
128 if (!res) {
129 DSSDBG("can't get PHY mem resource by name\n");
130 /*
131 * if hwmod/DT doesn't have the memory resource information
132 * split into HDMI sub blocks by name, we try again by getting
133 * the platform's first resource. this code will be removed when
134 * the driver can get the mem resources by name
135 */
136 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
137 if (!res) {
138 DSSERR("can't get PHY mem resource\n");
139 return -EINVAL;
140 }
141
142 temp_res.start = res->start + PHY_OFFSET;
143 temp_res.end = temp_res.start + PHY_SIZE - 1;
144 res = &temp_res;
145 }
146
147 phy->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
148 if (!phy->base) {
149 DSSERR("can't ioremap TX PHY\n");
150 return -ENOMEM;
151 }
152
153 phy->irq = platform_get_irq(pdev, 0);
154 if (phy->irq < 0) {
155 DSSERR("platform_get_irq failed\n");
156 return -ENODEV;
157 }
158
159 return 0;
160}
diff --git a/drivers/video/omap2/dss/hdmi_pll.c b/drivers/video/omap2/dss/hdmi_pll.c
deleted file mode 100644
index 5fc71215c303..000000000000
--- a/drivers/video/omap2/dss/hdmi_pll.c
+++ /dev/null
@@ -1,232 +0,0 @@
1/*
2 * HDMI PLL
3 *
4 * Copyright (C) 2013 Texas Instruments Incorporated
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 */
10
11#define DSS_SUBSYS_NAME "HDMIPLL"
12
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/err.h>
16#include <linux/io.h>
17#include <linux/platform_device.h>
18#include <video/omapdss.h>
19
20#include "dss.h"
21#include "hdmi.h"
22
23#define HDMI_DEFAULT_REGN 16
24#define HDMI_DEFAULT_REGM2 1
25
26void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s)
27{
28#define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\
29 hdmi_read_reg(pll->base, r))
30
31 DUMPPLL(PLLCTRL_PLL_CONTROL);
32 DUMPPLL(PLLCTRL_PLL_STATUS);
33 DUMPPLL(PLLCTRL_PLL_GO);
34 DUMPPLL(PLLCTRL_CFG1);
35 DUMPPLL(PLLCTRL_CFG2);
36 DUMPPLL(PLLCTRL_CFG3);
37 DUMPPLL(PLLCTRL_SSC_CFG1);
38 DUMPPLL(PLLCTRL_SSC_CFG2);
39 DUMPPLL(PLLCTRL_CFG4);
40}
41
42void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy)
43{
44 struct hdmi_pll_info *pi = &pll->info;
45 unsigned long refclk;
46 u32 mf;
47
48 /* use our funky units */
49 clkin /= 10000;
50
51 /*
52 * Input clock is predivided by N + 1
53 * out put of which is reference clk
54 */
55
56 pi->regn = HDMI_DEFAULT_REGN;
57
58 refclk = clkin / pi->regn;
59
60 pi->regm2 = HDMI_DEFAULT_REGM2;
61
62 /*
63 * multiplier is pixel_clk/ref_clk
64 * Multiplying by 100 to avoid fractional part removal
65 */
66 pi->regm = phy * pi->regm2 / refclk;
67
68 /*
69 * fractional multiplier is remainder of the difference between
70 * multiplier and actual phy(required pixel clock thus should be
71 * multiplied by 2^18(262144) divided by the reference clock
72 */
73 mf = (phy - pi->regm / pi->regm2 * refclk) * 262144;
74 pi->regmf = pi->regm2 * mf / refclk;
75
76 /*
77 * Dcofreq should be set to 1 if required pixel clock
78 * is greater than 1000MHz
79 */
80 pi->dcofreq = phy > 1000 * 100;
81 pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10;
82
83 /* Set the reference clock to sysclk reference */
84 pi->refsel = HDMI_REFSEL_SYSCLK;
85
86 DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf);
87 DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
88}
89
90
91static int hdmi_pll_config(struct hdmi_pll_data *pll)
92{
93 u32 r;
94 struct hdmi_pll_info *fmt = &pll->info;
95
96 /* PLL start always use manual mode */
97 REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, 0x0, 0, 0);
98
99 r = hdmi_read_reg(pll->base, PLLCTRL_CFG1);
100 r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */
101 r = FLD_MOD(r, fmt->regn - 1, 8, 1); /* CFG1_PLL_REGN */
102 hdmi_write_reg(pll->base, PLLCTRL_CFG1, r);
103
104 r = hdmi_read_reg(pll->base, PLLCTRL_CFG2);
105
106 r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */
107 r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */
108 r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */
109 r = FLD_MOD(r, fmt->refsel, 22, 21); /* REFSEL */
110
111 if (fmt->dcofreq) {
112 /* divider programming for frequency beyond 1000Mhz */
113 REG_FLD_MOD(pll->base, PLLCTRL_CFG3, fmt->regsd, 17, 10);
114 r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */
115 } else {
116 r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */
117 }
118
119 hdmi_write_reg(pll->base, PLLCTRL_CFG2, r);
120
121 r = hdmi_read_reg(pll->base, PLLCTRL_CFG4);
122 r = FLD_MOD(r, fmt->regm2, 24, 18);
123 r = FLD_MOD(r, fmt->regmf, 17, 0);
124 hdmi_write_reg(pll->base, PLLCTRL_CFG4, r);
125
126 /* go now */
127 REG_FLD_MOD(pll->base, PLLCTRL_PLL_GO, 0x1, 0, 0);
128
129 /* wait for bit change */
130 if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_GO,
131 0, 0, 1) != 1) {
132 DSSERR("PLL GO bit not set\n");
133 return -ETIMEDOUT;
134 }
135
136 /* Wait till the lock bit is set in PLL status */
137 if (hdmi_wait_for_bit_change(pll->base,
138 PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) {
139 DSSERR("cannot lock PLL\n");
140 DSSERR("CFG1 0x%x\n",
141 hdmi_read_reg(pll->base, PLLCTRL_CFG1));
142 DSSERR("CFG2 0x%x\n",
143 hdmi_read_reg(pll->base, PLLCTRL_CFG2));
144 DSSERR("CFG4 0x%x\n",
145 hdmi_read_reg(pll->base, PLLCTRL_CFG4));
146 return -ETIMEDOUT;
147 }
148
149 DSSDBG("PLL locked!\n");
150
151 return 0;
152}
153
154static int hdmi_pll_reset(struct hdmi_pll_data *pll)
155{
156 /* SYSRESET controlled by power FSM */
157 REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, 0x0, 3, 3);
158
159 /* READ 0x0 reset is in progress */
160 if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_STATUS, 0, 0, 1)
161 != 1) {
162 DSSERR("Failed to sysreset PLL\n");
163 return -ETIMEDOUT;
164 }
165
166 return 0;
167}
168
169int hdmi_pll_enable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp)
170{
171 u16 r = 0;
172
173 r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
174 if (r)
175 return r;
176
177 r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
178 if (r)
179 return r;
180
181 r = hdmi_pll_reset(pll);
182 if (r)
183 return r;
184
185 r = hdmi_pll_config(pll);
186 if (r)
187 return r;
188
189 return 0;
190}
191
192void hdmi_pll_disable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp)
193{
194 hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
195}
196
197#define PLL_OFFSET 0x200
198#define PLL_SIZE 0x100
199
200int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll)
201{
202 struct resource *res;
203 struct resource temp_res;
204
205 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll");
206 if (!res) {
207 DSSDBG("can't get PLL mem resource by name\n");
208 /*
209 * if hwmod/DT doesn't have the memory resource information
210 * split into HDMI sub blocks by name, we try again by getting
211 * the platform's first resource. this code will be removed when
212 * the driver can get the mem resources by name
213 */
214 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
215 if (!res) {
216 DSSERR("can't get PLL mem resource\n");
217 return -EINVAL;
218 }
219
220 temp_res.start = res->start + PLL_OFFSET;
221 temp_res.end = temp_res.start + PLL_SIZE - 1;
222 res = &temp_res;
223 }
224
225 pll->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
226 if (!pll->base) {
227 DSSERR("can't ioremap PLLCTRL\n");
228 return -ENOMEM;
229 }
230
231 return 0;
232}
diff --git a/drivers/video/omap2/dss/hdmi_wp.c b/drivers/video/omap2/dss/hdmi_wp.c
deleted file mode 100644
index f5f4ccf50d90..000000000000
--- a/drivers/video/omap2/dss/hdmi_wp.c
+++ /dev/null
@@ -1,275 +0,0 @@
1/*
2 * HDMI wrapper
3 *
4 * Copyright (C) 2013 Texas Instruments Incorporated
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 */
10
11#define DSS_SUBSYS_NAME "HDMIWP"
12
13#include <linux/kernel.h>
14#include <linux/err.h>
15#include <linux/io.h>
16#include <linux/platform_device.h>
17#include <video/omapdss.h>
18
19#include "dss.h"
20#include "hdmi.h"
21
22void hdmi_wp_dump(struct hdmi_wp_data *wp, struct seq_file *s)
23{
24#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, hdmi_read_reg(wp->base, r))
25
26 DUMPREG(HDMI_WP_REVISION);
27 DUMPREG(HDMI_WP_SYSCONFIG);
28 DUMPREG(HDMI_WP_IRQSTATUS_RAW);
29 DUMPREG(HDMI_WP_IRQSTATUS);
30 DUMPREG(HDMI_WP_IRQENABLE_SET);
31 DUMPREG(HDMI_WP_IRQENABLE_CLR);
32 DUMPREG(HDMI_WP_IRQWAKEEN);
33 DUMPREG(HDMI_WP_PWR_CTRL);
34 DUMPREG(HDMI_WP_DEBOUNCE);
35 DUMPREG(HDMI_WP_VIDEO_CFG);
36 DUMPREG(HDMI_WP_VIDEO_SIZE);
37 DUMPREG(HDMI_WP_VIDEO_TIMING_H);
38 DUMPREG(HDMI_WP_VIDEO_TIMING_V);
39 DUMPREG(HDMI_WP_CLK);
40 DUMPREG(HDMI_WP_AUDIO_CFG);
41 DUMPREG(HDMI_WP_AUDIO_CFG2);
42 DUMPREG(HDMI_WP_AUDIO_CTRL);
43 DUMPREG(HDMI_WP_AUDIO_DATA);
44}
45
46u32 hdmi_wp_get_irqstatus(struct hdmi_wp_data *wp)
47{
48 return hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS);
49}
50
51void hdmi_wp_set_irqstatus(struct hdmi_wp_data *wp, u32 irqstatus)
52{
53 hdmi_write_reg(wp->base, HDMI_WP_IRQSTATUS, irqstatus);
54 /* flush posted write */
55 hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS);
56}
57
58void hdmi_wp_set_irqenable(struct hdmi_wp_data *wp, u32 mask)
59{
60 hdmi_write_reg(wp->base, HDMI_WP_IRQENABLE_SET, mask);
61}
62
63void hdmi_wp_clear_irqenable(struct hdmi_wp_data *wp, u32 mask)
64{
65 hdmi_write_reg(wp->base, HDMI_WP_IRQENABLE_CLR, mask);
66}
67
68/* PHY_PWR_CMD */
69int hdmi_wp_set_phy_pwr(struct hdmi_wp_data *wp, enum hdmi_phy_pwr val)
70{
71 /* Return if already the state */
72 if (REG_GET(wp->base, HDMI_WP_PWR_CTRL, 5, 4) == val)
73 return 0;
74
75 /* Command for power control of HDMI PHY */
76 REG_FLD_MOD(wp->base, HDMI_WP_PWR_CTRL, val, 7, 6);
77
78 /* Status of the power control of HDMI PHY */
79 if (hdmi_wait_for_bit_change(wp->base, HDMI_WP_PWR_CTRL, 5, 4, val)
80 != val) {
81 DSSERR("Failed to set PHY power mode to %d\n", val);
82 return -ETIMEDOUT;
83 }
84
85 return 0;
86}
87
88/* PLL_PWR_CMD */
89int hdmi_wp_set_pll_pwr(struct hdmi_wp_data *wp, enum hdmi_pll_pwr val)
90{
91 /* Command for power control of HDMI PLL */
92 REG_FLD_MOD(wp->base, HDMI_WP_PWR_CTRL, val, 3, 2);
93
94 /* wait till PHY_PWR_STATUS is set */
95 if (hdmi_wait_for_bit_change(wp->base, HDMI_WP_PWR_CTRL, 1, 0, val)
96 != val) {
97 DSSERR("Failed to set PLL_PWR_STATUS\n");
98 return -ETIMEDOUT;
99 }
100
101 return 0;
102}
103
104int hdmi_wp_video_start(struct hdmi_wp_data *wp)
105{
106 REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, true, 31, 31);
107
108 return 0;
109}
110
111void hdmi_wp_video_stop(struct hdmi_wp_data *wp)
112{
113 REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, false, 31, 31);
114}
115
116void hdmi_wp_video_config_format(struct hdmi_wp_data *wp,
117 struct hdmi_video_format *video_fmt)
118{
119 u32 l = 0;
120
121 REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, video_fmt->packing_mode,
122 10, 8);
123
124 l |= FLD_VAL(video_fmt->y_res, 31, 16);
125 l |= FLD_VAL(video_fmt->x_res, 15, 0);
126 hdmi_write_reg(wp->base, HDMI_WP_VIDEO_SIZE, l);
127}
128
129void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp,
130 struct omap_video_timings *timings)
131{
132 u32 r;
133 bool vsync_pol, hsync_pol;
134 DSSDBG("Enter hdmi_wp_video_config_interface\n");
135
136 vsync_pol = timings->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH;
137 hsync_pol = timings->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH;
138
139 r = hdmi_read_reg(wp->base, HDMI_WP_VIDEO_CFG);
140 r = FLD_MOD(r, vsync_pol, 7, 7);
141 r = FLD_MOD(r, hsync_pol, 6, 6);
142 r = FLD_MOD(r, timings->interlace, 3, 3);
143 r = FLD_MOD(r, 1, 1, 0); /* HDMI_TIMING_MASTER_24BIT */
144 hdmi_write_reg(wp->base, HDMI_WP_VIDEO_CFG, r);
145}
146
147void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
148 struct omap_video_timings *timings)
149{
150 u32 timing_h = 0;
151 u32 timing_v = 0;
152
153 DSSDBG("Enter hdmi_wp_video_config_timing\n");
154
155 timing_h |= FLD_VAL(timings->hbp, 31, 20);
156 timing_h |= FLD_VAL(timings->hfp, 19, 8);
157 timing_h |= FLD_VAL(timings->hsw, 7, 0);
158 hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_H, timing_h);
159
160 timing_v |= FLD_VAL(timings->vbp, 31, 20);
161 timing_v |= FLD_VAL(timings->vfp, 19, 8);
162 timing_v |= FLD_VAL(timings->vsw, 7, 0);
163 hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_V, timing_v);
164}
165
166void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
167 struct omap_video_timings *timings, struct hdmi_config *param)
168{
169 DSSDBG("Enter hdmi_wp_video_init_format\n");
170
171 video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444;
172 video_fmt->y_res = param->timings.y_res;
173 video_fmt->x_res = param->timings.x_res;
174 if (param->timings.interlace)
175 video_fmt->y_res /= 2;
176
177 timings->hbp = param->timings.hbp;
178 timings->hfp = param->timings.hfp;
179 timings->hsw = param->timings.hsw;
180 timings->vbp = param->timings.vbp;
181 timings->vfp = param->timings.vfp;
182 timings->vsw = param->timings.vsw;
183 timings->vsync_level = param->timings.vsync_level;
184 timings->hsync_level = param->timings.hsync_level;
185 timings->interlace = param->timings.interlace;
186}
187
188#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
189void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,
190 struct hdmi_audio_format *aud_fmt)
191{
192 u32 r;
193
194 DSSDBG("Enter hdmi_wp_audio_config_format\n");
195
196 r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG);
197 r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
198 r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
199 r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5);
200 r = FLD_MOD(r, aud_fmt->type, 4, 4);
201 r = FLD_MOD(r, aud_fmt->justification, 3, 3);
202 r = FLD_MOD(r, aud_fmt->sample_order, 2, 2);
203 r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1);
204 r = FLD_MOD(r, aud_fmt->sample_size, 0, 0);
205 hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CFG, r);
206}
207
208void hdmi_wp_audio_config_dma(struct hdmi_wp_data *wp,
209 struct hdmi_audio_dma *aud_dma)
210{
211 u32 r;
212
213 DSSDBG("Enter hdmi_wp_audio_config_dma\n");
214
215 r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG2);
216 r = FLD_MOD(r, aud_dma->transfer_size, 15, 8);
217 r = FLD_MOD(r, aud_dma->block_size, 7, 0);
218 hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CFG2, r);
219
220 r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CTRL);
221 r = FLD_MOD(r, aud_dma->mode, 9, 9);
222 r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0);
223 hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CTRL, r);
224}
225
226int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable)
227{
228 REG_FLD_MOD(wp->base, HDMI_WP_AUDIO_CTRL, enable, 31, 31);
229
230 return 0;
231}
232
233int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable)
234{
235 REG_FLD_MOD(wp->base, HDMI_WP_AUDIO_CTRL, enable, 30, 30);
236
237 return 0;
238}
239#endif
240
241#define WP_SIZE 0x200
242
243int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp)
244{
245 struct resource *res;
246 struct resource temp_res;
247
248 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wp");
249 if (!res) {
250 DSSDBG("can't get WP mem resource by name\n");
251 /*
252 * if hwmod/DT doesn't have the memory resource information
253 * split into HDMI sub blocks by name, we try again by getting
254 * the platform's first resource. this code will be removed when
255 * the driver can get the mem resources by name
256 */
257 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
258 if (!res) {
259 DSSERR("can't get WP mem resource\n");
260 return -EINVAL;
261 }
262
263 temp_res.start = res->start;
264 temp_res.end = temp_res.start + WP_SIZE - 1;
265 res = &temp_res;
266 }
267
268 wp->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
269 if (!wp->base) {
270 DSSERR("can't ioremap HDMI WP\n");
271 return -ENOMEM;
272 }
273
274 return 0;
275}
diff --git a/drivers/video/omap2/dss/manager-sysfs.c b/drivers/video/omap2/dss/manager-sysfs.c
deleted file mode 100644
index 37b59fe28dc8..000000000000
--- a/drivers/video/omap2/dss/manager-sysfs.c
+++ /dev/null
@@ -1,529 +0,0 @@
1/*
2 * Copyright (C) 2009 Nokia Corporation
3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4 *
5 * Some code and ideas taken from drivers/video/omap/ driver
6 * by Imre Deak.
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 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#define DSS_SUBSYS_NAME "MANAGER"
22
23#include <linux/kernel.h>
24#include <linux/slab.h>
25#include <linux/module.h>
26#include <linux/platform_device.h>
27#include <linux/jiffies.h>
28
29#include <video/omapdss.h>
30
31#include "dss.h"
32#include "dss_features.h"
33
34static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
35{
36 return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
37}
38
39static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
40{
41 struct omap_dss_device *dssdev = mgr->get_device(mgr);
42
43 return snprintf(buf, PAGE_SIZE, "%s\n", dssdev ?
44 dssdev->name : "<none>");
45}
46
47static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
48 const char *buf, size_t size)
49{
50 int r = 0;
51 size_t len = size;
52 struct omap_dss_device *dssdev = NULL;
53 struct omap_dss_device *old_dssdev;
54
55 int match(struct omap_dss_device *dssdev, void *data)
56 {
57 const char *str = data;
58 return sysfs_streq(dssdev->name, str);
59 }
60
61 if (buf[size-1] == '\n')
62 --len;
63
64 if (len > 0)
65 dssdev = omap_dss_find_device((void *)buf, match);
66
67 if (len > 0 && dssdev == NULL)
68 return -EINVAL;
69
70 if (dssdev) {
71 DSSDBG("display %s found\n", dssdev->name);
72
73 if (omapdss_device_is_connected(dssdev)) {
74 DSSERR("new display is already connected\n");
75 r = -EINVAL;
76 goto put_device;
77 }
78
79 if (omapdss_device_is_enabled(dssdev)) {
80 DSSERR("new display is not disabled\n");
81 r = -EINVAL;
82 goto put_device;
83 }
84 }
85
86 old_dssdev = mgr->get_device(mgr);
87 if (old_dssdev) {
88 if (omapdss_device_is_enabled(old_dssdev)) {
89 DSSERR("old display is not disabled\n");
90 r = -EINVAL;
91 goto put_device;
92 }
93
94 old_dssdev->driver->disconnect(old_dssdev);
95 }
96
97 if (dssdev) {
98 r = dssdev->driver->connect(dssdev);
99 if (r) {
100 DSSERR("failed to connect new device\n");
101 goto put_device;
102 }
103
104 old_dssdev = mgr->get_device(mgr);
105 if (old_dssdev != dssdev) {
106 DSSERR("failed to connect device to this manager\n");
107 dssdev->driver->disconnect(dssdev);
108 goto put_device;
109 }
110
111 r = mgr->apply(mgr);
112 if (r) {
113 DSSERR("failed to apply dispc config\n");
114 goto put_device;
115 }
116 }
117
118put_device:
119 if (dssdev)
120 omap_dss_put_device(dssdev);
121
122 return r ? r : size;
123}
124
125static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
126 char *buf)
127{
128 struct omap_overlay_manager_info info;
129
130 mgr->get_manager_info(mgr, &info);
131
132 return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
133}
134
135static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
136 const char *buf, size_t size)
137{
138 struct omap_overlay_manager_info info;
139 u32 color;
140 int r;
141
142 r = kstrtouint(buf, 0, &color);
143 if (r)
144 return r;
145
146 mgr->get_manager_info(mgr, &info);
147
148 info.default_color = color;
149
150 r = mgr->set_manager_info(mgr, &info);
151 if (r)
152 return r;
153
154 r = mgr->apply(mgr);
155 if (r)
156 return r;
157
158 return size;
159}
160
161static const char *trans_key_type_str[] = {
162 "gfx-destination",
163 "video-source",
164};
165
166static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
167 char *buf)
168{
169 enum omap_dss_trans_key_type key_type;
170 struct omap_overlay_manager_info info;
171
172 mgr->get_manager_info(mgr, &info);
173
174 key_type = info.trans_key_type;
175 BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
176
177 return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
178}
179
180static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
181 const char *buf, size_t size)
182{
183 enum omap_dss_trans_key_type key_type;
184 struct omap_overlay_manager_info info;
185 int r;
186
187 for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
188 key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
189 if (sysfs_streq(buf, trans_key_type_str[key_type]))
190 break;
191 }
192
193 if (key_type == ARRAY_SIZE(trans_key_type_str))
194 return -EINVAL;
195
196 mgr->get_manager_info(mgr, &info);
197
198 info.trans_key_type = key_type;
199
200 r = mgr->set_manager_info(mgr, &info);
201 if (r)
202 return r;
203
204 r = mgr->apply(mgr);
205 if (r)
206 return r;
207
208 return size;
209}
210
211static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
212 char *buf)
213{
214 struct omap_overlay_manager_info info;
215
216 mgr->get_manager_info(mgr, &info);
217
218 return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
219}
220
221static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
222 const char *buf, size_t size)
223{
224 struct omap_overlay_manager_info info;
225 u32 key_value;
226 int r;
227
228 r = kstrtouint(buf, 0, &key_value);
229 if (r)
230 return r;
231
232 mgr->get_manager_info(mgr, &info);
233
234 info.trans_key = key_value;
235
236 r = mgr->set_manager_info(mgr, &info);
237 if (r)
238 return r;
239
240 r = mgr->apply(mgr);
241 if (r)
242 return r;
243
244 return size;
245}
246
247static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
248 char *buf)
249{
250 struct omap_overlay_manager_info info;
251
252 mgr->get_manager_info(mgr, &info);
253
254 return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
255}
256
257static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
258 const char *buf, size_t size)
259{
260 struct omap_overlay_manager_info info;
261 bool enable;
262 int r;
263
264 r = strtobool(buf, &enable);
265 if (r)
266 return r;
267
268 mgr->get_manager_info(mgr, &info);
269
270 info.trans_enabled = enable;
271
272 r = mgr->set_manager_info(mgr, &info);
273 if (r)
274 return r;
275
276 r = mgr->apply(mgr);
277 if (r)
278 return r;
279
280 return size;
281}
282
283static ssize_t manager_alpha_blending_enabled_show(
284 struct omap_overlay_manager *mgr, char *buf)
285{
286 struct omap_overlay_manager_info info;
287
288 if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
289 return -ENODEV;
290
291 mgr->get_manager_info(mgr, &info);
292
293 return snprintf(buf, PAGE_SIZE, "%d\n",
294 info.partial_alpha_enabled);
295}
296
297static ssize_t manager_alpha_blending_enabled_store(
298 struct omap_overlay_manager *mgr,
299 const char *buf, size_t size)
300{
301 struct omap_overlay_manager_info info;
302 bool enable;
303 int r;
304
305 if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
306 return -ENODEV;
307
308 r = strtobool(buf, &enable);
309 if (r)
310 return r;
311
312 mgr->get_manager_info(mgr, &info);
313
314 info.partial_alpha_enabled = enable;
315
316 r = mgr->set_manager_info(mgr, &info);
317 if (r)
318 return r;
319
320 r = mgr->apply(mgr);
321 if (r)
322 return r;
323
324 return size;
325}
326
327static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
328 char *buf)
329{
330 struct omap_overlay_manager_info info;
331
332 mgr->get_manager_info(mgr, &info);
333
334 return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
335}
336
337static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
338 const char *buf, size_t size)
339{
340 struct omap_overlay_manager_info info;
341 int r;
342 bool enable;
343
344 if (!dss_has_feature(FEAT_CPR))
345 return -ENODEV;
346
347 r = strtobool(buf, &enable);
348 if (r)
349 return r;
350
351 mgr->get_manager_info(mgr, &info);
352
353 if (info.cpr_enable == enable)
354 return size;
355
356 info.cpr_enable = enable;
357
358 r = mgr->set_manager_info(mgr, &info);
359 if (r)
360 return r;
361
362 r = mgr->apply(mgr);
363 if (r)
364 return r;
365
366 return size;
367}
368
369static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
370 char *buf)
371{
372 struct omap_overlay_manager_info info;
373
374 mgr->get_manager_info(mgr, &info);
375
376 return snprintf(buf, PAGE_SIZE,
377 "%d %d %d %d %d %d %d %d %d\n",
378 info.cpr_coefs.rr,
379 info.cpr_coefs.rg,
380 info.cpr_coefs.rb,
381 info.cpr_coefs.gr,
382 info.cpr_coefs.gg,
383 info.cpr_coefs.gb,
384 info.cpr_coefs.br,
385 info.cpr_coefs.bg,
386 info.cpr_coefs.bb);
387}
388
389static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
390 const char *buf, size_t size)
391{
392 struct omap_overlay_manager_info info;
393 struct omap_dss_cpr_coefs coefs;
394 int r, i;
395 s16 *arr;
396
397 if (!dss_has_feature(FEAT_CPR))
398 return -ENODEV;
399
400 if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
401 &coefs.rr, &coefs.rg, &coefs.rb,
402 &coefs.gr, &coefs.gg, &coefs.gb,
403 &coefs.br, &coefs.bg, &coefs.bb) != 9)
404 return -EINVAL;
405
406 arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
407 coefs.gr, coefs.gg, coefs.gb,
408 coefs.br, coefs.bg, coefs.bb };
409
410 for (i = 0; i < 9; ++i) {
411 if (arr[i] < -512 || arr[i] > 511)
412 return -EINVAL;
413 }
414
415 mgr->get_manager_info(mgr, &info);
416
417 info.cpr_coefs = coefs;
418
419 r = mgr->set_manager_info(mgr, &info);
420 if (r)
421 return r;
422
423 r = mgr->apply(mgr);
424 if (r)
425 return r;
426
427 return size;
428}
429
430struct manager_attribute {
431 struct attribute attr;
432 ssize_t (*show)(struct omap_overlay_manager *, char *);
433 ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
434};
435
436#define MANAGER_ATTR(_name, _mode, _show, _store) \
437 struct manager_attribute manager_attr_##_name = \
438 __ATTR(_name, _mode, _show, _store)
439
440static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
441static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
442 manager_display_show, manager_display_store);
443static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
444 manager_default_color_show, manager_default_color_store);
445static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
446 manager_trans_key_type_show, manager_trans_key_type_store);
447static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
448 manager_trans_key_value_show, manager_trans_key_value_store);
449static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
450 manager_trans_key_enabled_show,
451 manager_trans_key_enabled_store);
452static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
453 manager_alpha_blending_enabled_show,
454 manager_alpha_blending_enabled_store);
455static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
456 manager_cpr_enable_show,
457 manager_cpr_enable_store);
458static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
459 manager_cpr_coef_show,
460 manager_cpr_coef_store);
461
462
463static struct attribute *manager_sysfs_attrs[] = {
464 &manager_attr_name.attr,
465 &manager_attr_display.attr,
466 &manager_attr_default_color.attr,
467 &manager_attr_trans_key_type.attr,
468 &manager_attr_trans_key_value.attr,
469 &manager_attr_trans_key_enabled.attr,
470 &manager_attr_alpha_blending_enabled.attr,
471 &manager_attr_cpr_enable.attr,
472 &manager_attr_cpr_coef.attr,
473 NULL
474};
475
476static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
477 char *buf)
478{
479 struct omap_overlay_manager *manager;
480 struct manager_attribute *manager_attr;
481
482 manager = container_of(kobj, struct omap_overlay_manager, kobj);
483 manager_attr = container_of(attr, struct manager_attribute, attr);
484
485 if (!manager_attr->show)
486 return -ENOENT;
487
488 return manager_attr->show(manager, buf);
489}
490
491static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
492 const char *buf, size_t size)
493{
494 struct omap_overlay_manager *manager;
495 struct manager_attribute *manager_attr;
496
497 manager = container_of(kobj, struct omap_overlay_manager, kobj);
498 manager_attr = container_of(attr, struct manager_attribute, attr);
499
500 if (!manager_attr->store)
501 return -ENOENT;
502
503 return manager_attr->store(manager, buf, size);
504}
505
506static const struct sysfs_ops manager_sysfs_ops = {
507 .show = manager_attr_show,
508 .store = manager_attr_store,
509};
510
511static struct kobj_type manager_ktype = {
512 .sysfs_ops = &manager_sysfs_ops,
513 .default_attrs = manager_sysfs_attrs,
514};
515
516int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
517 struct platform_device *pdev)
518{
519 return kobject_init_and_add(&mgr->kobj, &manager_ktype,
520 &pdev->dev.kobj, "manager%d", mgr->id);
521}
522
523void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr)
524{
525 kobject_del(&mgr->kobj);
526 kobject_put(&mgr->kobj);
527
528 memset(&mgr->kobj, 0, sizeof(mgr->kobj));
529}
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
deleted file mode 100644
index 1aac9b4191a9..000000000000
--- a/drivers/video/omap2/dss/manager.c
+++ /dev/null
@@ -1,263 +0,0 @@
1/*
2 * linux/drivers/video/omap2/dss/manager.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
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#define DSS_SUBSYS_NAME "MANAGER"
24
25#include <linux/kernel.h>
26#include <linux/slab.h>
27#include <linux/module.h>
28#include <linux/platform_device.h>
29#include <linux/jiffies.h>
30
31#include <video/omapdss.h>
32
33#include "dss.h"
34#include "dss_features.h"
35
36static int num_managers;
37static struct omap_overlay_manager *managers;
38
39int dss_init_overlay_managers(void)
40{
41 int i;
42
43 num_managers = dss_feat_get_num_mgrs();
44
45 managers = kzalloc(sizeof(struct omap_overlay_manager) * num_managers,
46 GFP_KERNEL);
47
48 BUG_ON(managers == NULL);
49
50 for (i = 0; i < num_managers; ++i) {
51 struct omap_overlay_manager *mgr = &managers[i];
52
53 switch (i) {
54 case 0:
55 mgr->name = "lcd";
56 mgr->id = OMAP_DSS_CHANNEL_LCD;
57 break;
58 case 1:
59 mgr->name = "tv";
60 mgr->id = OMAP_DSS_CHANNEL_DIGIT;
61 break;
62 case 2:
63 mgr->name = "lcd2";
64 mgr->id = OMAP_DSS_CHANNEL_LCD2;
65 break;
66 case 3:
67 mgr->name = "lcd3";
68 mgr->id = OMAP_DSS_CHANNEL_LCD3;
69 break;
70 }
71
72 mgr->caps = 0;
73 mgr->supported_displays =
74 dss_feat_get_supported_displays(mgr->id);
75 mgr->supported_outputs =
76 dss_feat_get_supported_outputs(mgr->id);
77
78 INIT_LIST_HEAD(&mgr->overlays);
79 }
80
81 return 0;
82}
83
84int dss_init_overlay_managers_sysfs(struct platform_device *pdev)
85{
86 int i, r;
87
88 for (i = 0; i < num_managers; ++i) {
89 struct omap_overlay_manager *mgr = &managers[i];
90
91 r = dss_manager_kobj_init(mgr, pdev);
92 if (r)
93 DSSERR("failed to create sysfs file\n");
94 }
95
96 return 0;
97}
98
99void dss_uninit_overlay_managers(void)
100{
101 kfree(managers);
102 managers = NULL;
103 num_managers = 0;
104}
105
106void dss_uninit_overlay_managers_sysfs(struct platform_device *pdev)
107{
108 int i;
109
110 for (i = 0; i < num_managers; ++i) {
111 struct omap_overlay_manager *mgr = &managers[i];
112
113 dss_manager_kobj_uninit(mgr);
114 }
115}
116
117int omap_dss_get_num_overlay_managers(void)
118{
119 return num_managers;
120}
121EXPORT_SYMBOL(omap_dss_get_num_overlay_managers);
122
123struct omap_overlay_manager *omap_dss_get_overlay_manager(int num)
124{
125 if (num >= num_managers)
126 return NULL;
127
128 return &managers[num];
129}
130EXPORT_SYMBOL(omap_dss_get_overlay_manager);
131
132int dss_mgr_simple_check(struct omap_overlay_manager *mgr,
133 const struct omap_overlay_manager_info *info)
134{
135 if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) {
136 /*
137 * OMAP3 supports only graphics source transparency color key
138 * and alpha blending simultaneously. See TRM 15.4.2.4.2.2
139 * Alpha Mode.
140 */
141 if (info->partial_alpha_enabled && info->trans_enabled
142 && info->trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST) {
143 DSSERR("check_manager: illegal transparency key\n");
144 return -EINVAL;
145 }
146 }
147
148 return 0;
149}
150
151static int dss_mgr_check_zorder(struct omap_overlay_manager *mgr,
152 struct omap_overlay_info **overlay_infos)
153{
154 struct omap_overlay *ovl1, *ovl2;
155 struct omap_overlay_info *info1, *info2;
156
157 list_for_each_entry(ovl1, &mgr->overlays, list) {
158 info1 = overlay_infos[ovl1->id];
159
160 if (info1 == NULL)
161 continue;
162
163 list_for_each_entry(ovl2, &mgr->overlays, list) {
164 if (ovl1 == ovl2)
165 continue;
166
167 info2 = overlay_infos[ovl2->id];
168
169 if (info2 == NULL)
170 continue;
171
172 if (info1->zorder == info2->zorder) {
173 DSSERR("overlays %d and %d have the same "
174 "zorder %d\n",
175 ovl1->id, ovl2->id, info1->zorder);
176 return -EINVAL;
177 }
178 }
179 }
180
181 return 0;
182}
183
184int dss_mgr_check_timings(struct omap_overlay_manager *mgr,
185 const struct omap_video_timings *timings)
186{
187 if (!dispc_mgr_timings_ok(mgr->id, timings)) {
188 DSSERR("check_manager: invalid timings\n");
189 return -EINVAL;
190 }
191
192 return 0;
193}
194
195static int dss_mgr_check_lcd_config(struct omap_overlay_manager *mgr,
196 const struct dss_lcd_mgr_config *config)
197{
198 struct dispc_clock_info cinfo = config->clock_info;
199 int dl = config->video_port_width;
200 bool stallmode = config->stallmode;
201 bool fifohandcheck = config->fifohandcheck;
202
203 if (cinfo.lck_div < 1 || cinfo.lck_div > 255)
204 return -EINVAL;
205
206 if (cinfo.pck_div < 1 || cinfo.pck_div > 255)
207 return -EINVAL;
208
209 if (dl != 12 && dl != 16 && dl != 18 && dl != 24)
210 return -EINVAL;
211
212 /* fifohandcheck should be used only with stallmode */
213 if (stallmode == false && fifohandcheck == true)
214 return -EINVAL;
215
216 /*
217 * io pad mode can be only checked by using dssdev connected to the
218 * manager. Ignore checking these for now, add checks when manager
219 * is capable of holding information related to the connected interface
220 */
221
222 return 0;
223}
224
225int dss_mgr_check(struct omap_overlay_manager *mgr,
226 struct omap_overlay_manager_info *info,
227 const struct omap_video_timings *mgr_timings,
228 const struct dss_lcd_mgr_config *lcd_config,
229 struct omap_overlay_info **overlay_infos)
230{
231 struct omap_overlay *ovl;
232 int r;
233
234 if (dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) {
235 r = dss_mgr_check_zorder(mgr, overlay_infos);
236 if (r)
237 return r;
238 }
239
240 r = dss_mgr_check_timings(mgr, mgr_timings);
241 if (r)
242 return r;
243
244 r = dss_mgr_check_lcd_config(mgr, lcd_config);
245 if (r)
246 return r;
247
248 list_for_each_entry(ovl, &mgr->overlays, list) {
249 struct omap_overlay_info *oi;
250 int r;
251
252 oi = overlay_infos[ovl->id];
253
254 if (oi == NULL)
255 continue;
256
257 r = dss_ovl_check(ovl, oi, mgr_timings);
258 if (r)
259 return r;
260 }
261
262 return 0;
263}
diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c
deleted file mode 100644
index 2ab3afa615e8..000000000000
--- a/drivers/video/omap2/dss/output.c
+++ /dev/null
@@ -1,254 +0,0 @@
1/*
2 * Copyright (C) 2012 Texas Instruments Ltd
3 * Author: Archit Taneja <archit@ti.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/platform_device.h>
21#include <linux/slab.h>
22
23#include <video/omapdss.h>
24
25#include "dss.h"
26
27static LIST_HEAD(output_list);
28static DEFINE_MUTEX(output_lock);
29
30int omapdss_output_set_device(struct omap_dss_device *out,
31 struct omap_dss_device *dssdev)
32{
33 int r;
34
35 mutex_lock(&output_lock);
36
37 if (out->dst) {
38 DSSERR("output already has device %s connected to it\n",
39 out->dst->name);
40 r = -EINVAL;
41 goto err;
42 }
43
44 if (out->output_type != dssdev->type) {
45 DSSERR("output type and display type don't match\n");
46 r = -EINVAL;
47 goto err;
48 }
49
50 out->dst = dssdev;
51 dssdev->src = out;
52
53 mutex_unlock(&output_lock);
54
55 return 0;
56err:
57 mutex_unlock(&output_lock);
58
59 return r;
60}
61EXPORT_SYMBOL(omapdss_output_set_device);
62
63int omapdss_output_unset_device(struct omap_dss_device *out)
64{
65 int r;
66
67 mutex_lock(&output_lock);
68
69 if (!out->dst) {
70 DSSERR("output doesn't have a device connected to it\n");
71 r = -EINVAL;
72 goto err;
73 }
74
75 if (out->dst->state != OMAP_DSS_DISPLAY_DISABLED) {
76 DSSERR("device %s is not disabled, cannot unset device\n",
77 out->dst->name);
78 r = -EINVAL;
79 goto err;
80 }
81
82 out->dst->src = NULL;
83 out->dst = NULL;
84
85 mutex_unlock(&output_lock);
86
87 return 0;
88err:
89 mutex_unlock(&output_lock);
90
91 return r;
92}
93EXPORT_SYMBOL(omapdss_output_unset_device);
94
95int omapdss_register_output(struct omap_dss_device *out)
96{
97 list_add_tail(&out->list, &output_list);
98 return 0;
99}
100EXPORT_SYMBOL(omapdss_register_output);
101
102void omapdss_unregister_output(struct omap_dss_device *out)
103{
104 list_del(&out->list);
105}
106EXPORT_SYMBOL(omapdss_unregister_output);
107
108struct omap_dss_device *omap_dss_get_output(enum omap_dss_output_id id)
109{
110 struct omap_dss_device *out;
111
112 list_for_each_entry(out, &output_list, list) {
113 if (out->id == id)
114 return out;
115 }
116
117 return NULL;
118}
119EXPORT_SYMBOL(omap_dss_get_output);
120
121struct omap_dss_device *omap_dss_find_output(const char *name)
122{
123 struct omap_dss_device *out;
124
125 list_for_each_entry(out, &output_list, list) {
126 if (strcmp(out->name, name) == 0)
127 return omap_dss_get_device(out);
128 }
129
130 return NULL;
131}
132EXPORT_SYMBOL(omap_dss_find_output);
133
134struct omap_dss_device *omap_dss_find_output_by_node(struct device_node *node)
135{
136 struct omap_dss_device *out;
137
138 list_for_each_entry(out, &output_list, list) {
139 if (out->dev->of_node == node)
140 return omap_dss_get_device(out);
141 }
142
143 return NULL;
144}
145EXPORT_SYMBOL(omap_dss_find_output_by_node);
146
147struct omap_dss_device *omapdss_find_output_from_display(struct omap_dss_device *dssdev)
148{
149 while (dssdev->src)
150 dssdev = dssdev->src;
151
152 if (dssdev->id != 0)
153 return omap_dss_get_device(dssdev);
154
155 return NULL;
156}
157EXPORT_SYMBOL(omapdss_find_output_from_display);
158
159struct omap_overlay_manager *omapdss_find_mgr_from_display(struct omap_dss_device *dssdev)
160{
161 struct omap_dss_device *out;
162 struct omap_overlay_manager *mgr;
163
164 out = omapdss_find_output_from_display(dssdev);
165
166 if (out == NULL)
167 return NULL;
168
169 mgr = out->manager;
170
171 omap_dss_put_device(out);
172
173 return mgr;
174}
175EXPORT_SYMBOL(omapdss_find_mgr_from_display);
176
177static const struct dss_mgr_ops *dss_mgr_ops;
178
179int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops)
180{
181 if (dss_mgr_ops)
182 return -EBUSY;
183
184 dss_mgr_ops = mgr_ops;
185
186 return 0;
187}
188EXPORT_SYMBOL(dss_install_mgr_ops);
189
190void dss_uninstall_mgr_ops(void)
191{
192 dss_mgr_ops = NULL;
193}
194EXPORT_SYMBOL(dss_uninstall_mgr_ops);
195
196int dss_mgr_connect(struct omap_overlay_manager *mgr,
197 struct omap_dss_device *dst)
198{
199 return dss_mgr_ops->connect(mgr, dst);
200}
201EXPORT_SYMBOL(dss_mgr_connect);
202
203void dss_mgr_disconnect(struct omap_overlay_manager *mgr,
204 struct omap_dss_device *dst)
205{
206 dss_mgr_ops->disconnect(mgr, dst);
207}
208EXPORT_SYMBOL(dss_mgr_disconnect);
209
210void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
211 const struct omap_video_timings *timings)
212{
213 dss_mgr_ops->set_timings(mgr, timings);
214}
215EXPORT_SYMBOL(dss_mgr_set_timings);
216
217void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
218 const struct dss_lcd_mgr_config *config)
219{
220 dss_mgr_ops->set_lcd_config(mgr, config);
221}
222EXPORT_SYMBOL(dss_mgr_set_lcd_config);
223
224int dss_mgr_enable(struct omap_overlay_manager *mgr)
225{
226 return dss_mgr_ops->enable(mgr);
227}
228EXPORT_SYMBOL(dss_mgr_enable);
229
230void dss_mgr_disable(struct omap_overlay_manager *mgr)
231{
232 dss_mgr_ops->disable(mgr);
233}
234EXPORT_SYMBOL(dss_mgr_disable);
235
236void dss_mgr_start_update(struct omap_overlay_manager *mgr)
237{
238 dss_mgr_ops->start_update(mgr);
239}
240EXPORT_SYMBOL(dss_mgr_start_update);
241
242int dss_mgr_register_framedone_handler(struct omap_overlay_manager *mgr,
243 void (*handler)(void *), void *data)
244{
245 return dss_mgr_ops->register_framedone_handler(mgr, handler, data);
246}
247EXPORT_SYMBOL(dss_mgr_register_framedone_handler);
248
249void dss_mgr_unregister_framedone_handler(struct omap_overlay_manager *mgr,
250 void (*handler)(void *), void *data)
251{
252 dss_mgr_ops->unregister_framedone_handler(mgr, handler, data);
253}
254EXPORT_SYMBOL(dss_mgr_unregister_framedone_handler);
diff --git a/drivers/video/omap2/dss/overlay-sysfs.c b/drivers/video/omap2/dss/overlay-sysfs.c
deleted file mode 100644
index 4cc5ddebfb34..000000000000
--- a/drivers/video/omap2/dss/overlay-sysfs.c
+++ /dev/null
@@ -1,456 +0,0 @@
1/*
2 * Copyright (C) 2009 Nokia Corporation
3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4 *
5 * Some code and ideas taken from drivers/video/omap/ driver
6 * by Imre Deak.
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 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#define DSS_SUBSYS_NAME "OVERLAY"
22
23#include <linux/module.h>
24#include <linux/err.h>
25#include <linux/sysfs.h>
26#include <linux/kobject.h>
27#include <linux/platform_device.h>
28
29#include <video/omapdss.h>
30
31#include "dss.h"
32#include "dss_features.h"
33
34static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
35{
36 return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
37}
38
39static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
40{
41 return snprintf(buf, PAGE_SIZE, "%s\n",
42 ovl->manager ? ovl->manager->name : "<none>");
43}
44
45static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
46 size_t size)
47{
48 int i, r;
49 struct omap_overlay_manager *mgr = NULL;
50 struct omap_overlay_manager *old_mgr;
51 int len = size;
52
53 if (buf[size-1] == '\n')
54 --len;
55
56 if (len > 0) {
57 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
58 mgr = omap_dss_get_overlay_manager(i);
59
60 if (sysfs_streq(buf, mgr->name))
61 break;
62
63 mgr = NULL;
64 }
65 }
66
67 if (len > 0 && mgr == NULL)
68 return -EINVAL;
69
70 if (mgr)
71 DSSDBG("manager %s found\n", mgr->name);
72
73 if (mgr == ovl->manager)
74 return size;
75
76 old_mgr = ovl->manager;
77
78 r = dispc_runtime_get();
79 if (r)
80 return r;
81
82 /* detach old manager */
83 if (old_mgr) {
84 r = ovl->unset_manager(ovl);
85 if (r) {
86 DSSERR("detach failed\n");
87 goto err;
88 }
89
90 r = old_mgr->apply(old_mgr);
91 if (r)
92 goto err;
93 }
94
95 if (mgr) {
96 r = ovl->set_manager(ovl, mgr);
97 if (r) {
98 DSSERR("Failed to attach overlay\n");
99 goto err;
100 }
101
102 r = mgr->apply(mgr);
103 if (r)
104 goto err;
105 }
106
107 dispc_runtime_put();
108
109 return size;
110
111err:
112 dispc_runtime_put();
113 return r;
114}
115
116static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
117{
118 struct omap_overlay_info info;
119
120 ovl->get_overlay_info(ovl, &info);
121
122 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
123 info.width, info.height);
124}
125
126static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
127{
128 struct omap_overlay_info info;
129
130 ovl->get_overlay_info(ovl, &info);
131
132 return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
133}
134
135static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
136{
137 struct omap_overlay_info info;
138
139 ovl->get_overlay_info(ovl, &info);
140
141 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
142 info.pos_x, info.pos_y);
143}
144
145static ssize_t overlay_position_store(struct omap_overlay *ovl,
146 const char *buf, size_t size)
147{
148 int r;
149 char *last;
150 struct omap_overlay_info info;
151
152 ovl->get_overlay_info(ovl, &info);
153
154 info.pos_x = simple_strtoul(buf, &last, 10);
155 ++last;
156 if (last - buf >= size)
157 return -EINVAL;
158
159 info.pos_y = simple_strtoul(last, &last, 10);
160
161 r = ovl->set_overlay_info(ovl, &info);
162 if (r)
163 return r;
164
165 if (ovl->manager) {
166 r = ovl->manager->apply(ovl->manager);
167 if (r)
168 return r;
169 }
170
171 return size;
172}
173
174static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
175{
176 struct omap_overlay_info info;
177
178 ovl->get_overlay_info(ovl, &info);
179
180 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
181 info.out_width, info.out_height);
182}
183
184static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
185 const char *buf, size_t size)
186{
187 int r;
188 char *last;
189 struct omap_overlay_info info;
190
191 ovl->get_overlay_info(ovl, &info);
192
193 info.out_width = simple_strtoul(buf, &last, 10);
194 ++last;
195 if (last - buf >= size)
196 return -EINVAL;
197
198 info.out_height = simple_strtoul(last, &last, 10);
199
200 r = ovl->set_overlay_info(ovl, &info);
201 if (r)
202 return r;
203
204 if (ovl->manager) {
205 r = ovl->manager->apply(ovl->manager);
206 if (r)
207 return r;
208 }
209
210 return size;
211}
212
213static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
214{
215 return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
216}
217
218static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
219 size_t size)
220{
221 int r;
222 bool enable;
223
224 r = strtobool(buf, &enable);
225 if (r)
226 return r;
227
228 if (enable)
229 r = ovl->enable(ovl);
230 else
231 r = ovl->disable(ovl);
232
233 if (r)
234 return r;
235
236 return size;
237}
238
239static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
240{
241 struct omap_overlay_info info;
242
243 ovl->get_overlay_info(ovl, &info);
244
245 return snprintf(buf, PAGE_SIZE, "%d\n",
246 info.global_alpha);
247}
248
249static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
250 const char *buf, size_t size)
251{
252 int r;
253 u8 alpha;
254 struct omap_overlay_info info;
255
256 if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
257 return -ENODEV;
258
259 r = kstrtou8(buf, 0, &alpha);
260 if (r)
261 return r;
262
263 ovl->get_overlay_info(ovl, &info);
264
265 info.global_alpha = alpha;
266
267 r = ovl->set_overlay_info(ovl, &info);
268 if (r)
269 return r;
270
271 if (ovl->manager) {
272 r = ovl->manager->apply(ovl->manager);
273 if (r)
274 return r;
275 }
276
277 return size;
278}
279
280static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
281 char *buf)
282{
283 struct omap_overlay_info info;
284
285 ovl->get_overlay_info(ovl, &info);
286
287 return snprintf(buf, PAGE_SIZE, "%d\n",
288 info.pre_mult_alpha);
289}
290
291static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
292 const char *buf, size_t size)
293{
294 int r;
295 u8 alpha;
296 struct omap_overlay_info info;
297
298 if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
299 return -ENODEV;
300
301 r = kstrtou8(buf, 0, &alpha);
302 if (r)
303 return r;
304
305 ovl->get_overlay_info(ovl, &info);
306
307 info.pre_mult_alpha = alpha;
308
309 r = ovl->set_overlay_info(ovl, &info);
310 if (r)
311 return r;
312
313 if (ovl->manager) {
314 r = ovl->manager->apply(ovl->manager);
315 if (r)
316 return r;
317 }
318
319 return size;
320}
321
322static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
323{
324 struct omap_overlay_info info;
325
326 ovl->get_overlay_info(ovl, &info);
327
328 return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
329}
330
331static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
332 const char *buf, size_t size)
333{
334 int r;
335 u8 zorder;
336 struct omap_overlay_info info;
337
338 if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
339 return -ENODEV;
340
341 r = kstrtou8(buf, 0, &zorder);
342 if (r)
343 return r;
344
345 ovl->get_overlay_info(ovl, &info);
346
347 info.zorder = zorder;
348
349 r = ovl->set_overlay_info(ovl, &info);
350 if (r)
351 return r;
352
353 if (ovl->manager) {
354 r = ovl->manager->apply(ovl->manager);
355 if (r)
356 return r;
357 }
358
359 return size;
360}
361
362struct overlay_attribute {
363 struct attribute attr;
364 ssize_t (*show)(struct omap_overlay *, char *);
365 ssize_t (*store)(struct omap_overlay *, const char *, size_t);
366};
367
368#define OVERLAY_ATTR(_name, _mode, _show, _store) \
369 struct overlay_attribute overlay_attr_##_name = \
370 __ATTR(_name, _mode, _show, _store)
371
372static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
373static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
374 overlay_manager_show, overlay_manager_store);
375static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
376static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
377static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
378 overlay_position_show, overlay_position_store);
379static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
380 overlay_output_size_show, overlay_output_size_store);
381static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
382 overlay_enabled_show, overlay_enabled_store);
383static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
384 overlay_global_alpha_show, overlay_global_alpha_store);
385static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
386 overlay_pre_mult_alpha_show,
387 overlay_pre_mult_alpha_store);
388static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
389 overlay_zorder_show, overlay_zorder_store);
390
391static struct attribute *overlay_sysfs_attrs[] = {
392 &overlay_attr_name.attr,
393 &overlay_attr_manager.attr,
394 &overlay_attr_input_size.attr,
395 &overlay_attr_screen_width.attr,
396 &overlay_attr_position.attr,
397 &overlay_attr_output_size.attr,
398 &overlay_attr_enabled.attr,
399 &overlay_attr_global_alpha.attr,
400 &overlay_attr_pre_mult_alpha.attr,
401 &overlay_attr_zorder.attr,
402 NULL
403};
404
405static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
406 char *buf)
407{
408 struct omap_overlay *overlay;
409 struct overlay_attribute *overlay_attr;
410
411 overlay = container_of(kobj, struct omap_overlay, kobj);
412 overlay_attr = container_of(attr, struct overlay_attribute, attr);
413
414 if (!overlay_attr->show)
415 return -ENOENT;
416
417 return overlay_attr->show(overlay, buf);
418}
419
420static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
421 const char *buf, size_t size)
422{
423 struct omap_overlay *overlay;
424 struct overlay_attribute *overlay_attr;
425
426 overlay = container_of(kobj, struct omap_overlay, kobj);
427 overlay_attr = container_of(attr, struct overlay_attribute, attr);
428
429 if (!overlay_attr->store)
430 return -ENOENT;
431
432 return overlay_attr->store(overlay, buf, size);
433}
434
435static const struct sysfs_ops overlay_sysfs_ops = {
436 .show = overlay_attr_show,
437 .store = overlay_attr_store,
438};
439
440static struct kobj_type overlay_ktype = {
441 .sysfs_ops = &overlay_sysfs_ops,
442 .default_attrs = overlay_sysfs_attrs,
443};
444
445int dss_overlay_kobj_init(struct omap_overlay *ovl,
446 struct platform_device *pdev)
447{
448 return kobject_init_and_add(&ovl->kobj, &overlay_ktype,
449 &pdev->dev.kobj, "overlay%d", ovl->id);
450}
451
452void dss_overlay_kobj_uninit(struct omap_overlay *ovl)
453{
454 kobject_del(&ovl->kobj);
455 kobject_put(&ovl->kobj);
456}
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
deleted file mode 100644
index 2f7cee985cdd..000000000000
--- a/drivers/video/omap2/dss/overlay.c
+++ /dev/null
@@ -1,202 +0,0 @@
1/*
2 * linux/drivers/video/omap2/dss/overlay.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
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#define DSS_SUBSYS_NAME "OVERLAY"
24
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/err.h>
28#include <linux/sysfs.h>
29#include <linux/platform_device.h>
30#include <linux/delay.h>
31#include <linux/slab.h>
32
33#include <video/omapdss.h>
34
35#include "dss.h"
36#include "dss_features.h"
37
38static int num_overlays;
39static struct omap_overlay *overlays;
40
41int omap_dss_get_num_overlays(void)
42{
43 return num_overlays;
44}
45EXPORT_SYMBOL(omap_dss_get_num_overlays);
46
47struct omap_overlay *omap_dss_get_overlay(int num)
48{
49 if (num >= num_overlays)
50 return NULL;
51
52 return &overlays[num];
53}
54EXPORT_SYMBOL(omap_dss_get_overlay);
55
56void dss_init_overlays(struct platform_device *pdev)
57{
58 int i, r;
59
60 num_overlays = dss_feat_get_num_ovls();
61
62 overlays = kzalloc(sizeof(struct omap_overlay) * num_overlays,
63 GFP_KERNEL);
64
65 BUG_ON(overlays == NULL);
66
67 for (i = 0; i < num_overlays; ++i) {
68 struct omap_overlay *ovl = &overlays[i];
69
70 switch (i) {
71 case 0:
72 ovl->name = "gfx";
73 ovl->id = OMAP_DSS_GFX;
74 break;
75 case 1:
76 ovl->name = "vid1";
77 ovl->id = OMAP_DSS_VIDEO1;
78 break;
79 case 2:
80 ovl->name = "vid2";
81 ovl->id = OMAP_DSS_VIDEO2;
82 break;
83 case 3:
84 ovl->name = "vid3";
85 ovl->id = OMAP_DSS_VIDEO3;
86 break;
87 }
88
89 ovl->caps = dss_feat_get_overlay_caps(ovl->id);
90 ovl->supported_modes =
91 dss_feat_get_supported_color_modes(ovl->id);
92
93 r = dss_overlay_kobj_init(ovl, pdev);
94 if (r)
95 DSSERR("failed to create sysfs file\n");
96 }
97}
98
99void dss_uninit_overlays(struct platform_device *pdev)
100{
101 int i;
102
103 for (i = 0; i < num_overlays; ++i) {
104 struct omap_overlay *ovl = &overlays[i];
105 dss_overlay_kobj_uninit(ovl);
106 }
107
108 kfree(overlays);
109 overlays = NULL;
110 num_overlays = 0;
111}
112
113int dss_ovl_simple_check(struct omap_overlay *ovl,
114 const struct omap_overlay_info *info)
115{
116 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
117 if (info->out_width != 0 && info->width != info->out_width) {
118 DSSERR("check_overlay: overlay %d doesn't support "
119 "scaling\n", ovl->id);
120 return -EINVAL;
121 }
122
123 if (info->out_height != 0 && info->height != info->out_height) {
124 DSSERR("check_overlay: overlay %d doesn't support "
125 "scaling\n", ovl->id);
126 return -EINVAL;
127 }
128 }
129
130 if ((ovl->supported_modes & info->color_mode) == 0) {
131 DSSERR("check_overlay: overlay %d doesn't support mode %d\n",
132 ovl->id, info->color_mode);
133 return -EINVAL;
134 }
135
136 if (info->zorder >= omap_dss_get_num_overlays()) {
137 DSSERR("check_overlay: zorder %d too high\n", info->zorder);
138 return -EINVAL;
139 }
140
141 if (dss_feat_rotation_type_supported(info->rotation_type) == 0) {
142 DSSERR("check_overlay: rotation type %d not supported\n",
143 info->rotation_type);
144 return -EINVAL;
145 }
146
147 return 0;
148}
149
150int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info,
151 const struct omap_video_timings *mgr_timings)
152{
153 u16 outw, outh;
154 u16 dw, dh;
155
156 dw = mgr_timings->x_res;
157 dh = mgr_timings->y_res;
158
159 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
160 outw = info->width;
161 outh = info->height;
162 } else {
163 if (info->out_width == 0)
164 outw = info->width;
165 else
166 outw = info->out_width;
167
168 if (info->out_height == 0)
169 outh = info->height;
170 else
171 outh = info->out_height;
172 }
173
174 if (dw < info->pos_x + outw) {
175 DSSERR("overlay %d horizontally not inside the display area "
176 "(%d + %d >= %d)\n",
177 ovl->id, info->pos_x, outw, dw);
178 return -EINVAL;
179 }
180
181 if (dh < info->pos_y + outh) {
182 DSSERR("overlay %d vertically not inside the display area "
183 "(%d + %d >= %d)\n",
184 ovl->id, info->pos_y, outh, dh);
185 return -EINVAL;
186 }
187
188 return 0;
189}
190
191/*
192 * Checks if replication logic should be used. Only use when overlay is in
193 * RGB12U or RGB16 mode, and video port width interface is 18bpp or 24bpp
194 */
195bool dss_ovl_use_replication(struct dss_lcd_mgr_config config,
196 enum omap_color_mode mode)
197{
198 if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16)
199 return false;
200
201 return config.video_port_width > 16;
202}
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
deleted file mode 100644
index c8a81a2b879c..000000000000
--- a/drivers/video/omap2/dss/rfbi.c
+++ /dev/null
@@ -1,1058 +0,0 @@
1/*
2 * linux/drivers/video/omap2/dss/rfbi.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
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#define DSS_SUBSYS_NAME "RFBI"
24
25#include <linux/kernel.h>
26#include <linux/dma-mapping.h>
27#include <linux/export.h>
28#include <linux/vmalloc.h>
29#include <linux/clk.h>
30#include <linux/io.h>
31#include <linux/delay.h>
32#include <linux/kfifo.h>
33#include <linux/ktime.h>
34#include <linux/hrtimer.h>
35#include <linux/seq_file.h>
36#include <linux/semaphore.h>
37#include <linux/platform_device.h>
38#include <linux/pm_runtime.h>
39
40#include <video/omapdss.h>
41#include "dss.h"
42
43struct rfbi_reg { u16 idx; };
44
45#define RFBI_REG(idx) ((const struct rfbi_reg) { idx })
46
47#define RFBI_REVISION RFBI_REG(0x0000)
48#define RFBI_SYSCONFIG RFBI_REG(0x0010)
49#define RFBI_SYSSTATUS RFBI_REG(0x0014)
50#define RFBI_CONTROL RFBI_REG(0x0040)
51#define RFBI_PIXEL_CNT RFBI_REG(0x0044)
52#define RFBI_LINE_NUMBER RFBI_REG(0x0048)
53#define RFBI_CMD RFBI_REG(0x004c)
54#define RFBI_PARAM RFBI_REG(0x0050)
55#define RFBI_DATA RFBI_REG(0x0054)
56#define RFBI_READ RFBI_REG(0x0058)
57#define RFBI_STATUS RFBI_REG(0x005c)
58
59#define RFBI_CONFIG(n) RFBI_REG(0x0060 + (n)*0x18)
60#define RFBI_ONOFF_TIME(n) RFBI_REG(0x0064 + (n)*0x18)
61#define RFBI_CYCLE_TIME(n) RFBI_REG(0x0068 + (n)*0x18)
62#define RFBI_DATA_CYCLE1(n) RFBI_REG(0x006c + (n)*0x18)
63#define RFBI_DATA_CYCLE2(n) RFBI_REG(0x0070 + (n)*0x18)
64#define RFBI_DATA_CYCLE3(n) RFBI_REG(0x0074 + (n)*0x18)
65
66#define RFBI_VSYNC_WIDTH RFBI_REG(0x0090)
67#define RFBI_HSYNC_WIDTH RFBI_REG(0x0094)
68
69#define REG_FLD_MOD(idx, val, start, end) \
70 rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end))
71
72enum omap_rfbi_cycleformat {
73 OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0,
74 OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1,
75 OMAP_DSS_RFBI_CYCLEFORMAT_3_1 = 2,
76 OMAP_DSS_RFBI_CYCLEFORMAT_3_2 = 3,
77};
78
79enum omap_rfbi_datatype {
80 OMAP_DSS_RFBI_DATATYPE_12 = 0,
81 OMAP_DSS_RFBI_DATATYPE_16 = 1,
82 OMAP_DSS_RFBI_DATATYPE_18 = 2,
83 OMAP_DSS_RFBI_DATATYPE_24 = 3,
84};
85
86enum omap_rfbi_parallelmode {
87 OMAP_DSS_RFBI_PARALLELMODE_8 = 0,
88 OMAP_DSS_RFBI_PARALLELMODE_9 = 1,
89 OMAP_DSS_RFBI_PARALLELMODE_12 = 2,
90 OMAP_DSS_RFBI_PARALLELMODE_16 = 3,
91};
92
93static int rfbi_convert_timings(struct rfbi_timings *t);
94static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div);
95
96static struct {
97 struct platform_device *pdev;
98 void __iomem *base;
99
100 unsigned long l4_khz;
101
102 enum omap_rfbi_datatype datatype;
103 enum omap_rfbi_parallelmode parallelmode;
104
105 enum omap_rfbi_te_mode te_mode;
106 int te_enabled;
107
108 void (*framedone_callback)(void *data);
109 void *framedone_callback_data;
110
111 struct omap_dss_device *dssdev[2];
112
113 struct semaphore bus_lock;
114
115 struct omap_video_timings timings;
116 int pixel_size;
117 int data_lines;
118 struct rfbi_timings intf_timings;
119
120 struct omap_dss_device output;
121} rfbi;
122
123static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
124{
125 __raw_writel(val, rfbi.base + idx.idx);
126}
127
128static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
129{
130 return __raw_readl(rfbi.base + idx.idx);
131}
132
133static int rfbi_runtime_get(void)
134{
135 int r;
136
137 DSSDBG("rfbi_runtime_get\n");
138
139 r = pm_runtime_get_sync(&rfbi.pdev->dev);
140 WARN_ON(r < 0);
141 return r < 0 ? r : 0;
142}
143
144static void rfbi_runtime_put(void)
145{
146 int r;
147
148 DSSDBG("rfbi_runtime_put\n");
149
150 r = pm_runtime_put_sync(&rfbi.pdev->dev);
151 WARN_ON(r < 0 && r != -ENOSYS);
152}
153
154static void rfbi_bus_lock(void)
155{
156 down(&rfbi.bus_lock);
157}
158
159static void rfbi_bus_unlock(void)
160{
161 up(&rfbi.bus_lock);
162}
163
164static void rfbi_write_command(const void *buf, u32 len)
165{
166 switch (rfbi.parallelmode) {
167 case OMAP_DSS_RFBI_PARALLELMODE_8:
168 {
169 const u8 *b = buf;
170 for (; len; len--)
171 rfbi_write_reg(RFBI_CMD, *b++);
172 break;
173 }
174
175 case OMAP_DSS_RFBI_PARALLELMODE_16:
176 {
177 const u16 *w = buf;
178 BUG_ON(len & 1);
179 for (; len; len -= 2)
180 rfbi_write_reg(RFBI_CMD, *w++);
181 break;
182 }
183
184 case OMAP_DSS_RFBI_PARALLELMODE_9:
185 case OMAP_DSS_RFBI_PARALLELMODE_12:
186 default:
187 BUG();
188 }
189}
190
191static void rfbi_read_data(void *buf, u32 len)
192{
193 switch (rfbi.parallelmode) {
194 case OMAP_DSS_RFBI_PARALLELMODE_8:
195 {
196 u8 *b = buf;
197 for (; len; len--) {
198 rfbi_write_reg(RFBI_READ, 0);
199 *b++ = rfbi_read_reg(RFBI_READ);
200 }
201 break;
202 }
203
204 case OMAP_DSS_RFBI_PARALLELMODE_16:
205 {
206 u16 *w = buf;
207 BUG_ON(len & ~1);
208 for (; len; len -= 2) {
209 rfbi_write_reg(RFBI_READ, 0);
210 *w++ = rfbi_read_reg(RFBI_READ);
211 }
212 break;
213 }
214
215 case OMAP_DSS_RFBI_PARALLELMODE_9:
216 case OMAP_DSS_RFBI_PARALLELMODE_12:
217 default:
218 BUG();
219 }
220}
221
222static void rfbi_write_data(const void *buf, u32 len)
223{
224 switch (rfbi.parallelmode) {
225 case OMAP_DSS_RFBI_PARALLELMODE_8:
226 {
227 const u8 *b = buf;
228 for (; len; len--)
229 rfbi_write_reg(RFBI_PARAM, *b++);
230 break;
231 }
232
233 case OMAP_DSS_RFBI_PARALLELMODE_16:
234 {
235 const u16 *w = buf;
236 BUG_ON(len & 1);
237 for (; len; len -= 2)
238 rfbi_write_reg(RFBI_PARAM, *w++);
239 break;
240 }
241
242 case OMAP_DSS_RFBI_PARALLELMODE_9:
243 case OMAP_DSS_RFBI_PARALLELMODE_12:
244 default:
245 BUG();
246
247 }
248}
249
250static void rfbi_write_pixels(const void __iomem *buf, int scr_width,
251 u16 x, u16 y,
252 u16 w, u16 h)
253{
254 int start_offset = scr_width * y + x;
255 int horiz_offset = scr_width - w;
256 int i;
257
258 if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
259 rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
260 const u16 __iomem *pd = buf;
261 pd += start_offset;
262
263 for (; h; --h) {
264 for (i = 0; i < w; ++i) {
265 const u8 __iomem *b = (const u8 __iomem *)pd;
266 rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
267 rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
268 ++pd;
269 }
270 pd += horiz_offset;
271 }
272 } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_24 &&
273 rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
274 const u32 __iomem *pd = buf;
275 pd += start_offset;
276
277 for (; h; --h) {
278 for (i = 0; i < w; ++i) {
279 const u8 __iomem *b = (const u8 __iomem *)pd;
280 rfbi_write_reg(RFBI_PARAM, __raw_readb(b+2));
281 rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
282 rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
283 ++pd;
284 }
285 pd += horiz_offset;
286 }
287 } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
288 rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_16) {
289 const u16 __iomem *pd = buf;
290 pd += start_offset;
291
292 for (; h; --h) {
293 for (i = 0; i < w; ++i) {
294 rfbi_write_reg(RFBI_PARAM, __raw_readw(pd));
295 ++pd;
296 }
297 pd += horiz_offset;
298 }
299 } else {
300 BUG();
301 }
302}
303
304static int rfbi_transfer_area(struct omap_dss_device *dssdev,
305 void (*callback)(void *data), void *data)
306{
307 u32 l;
308 int r;
309 struct omap_overlay_manager *mgr = rfbi.output.manager;
310 u16 width = rfbi.timings.x_res;
311 u16 height = rfbi.timings.y_res;
312
313 /*BUG_ON(callback == 0);*/
314 BUG_ON(rfbi.framedone_callback != NULL);
315
316 DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
317
318 dss_mgr_set_timings(mgr, &rfbi.timings);
319
320 r = dss_mgr_enable(mgr);
321 if (r)
322 return r;
323
324 rfbi.framedone_callback = callback;
325 rfbi.framedone_callback_data = data;
326
327 rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
328
329 l = rfbi_read_reg(RFBI_CONTROL);
330 l = FLD_MOD(l, 1, 0, 0); /* enable */
331 if (!rfbi.te_enabled)
332 l = FLD_MOD(l, 1, 4, 4); /* ITE */
333
334 rfbi_write_reg(RFBI_CONTROL, l);
335
336 return 0;
337}
338
339static void framedone_callback(void *data)
340{
341 void (*callback)(void *data);
342
343 DSSDBG("FRAMEDONE\n");
344
345 REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0);
346
347 callback = rfbi.framedone_callback;
348 rfbi.framedone_callback = NULL;
349
350 if (callback != NULL)
351 callback(rfbi.framedone_callback_data);
352}
353
354#if 1 /* VERBOSE */
355static void rfbi_print_timings(void)
356{
357 u32 l;
358 u32 time;
359
360 l = rfbi_read_reg(RFBI_CONFIG(0));
361 time = 1000000000 / rfbi.l4_khz;
362 if (l & (1 << 4))
363 time *= 2;
364
365 DSSDBG("Tick time %u ps\n", time);
366 l = rfbi_read_reg(RFBI_ONOFF_TIME(0));
367 DSSDBG("CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
368 "REONTIME %d, REOFFTIME %d\n",
369 l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
370 (l >> 20) & 0x0f, (l >> 24) & 0x3f);
371
372 l = rfbi_read_reg(RFBI_CYCLE_TIME(0));
373 DSSDBG("WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
374 "ACCESSTIME %d\n",
375 (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f,
376 (l >> 22) & 0x3f);
377}
378#else
379static void rfbi_print_timings(void) {}
380#endif
381
382
383
384
385static u32 extif_clk_period;
386
387static inline unsigned long round_to_extif_ticks(unsigned long ps, int div)
388{
389 int bus_tick = extif_clk_period * div;
390 return (ps + bus_tick - 1) / bus_tick * bus_tick;
391}
392
393static int calc_reg_timing(struct rfbi_timings *t, int div)
394{
395 t->clk_div = div;
396
397 t->cs_on_time = round_to_extif_ticks(t->cs_on_time, div);
398
399 t->we_on_time = round_to_extif_ticks(t->we_on_time, div);
400 t->we_off_time = round_to_extif_ticks(t->we_off_time, div);
401 t->we_cycle_time = round_to_extif_ticks(t->we_cycle_time, div);
402
403 t->re_on_time = round_to_extif_ticks(t->re_on_time, div);
404 t->re_off_time = round_to_extif_ticks(t->re_off_time, div);
405 t->re_cycle_time = round_to_extif_ticks(t->re_cycle_time, div);
406
407 t->access_time = round_to_extif_ticks(t->access_time, div);
408 t->cs_off_time = round_to_extif_ticks(t->cs_off_time, div);
409 t->cs_pulse_width = round_to_extif_ticks(t->cs_pulse_width, div);
410
411 DSSDBG("[reg]cson %d csoff %d reon %d reoff %d\n",
412 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
413 DSSDBG("[reg]weon %d weoff %d recyc %d wecyc %d\n",
414 t->we_on_time, t->we_off_time, t->re_cycle_time,
415 t->we_cycle_time);
416 DSSDBG("[reg]rdaccess %d cspulse %d\n",
417 t->access_time, t->cs_pulse_width);
418
419 return rfbi_convert_timings(t);
420}
421
422static int calc_extif_timings(struct rfbi_timings *t)
423{
424 u32 max_clk_div;
425 int div;
426
427 rfbi_get_clk_info(&extif_clk_period, &max_clk_div);
428 for (div = 1; div <= max_clk_div; div++) {
429 if (calc_reg_timing(t, div) == 0)
430 break;
431 }
432
433 if (div <= max_clk_div)
434 return 0;
435
436 DSSERR("can't setup timings\n");
437 return -1;
438}
439
440
441static void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t)
442{
443 int r;
444
445 if (!t->converted) {
446 r = calc_extif_timings(t);
447 if (r < 0)
448 DSSERR("Failed to calc timings\n");
449 }
450
451 BUG_ON(!t->converted);
452
453 rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]);
454 rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]);
455
456 /* TIMEGRANULARITY */
457 REG_FLD_MOD(RFBI_CONFIG(rfbi_module),
458 (t->tim[2] ? 1 : 0), 4, 4);
459
460 rfbi_print_timings();
461}
462
463static int ps_to_rfbi_ticks(int time, int div)
464{
465 unsigned long tick_ps;
466 int ret;
467
468 /* Calculate in picosecs to yield more exact results */
469 tick_ps = 1000000000 / (rfbi.l4_khz) * div;
470
471 ret = (time + tick_ps - 1) / tick_ps;
472
473 return ret;
474}
475
476static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
477{
478 *clk_period = 1000000000 / rfbi.l4_khz;
479 *max_clk_div = 2;
480}
481
482static int rfbi_convert_timings(struct rfbi_timings *t)
483{
484 u32 l;
485 int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
486 int actim, recyc, wecyc;
487 int div = t->clk_div;
488
489 if (div <= 0 || div > 2)
490 return -1;
491
492 /* Make sure that after conversion it still holds that:
493 * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff,
494 * csoff > cson, csoff >= max(weoff, reoff), actim > reon
495 */
496 weon = ps_to_rfbi_ticks(t->we_on_time, div);
497 weoff = ps_to_rfbi_ticks(t->we_off_time, div);
498 if (weoff <= weon)
499 weoff = weon + 1;
500 if (weon > 0x0f)
501 return -1;
502 if (weoff > 0x3f)
503 return -1;
504
505 reon = ps_to_rfbi_ticks(t->re_on_time, div);
506 reoff = ps_to_rfbi_ticks(t->re_off_time, div);
507 if (reoff <= reon)
508 reoff = reon + 1;
509 if (reon > 0x0f)
510 return -1;
511 if (reoff > 0x3f)
512 return -1;
513
514 cson = ps_to_rfbi_ticks(t->cs_on_time, div);
515 csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
516 if (csoff <= cson)
517 csoff = cson + 1;
518 if (csoff < max(weoff, reoff))
519 csoff = max(weoff, reoff);
520 if (cson > 0x0f)
521 return -1;
522 if (csoff > 0x3f)
523 return -1;
524
525 l = cson;
526 l |= csoff << 4;
527 l |= weon << 10;
528 l |= weoff << 14;
529 l |= reon << 20;
530 l |= reoff << 24;
531
532 t->tim[0] = l;
533
534 actim = ps_to_rfbi_ticks(t->access_time, div);
535 if (actim <= reon)
536 actim = reon + 1;
537 if (actim > 0x3f)
538 return -1;
539
540 wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
541 if (wecyc < weoff)
542 wecyc = weoff;
543 if (wecyc > 0x3f)
544 return -1;
545
546 recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
547 if (recyc < reoff)
548 recyc = reoff;
549 if (recyc > 0x3f)
550 return -1;
551
552 cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
553 if (cs_pulse > 0x3f)
554 return -1;
555
556 l = wecyc;
557 l |= recyc << 6;
558 l |= cs_pulse << 12;
559 l |= actim << 22;
560
561 t->tim[1] = l;
562
563 t->tim[2] = div - 1;
564
565 t->converted = 1;
566
567 return 0;
568}
569
570/* xxx FIX module selection missing */
571static int rfbi_setup_te(enum omap_rfbi_te_mode mode,
572 unsigned hs_pulse_time, unsigned vs_pulse_time,
573 int hs_pol_inv, int vs_pol_inv, int extif_div)
574{
575 int hs, vs;
576 int min;
577 u32 l;
578
579 hs = ps_to_rfbi_ticks(hs_pulse_time, 1);
580 vs = ps_to_rfbi_ticks(vs_pulse_time, 1);
581 if (hs < 2)
582 return -EDOM;
583 if (mode == OMAP_DSS_RFBI_TE_MODE_2)
584 min = 2;
585 else /* OMAP_DSS_RFBI_TE_MODE_1 */
586 min = 4;
587 if (vs < min)
588 return -EDOM;
589 if (vs == hs)
590 return -EINVAL;
591 rfbi.te_mode = mode;
592 DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n",
593 mode, hs, vs, hs_pol_inv, vs_pol_inv);
594
595 rfbi_write_reg(RFBI_HSYNC_WIDTH, hs);
596 rfbi_write_reg(RFBI_VSYNC_WIDTH, vs);
597
598 l = rfbi_read_reg(RFBI_CONFIG(0));
599 if (hs_pol_inv)
600 l &= ~(1 << 21);
601 else
602 l |= 1 << 21;
603 if (vs_pol_inv)
604 l &= ~(1 << 20);
605 else
606 l |= 1 << 20;
607
608 return 0;
609}
610
611/* xxx FIX module selection missing */
612static int rfbi_enable_te(bool enable, unsigned line)
613{
614 u32 l;
615
616 DSSDBG("te %d line %d mode %d\n", enable, line, rfbi.te_mode);
617 if (line > (1 << 11) - 1)
618 return -EINVAL;
619
620 l = rfbi_read_reg(RFBI_CONFIG(0));
621 l &= ~(0x3 << 2);
622 if (enable) {
623 rfbi.te_enabled = 1;
624 l |= rfbi.te_mode << 2;
625 } else
626 rfbi.te_enabled = 0;
627 rfbi_write_reg(RFBI_CONFIG(0), l);
628 rfbi_write_reg(RFBI_LINE_NUMBER, line);
629
630 return 0;
631}
632
633static int rfbi_configure_bus(int rfbi_module, int bpp, int lines)
634{
635 u32 l;
636 int cycle1 = 0, cycle2 = 0, cycle3 = 0;
637 enum omap_rfbi_cycleformat cycleformat;
638 enum omap_rfbi_datatype datatype;
639 enum omap_rfbi_parallelmode parallelmode;
640
641 switch (bpp) {
642 case 12:
643 datatype = OMAP_DSS_RFBI_DATATYPE_12;
644 break;
645 case 16:
646 datatype = OMAP_DSS_RFBI_DATATYPE_16;
647 break;
648 case 18:
649 datatype = OMAP_DSS_RFBI_DATATYPE_18;
650 break;
651 case 24:
652 datatype = OMAP_DSS_RFBI_DATATYPE_24;
653 break;
654 default:
655 BUG();
656 return 1;
657 }
658 rfbi.datatype = datatype;
659
660 switch (lines) {
661 case 8:
662 parallelmode = OMAP_DSS_RFBI_PARALLELMODE_8;
663 break;
664 case 9:
665 parallelmode = OMAP_DSS_RFBI_PARALLELMODE_9;
666 break;
667 case 12:
668 parallelmode = OMAP_DSS_RFBI_PARALLELMODE_12;
669 break;
670 case 16:
671 parallelmode = OMAP_DSS_RFBI_PARALLELMODE_16;
672 break;
673 default:
674 BUG();
675 return 1;
676 }
677 rfbi.parallelmode = parallelmode;
678
679 if ((bpp % lines) == 0) {
680 switch (bpp / lines) {
681 case 1:
682 cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_1_1;
683 break;
684 case 2:
685 cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_2_1;
686 break;
687 case 3:
688 cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_1;
689 break;
690 default:
691 BUG();
692 return 1;
693 }
694 } else if ((2 * bpp % lines) == 0) {
695 if ((2 * bpp / lines) == 3)
696 cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_2;
697 else {
698 BUG();
699 return 1;
700 }
701 } else {
702 BUG();
703 return 1;
704 }
705
706 switch (cycleformat) {
707 case OMAP_DSS_RFBI_CYCLEFORMAT_1_1:
708 cycle1 = lines;
709 break;
710
711 case OMAP_DSS_RFBI_CYCLEFORMAT_2_1:
712 cycle1 = lines;
713 cycle2 = lines;
714 break;
715
716 case OMAP_DSS_RFBI_CYCLEFORMAT_3_1:
717 cycle1 = lines;
718 cycle2 = lines;
719 cycle3 = lines;
720 break;
721
722 case OMAP_DSS_RFBI_CYCLEFORMAT_3_2:
723 cycle1 = lines;
724 cycle2 = (lines / 2) | ((lines / 2) << 16);
725 cycle3 = (lines << 16);
726 break;
727 }
728
729 REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */
730
731 l = 0;
732 l |= FLD_VAL(parallelmode, 1, 0);
733 l |= FLD_VAL(0, 3, 2); /* TRIGGERMODE: ITE */
734 l |= FLD_VAL(0, 4, 4); /* TIMEGRANULARITY */
735 l |= FLD_VAL(datatype, 6, 5);
736 /* l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */
737 l |= FLD_VAL(0, 8, 7); /* L4FORMAT, 1pix/L4 */
738 l |= FLD_VAL(cycleformat, 10, 9);
739 l |= FLD_VAL(0, 12, 11); /* UNUSEDBITS */
740 l |= FLD_VAL(0, 16, 16); /* A0POLARITY */
741 l |= FLD_VAL(0, 17, 17); /* REPOLARITY */
742 l |= FLD_VAL(0, 18, 18); /* WEPOLARITY */
743 l |= FLD_VAL(0, 19, 19); /* CSPOLARITY */
744 l |= FLD_VAL(1, 20, 20); /* TE_VSYNC_POLARITY */
745 l |= FLD_VAL(1, 21, 21); /* HSYNCPOLARITY */
746 rfbi_write_reg(RFBI_CONFIG(rfbi_module), l);
747
748 rfbi_write_reg(RFBI_DATA_CYCLE1(rfbi_module), cycle1);
749 rfbi_write_reg(RFBI_DATA_CYCLE2(rfbi_module), cycle2);
750 rfbi_write_reg(RFBI_DATA_CYCLE3(rfbi_module), cycle3);
751
752
753 l = rfbi_read_reg(RFBI_CONTROL);
754 l = FLD_MOD(l, rfbi_module+1, 3, 2); /* Select CSx */
755 l = FLD_MOD(l, 0, 1, 1); /* clear bypass */
756 rfbi_write_reg(RFBI_CONTROL, l);
757
758
759 DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n",
760 bpp, lines, cycle1, cycle2, cycle3);
761
762 return 0;
763}
764
765static int rfbi_configure(struct omap_dss_device *dssdev)
766{
767 return rfbi_configure_bus(dssdev->phy.rfbi.channel, rfbi.pixel_size,
768 rfbi.data_lines);
769}
770
771static int rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *),
772 void *data)
773{
774 return rfbi_transfer_area(dssdev, callback, data);
775}
776
777static void rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
778{
779 rfbi.timings.x_res = w;
780 rfbi.timings.y_res = h;
781}
782
783static void rfbi_set_pixel_size(struct omap_dss_device *dssdev, int pixel_size)
784{
785 rfbi.pixel_size = pixel_size;
786}
787
788static void rfbi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
789{
790 rfbi.data_lines = data_lines;
791}
792
793static void rfbi_set_interface_timings(struct omap_dss_device *dssdev,
794 struct rfbi_timings *timings)
795{
796 rfbi.intf_timings = *timings;
797}
798
799static void rfbi_dump_regs(struct seq_file *s)
800{
801#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
802
803 if (rfbi_runtime_get())
804 return;
805
806 DUMPREG(RFBI_REVISION);
807 DUMPREG(RFBI_SYSCONFIG);
808 DUMPREG(RFBI_SYSSTATUS);
809 DUMPREG(RFBI_CONTROL);
810 DUMPREG(RFBI_PIXEL_CNT);
811 DUMPREG(RFBI_LINE_NUMBER);
812 DUMPREG(RFBI_CMD);
813 DUMPREG(RFBI_PARAM);
814 DUMPREG(RFBI_DATA);
815 DUMPREG(RFBI_READ);
816 DUMPREG(RFBI_STATUS);
817
818 DUMPREG(RFBI_CONFIG(0));
819 DUMPREG(RFBI_ONOFF_TIME(0));
820 DUMPREG(RFBI_CYCLE_TIME(0));
821 DUMPREG(RFBI_DATA_CYCLE1(0));
822 DUMPREG(RFBI_DATA_CYCLE2(0));
823 DUMPREG(RFBI_DATA_CYCLE3(0));
824
825 DUMPREG(RFBI_CONFIG(1));
826 DUMPREG(RFBI_ONOFF_TIME(1));
827 DUMPREG(RFBI_CYCLE_TIME(1));
828 DUMPREG(RFBI_DATA_CYCLE1(1));
829 DUMPREG(RFBI_DATA_CYCLE2(1));
830 DUMPREG(RFBI_DATA_CYCLE3(1));
831
832 DUMPREG(RFBI_VSYNC_WIDTH);
833 DUMPREG(RFBI_HSYNC_WIDTH);
834
835 rfbi_runtime_put();
836#undef DUMPREG
837}
838
839static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
840{
841 struct omap_overlay_manager *mgr = rfbi.output.manager;
842 struct dss_lcd_mgr_config mgr_config;
843
844 mgr_config.io_pad_mode = DSS_IO_PAD_MODE_RFBI;
845
846 mgr_config.stallmode = true;
847 /* Do we need fifohandcheck for RFBI? */
848 mgr_config.fifohandcheck = false;
849
850 mgr_config.video_port_width = rfbi.pixel_size;
851 mgr_config.lcden_sig_polarity = 0;
852
853 dss_mgr_set_lcd_config(mgr, &mgr_config);
854
855 /*
856 * Set rfbi.timings with default values, the x_res and y_res fields
857 * are expected to be already configured by the panel driver via
858 * omapdss_rfbi_set_size()
859 */
860 rfbi.timings.hsw = 1;
861 rfbi.timings.hfp = 1;
862 rfbi.timings.hbp = 1;
863 rfbi.timings.vsw = 1;
864 rfbi.timings.vfp = 0;
865 rfbi.timings.vbp = 0;
866
867 rfbi.timings.interlace = false;
868 rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
869 rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
870 rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
871 rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
872 rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
873
874 dss_mgr_set_timings(mgr, &rfbi.timings);
875}
876
877static int rfbi_display_enable(struct omap_dss_device *dssdev)
878{
879 struct omap_dss_device *out = &rfbi.output;
880 int r;
881
882 if (out == NULL || out->manager == NULL) {
883 DSSERR("failed to enable display: no output/manager\n");
884 return -ENODEV;
885 }
886
887 r = rfbi_runtime_get();
888 if (r)
889 return r;
890
891 r = dss_mgr_register_framedone_handler(out->manager,
892 framedone_callback, NULL);
893 if (r) {
894 DSSERR("can't get FRAMEDONE irq\n");
895 goto err1;
896 }
897
898 rfbi_config_lcd_manager(dssdev);
899
900 rfbi_configure_bus(dssdev->phy.rfbi.channel, rfbi.pixel_size,
901 rfbi.data_lines);
902
903 rfbi_set_timings(dssdev->phy.rfbi.channel, &rfbi.intf_timings);
904
905 return 0;
906err1:
907 rfbi_runtime_put();
908 return r;
909}
910
911static void rfbi_display_disable(struct omap_dss_device *dssdev)
912{
913 struct omap_dss_device *out = &rfbi.output;
914
915 dss_mgr_unregister_framedone_handler(out->manager,
916 framedone_callback, NULL);
917
918 rfbi_runtime_put();
919}
920
921static int rfbi_init_display(struct omap_dss_device *dssdev)
922{
923 rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
924 return 0;
925}
926
927static void rfbi_init_output(struct platform_device *pdev)
928{
929 struct omap_dss_device *out = &rfbi.output;
930
931 out->dev = &pdev->dev;
932 out->id = OMAP_DSS_OUTPUT_DBI;
933 out->output_type = OMAP_DISPLAY_TYPE_DBI;
934 out->name = "rfbi.0";
935 out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
936 out->owner = THIS_MODULE;
937
938 omapdss_register_output(out);
939}
940
941static void __exit rfbi_uninit_output(struct platform_device *pdev)
942{
943 struct omap_dss_device *out = &rfbi.output;
944
945 omapdss_unregister_output(out);
946}
947
948/* RFBI HW IP initialisation */
949static int omap_rfbihw_probe(struct platform_device *pdev)
950{
951 u32 rev;
952 struct resource *rfbi_mem;
953 struct clk *clk;
954 int r;
955
956 rfbi.pdev = pdev;
957
958 sema_init(&rfbi.bus_lock, 1);
959
960 rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0);
961 if (!rfbi_mem) {
962 DSSERR("can't get IORESOURCE_MEM RFBI\n");
963 return -EINVAL;
964 }
965
966 rfbi.base = devm_ioremap(&pdev->dev, rfbi_mem->start,
967 resource_size(rfbi_mem));
968 if (!rfbi.base) {
969 DSSERR("can't ioremap RFBI\n");
970 return -ENOMEM;
971 }
972
973 clk = clk_get(&pdev->dev, "ick");
974 if (IS_ERR(clk)) {
975 DSSERR("can't get ick\n");
976 return PTR_ERR(clk);
977 }
978
979 rfbi.l4_khz = clk_get_rate(clk) / 1000;
980
981 clk_put(clk);
982
983 pm_runtime_enable(&pdev->dev);
984
985 r = rfbi_runtime_get();
986 if (r)
987 goto err_runtime_get;
988
989 msleep(10);
990
991 rev = rfbi_read_reg(RFBI_REVISION);
992 dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n",
993 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
994
995 rfbi_runtime_put();
996
997 dss_debugfs_create_file("rfbi", rfbi_dump_regs);
998
999 rfbi_init_output(pdev);
1000
1001 return 0;
1002
1003err_runtime_get:
1004 pm_runtime_disable(&pdev->dev);
1005 return r;
1006}
1007
1008static int __exit omap_rfbihw_remove(struct platform_device *pdev)
1009{
1010 rfbi_uninit_output(pdev);
1011
1012 pm_runtime_disable(&pdev->dev);
1013
1014 return 0;
1015}
1016
1017static int rfbi_runtime_suspend(struct device *dev)
1018{
1019 dispc_runtime_put();
1020
1021 return 0;
1022}
1023
1024static int rfbi_runtime_resume(struct device *dev)
1025{
1026 int r;
1027
1028 r = dispc_runtime_get();
1029 if (r < 0)
1030 return r;
1031
1032 return 0;
1033}
1034
1035static const struct dev_pm_ops rfbi_pm_ops = {
1036 .runtime_suspend = rfbi_runtime_suspend,
1037 .runtime_resume = rfbi_runtime_resume,
1038};
1039
1040static struct platform_driver omap_rfbihw_driver = {
1041 .probe = omap_rfbihw_probe,
1042 .remove = __exit_p(omap_rfbihw_remove),
1043 .driver = {
1044 .name = "omapdss_rfbi",
1045 .owner = THIS_MODULE,
1046 .pm = &rfbi_pm_ops,
1047 },
1048};
1049
1050int __init rfbi_init_platform_driver(void)
1051{
1052 return platform_driver_register(&omap_rfbihw_driver);
1053}
1054
1055void __exit rfbi_uninit_platform_driver(void)
1056{
1057 platform_driver_unregister(&omap_rfbihw_driver);
1058}
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
deleted file mode 100644
index 911dcc9173a6..000000000000
--- a/drivers/video/omap2/dss/sdi.c
+++ /dev/null
@@ -1,433 +0,0 @@
1/*
2 * linux/drivers/video/omap2/dss/sdi.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.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 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#define DSS_SUBSYS_NAME "SDI"
21
22#include <linux/kernel.h>
23#include <linux/delay.h>
24#include <linux/err.h>
25#include <linux/regulator/consumer.h>
26#include <linux/export.h>
27#include <linux/platform_device.h>
28#include <linux/string.h>
29#include <linux/of.h>
30
31#include <video/omapdss.h>
32#include "dss.h"
33
34static struct {
35 struct platform_device *pdev;
36
37 bool update_enabled;
38 struct regulator *vdds_sdi_reg;
39
40 struct dss_lcd_mgr_config mgr_config;
41 struct omap_video_timings timings;
42 int datapairs;
43
44 struct omap_dss_device output;
45
46 bool port_initialized;
47} sdi;
48
49struct sdi_clk_calc_ctx {
50 unsigned long pck_min, pck_max;
51
52 unsigned long fck;
53 struct dispc_clock_info dispc_cinfo;
54};
55
56static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
57 unsigned long pck, void *data)
58{
59 struct sdi_clk_calc_ctx *ctx = data;
60
61 ctx->dispc_cinfo.lck_div = lckd;
62 ctx->dispc_cinfo.pck_div = pckd;
63 ctx->dispc_cinfo.lck = lck;
64 ctx->dispc_cinfo.pck = pck;
65
66 return true;
67}
68
69static bool dpi_calc_dss_cb(unsigned long fck, void *data)
70{
71 struct sdi_clk_calc_ctx *ctx = data;
72
73 ctx->fck = fck;
74
75 return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max,
76 dpi_calc_dispc_cb, ctx);
77}
78
79static int sdi_calc_clock_div(unsigned long pclk,
80 unsigned long *fck,
81 struct dispc_clock_info *dispc_cinfo)
82{
83 int i;
84 struct sdi_clk_calc_ctx ctx;
85
86 /*
87 * DSS fclk gives us very few possibilities, so finding a good pixel
88 * clock may not be possible. We try multiple times to find the clock,
89 * each time widening the pixel clock range we look for, up to
90 * +/- 1MHz.
91 */
92
93 for (i = 0; i < 10; ++i) {
94 bool ok;
95
96 memset(&ctx, 0, sizeof(ctx));
97 if (pclk > 1000 * i * i * i)
98 ctx.pck_min = max(pclk - 1000 * i * i * i, 0lu);
99 else
100 ctx.pck_min = 0;
101 ctx.pck_max = pclk + 1000 * i * i * i;
102
103 ok = dss_div_calc(pclk, ctx.pck_min, dpi_calc_dss_cb, &ctx);
104 if (ok) {
105 *fck = ctx.fck;
106 *dispc_cinfo = ctx.dispc_cinfo;
107 return 0;
108 }
109 }
110
111 return -EINVAL;
112}
113
114static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
115{
116 struct omap_overlay_manager *mgr = sdi.output.manager;
117
118 sdi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
119
120 sdi.mgr_config.stallmode = false;
121 sdi.mgr_config.fifohandcheck = false;
122
123 sdi.mgr_config.video_port_width = 24;
124 sdi.mgr_config.lcden_sig_polarity = 1;
125
126 dss_mgr_set_lcd_config(mgr, &sdi.mgr_config);
127}
128
129static int sdi_display_enable(struct omap_dss_device *dssdev)
130{
131 struct omap_dss_device *out = &sdi.output;
132 struct omap_video_timings *t = &sdi.timings;
133 unsigned long fck;
134 struct dispc_clock_info dispc_cinfo;
135 unsigned long pck;
136 int r;
137
138 if (out == NULL || out->manager == NULL) {
139 DSSERR("failed to enable display: no output/manager\n");
140 return -ENODEV;
141 }
142
143 r = regulator_enable(sdi.vdds_sdi_reg);
144 if (r)
145 goto err_reg_enable;
146
147 r = dispc_runtime_get();
148 if (r)
149 goto err_get_dispc;
150
151 /* 15.5.9.1.2 */
152 t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
153 t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
154
155 r = sdi_calc_clock_div(t->pixelclock, &fck, &dispc_cinfo);
156 if (r)
157 goto err_calc_clock_div;
158
159 sdi.mgr_config.clock_info = dispc_cinfo;
160
161 pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div;
162
163 if (pck != t->pixelclock) {
164 DSSWARN("Could not find exact pixel clock. Requested %d Hz, got %lu Hz\n",
165 t->pixelclock, pck);
166
167 t->pixelclock = pck;
168 }
169
170
171 dss_mgr_set_timings(out->manager, t);
172
173 r = dss_set_fck_rate(fck);
174 if (r)
175 goto err_set_dss_clock_div;
176
177 sdi_config_lcd_manager(dssdev);
178
179 /*
180 * LCLK and PCLK divisors are located in shadow registers, and we
181 * normally write them to DISPC registers when enabling the output.
182 * However, SDI uses pck-free as source clock for its PLL, and pck-free
183 * is affected by the divisors. And as we need the PLL before enabling
184 * the output, we need to write the divisors early.
185 *
186 * It seems just writing to the DISPC register is enough, and we don't
187 * need to care about the shadow register mechanism for pck-free. The
188 * exact reason for this is unknown.
189 */
190 dispc_mgr_set_clock_div(out->manager->id, &sdi.mgr_config.clock_info);
191
192 dss_sdi_init(sdi.datapairs);
193 r = dss_sdi_enable();
194 if (r)
195 goto err_sdi_enable;
196 mdelay(2);
197
198 r = dss_mgr_enable(out->manager);
199 if (r)
200 goto err_mgr_enable;
201
202 return 0;
203
204err_mgr_enable:
205 dss_sdi_disable();
206err_sdi_enable:
207err_set_dss_clock_div:
208err_calc_clock_div:
209 dispc_runtime_put();
210err_get_dispc:
211 regulator_disable(sdi.vdds_sdi_reg);
212err_reg_enable:
213 return r;
214}
215
216static void sdi_display_disable(struct omap_dss_device *dssdev)
217{
218 struct omap_overlay_manager *mgr = sdi.output.manager;
219
220 dss_mgr_disable(mgr);
221
222 dss_sdi_disable();
223
224 dispc_runtime_put();
225
226 regulator_disable(sdi.vdds_sdi_reg);
227}
228
229static void sdi_set_timings(struct omap_dss_device *dssdev,
230 struct omap_video_timings *timings)
231{
232 sdi.timings = *timings;
233}
234
235static void sdi_get_timings(struct omap_dss_device *dssdev,
236 struct omap_video_timings *timings)
237{
238 *timings = sdi.timings;
239}
240
241static int sdi_check_timings(struct omap_dss_device *dssdev,
242 struct omap_video_timings *timings)
243{
244 struct omap_overlay_manager *mgr = sdi.output.manager;
245
246 if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
247 return -EINVAL;
248
249 if (timings->pixelclock == 0)
250 return -EINVAL;
251
252 return 0;
253}
254
255static void sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs)
256{
257 sdi.datapairs = datapairs;
258}
259
260static int sdi_init_regulator(void)
261{
262 struct regulator *vdds_sdi;
263
264 if (sdi.vdds_sdi_reg)
265 return 0;
266
267 vdds_sdi = devm_regulator_get(&sdi.pdev->dev, "vdds_sdi");
268 if (IS_ERR(vdds_sdi)) {
269 if (PTR_ERR(vdds_sdi) != -EPROBE_DEFER)
270 DSSERR("can't get VDDS_SDI regulator\n");
271 return PTR_ERR(vdds_sdi);
272 }
273
274 sdi.vdds_sdi_reg = vdds_sdi;
275
276 return 0;
277}
278
279static int sdi_connect(struct omap_dss_device *dssdev,
280 struct omap_dss_device *dst)
281{
282 struct omap_overlay_manager *mgr;
283 int r;
284
285 r = sdi_init_regulator();
286 if (r)
287 return r;
288
289 mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
290 if (!mgr)
291 return -ENODEV;
292
293 r = dss_mgr_connect(mgr, dssdev);
294 if (r)
295 return r;
296
297 r = omapdss_output_set_device(dssdev, dst);
298 if (r) {
299 DSSERR("failed to connect output to new device: %s\n",
300 dst->name);
301 dss_mgr_disconnect(mgr, dssdev);
302 return r;
303 }
304
305 return 0;
306}
307
308static void sdi_disconnect(struct omap_dss_device *dssdev,
309 struct omap_dss_device *dst)
310{
311 WARN_ON(dst != dssdev->dst);
312
313 if (dst != dssdev->dst)
314 return;
315
316 omapdss_output_unset_device(dssdev);
317
318 if (dssdev->manager)
319 dss_mgr_disconnect(dssdev->manager, dssdev);
320}
321
322static const struct omapdss_sdi_ops sdi_ops = {
323 .connect = sdi_connect,
324 .disconnect = sdi_disconnect,
325
326 .enable = sdi_display_enable,
327 .disable = sdi_display_disable,
328
329 .check_timings = sdi_check_timings,
330 .set_timings = sdi_set_timings,
331 .get_timings = sdi_get_timings,
332
333 .set_datapairs = sdi_set_datapairs,
334};
335
336static void sdi_init_output(struct platform_device *pdev)
337{
338 struct omap_dss_device *out = &sdi.output;
339
340 out->dev = &pdev->dev;
341 out->id = OMAP_DSS_OUTPUT_SDI;
342 out->output_type = OMAP_DISPLAY_TYPE_SDI;
343 out->name = "sdi.0";
344 out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
345 out->ops.sdi = &sdi_ops;
346 out->owner = THIS_MODULE;
347
348 omapdss_register_output(out);
349}
350
351static void __exit sdi_uninit_output(struct platform_device *pdev)
352{
353 struct omap_dss_device *out = &sdi.output;
354
355 omapdss_unregister_output(out);
356}
357
358static int omap_sdi_probe(struct platform_device *pdev)
359{
360 sdi.pdev = pdev;
361
362 sdi_init_output(pdev);
363
364 return 0;
365}
366
367static int __exit omap_sdi_remove(struct platform_device *pdev)
368{
369 sdi_uninit_output(pdev);
370
371 return 0;
372}
373
374static struct platform_driver omap_sdi_driver = {
375 .probe = omap_sdi_probe,
376 .remove = __exit_p(omap_sdi_remove),
377 .driver = {
378 .name = "omapdss_sdi",
379 .owner = THIS_MODULE,
380 },
381};
382
383int __init sdi_init_platform_driver(void)
384{
385 return platform_driver_register(&omap_sdi_driver);
386}
387
388void __exit sdi_uninit_platform_driver(void)
389{
390 platform_driver_unregister(&omap_sdi_driver);
391}
392
393int __init sdi_init_port(struct platform_device *pdev, struct device_node *port)
394{
395 struct device_node *ep;
396 u32 datapairs;
397 int r;
398
399 ep = omapdss_of_get_next_endpoint(port, NULL);
400 if (!ep)
401 return 0;
402
403 r = of_property_read_u32(ep, "datapairs", &datapairs);
404 if (r) {
405 DSSERR("failed to parse datapairs\n");
406 goto err_datapairs;
407 }
408
409 sdi.datapairs = datapairs;
410
411 of_node_put(ep);
412
413 sdi.pdev = pdev;
414
415 sdi_init_output(pdev);
416
417 sdi.port_initialized = true;
418
419 return 0;
420
421err_datapairs:
422 of_node_put(ep);
423
424 return r;
425}
426
427void __exit sdi_uninit_port(void)
428{
429 if (!sdi.port_initialized)
430 return;
431
432 sdi_uninit_output(sdi.pdev);
433}
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
deleted file mode 100644
index 21d81113962b..000000000000
--- a/drivers/video/omap2/dss/venc.c
+++ /dev/null
@@ -1,980 +0,0 @@
1/*
2 * linux/drivers/video/omap2/dss/venc.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * VENC settings from TI's DSS driver
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published by
11 * the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#define DSS_SUBSYS_NAME "VENC"
23
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/clk.h>
27#include <linux/err.h>
28#include <linux/io.h>
29#include <linux/mutex.h>
30#include <linux/completion.h>
31#include <linux/delay.h>
32#include <linux/string.h>
33#include <linux/seq_file.h>
34#include <linux/platform_device.h>
35#include <linux/regulator/consumer.h>
36#include <linux/pm_runtime.h>
37#include <linux/of.h>
38
39#include <video/omapdss.h>
40
41#include "dss.h"
42#include "dss_features.h"
43
44/* Venc registers */
45#define VENC_REV_ID 0x00
46#define VENC_STATUS 0x04
47#define VENC_F_CONTROL 0x08
48#define VENC_VIDOUT_CTRL 0x10
49#define VENC_SYNC_CTRL 0x14
50#define VENC_LLEN 0x1C
51#define VENC_FLENS 0x20
52#define VENC_HFLTR_CTRL 0x24
53#define VENC_CC_CARR_WSS_CARR 0x28
54#define VENC_C_PHASE 0x2C
55#define VENC_GAIN_U 0x30
56#define VENC_GAIN_V 0x34
57#define VENC_GAIN_Y 0x38
58#define VENC_BLACK_LEVEL 0x3C
59#define VENC_BLANK_LEVEL 0x40
60#define VENC_X_COLOR 0x44
61#define VENC_M_CONTROL 0x48
62#define VENC_BSTAMP_WSS_DATA 0x4C
63#define VENC_S_CARR 0x50
64#define VENC_LINE21 0x54
65#define VENC_LN_SEL 0x58
66#define VENC_L21__WC_CTL 0x5C
67#define VENC_HTRIGGER_VTRIGGER 0x60
68#define VENC_SAVID__EAVID 0x64
69#define VENC_FLEN__FAL 0x68
70#define VENC_LAL__PHASE_RESET 0x6C
71#define VENC_HS_INT_START_STOP_X 0x70
72#define VENC_HS_EXT_START_STOP_X 0x74
73#define VENC_VS_INT_START_X 0x78
74#define VENC_VS_INT_STOP_X__VS_INT_START_Y 0x7C
75#define VENC_VS_INT_STOP_Y__VS_EXT_START_X 0x80
76#define VENC_VS_EXT_STOP_X__VS_EXT_START_Y 0x84
77#define VENC_VS_EXT_STOP_Y 0x88
78#define VENC_AVID_START_STOP_X 0x90
79#define VENC_AVID_START_STOP_Y 0x94
80#define VENC_FID_INT_START_X__FID_INT_START_Y 0xA0
81#define VENC_FID_INT_OFFSET_Y__FID_EXT_START_X 0xA4
82#define VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y 0xA8
83#define VENC_TVDETGP_INT_START_STOP_X 0xB0
84#define VENC_TVDETGP_INT_START_STOP_Y 0xB4
85#define VENC_GEN_CTRL 0xB8
86#define VENC_OUTPUT_CONTROL 0xC4
87#define VENC_OUTPUT_TEST 0xC8
88#define VENC_DAC_B__DAC_C 0xC8
89
90struct venc_config {
91 u32 f_control;
92 u32 vidout_ctrl;
93 u32 sync_ctrl;
94 u32 llen;
95 u32 flens;
96 u32 hfltr_ctrl;
97 u32 cc_carr_wss_carr;
98 u32 c_phase;
99 u32 gain_u;
100 u32 gain_v;
101 u32 gain_y;
102 u32 black_level;
103 u32 blank_level;
104 u32 x_color;
105 u32 m_control;
106 u32 bstamp_wss_data;
107 u32 s_carr;
108 u32 line21;
109 u32 ln_sel;
110 u32 l21__wc_ctl;
111 u32 htrigger_vtrigger;
112 u32 savid__eavid;
113 u32 flen__fal;
114 u32 lal__phase_reset;
115 u32 hs_int_start_stop_x;
116 u32 hs_ext_start_stop_x;
117 u32 vs_int_start_x;
118 u32 vs_int_stop_x__vs_int_start_y;
119 u32 vs_int_stop_y__vs_ext_start_x;
120 u32 vs_ext_stop_x__vs_ext_start_y;
121 u32 vs_ext_stop_y;
122 u32 avid_start_stop_x;
123 u32 avid_start_stop_y;
124 u32 fid_int_start_x__fid_int_start_y;
125 u32 fid_int_offset_y__fid_ext_start_x;
126 u32 fid_ext_start_y__fid_ext_offset_y;
127 u32 tvdetgp_int_start_stop_x;
128 u32 tvdetgp_int_start_stop_y;
129 u32 gen_ctrl;
130};
131
132/* from TRM */
133static const struct venc_config venc_config_pal_trm = {
134 .f_control = 0,
135 .vidout_ctrl = 1,
136 .sync_ctrl = 0x40,
137 .llen = 0x35F, /* 863 */
138 .flens = 0x270, /* 624 */
139 .hfltr_ctrl = 0,
140 .cc_carr_wss_carr = 0x2F7225ED,
141 .c_phase = 0,
142 .gain_u = 0x111,
143 .gain_v = 0x181,
144 .gain_y = 0x140,
145 .black_level = 0x3B,
146 .blank_level = 0x3B,
147 .x_color = 0x7,
148 .m_control = 0x2,
149 .bstamp_wss_data = 0x3F,
150 .s_carr = 0x2A098ACB,
151 .line21 = 0,
152 .ln_sel = 0x01290015,
153 .l21__wc_ctl = 0x0000F603,
154 .htrigger_vtrigger = 0,
155
156 .savid__eavid = 0x06A70108,
157 .flen__fal = 0x00180270,
158 .lal__phase_reset = 0x00040135,
159 .hs_int_start_stop_x = 0x00880358,
160 .hs_ext_start_stop_x = 0x000F035F,
161 .vs_int_start_x = 0x01A70000,
162 .vs_int_stop_x__vs_int_start_y = 0x000001A7,
163 .vs_int_stop_y__vs_ext_start_x = 0x01AF0000,
164 .vs_ext_stop_x__vs_ext_start_y = 0x000101AF,
165 .vs_ext_stop_y = 0x00000025,
166 .avid_start_stop_x = 0x03530083,
167 .avid_start_stop_y = 0x026C002E,
168 .fid_int_start_x__fid_int_start_y = 0x0001008A,
169 .fid_int_offset_y__fid_ext_start_x = 0x002E0138,
170 .fid_ext_start_y__fid_ext_offset_y = 0x01380001,
171
172 .tvdetgp_int_start_stop_x = 0x00140001,
173 .tvdetgp_int_start_stop_y = 0x00010001,
174 .gen_ctrl = 0x00FF0000,
175};
176
177/* from TRM */
178static const struct venc_config venc_config_ntsc_trm = {
179 .f_control = 0,
180 .vidout_ctrl = 1,
181 .sync_ctrl = 0x8040,
182 .llen = 0x359,
183 .flens = 0x20C,
184 .hfltr_ctrl = 0,
185 .cc_carr_wss_carr = 0x043F2631,
186 .c_phase = 0,
187 .gain_u = 0x102,
188 .gain_v = 0x16C,
189 .gain_y = 0x12F,
190 .black_level = 0x43,
191 .blank_level = 0x38,
192 .x_color = 0x7,
193 .m_control = 0x1,
194 .bstamp_wss_data = 0x38,
195 .s_carr = 0x21F07C1F,
196 .line21 = 0,
197 .ln_sel = 0x01310011,
198 .l21__wc_ctl = 0x0000F003,
199 .htrigger_vtrigger = 0,
200
201 .savid__eavid = 0x069300F4,
202 .flen__fal = 0x0016020C,
203 .lal__phase_reset = 0x00060107,
204 .hs_int_start_stop_x = 0x008E0350,
205 .hs_ext_start_stop_x = 0x000F0359,
206 .vs_int_start_x = 0x01A00000,
207 .vs_int_stop_x__vs_int_start_y = 0x020701A0,
208 .vs_int_stop_y__vs_ext_start_x = 0x01AC0024,
209 .vs_ext_stop_x__vs_ext_start_y = 0x020D01AC,
210 .vs_ext_stop_y = 0x00000006,
211 .avid_start_stop_x = 0x03480078,
212 .avid_start_stop_y = 0x02060024,
213 .fid_int_start_x__fid_int_start_y = 0x0001008A,
214 .fid_int_offset_y__fid_ext_start_x = 0x01AC0106,
215 .fid_ext_start_y__fid_ext_offset_y = 0x01060006,
216
217 .tvdetgp_int_start_stop_x = 0x00140001,
218 .tvdetgp_int_start_stop_y = 0x00010001,
219 .gen_ctrl = 0x00F90000,
220};
221
222static const struct venc_config venc_config_pal_bdghi = {
223 .f_control = 0,
224 .vidout_ctrl = 0,
225 .sync_ctrl = 0,
226 .hfltr_ctrl = 0,
227 .x_color = 0,
228 .line21 = 0,
229 .ln_sel = 21,
230 .htrigger_vtrigger = 0,
231 .tvdetgp_int_start_stop_x = 0x00140001,
232 .tvdetgp_int_start_stop_y = 0x00010001,
233 .gen_ctrl = 0x00FB0000,
234
235 .llen = 864-1,
236 .flens = 625-1,
237 .cc_carr_wss_carr = 0x2F7625ED,
238 .c_phase = 0xDF,
239 .gain_u = 0x111,
240 .gain_v = 0x181,
241 .gain_y = 0x140,
242 .black_level = 0x3e,
243 .blank_level = 0x3e,
244 .m_control = 0<<2 | 1<<1,
245 .bstamp_wss_data = 0x42,
246 .s_carr = 0x2a098acb,
247 .l21__wc_ctl = 0<<13 | 0x16<<8 | 0<<0,
248 .savid__eavid = 0x06A70108,
249 .flen__fal = 23<<16 | 624<<0,
250 .lal__phase_reset = 2<<17 | 310<<0,
251 .hs_int_start_stop_x = 0x00920358,
252 .hs_ext_start_stop_x = 0x000F035F,
253 .vs_int_start_x = 0x1a7<<16,
254 .vs_int_stop_x__vs_int_start_y = 0x000601A7,
255 .vs_int_stop_y__vs_ext_start_x = 0x01AF0036,
256 .vs_ext_stop_x__vs_ext_start_y = 0x27101af,
257 .vs_ext_stop_y = 0x05,
258 .avid_start_stop_x = 0x03530082,
259 .avid_start_stop_y = 0x0270002E,
260 .fid_int_start_x__fid_int_start_y = 0x0005008A,
261 .fid_int_offset_y__fid_ext_start_x = 0x002E0138,
262 .fid_ext_start_y__fid_ext_offset_y = 0x01380005,
263};
264
265const struct omap_video_timings omap_dss_pal_timings = {
266 .x_res = 720,
267 .y_res = 574,
268 .pixelclock = 13500000,
269 .hsw = 64,
270 .hfp = 12,
271 .hbp = 68,
272 .vsw = 5,
273 .vfp = 5,
274 .vbp = 41,
275
276 .interlace = true,
277};
278EXPORT_SYMBOL(omap_dss_pal_timings);
279
280const struct omap_video_timings omap_dss_ntsc_timings = {
281 .x_res = 720,
282 .y_res = 482,
283 .pixelclock = 13500000,
284 .hsw = 64,
285 .hfp = 16,
286 .hbp = 58,
287 .vsw = 6,
288 .vfp = 6,
289 .vbp = 31,
290
291 .interlace = true,
292};
293EXPORT_SYMBOL(omap_dss_ntsc_timings);
294
295static struct {
296 struct platform_device *pdev;
297 void __iomem *base;
298 struct mutex venc_lock;
299 u32 wss_data;
300 struct regulator *vdda_dac_reg;
301
302 struct clk *tv_dac_clk;
303
304 struct omap_video_timings timings;
305 enum omap_dss_venc_type type;
306 bool invert_polarity;
307
308 struct omap_dss_device output;
309} venc;
310
311static inline void venc_write_reg(int idx, u32 val)
312{
313 __raw_writel(val, venc.base + idx);
314}
315
316static inline u32 venc_read_reg(int idx)
317{
318 u32 l = __raw_readl(venc.base + idx);
319 return l;
320}
321
322static void venc_write_config(const struct venc_config *config)
323{
324 DSSDBG("write venc conf\n");
325
326 venc_write_reg(VENC_LLEN, config->llen);
327 venc_write_reg(VENC_FLENS, config->flens);
328 venc_write_reg(VENC_CC_CARR_WSS_CARR, config->cc_carr_wss_carr);
329 venc_write_reg(VENC_C_PHASE, config->c_phase);
330 venc_write_reg(VENC_GAIN_U, config->gain_u);
331 venc_write_reg(VENC_GAIN_V, config->gain_v);
332 venc_write_reg(VENC_GAIN_Y, config->gain_y);
333 venc_write_reg(VENC_BLACK_LEVEL, config->black_level);
334 venc_write_reg(VENC_BLANK_LEVEL, config->blank_level);
335 venc_write_reg(VENC_M_CONTROL, config->m_control);
336 venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
337 venc.wss_data);
338 venc_write_reg(VENC_S_CARR, config->s_carr);
339 venc_write_reg(VENC_L21__WC_CTL, config->l21__wc_ctl);
340 venc_write_reg(VENC_SAVID__EAVID, config->savid__eavid);
341 venc_write_reg(VENC_FLEN__FAL, config->flen__fal);
342 venc_write_reg(VENC_LAL__PHASE_RESET, config->lal__phase_reset);
343 venc_write_reg(VENC_HS_INT_START_STOP_X, config->hs_int_start_stop_x);
344 venc_write_reg(VENC_HS_EXT_START_STOP_X, config->hs_ext_start_stop_x);
345 venc_write_reg(VENC_VS_INT_START_X, config->vs_int_start_x);
346 venc_write_reg(VENC_VS_INT_STOP_X__VS_INT_START_Y,
347 config->vs_int_stop_x__vs_int_start_y);
348 venc_write_reg(VENC_VS_INT_STOP_Y__VS_EXT_START_X,
349 config->vs_int_stop_y__vs_ext_start_x);
350 venc_write_reg(VENC_VS_EXT_STOP_X__VS_EXT_START_Y,
351 config->vs_ext_stop_x__vs_ext_start_y);
352 venc_write_reg(VENC_VS_EXT_STOP_Y, config->vs_ext_stop_y);
353 venc_write_reg(VENC_AVID_START_STOP_X, config->avid_start_stop_x);
354 venc_write_reg(VENC_AVID_START_STOP_Y, config->avid_start_stop_y);
355 venc_write_reg(VENC_FID_INT_START_X__FID_INT_START_Y,
356 config->fid_int_start_x__fid_int_start_y);
357 venc_write_reg(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X,
358 config->fid_int_offset_y__fid_ext_start_x);
359 venc_write_reg(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y,
360 config->fid_ext_start_y__fid_ext_offset_y);
361
362 venc_write_reg(VENC_DAC_B__DAC_C, venc_read_reg(VENC_DAC_B__DAC_C));
363 venc_write_reg(VENC_VIDOUT_CTRL, config->vidout_ctrl);
364 venc_write_reg(VENC_HFLTR_CTRL, config->hfltr_ctrl);
365 venc_write_reg(VENC_X_COLOR, config->x_color);
366 venc_write_reg(VENC_LINE21, config->line21);
367 venc_write_reg(VENC_LN_SEL, config->ln_sel);
368 venc_write_reg(VENC_HTRIGGER_VTRIGGER, config->htrigger_vtrigger);
369 venc_write_reg(VENC_TVDETGP_INT_START_STOP_X,
370 config->tvdetgp_int_start_stop_x);
371 venc_write_reg(VENC_TVDETGP_INT_START_STOP_Y,
372 config->tvdetgp_int_start_stop_y);
373 venc_write_reg(VENC_GEN_CTRL, config->gen_ctrl);
374 venc_write_reg(VENC_F_CONTROL, config->f_control);
375 venc_write_reg(VENC_SYNC_CTRL, config->sync_ctrl);
376}
377
378static void venc_reset(void)
379{
380 int t = 1000;
381
382 venc_write_reg(VENC_F_CONTROL, 1<<8);
383 while (venc_read_reg(VENC_F_CONTROL) & (1<<8)) {
384 if (--t == 0) {
385 DSSERR("Failed to reset venc\n");
386 return;
387 }
388 }
389
390#ifdef CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET
391 /* the magical sleep that makes things work */
392 /* XXX more info? What bug this circumvents? */
393 msleep(20);
394#endif
395}
396
397static int venc_runtime_get(void)
398{
399 int r;
400
401 DSSDBG("venc_runtime_get\n");
402
403 r = pm_runtime_get_sync(&venc.pdev->dev);
404 WARN_ON(r < 0);
405 return r < 0 ? r : 0;
406}
407
408static void venc_runtime_put(void)
409{
410 int r;
411
412 DSSDBG("venc_runtime_put\n");
413
414 r = pm_runtime_put_sync(&venc.pdev->dev);
415 WARN_ON(r < 0 && r != -ENOSYS);
416}
417
418static const struct venc_config *venc_timings_to_config(
419 struct omap_video_timings *timings)
420{
421 if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
422 return &venc_config_pal_trm;
423
424 if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
425 return &venc_config_ntsc_trm;
426
427 BUG();
428 return NULL;
429}
430
431static int venc_power_on(struct omap_dss_device *dssdev)
432{
433 struct omap_overlay_manager *mgr = venc.output.manager;
434 u32 l;
435 int r;
436
437 r = venc_runtime_get();
438 if (r)
439 goto err0;
440
441 venc_reset();
442 venc_write_config(venc_timings_to_config(&venc.timings));
443
444 dss_set_venc_output(venc.type);
445 dss_set_dac_pwrdn_bgz(1);
446
447 l = 0;
448
449 if (venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
450 l |= 1 << 1;
451 else /* S-Video */
452 l |= (1 << 0) | (1 << 2);
453
454 if (venc.invert_polarity == false)
455 l |= 1 << 3;
456
457 venc_write_reg(VENC_OUTPUT_CONTROL, l);
458
459 dss_mgr_set_timings(mgr, &venc.timings);
460
461 r = regulator_enable(venc.vdda_dac_reg);
462 if (r)
463 goto err1;
464
465 r = dss_mgr_enable(mgr);
466 if (r)
467 goto err2;
468
469 return 0;
470
471err2:
472 regulator_disable(venc.vdda_dac_reg);
473err1:
474 venc_write_reg(VENC_OUTPUT_CONTROL, 0);
475 dss_set_dac_pwrdn_bgz(0);
476
477 venc_runtime_put();
478err0:
479 return r;
480}
481
482static void venc_power_off(struct omap_dss_device *dssdev)
483{
484 struct omap_overlay_manager *mgr = venc.output.manager;
485
486 venc_write_reg(VENC_OUTPUT_CONTROL, 0);
487 dss_set_dac_pwrdn_bgz(0);
488
489 dss_mgr_disable(mgr);
490
491 regulator_disable(venc.vdda_dac_reg);
492
493 venc_runtime_put();
494}
495
496static int venc_display_enable(struct omap_dss_device *dssdev)
497{
498 struct omap_dss_device *out = &venc.output;
499 int r;
500
501 DSSDBG("venc_display_enable\n");
502
503 mutex_lock(&venc.venc_lock);
504
505 if (out == NULL || out->manager == NULL) {
506 DSSERR("Failed to enable display: no output/manager\n");
507 r = -ENODEV;
508 goto err0;
509 }
510
511 r = venc_power_on(dssdev);
512 if (r)
513 goto err0;
514
515 venc.wss_data = 0;
516
517 mutex_unlock(&venc.venc_lock);
518
519 return 0;
520err0:
521 mutex_unlock(&venc.venc_lock);
522 return r;
523}
524
525static void venc_display_disable(struct omap_dss_device *dssdev)
526{
527 DSSDBG("venc_display_disable\n");
528
529 mutex_lock(&venc.venc_lock);
530
531 venc_power_off(dssdev);
532
533 mutex_unlock(&venc.venc_lock);
534}
535
536static void venc_set_timings(struct omap_dss_device *dssdev,
537 struct omap_video_timings *timings)
538{
539 DSSDBG("venc_set_timings\n");
540
541 mutex_lock(&venc.venc_lock);
542
543 /* Reset WSS data when the TV standard changes. */
544 if (memcmp(&venc.timings, timings, sizeof(*timings)))
545 venc.wss_data = 0;
546
547 venc.timings = *timings;
548
549 dispc_set_tv_pclk(13500000);
550
551 mutex_unlock(&venc.venc_lock);
552}
553
554static int venc_check_timings(struct omap_dss_device *dssdev,
555 struct omap_video_timings *timings)
556{
557 DSSDBG("venc_check_timings\n");
558
559 if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
560 return 0;
561
562 if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
563 return 0;
564
565 return -EINVAL;
566}
567
568static void venc_get_timings(struct omap_dss_device *dssdev,
569 struct omap_video_timings *timings)
570{
571 mutex_lock(&venc.venc_lock);
572
573 *timings = venc.timings;
574
575 mutex_unlock(&venc.venc_lock);
576}
577
578static u32 venc_get_wss(struct omap_dss_device *dssdev)
579{
580 /* Invert due to VENC_L21_WC_CTL:INV=1 */
581 return (venc.wss_data >> 8) ^ 0xfffff;
582}
583
584static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
585{
586 const struct venc_config *config;
587 int r;
588
589 DSSDBG("venc_set_wss\n");
590
591 mutex_lock(&venc.venc_lock);
592
593 config = venc_timings_to_config(&venc.timings);
594
595 /* Invert due to VENC_L21_WC_CTL:INV=1 */
596 venc.wss_data = (wss ^ 0xfffff) << 8;
597
598 r = venc_runtime_get();
599 if (r)
600 goto err;
601
602 venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
603 venc.wss_data);
604
605 venc_runtime_put();
606
607err:
608 mutex_unlock(&venc.venc_lock);
609
610 return r;
611}
612
613static void venc_set_type(struct omap_dss_device *dssdev,
614 enum omap_dss_venc_type type)
615{
616 mutex_lock(&venc.venc_lock);
617
618 venc.type = type;
619
620 mutex_unlock(&venc.venc_lock);
621}
622
623static void venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
624 bool invert_polarity)
625{
626 mutex_lock(&venc.venc_lock);
627
628 venc.invert_polarity = invert_polarity;
629
630 mutex_unlock(&venc.venc_lock);
631}
632
633static int venc_init_regulator(void)
634{
635 struct regulator *vdda_dac;
636
637 if (venc.vdda_dac_reg != NULL)
638 return 0;
639
640 if (venc.pdev->dev.of_node)
641 vdda_dac = devm_regulator_get(&venc.pdev->dev, "vdda");
642 else
643 vdda_dac = devm_regulator_get(&venc.pdev->dev, "vdda_dac");
644
645 if (IS_ERR(vdda_dac)) {
646 if (PTR_ERR(vdda_dac) != -EPROBE_DEFER)
647 DSSERR("can't get VDDA_DAC regulator\n");
648 return PTR_ERR(vdda_dac);
649 }
650
651 venc.vdda_dac_reg = vdda_dac;
652
653 return 0;
654}
655
656static void venc_dump_regs(struct seq_file *s)
657{
658#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
659
660 if (venc_runtime_get())
661 return;
662
663 DUMPREG(VENC_F_CONTROL);
664 DUMPREG(VENC_VIDOUT_CTRL);
665 DUMPREG(VENC_SYNC_CTRL);
666 DUMPREG(VENC_LLEN);
667 DUMPREG(VENC_FLENS);
668 DUMPREG(VENC_HFLTR_CTRL);
669 DUMPREG(VENC_CC_CARR_WSS_CARR);
670 DUMPREG(VENC_C_PHASE);
671 DUMPREG(VENC_GAIN_U);
672 DUMPREG(VENC_GAIN_V);
673 DUMPREG(VENC_GAIN_Y);
674 DUMPREG(VENC_BLACK_LEVEL);
675 DUMPREG(VENC_BLANK_LEVEL);
676 DUMPREG(VENC_X_COLOR);
677 DUMPREG(VENC_M_CONTROL);
678 DUMPREG(VENC_BSTAMP_WSS_DATA);
679 DUMPREG(VENC_S_CARR);
680 DUMPREG(VENC_LINE21);
681 DUMPREG(VENC_LN_SEL);
682 DUMPREG(VENC_L21__WC_CTL);
683 DUMPREG(VENC_HTRIGGER_VTRIGGER);
684 DUMPREG(VENC_SAVID__EAVID);
685 DUMPREG(VENC_FLEN__FAL);
686 DUMPREG(VENC_LAL__PHASE_RESET);
687 DUMPREG(VENC_HS_INT_START_STOP_X);
688 DUMPREG(VENC_HS_EXT_START_STOP_X);
689 DUMPREG(VENC_VS_INT_START_X);
690 DUMPREG(VENC_VS_INT_STOP_X__VS_INT_START_Y);
691 DUMPREG(VENC_VS_INT_STOP_Y__VS_EXT_START_X);
692 DUMPREG(VENC_VS_EXT_STOP_X__VS_EXT_START_Y);
693 DUMPREG(VENC_VS_EXT_STOP_Y);
694 DUMPREG(VENC_AVID_START_STOP_X);
695 DUMPREG(VENC_AVID_START_STOP_Y);
696 DUMPREG(VENC_FID_INT_START_X__FID_INT_START_Y);
697 DUMPREG(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X);
698 DUMPREG(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y);
699 DUMPREG(VENC_TVDETGP_INT_START_STOP_X);
700 DUMPREG(VENC_TVDETGP_INT_START_STOP_Y);
701 DUMPREG(VENC_GEN_CTRL);
702 DUMPREG(VENC_OUTPUT_CONTROL);
703 DUMPREG(VENC_OUTPUT_TEST);
704
705 venc_runtime_put();
706
707#undef DUMPREG
708}
709
710static int venc_get_clocks(struct platform_device *pdev)
711{
712 struct clk *clk;
713
714 if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
715 clk = devm_clk_get(&pdev->dev, "tv_dac_clk");
716 if (IS_ERR(clk)) {
717 DSSERR("can't get tv_dac_clk\n");
718 return PTR_ERR(clk);
719 }
720 } else {
721 clk = NULL;
722 }
723
724 venc.tv_dac_clk = clk;
725
726 return 0;
727}
728
729static int venc_connect(struct omap_dss_device *dssdev,
730 struct omap_dss_device *dst)
731{
732 struct omap_overlay_manager *mgr;
733 int r;
734
735 r = venc_init_regulator();
736 if (r)
737 return r;
738
739 mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
740 if (!mgr)
741 return -ENODEV;
742
743 r = dss_mgr_connect(mgr, dssdev);
744 if (r)
745 return r;
746
747 r = omapdss_output_set_device(dssdev, dst);
748 if (r) {
749 DSSERR("failed to connect output to new device: %s\n",
750 dst->name);
751 dss_mgr_disconnect(mgr, dssdev);
752 return r;
753 }
754
755 return 0;
756}
757
758static void venc_disconnect(struct omap_dss_device *dssdev,
759 struct omap_dss_device *dst)
760{
761 WARN_ON(dst != dssdev->dst);
762
763 if (dst != dssdev->dst)
764 return;
765
766 omapdss_output_unset_device(dssdev);
767
768 if (dssdev->manager)
769 dss_mgr_disconnect(dssdev->manager, dssdev);
770}
771
772static const struct omapdss_atv_ops venc_ops = {
773 .connect = venc_connect,
774 .disconnect = venc_disconnect,
775
776 .enable = venc_display_enable,
777 .disable = venc_display_disable,
778
779 .check_timings = venc_check_timings,
780 .set_timings = venc_set_timings,
781 .get_timings = venc_get_timings,
782
783 .set_type = venc_set_type,
784 .invert_vid_out_polarity = venc_invert_vid_out_polarity,
785
786 .set_wss = venc_set_wss,
787 .get_wss = venc_get_wss,
788};
789
790static void venc_init_output(struct platform_device *pdev)
791{
792 struct omap_dss_device *out = &venc.output;
793
794 out->dev = &pdev->dev;
795 out->id = OMAP_DSS_OUTPUT_VENC;
796 out->output_type = OMAP_DISPLAY_TYPE_VENC;
797 out->name = "venc.0";
798 out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
799 out->ops.atv = &venc_ops;
800 out->owner = THIS_MODULE;
801
802 omapdss_register_output(out);
803}
804
805static void __exit venc_uninit_output(struct platform_device *pdev)
806{
807 struct omap_dss_device *out = &venc.output;
808
809 omapdss_unregister_output(out);
810}
811
812static int venc_probe_of(struct platform_device *pdev)
813{
814 struct device_node *node = pdev->dev.of_node;
815 struct device_node *ep;
816 u32 channels;
817 int r;
818
819 ep = omapdss_of_get_first_endpoint(node);
820 if (!ep)
821 return 0;
822
823 venc.invert_polarity = of_property_read_bool(ep, "ti,invert-polarity");
824
825 r = of_property_read_u32(ep, "ti,channels", &channels);
826 if (r) {
827 dev_err(&pdev->dev,
828 "failed to read property 'ti,channels': %d\n", r);
829 goto err;
830 }
831
832 switch (channels) {
833 case 1:
834 venc.type = OMAP_DSS_VENC_TYPE_COMPOSITE;
835 break;
836 case 2:
837 venc.type = OMAP_DSS_VENC_TYPE_SVIDEO;
838 break;
839 default:
840 dev_err(&pdev->dev, "bad channel propert '%d'\n", channels);
841 r = -EINVAL;
842 goto err;
843 }
844
845 of_node_put(ep);
846
847 return 0;
848err:
849 of_node_put(ep);
850
851 return 0;
852}
853
854/* VENC HW IP initialisation */
855static int omap_venchw_probe(struct platform_device *pdev)
856{
857 u8 rev_id;
858 struct resource *venc_mem;
859 int r;
860
861 venc.pdev = pdev;
862
863 mutex_init(&venc.venc_lock);
864
865 venc.wss_data = 0;
866
867 venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0);
868 if (!venc_mem) {
869 DSSERR("can't get IORESOURCE_MEM VENC\n");
870 return -EINVAL;
871 }
872
873 venc.base = devm_ioremap(&pdev->dev, venc_mem->start,
874 resource_size(venc_mem));
875 if (!venc.base) {
876 DSSERR("can't ioremap VENC\n");
877 return -ENOMEM;
878 }
879
880 r = venc_get_clocks(pdev);
881 if (r)
882 return r;
883
884 pm_runtime_enable(&pdev->dev);
885
886 r = venc_runtime_get();
887 if (r)
888 goto err_runtime_get;
889
890 rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
891 dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id);
892
893 venc_runtime_put();
894
895 if (pdev->dev.of_node) {
896 r = venc_probe_of(pdev);
897 if (r) {
898 DSSERR("Invalid DT data\n");
899 goto err_probe_of;
900 }
901 }
902
903 dss_debugfs_create_file("venc", venc_dump_regs);
904
905 venc_init_output(pdev);
906
907 return 0;
908
909err_probe_of:
910err_runtime_get:
911 pm_runtime_disable(&pdev->dev);
912 return r;
913}
914
915static int __exit omap_venchw_remove(struct platform_device *pdev)
916{
917 venc_uninit_output(pdev);
918
919 pm_runtime_disable(&pdev->dev);
920
921 return 0;
922}
923
924static int venc_runtime_suspend(struct device *dev)
925{
926 if (venc.tv_dac_clk)
927 clk_disable_unprepare(venc.tv_dac_clk);
928
929 dispc_runtime_put();
930
931 return 0;
932}
933
934static int venc_runtime_resume(struct device *dev)
935{
936 int r;
937
938 r = dispc_runtime_get();
939 if (r < 0)
940 return r;
941
942 if (venc.tv_dac_clk)
943 clk_prepare_enable(venc.tv_dac_clk);
944
945 return 0;
946}
947
948static const struct dev_pm_ops venc_pm_ops = {
949 .runtime_suspend = venc_runtime_suspend,
950 .runtime_resume = venc_runtime_resume,
951};
952
953
954static const struct of_device_id venc_of_match[] = {
955 { .compatible = "ti,omap2-venc", },
956 { .compatible = "ti,omap3-venc", },
957 { .compatible = "ti,omap4-venc", },
958 {},
959};
960
961static struct platform_driver omap_venchw_driver = {
962 .probe = omap_venchw_probe,
963 .remove = __exit_p(omap_venchw_remove),
964 .driver = {
965 .name = "omapdss_venc",
966 .owner = THIS_MODULE,
967 .pm = &venc_pm_ops,
968 .of_match_table = venc_of_match,
969 },
970};
971
972int __init venc_init_platform_driver(void)
973{
974 return platform_driver_register(&omap_venchw_driver);
975}
976
977void __exit venc_uninit_platform_driver(void)
978{
979 platform_driver_unregister(&omap_venchw_driver);
980}
diff --git a/drivers/video/omap2/dss/venc_panel.c b/drivers/video/omap2/dss/venc_panel.c
deleted file mode 100644
index af68cd444d7e..000000000000
--- a/drivers/video/omap2/dss/venc_panel.c
+++ /dev/null
@@ -1,232 +0,0 @@
1/*
2 * Copyright (C) 2009 Nokia Corporation
3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4 *
5 * VENC panel driver
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 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/kernel.h>
21#include <linux/err.h>
22#include <linux/io.h>
23#include <linux/mutex.h>
24#include <linux/module.h>
25
26#include <video/omapdss.h>
27
28#include "dss.h"
29
30static struct {
31 struct mutex lock;
32} venc_panel;
33
34static ssize_t display_output_type_show(struct device *dev,
35 struct device_attribute *attr, char *buf)
36{
37 struct omap_dss_device *dssdev = to_dss_device(dev);
38 const char *ret;
39
40 switch (dssdev->phy.venc.type) {
41 case OMAP_DSS_VENC_TYPE_COMPOSITE:
42 ret = "composite";
43 break;
44 case OMAP_DSS_VENC_TYPE_SVIDEO:
45 ret = "svideo";
46 break;
47 default:
48 return -EINVAL;
49 }
50
51 return snprintf(buf, PAGE_SIZE, "%s\n", ret);
52}
53
54static ssize_t display_output_type_store(struct device *dev,
55 struct device_attribute *attr, const char *buf, size_t size)
56{
57 struct omap_dss_device *dssdev = to_dss_device(dev);
58 enum omap_dss_venc_type new_type;
59
60 if (sysfs_streq("composite", buf))
61 new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
62 else if (sysfs_streq("svideo", buf))
63 new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
64 else
65 return -EINVAL;
66
67 mutex_lock(&venc_panel.lock);
68
69 if (dssdev->phy.venc.type != new_type) {
70 dssdev->phy.venc.type = new_type;
71 omapdss_venc_set_type(dssdev, new_type);
72 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
73 omapdss_venc_display_disable(dssdev);
74 omapdss_venc_display_enable(dssdev);
75 }
76 }
77
78 mutex_unlock(&venc_panel.lock);
79
80 return size;
81}
82
83static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
84 display_output_type_show, display_output_type_store);
85
86static int venc_panel_probe(struct omap_dss_device *dssdev)
87{
88 /* set default timings to PAL */
89 const struct omap_video_timings default_timings = {
90 .x_res = 720,
91 .y_res = 574,
92 .pixelclock = 13500000,
93 .hsw = 64,
94 .hfp = 12,
95 .hbp = 68,
96 .vsw = 5,
97 .vfp = 5,
98 .vbp = 41,
99
100 .vsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
101 .hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
102
103 .interlace = true,
104 };
105
106 mutex_init(&venc_panel.lock);
107
108 dssdev->panel.timings = default_timings;
109
110 return device_create_file(dssdev->dev, &dev_attr_output_type);
111}
112
113static void venc_panel_remove(struct omap_dss_device *dssdev)
114{
115 device_remove_file(dssdev->dev, &dev_attr_output_type);
116}
117
118static int venc_panel_enable(struct omap_dss_device *dssdev)
119{
120 int r;
121
122 dev_dbg(dssdev->dev, "venc_panel_enable\n");
123
124 mutex_lock(&venc_panel.lock);
125
126 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
127 r = -EINVAL;
128 goto err;
129 }
130
131 omapdss_venc_set_timings(dssdev, &dssdev->panel.timings);
132 omapdss_venc_set_type(dssdev, dssdev->phy.venc.type);
133 omapdss_venc_invert_vid_out_polarity(dssdev,
134 dssdev->phy.venc.invert_polarity);
135
136 r = omapdss_venc_display_enable(dssdev);
137 if (r)
138 goto err;
139
140 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
141
142 mutex_unlock(&venc_panel.lock);
143
144 return 0;
145err:
146 mutex_unlock(&venc_panel.lock);
147
148 return r;
149}
150
151static void venc_panel_disable(struct omap_dss_device *dssdev)
152{
153 dev_dbg(dssdev->dev, "venc_panel_disable\n");
154
155 mutex_lock(&venc_panel.lock);
156
157 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
158 goto end;
159
160 omapdss_venc_display_disable(dssdev);
161
162 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
163end:
164 mutex_unlock(&venc_panel.lock);
165}
166
167static void venc_panel_set_timings(struct omap_dss_device *dssdev,
168 struct omap_video_timings *timings)
169{
170 dev_dbg(dssdev->dev, "venc_panel_set_timings\n");
171
172 mutex_lock(&venc_panel.lock);
173
174 omapdss_venc_set_timings(dssdev, timings);
175 dssdev->panel.timings = *timings;
176
177 mutex_unlock(&venc_panel.lock);
178}
179
180static int venc_panel_check_timings(struct omap_dss_device *dssdev,
181 struct omap_video_timings *timings)
182{
183 dev_dbg(dssdev->dev, "venc_panel_check_timings\n");
184
185 return omapdss_venc_check_timings(dssdev, timings);
186}
187
188static u32 venc_panel_get_wss(struct omap_dss_device *dssdev)
189{
190 dev_dbg(dssdev->dev, "venc_panel_get_wss\n");
191
192 return omapdss_venc_get_wss(dssdev);
193}
194
195static int venc_panel_set_wss(struct omap_dss_device *dssdev, u32 wss)
196{
197 dev_dbg(dssdev->dev, "venc_panel_set_wss\n");
198
199 return omapdss_venc_set_wss(dssdev, wss);
200}
201
202static struct omap_dss_driver venc_driver = {
203 .probe = venc_panel_probe,
204 .remove = venc_panel_remove,
205
206 .enable = venc_panel_enable,
207 .disable = venc_panel_disable,
208
209 .get_resolution = omapdss_default_get_resolution,
210 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
211
212 .set_timings = venc_panel_set_timings,
213 .check_timings = venc_panel_check_timings,
214
215 .get_wss = venc_panel_get_wss,
216 .set_wss = venc_panel_set_wss,
217
218 .driver = {
219 .name = "venc",
220 .owner = THIS_MODULE,
221 },
222};
223
224int venc_panel_init(void)
225{
226 return omap_dss_register_driver(&venc_driver);
227}
228
229void venc_panel_exit(void)
230{
231 omap_dss_unregister_driver(&venc_driver);
232}
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig
deleted file mode 100644
index 4cb12ce68855..000000000000
--- a/drivers/video/omap2/omapfb/Kconfig
+++ /dev/null
@@ -1,27 +0,0 @@
1menuconfig FB_OMAP2
2 tristate "OMAP2+ frame buffer support"
3 depends on FB && OMAP2_DSS && !DRM_OMAP
4
5 select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
6 select FB_CFB_FILLRECT
7 select FB_CFB_COPYAREA
8 select FB_CFB_IMAGEBLIT
9 help
10 Frame buffer driver for OMAP2+ based boards.
11
12config FB_OMAP2_DEBUG_SUPPORT
13 bool "Debug support for OMAP2+ FB"
14 default y
15 depends on FB_OMAP2
16 help
17 Support for debug output. You have to enable the actual printing
18 with 'debug' module parameter.
19
20config FB_OMAP2_NUM_FBS
21 int "Number of framebuffers"
22 range 1 10
23 default 3
24 depends on FB_OMAP2
25 help
26 Select the number of framebuffers created. OMAP2/3 has 3 overlays
27 so normally this would be 3.
diff --git a/drivers/video/omap2/omapfb/Makefile b/drivers/video/omap2/omapfb/Makefile
deleted file mode 100644
index 51c2e00d9bf8..000000000000
--- a/drivers/video/omap2/omapfb/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
1obj-$(CONFIG_FB_OMAP2) += omapfb.o
2omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
deleted file mode 100644
index 146b6f5428db..000000000000
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ /dev/null
@@ -1,922 +0,0 @@
1/*
2 * linux/drivers/video/omap2/omapfb-ioctl.c
3 *
4 * Copyright (C) 2008 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
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/fb.h>
24#include <linux/device.h>
25#include <linux/uaccess.h>
26#include <linux/platform_device.h>
27#include <linux/mm.h>
28#include <linux/omapfb.h>
29#include <linux/vmalloc.h>
30#include <linux/export.h>
31#include <linux/sizes.h>
32
33#include <video/omapdss.h>
34#include <video/omapvrfb.h>
35
36#include "omapfb.h"
37
38static u8 get_mem_idx(struct omapfb_info *ofbi)
39{
40 if (ofbi->id == ofbi->region->id)
41 return 0;
42
43 return OMAPFB_MEM_IDX_ENABLED | ofbi->region->id;
44}
45
46static struct omapfb2_mem_region *get_mem_region(struct omapfb_info *ofbi,
47 u8 mem_idx)
48{
49 struct omapfb2_device *fbdev = ofbi->fbdev;
50
51 if (mem_idx & OMAPFB_MEM_IDX_ENABLED)
52 mem_idx &= OMAPFB_MEM_IDX_MASK;
53 else
54 mem_idx = ofbi->id;
55
56 if (mem_idx >= fbdev->num_fbs)
57 return NULL;
58
59 return &fbdev->regions[mem_idx];
60}
61
62static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
63{
64 struct omapfb_info *ofbi = FB2OFB(fbi);
65 struct omapfb2_device *fbdev = ofbi->fbdev;
66 struct omap_overlay *ovl;
67 struct omap_overlay_info old_info;
68 struct omapfb2_mem_region *old_rg, *new_rg;
69 int r = 0;
70
71 DBG("omapfb_setup_plane\n");
72
73 if (ofbi->num_overlays == 0) {
74 r = -EINVAL;
75 goto out;
76 }
77
78 /* XXX uses only the first overlay */
79 ovl = ofbi->overlays[0];
80
81 old_rg = ofbi->region;
82 new_rg = get_mem_region(ofbi, pi->mem_idx);
83 if (!new_rg) {
84 r = -EINVAL;
85 goto out;
86 }
87
88 /* Take the locks in a specific order to keep lockdep happy */
89 if (old_rg->id < new_rg->id) {
90 omapfb_get_mem_region(old_rg);
91 omapfb_get_mem_region(new_rg);
92 } else if (new_rg->id < old_rg->id) {
93 omapfb_get_mem_region(new_rg);
94 omapfb_get_mem_region(old_rg);
95 } else
96 omapfb_get_mem_region(old_rg);
97
98 if (pi->enabled && !new_rg->size) {
99 /*
100 * This plane's memory was freed, can't enable it
101 * until it's reallocated.
102 */
103 r = -EINVAL;
104 goto put_mem;
105 }
106
107 ovl->get_overlay_info(ovl, &old_info);
108
109 if (old_rg != new_rg) {
110 ofbi->region = new_rg;
111 set_fb_fix(fbi);
112 }
113
114 if (!pi->enabled) {
115 r = ovl->disable(ovl);
116 if (r)
117 goto undo;
118 }
119
120 if (pi->enabled) {
121 r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y,
122 pi->out_width, pi->out_height);
123 if (r)
124 goto undo;
125 } else {
126 struct omap_overlay_info info;
127
128 ovl->get_overlay_info(ovl, &info);
129
130 info.pos_x = pi->pos_x;
131 info.pos_y = pi->pos_y;
132 info.out_width = pi->out_width;
133 info.out_height = pi->out_height;
134
135 r = ovl->set_overlay_info(ovl, &info);
136 if (r)
137 goto undo;
138 }
139
140 if (ovl->manager)
141 ovl->manager->apply(ovl->manager);
142
143 if (pi->enabled) {
144 r = ovl->enable(ovl);
145 if (r)
146 goto undo;
147 }
148
149 /* Release the locks in a specific order to keep lockdep happy */
150 if (old_rg->id > new_rg->id) {
151 omapfb_put_mem_region(old_rg);
152 omapfb_put_mem_region(new_rg);
153 } else if (new_rg->id > old_rg->id) {
154 omapfb_put_mem_region(new_rg);
155 omapfb_put_mem_region(old_rg);
156 } else
157 omapfb_put_mem_region(old_rg);
158
159 return 0;
160
161 undo:
162 if (old_rg != new_rg) {
163 ofbi->region = old_rg;
164 set_fb_fix(fbi);
165 }
166
167 ovl->set_overlay_info(ovl, &old_info);
168 put_mem:
169 /* Release the locks in a specific order to keep lockdep happy */
170 if (old_rg->id > new_rg->id) {
171 omapfb_put_mem_region(old_rg);
172 omapfb_put_mem_region(new_rg);
173 } else if (new_rg->id > old_rg->id) {
174 omapfb_put_mem_region(new_rg);
175 omapfb_put_mem_region(old_rg);
176 } else
177 omapfb_put_mem_region(old_rg);
178 out:
179 dev_err(fbdev->dev, "setup_plane failed\n");
180
181 return r;
182}
183
184static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
185{
186 struct omapfb_info *ofbi = FB2OFB(fbi);
187
188 if (ofbi->num_overlays == 0) {
189 memset(pi, 0, sizeof(*pi));
190 } else {
191 struct omap_overlay *ovl;
192 struct omap_overlay_info ovli;
193
194 ovl = ofbi->overlays[0];
195 ovl->get_overlay_info(ovl, &ovli);
196
197 pi->pos_x = ovli.pos_x;
198 pi->pos_y = ovli.pos_y;
199 pi->enabled = ovl->is_enabled(ovl);
200 pi->channel_out = 0; /* xxx */
201 pi->mirror = 0;
202 pi->mem_idx = get_mem_idx(ofbi);
203 pi->out_width = ovli.out_width;
204 pi->out_height = ovli.out_height;
205 }
206
207 return 0;
208}
209
210static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
211{
212 struct omapfb_info *ofbi = FB2OFB(fbi);
213 struct omapfb2_device *fbdev = ofbi->fbdev;
214 struct omap_dss_device *display = fb2display(fbi);
215 struct omapfb2_mem_region *rg;
216 int r = 0, i;
217 size_t size;
218
219 if (mi->type != OMAPFB_MEMTYPE_SDRAM)
220 return -EINVAL;
221
222 size = PAGE_ALIGN(mi->size);
223
224 if (display && display->driver->sync)
225 display->driver->sync(display);
226
227 rg = ofbi->region;
228
229 down_write_nested(&rg->lock, rg->id);
230 atomic_inc(&rg->lock_count);
231
232 if (rg->size == size && rg->type == mi->type)
233 goto out;
234
235 if (atomic_read(&rg->map_count)) {
236 r = -EBUSY;
237 goto out;
238 }
239
240 for (i = 0; i < fbdev->num_fbs; i++) {
241 struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
242 int j;
243
244 if (ofbi2->region != rg)
245 continue;
246
247 for (j = 0; j < ofbi2->num_overlays; j++) {
248 struct omap_overlay *ovl;
249 ovl = ofbi2->overlays[j];
250 if (ovl->is_enabled(ovl)) {
251 r = -EBUSY;
252 goto out;
253 }
254 }
255 }
256
257 r = omapfb_realloc_fbmem(fbi, size, mi->type);
258 if (r) {
259 dev_err(fbdev->dev, "realloc fbmem failed\n");
260 goto out;
261 }
262
263 out:
264 atomic_dec(&rg->lock_count);
265 up_write(&rg->lock);
266
267 return r;
268}
269
270static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
271{
272 struct omapfb_info *ofbi = FB2OFB(fbi);
273 struct omapfb2_mem_region *rg;
274
275 rg = omapfb_get_mem_region(ofbi->region);
276 memset(mi, 0, sizeof(*mi));
277
278 mi->size = rg->size;
279 mi->type = rg->type;
280
281 omapfb_put_mem_region(rg);
282
283 return 0;
284}
285
286static int omapfb_update_window(struct fb_info *fbi,
287 u32 x, u32 y, u32 w, u32 h)
288{
289 struct omap_dss_device *display = fb2display(fbi);
290 u16 dw, dh;
291
292 if (!display)
293 return 0;
294
295 if (w == 0 || h == 0)
296 return 0;
297
298 display->driver->get_resolution(display, &dw, &dh);
299
300 if (x + w > dw || y + h > dh)
301 return -EINVAL;
302
303 return display->driver->update(display, x, y, w, h);
304}
305
306int omapfb_set_update_mode(struct fb_info *fbi,
307 enum omapfb_update_mode mode)
308{
309 struct omap_dss_device *display = fb2display(fbi);
310 struct omapfb_info *ofbi = FB2OFB(fbi);
311 struct omapfb2_device *fbdev = ofbi->fbdev;
312 struct omapfb_display_data *d;
313 int r;
314
315 if (!display)
316 return -EINVAL;
317
318 if (mode != OMAPFB_AUTO_UPDATE && mode != OMAPFB_MANUAL_UPDATE)
319 return -EINVAL;
320
321 omapfb_lock(fbdev);
322
323 d = get_display_data(fbdev, display);
324
325 if (d->update_mode == mode) {
326 omapfb_unlock(fbdev);
327 return 0;
328 }
329
330 r = 0;
331
332 if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
333 if (mode == OMAPFB_AUTO_UPDATE)
334 omapfb_start_auto_update(fbdev, display);
335 else /* MANUAL_UPDATE */
336 omapfb_stop_auto_update(fbdev, display);
337
338 d->update_mode = mode;
339 } else { /* AUTO_UPDATE */
340 if (mode == OMAPFB_MANUAL_UPDATE)
341 r = -EINVAL;
342 }
343
344 omapfb_unlock(fbdev);
345
346 return r;
347}
348
349int omapfb_get_update_mode(struct fb_info *fbi,
350 enum omapfb_update_mode *mode)
351{
352 struct omap_dss_device *display = fb2display(fbi);
353 struct omapfb_info *ofbi = FB2OFB(fbi);
354 struct omapfb2_device *fbdev = ofbi->fbdev;
355 struct omapfb_display_data *d;
356
357 if (!display)
358 return -EINVAL;
359
360 omapfb_lock(fbdev);
361
362 d = get_display_data(fbdev, display);
363
364 *mode = d->update_mode;
365
366 omapfb_unlock(fbdev);
367
368 return 0;
369}
370
371/* XXX this color key handling is a hack... */
372static struct omapfb_color_key omapfb_color_keys[2];
373
374static int _omapfb_set_color_key(struct omap_overlay_manager *mgr,
375 struct omapfb_color_key *ck)
376{
377 struct omap_overlay_manager_info info;
378 enum omap_dss_trans_key_type kt;
379 int r;
380
381 mgr->get_manager_info(mgr, &info);
382
383 if (ck->key_type == OMAPFB_COLOR_KEY_DISABLED) {
384 info.trans_enabled = false;
385 omapfb_color_keys[mgr->id] = *ck;
386
387 r = mgr->set_manager_info(mgr, &info);
388 if (r)
389 return r;
390
391 r = mgr->apply(mgr);
392
393 return r;
394 }
395
396 switch (ck->key_type) {
397 case OMAPFB_COLOR_KEY_GFX_DST:
398 kt = OMAP_DSS_COLOR_KEY_GFX_DST;
399 break;
400 case OMAPFB_COLOR_KEY_VID_SRC:
401 kt = OMAP_DSS_COLOR_KEY_VID_SRC;
402 break;
403 default:
404 return -EINVAL;
405 }
406
407 info.default_color = ck->background;
408 info.trans_key = ck->trans_key;
409 info.trans_key_type = kt;
410 info.trans_enabled = true;
411
412 omapfb_color_keys[mgr->id] = *ck;
413
414 r = mgr->set_manager_info(mgr, &info);
415 if (r)
416 return r;
417
418 r = mgr->apply(mgr);
419
420 return r;
421}
422
423static int omapfb_set_color_key(struct fb_info *fbi,
424 struct omapfb_color_key *ck)
425{
426 struct omapfb_info *ofbi = FB2OFB(fbi);
427 struct omapfb2_device *fbdev = ofbi->fbdev;
428 int r;
429 int i;
430 struct omap_overlay_manager *mgr = NULL;
431
432 omapfb_lock(fbdev);
433
434 for (i = 0; i < ofbi->num_overlays; i++) {
435 if (ofbi->overlays[i]->manager) {
436 mgr = ofbi->overlays[i]->manager;
437 break;
438 }
439 }
440
441 if (!mgr) {
442 r = -EINVAL;
443 goto err;
444 }
445
446 r = _omapfb_set_color_key(mgr, ck);
447err:
448 omapfb_unlock(fbdev);
449
450 return r;
451}
452
453static int omapfb_get_color_key(struct fb_info *fbi,
454 struct omapfb_color_key *ck)
455{
456 struct omapfb_info *ofbi = FB2OFB(fbi);
457 struct omapfb2_device *fbdev = ofbi->fbdev;
458 struct omap_overlay_manager *mgr = NULL;
459 int r = 0;
460 int i;
461
462 omapfb_lock(fbdev);
463
464 for (i = 0; i < ofbi->num_overlays; i++) {
465 if (ofbi->overlays[i]->manager) {
466 mgr = ofbi->overlays[i]->manager;
467 break;
468 }
469 }
470
471 if (!mgr) {
472 r = -EINVAL;
473 goto err;
474 }
475
476 *ck = omapfb_color_keys[mgr->id];
477err:
478 omapfb_unlock(fbdev);
479
480 return r;
481}
482
483static int omapfb_memory_read(struct fb_info *fbi,
484 struct omapfb_memory_read *mr)
485{
486 struct omap_dss_device *display = fb2display(fbi);
487 void *buf;
488 int r;
489
490 if (!display || !display->driver->memory_read)
491 return -ENOENT;
492
493 if (!access_ok(VERIFY_WRITE, mr->buffer, mr->buffer_size))
494 return -EFAULT;
495
496 if (mr->w * mr->h * 3 > mr->buffer_size)
497 return -EINVAL;
498
499 buf = vmalloc(mr->buffer_size);
500 if (!buf) {
501 DBG("vmalloc failed\n");
502 return -ENOMEM;
503 }
504
505 r = display->driver->memory_read(display, buf, mr->buffer_size,
506 mr->x, mr->y, mr->w, mr->h);
507
508 if (r > 0) {
509 if (copy_to_user(mr->buffer, buf, mr->buffer_size))
510 r = -EFAULT;
511 }
512
513 vfree(buf);
514
515 return r;
516}
517
518static int omapfb_get_ovl_colormode(struct omapfb2_device *fbdev,
519 struct omapfb_ovl_colormode *mode)
520{
521 int ovl_idx = mode->overlay_idx;
522 int mode_idx = mode->mode_idx;
523 struct omap_overlay *ovl;
524 enum omap_color_mode supported_modes;
525 struct fb_var_screeninfo var;
526 int i;
527
528 if (ovl_idx >= fbdev->num_overlays)
529 return -ENODEV;
530 ovl = fbdev->overlays[ovl_idx];
531 supported_modes = ovl->supported_modes;
532
533 mode_idx = mode->mode_idx;
534
535 for (i = 0; i < sizeof(supported_modes) * 8; i++) {
536 if (!(supported_modes & (1 << i)))
537 continue;
538 /*
539 * It's possible that the FB doesn't support a mode
540 * that is supported by the overlay, so call the
541 * following here.
542 */
543 if (dss_mode_to_fb_mode(1 << i, &var) < 0)
544 continue;
545
546 mode_idx--;
547 if (mode_idx < 0)
548 break;
549 }
550
551 if (i == sizeof(supported_modes) * 8)
552 return -ENOENT;
553
554 mode->bits_per_pixel = var.bits_per_pixel;
555 mode->nonstd = var.nonstd;
556 mode->red = var.red;
557 mode->green = var.green;
558 mode->blue = var.blue;
559 mode->transp = var.transp;
560
561 return 0;
562}
563
564static int omapfb_wait_for_go(struct fb_info *fbi)
565{
566 struct omapfb_info *ofbi = FB2OFB(fbi);
567 int r = 0;
568 int i;
569
570 for (i = 0; i < ofbi->num_overlays; ++i) {
571 struct omap_overlay *ovl = ofbi->overlays[i];
572 r = ovl->wait_for_go(ovl);
573 if (r)
574 break;
575 }
576
577 return r;
578}
579
580int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
581{
582 struct omapfb_info *ofbi = FB2OFB(fbi);
583 struct omapfb2_device *fbdev = ofbi->fbdev;
584 struct omap_dss_device *display = fb2display(fbi);
585 struct omap_overlay_manager *mgr;
586
587 union {
588 struct omapfb_update_window_old uwnd_o;
589 struct omapfb_update_window uwnd;
590 struct omapfb_plane_info plane_info;
591 struct omapfb_caps caps;
592 struct omapfb_mem_info mem_info;
593 struct omapfb_color_key color_key;
594 struct omapfb_ovl_colormode ovl_colormode;
595 enum omapfb_update_mode update_mode;
596 int test_num;
597 struct omapfb_memory_read memory_read;
598 struct omapfb_vram_info vram_info;
599 struct omapfb_tearsync_info tearsync_info;
600 struct omapfb_display_info display_info;
601 u32 crt;
602 } p;
603
604 int r = 0;
605
606 switch (cmd) {
607 case OMAPFB_SYNC_GFX:
608 DBG("ioctl SYNC_GFX\n");
609 if (!display || !display->driver->sync) {
610 /* DSS1 never returns an error here, so we neither */
611 /*r = -EINVAL;*/
612 break;
613 }
614
615 r = display->driver->sync(display);
616 break;
617
618 case OMAPFB_UPDATE_WINDOW_OLD:
619 DBG("ioctl UPDATE_WINDOW_OLD\n");
620 if (!display || !display->driver->update) {
621 r = -EINVAL;
622 break;
623 }
624
625 if (copy_from_user(&p.uwnd_o,
626 (void __user *)arg,
627 sizeof(p.uwnd_o))) {
628 r = -EFAULT;
629 break;
630 }
631
632 r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y,
633 p.uwnd_o.width, p.uwnd_o.height);
634 break;
635
636 case OMAPFB_UPDATE_WINDOW:
637 DBG("ioctl UPDATE_WINDOW\n");
638 if (!display || !display->driver->update) {
639 r = -EINVAL;
640 break;
641 }
642
643 if (copy_from_user(&p.uwnd, (void __user *)arg,
644 sizeof(p.uwnd))) {
645 r = -EFAULT;
646 break;
647 }
648
649 r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y,
650 p.uwnd.width, p.uwnd.height);
651 break;
652
653 case OMAPFB_SETUP_PLANE:
654 DBG("ioctl SETUP_PLANE\n");
655 if (copy_from_user(&p.plane_info, (void __user *)arg,
656 sizeof(p.plane_info)))
657 r = -EFAULT;
658 else
659 r = omapfb_setup_plane(fbi, &p.plane_info);
660 break;
661
662 case OMAPFB_QUERY_PLANE:
663 DBG("ioctl QUERY_PLANE\n");
664 r = omapfb_query_plane(fbi, &p.plane_info);
665 if (r < 0)
666 break;
667 if (copy_to_user((void __user *)arg, &p.plane_info,
668 sizeof(p.plane_info)))
669 r = -EFAULT;
670 break;
671
672 case OMAPFB_SETUP_MEM:
673 DBG("ioctl SETUP_MEM\n");
674 if (copy_from_user(&p.mem_info, (void __user *)arg,
675 sizeof(p.mem_info)))
676 r = -EFAULT;
677 else
678 r = omapfb_setup_mem(fbi, &p.mem_info);
679 break;
680
681 case OMAPFB_QUERY_MEM:
682 DBG("ioctl QUERY_MEM\n");
683 r = omapfb_query_mem(fbi, &p.mem_info);
684 if (r < 0)
685 break;
686 if (copy_to_user((void __user *)arg, &p.mem_info,
687 sizeof(p.mem_info)))
688 r = -EFAULT;
689 break;
690
691 case OMAPFB_GET_CAPS:
692 DBG("ioctl GET_CAPS\n");
693 if (!display) {
694 r = -EINVAL;
695 break;
696 }
697
698 memset(&p.caps, 0, sizeof(p.caps));
699 if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
700 p.caps.ctrl |= OMAPFB_CAPS_MANUAL_UPDATE;
701 if (display->caps & OMAP_DSS_DISPLAY_CAP_TEAR_ELIM)
702 p.caps.ctrl |= OMAPFB_CAPS_TEARSYNC;
703
704 if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps)))
705 r = -EFAULT;
706 break;
707
708 case OMAPFB_GET_OVERLAY_COLORMODE:
709 DBG("ioctl GET_OVERLAY_COLORMODE\n");
710 if (copy_from_user(&p.ovl_colormode, (void __user *)arg,
711 sizeof(p.ovl_colormode))) {
712 r = -EFAULT;
713 break;
714 }
715 r = omapfb_get_ovl_colormode(fbdev, &p.ovl_colormode);
716 if (r < 0)
717 break;
718 if (copy_to_user((void __user *)arg, &p.ovl_colormode,
719 sizeof(p.ovl_colormode)))
720 r = -EFAULT;
721 break;
722
723 case OMAPFB_SET_UPDATE_MODE:
724 DBG("ioctl SET_UPDATE_MODE\n");
725 if (get_user(p.update_mode, (int __user *)arg))
726 r = -EFAULT;
727 else
728 r = omapfb_set_update_mode(fbi, p.update_mode);
729 break;
730
731 case OMAPFB_GET_UPDATE_MODE:
732 DBG("ioctl GET_UPDATE_MODE\n");
733 r = omapfb_get_update_mode(fbi, &p.update_mode);
734 if (r)
735 break;
736 if (put_user(p.update_mode,
737 (enum omapfb_update_mode __user *)arg))
738 r = -EFAULT;
739 break;
740
741 case OMAPFB_SET_COLOR_KEY:
742 DBG("ioctl SET_COLOR_KEY\n");
743 if (copy_from_user(&p.color_key, (void __user *)arg,
744 sizeof(p.color_key)))
745 r = -EFAULT;
746 else
747 r = omapfb_set_color_key(fbi, &p.color_key);
748 break;
749
750 case OMAPFB_GET_COLOR_KEY:
751 DBG("ioctl GET_COLOR_KEY\n");
752 r = omapfb_get_color_key(fbi, &p.color_key);
753 if (r)
754 break;
755 if (copy_to_user((void __user *)arg, &p.color_key,
756 sizeof(p.color_key)))
757 r = -EFAULT;
758 break;
759
760 case FBIO_WAITFORVSYNC:
761 if (get_user(p.crt, (__u32 __user *)arg)) {
762 r = -EFAULT;
763 break;
764 }
765 if (p.crt != 0) {
766 r = -ENODEV;
767 break;
768 }
769 /* FALLTHROUGH */
770
771 case OMAPFB_WAITFORVSYNC:
772 DBG("ioctl WAITFORVSYNC\n");
773
774 if (!display) {
775 r = -EINVAL;
776 break;
777 }
778
779 mgr = omapdss_find_mgr_from_display(display);
780 if (!mgr) {
781 r = -EINVAL;
782 break;
783 }
784
785 r = mgr->wait_for_vsync(mgr);
786 break;
787
788 case OMAPFB_WAITFORGO:
789 DBG("ioctl WAITFORGO\n");
790 if (!display) {
791 r = -EINVAL;
792 break;
793 }
794
795 r = omapfb_wait_for_go(fbi);
796 break;
797
798 /* LCD and CTRL tests do the same thing for backward
799 * compatibility */
800 case OMAPFB_LCD_TEST:
801 DBG("ioctl LCD_TEST\n");
802 if (get_user(p.test_num, (int __user *)arg)) {
803 r = -EFAULT;
804 break;
805 }
806 if (!display || !display->driver->run_test) {
807 r = -EINVAL;
808 break;
809 }
810
811 r = display->driver->run_test(display, p.test_num);
812
813 break;
814
815 case OMAPFB_CTRL_TEST:
816 DBG("ioctl CTRL_TEST\n");
817 if (get_user(p.test_num, (int __user *)arg)) {
818 r = -EFAULT;
819 break;
820 }
821 if (!display || !display->driver->run_test) {
822 r = -EINVAL;
823 break;
824 }
825
826 r = display->driver->run_test(display, p.test_num);
827
828 break;
829
830 case OMAPFB_MEMORY_READ:
831 DBG("ioctl MEMORY_READ\n");
832
833 if (copy_from_user(&p.memory_read, (void __user *)arg,
834 sizeof(p.memory_read))) {
835 r = -EFAULT;
836 break;
837 }
838
839 r = omapfb_memory_read(fbi, &p.memory_read);
840
841 break;
842
843 case OMAPFB_GET_VRAM_INFO: {
844 DBG("ioctl GET_VRAM_INFO\n");
845
846 /*
847 * We don't have the ability to get this vram info anymore.
848 * Fill in something that should keep the applications working.
849 */
850 p.vram_info.total = SZ_1M * 64;
851 p.vram_info.free = SZ_1M * 64;
852 p.vram_info.largest_free_block = SZ_1M * 64;
853
854 if (copy_to_user((void __user *)arg, &p.vram_info,
855 sizeof(p.vram_info)))
856 r = -EFAULT;
857 break;
858 }
859
860 case OMAPFB_SET_TEARSYNC: {
861 DBG("ioctl SET_TEARSYNC\n");
862
863 if (copy_from_user(&p.tearsync_info, (void __user *)arg,
864 sizeof(p.tearsync_info))) {
865 r = -EFAULT;
866 break;
867 }
868
869 if (!display || !display->driver->enable_te) {
870 r = -ENODEV;
871 break;
872 }
873
874 r = display->driver->enable_te(display,
875 !!p.tearsync_info.enabled);
876
877 break;
878 }
879
880 case OMAPFB_GET_DISPLAY_INFO: {
881 u16 xres, yres;
882
883 DBG("ioctl GET_DISPLAY_INFO\n");
884
885 if (display == NULL) {
886 r = -ENODEV;
887 break;
888 }
889
890 display->driver->get_resolution(display, &xres, &yres);
891
892 p.display_info.xres = xres;
893 p.display_info.yres = yres;
894
895 if (display->driver->get_dimensions) {
896 u32 w, h;
897 display->driver->get_dimensions(display, &w, &h);
898 p.display_info.width = w;
899 p.display_info.height = h;
900 } else {
901 p.display_info.width = 0;
902 p.display_info.height = 0;
903 }
904
905 if (copy_to_user((void __user *)arg, &p.display_info,
906 sizeof(p.display_info)))
907 r = -EFAULT;
908 break;
909 }
910
911 default:
912 dev_err(fbdev->dev, "Unknown ioctl 0x%x\n", cmd);
913 r = -EINVAL;
914 }
915
916 if (r < 0)
917 DBG("ioctl failed: %d\n", r);
918
919 return r;
920}
921
922
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
deleted file mode 100644
index ec2d132c782d..000000000000
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ /dev/null
@@ -1,2656 +0,0 @@
1/*
2 * linux/drivers/video/omap2/omapfb-main.c
3 *
4 * Copyright (C) 2008 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
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/module.h>
24#include <linux/delay.h>
25#include <linux/slab.h>
26#include <linux/fb.h>
27#include <linux/dma-mapping.h>
28#include <linux/vmalloc.h>
29#include <linux/device.h>
30#include <linux/platform_device.h>
31#include <linux/omapfb.h>
32
33#include <video/omapdss.h>
34#include <video/omapvrfb.h>
35
36#include "omapfb.h"
37
38#define MODULE_NAME "omapfb"
39
40#define OMAPFB_PLANE_XRES_MIN 8
41#define OMAPFB_PLANE_YRES_MIN 8
42
43static char *def_mode;
44static char *def_vram;
45static bool def_vrfb;
46static int def_rotate;
47static bool def_mirror;
48static bool auto_update;
49static unsigned int auto_update_freq;
50module_param(auto_update, bool, 0);
51module_param(auto_update_freq, uint, 0644);
52
53#ifdef DEBUG
54bool omapfb_debug;
55module_param_named(debug, omapfb_debug, bool, 0644);
56static bool omapfb_test_pattern;
57module_param_named(test, omapfb_test_pattern, bool, 0644);
58#endif
59
60static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi);
61static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
62 struct omap_dss_device *dssdev);
63
64#ifdef DEBUG
65static void draw_pixel(struct fb_info *fbi, int x, int y, unsigned color)
66{
67 struct fb_var_screeninfo *var = &fbi->var;
68 struct fb_fix_screeninfo *fix = &fbi->fix;
69 void __iomem *addr = fbi->screen_base;
70 const unsigned bytespp = var->bits_per_pixel >> 3;
71 const unsigned line_len = fix->line_length / bytespp;
72
73 int r = (color >> 16) & 0xff;
74 int g = (color >> 8) & 0xff;
75 int b = (color >> 0) & 0xff;
76
77 if (var->bits_per_pixel == 16) {
78 u16 __iomem *p = (u16 __iomem *)addr;
79 p += y * line_len + x;
80
81 r = r * 32 / 256;
82 g = g * 64 / 256;
83 b = b * 32 / 256;
84
85 __raw_writew((r << 11) | (g << 5) | (b << 0), p);
86 } else if (var->bits_per_pixel == 24) {
87 u8 __iomem *p = (u8 __iomem *)addr;
88 p += (y * line_len + x) * 3;
89
90 __raw_writeb(b, p + 0);
91 __raw_writeb(g, p + 1);
92 __raw_writeb(r, p + 2);
93 } else if (var->bits_per_pixel == 32) {
94 u32 __iomem *p = (u32 __iomem *)addr;
95 p += y * line_len + x;
96 __raw_writel(color, p);
97 }
98}
99
100static void fill_fb(struct fb_info *fbi)
101{
102 struct fb_var_screeninfo *var = &fbi->var;
103 const short w = var->xres_virtual;
104 const short h = var->yres_virtual;
105 void __iomem *addr = fbi->screen_base;
106 int y, x;
107
108 if (!addr)
109 return;
110
111 DBG("fill_fb %dx%d, line_len %d bytes\n", w, h, fbi->fix.line_length);
112
113 for (y = 0; y < h; y++) {
114 for (x = 0; x < w; x++) {
115 if (x < 20 && y < 20)
116 draw_pixel(fbi, x, y, 0xffffff);
117 else if (x < 20 && (y > 20 && y < h - 20))
118 draw_pixel(fbi, x, y, 0xff);
119 else if (y < 20 && (x > 20 && x < w - 20))
120 draw_pixel(fbi, x, y, 0xff00);
121 else if (x > w - 20 && (y > 20 && y < h - 20))
122 draw_pixel(fbi, x, y, 0xff0000);
123 else if (y > h - 20 && (x > 20 && x < w - 20))
124 draw_pixel(fbi, x, y, 0xffff00);
125 else if (x == 20 || x == w - 20 ||
126 y == 20 || y == h - 20)
127 draw_pixel(fbi, x, y, 0xffffff);
128 else if (x == y || w - x == h - y)
129 draw_pixel(fbi, x, y, 0xff00ff);
130 else if (w - x == y || x == h - y)
131 draw_pixel(fbi, x, y, 0x00ffff);
132 else if (x > 20 && y > 20 && x < w - 20 && y < h - 20) {
133 int t = x * 3 / w;
134 unsigned r = 0, g = 0, b = 0;
135 unsigned c;
136 if (var->bits_per_pixel == 16) {
137 if (t == 0)
138 b = (y % 32) * 256 / 32;
139 else if (t == 1)
140 g = (y % 64) * 256 / 64;
141 else if (t == 2)
142 r = (y % 32) * 256 / 32;
143 } else {
144 if (t == 0)
145 b = (y % 256);
146 else if (t == 1)
147 g = (y % 256);
148 else if (t == 2)
149 r = (y % 256);
150 }
151 c = (r << 16) | (g << 8) | (b << 0);
152 draw_pixel(fbi, x, y, c);
153 } else {
154 draw_pixel(fbi, x, y, 0);
155 }
156 }
157 }
158}
159#endif
160
161static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
162{
163 const struct vrfb *vrfb = &ofbi->region->vrfb;
164 unsigned offset;
165
166 switch (rot) {
167 case FB_ROTATE_UR:
168 offset = 0;
169 break;
170 case FB_ROTATE_CW:
171 offset = vrfb->yoffset;
172 break;
173 case FB_ROTATE_UD:
174 offset = vrfb->yoffset * OMAP_VRFB_LINE_LEN + vrfb->xoffset;
175 break;
176 case FB_ROTATE_CCW:
177 offset = vrfb->xoffset * OMAP_VRFB_LINE_LEN;
178 break;
179 default:
180 BUG();
181 return 0;
182 }
183
184 offset *= vrfb->bytespp;
185
186 return offset;
187}
188
189static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot)
190{
191 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
192 return ofbi->region->vrfb.paddr[rot]
193 + omapfb_get_vrfb_offset(ofbi, rot);
194 } else {
195 return ofbi->region->paddr;
196 }
197}
198
199static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi)
200{
201 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
202 return ofbi->region->vrfb.paddr[0];
203 else
204 return ofbi->region->paddr;
205}
206
207static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi)
208{
209 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
210 return ofbi->region->vrfb.vaddr[0];
211 else
212 return ofbi->region->vaddr;
213}
214
215static struct omapfb_colormode omapfb_colormodes[] = {
216 {
217 .dssmode = OMAP_DSS_COLOR_UYVY,
218 .bits_per_pixel = 16,
219 .nonstd = OMAPFB_COLOR_YUV422,
220 }, {
221 .dssmode = OMAP_DSS_COLOR_YUV2,
222 .bits_per_pixel = 16,
223 .nonstd = OMAPFB_COLOR_YUY422,
224 }, {
225 .dssmode = OMAP_DSS_COLOR_ARGB16,
226 .bits_per_pixel = 16,
227 .red = { .length = 4, .offset = 8, .msb_right = 0 },
228 .green = { .length = 4, .offset = 4, .msb_right = 0 },
229 .blue = { .length = 4, .offset = 0, .msb_right = 0 },
230 .transp = { .length = 4, .offset = 12, .msb_right = 0 },
231 }, {
232 .dssmode = OMAP_DSS_COLOR_RGB16,
233 .bits_per_pixel = 16,
234 .red = { .length = 5, .offset = 11, .msb_right = 0 },
235 .green = { .length = 6, .offset = 5, .msb_right = 0 },
236 .blue = { .length = 5, .offset = 0, .msb_right = 0 },
237 .transp = { .length = 0, .offset = 0, .msb_right = 0 },
238 }, {
239 .dssmode = OMAP_DSS_COLOR_RGB24P,
240 .bits_per_pixel = 24,
241 .red = { .length = 8, .offset = 16, .msb_right = 0 },
242 .green = { .length = 8, .offset = 8, .msb_right = 0 },
243 .blue = { .length = 8, .offset = 0, .msb_right = 0 },
244 .transp = { .length = 0, .offset = 0, .msb_right = 0 },
245 }, {
246 .dssmode = OMAP_DSS_COLOR_RGB24U,
247 .bits_per_pixel = 32,
248 .red = { .length = 8, .offset = 16, .msb_right = 0 },
249 .green = { .length = 8, .offset = 8, .msb_right = 0 },
250 .blue = { .length = 8, .offset = 0, .msb_right = 0 },
251 .transp = { .length = 0, .offset = 0, .msb_right = 0 },
252 }, {
253 .dssmode = OMAP_DSS_COLOR_ARGB32,
254 .bits_per_pixel = 32,
255 .red = { .length = 8, .offset = 16, .msb_right = 0 },
256 .green = { .length = 8, .offset = 8, .msb_right = 0 },
257 .blue = { .length = 8, .offset = 0, .msb_right = 0 },
258 .transp = { .length = 8, .offset = 24, .msb_right = 0 },
259 }, {
260 .dssmode = OMAP_DSS_COLOR_RGBA32,
261 .bits_per_pixel = 32,
262 .red = { .length = 8, .offset = 24, .msb_right = 0 },
263 .green = { .length = 8, .offset = 16, .msb_right = 0 },
264 .blue = { .length = 8, .offset = 8, .msb_right = 0 },
265 .transp = { .length = 8, .offset = 0, .msb_right = 0 },
266 }, {
267 .dssmode = OMAP_DSS_COLOR_RGBX32,
268 .bits_per_pixel = 32,
269 .red = { .length = 8, .offset = 24, .msb_right = 0 },
270 .green = { .length = 8, .offset = 16, .msb_right = 0 },
271 .blue = { .length = 8, .offset = 8, .msb_right = 0 },
272 .transp = { .length = 0, .offset = 0, .msb_right = 0 },
273 },
274};
275
276static bool cmp_var_to_colormode(struct fb_var_screeninfo *var,
277 struct omapfb_colormode *color)
278{
279 bool cmp_component(struct fb_bitfield *f1, struct fb_bitfield *f2)
280 {
281 return f1->length == f2->length &&
282 f1->offset == f2->offset &&
283 f1->msb_right == f2->msb_right;
284 }
285
286 if (var->bits_per_pixel == 0 ||
287 var->red.length == 0 ||
288 var->blue.length == 0 ||
289 var->green.length == 0)
290 return 0;
291
292 return var->bits_per_pixel == color->bits_per_pixel &&
293 cmp_component(&var->red, &color->red) &&
294 cmp_component(&var->green, &color->green) &&
295 cmp_component(&var->blue, &color->blue) &&
296 cmp_component(&var->transp, &color->transp);
297}
298
299static void assign_colormode_to_var(struct fb_var_screeninfo *var,
300 struct omapfb_colormode *color)
301{
302 var->bits_per_pixel = color->bits_per_pixel;
303 var->nonstd = color->nonstd;
304 var->red = color->red;
305 var->green = color->green;
306 var->blue = color->blue;
307 var->transp = color->transp;
308}
309
310static int fb_mode_to_dss_mode(struct fb_var_screeninfo *var,
311 enum omap_color_mode *mode)
312{
313 enum omap_color_mode dssmode;
314 int i;
315
316 /* first match with nonstd field */
317 if (var->nonstd) {
318 for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
319 struct omapfb_colormode *m = &omapfb_colormodes[i];
320 if (var->nonstd == m->nonstd) {
321 assign_colormode_to_var(var, m);
322 *mode = m->dssmode;
323 return 0;
324 }
325 }
326
327 return -EINVAL;
328 }
329
330 /* then try exact match of bpp and colors */
331 for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
332 struct omapfb_colormode *m = &omapfb_colormodes[i];
333 if (cmp_var_to_colormode(var, m)) {
334 assign_colormode_to_var(var, m);
335 *mode = m->dssmode;
336 return 0;
337 }
338 }
339
340 /* match with bpp if user has not filled color fields
341 * properly */
342 switch (var->bits_per_pixel) {
343 case 1:
344 dssmode = OMAP_DSS_COLOR_CLUT1;
345 break;
346 case 2:
347 dssmode = OMAP_DSS_COLOR_CLUT2;
348 break;
349 case 4:
350 dssmode = OMAP_DSS_COLOR_CLUT4;
351 break;
352 case 8:
353 dssmode = OMAP_DSS_COLOR_CLUT8;
354 break;
355 case 12:
356 dssmode = OMAP_DSS_COLOR_RGB12U;
357 break;
358 case 16:
359 dssmode = OMAP_DSS_COLOR_RGB16;
360 break;
361 case 24:
362 dssmode = OMAP_DSS_COLOR_RGB24P;
363 break;
364 case 32:
365 dssmode = OMAP_DSS_COLOR_RGB24U;
366 break;
367 default:
368 return -EINVAL;
369 }
370
371 for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
372 struct omapfb_colormode *m = &omapfb_colormodes[i];
373 if (dssmode == m->dssmode) {
374 assign_colormode_to_var(var, m);
375 *mode = m->dssmode;
376 return 0;
377 }
378 }
379
380 return -EINVAL;
381}
382
383static int check_fb_res_bounds(struct fb_var_screeninfo *var)
384{
385 int xres_min = OMAPFB_PLANE_XRES_MIN;
386 int xres_max = 2048;
387 int yres_min = OMAPFB_PLANE_YRES_MIN;
388 int yres_max = 2048;
389
390 /* XXX: some applications seem to set virtual res to 0. */
391 if (var->xres_virtual == 0)
392 var->xres_virtual = var->xres;
393
394 if (var->yres_virtual == 0)
395 var->yres_virtual = var->yres;
396
397 if (var->xres_virtual < xres_min || var->yres_virtual < yres_min)
398 return -EINVAL;
399
400 if (var->xres < xres_min)
401 var->xres = xres_min;
402 if (var->yres < yres_min)
403 var->yres = yres_min;
404 if (var->xres > xres_max)
405 var->xres = xres_max;
406 if (var->yres > yres_max)
407 var->yres = yres_max;
408
409 if (var->xres > var->xres_virtual)
410 var->xres = var->xres_virtual;
411 if (var->yres > var->yres_virtual)
412 var->yres = var->yres_virtual;
413
414 return 0;
415}
416
417static void shrink_height(unsigned long max_frame_size,
418 struct fb_var_screeninfo *var)
419{
420 DBG("can't fit FB into memory, reducing y\n");
421 var->yres_virtual = max_frame_size /
422 (var->xres_virtual * var->bits_per_pixel >> 3);
423
424 if (var->yres_virtual < OMAPFB_PLANE_YRES_MIN)
425 var->yres_virtual = OMAPFB_PLANE_YRES_MIN;
426
427 if (var->yres > var->yres_virtual)
428 var->yres = var->yres_virtual;
429}
430
431static void shrink_width(unsigned long max_frame_size,
432 struct fb_var_screeninfo *var)
433{
434 DBG("can't fit FB into memory, reducing x\n");
435 var->xres_virtual = max_frame_size / var->yres_virtual /
436 (var->bits_per_pixel >> 3);
437
438 if (var->xres_virtual < OMAPFB_PLANE_XRES_MIN)
439 var->xres_virtual = OMAPFB_PLANE_XRES_MIN;
440
441 if (var->xres > var->xres_virtual)
442 var->xres = var->xres_virtual;
443}
444
445static int check_vrfb_fb_size(unsigned long region_size,
446 const struct fb_var_screeninfo *var)
447{
448 unsigned long min_phys_size = omap_vrfb_min_phys_size(var->xres_virtual,
449 var->yres_virtual, var->bits_per_pixel >> 3);
450
451 return min_phys_size > region_size ? -EINVAL : 0;
452}
453
454static int check_fb_size(const struct omapfb_info *ofbi,
455 struct fb_var_screeninfo *var)
456{
457 unsigned long max_frame_size = ofbi->region->size;
458 int bytespp = var->bits_per_pixel >> 3;
459 unsigned long line_size = var->xres_virtual * bytespp;
460
461 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
462 /* One needs to check for both VRFB and OMAPFB limitations. */
463 if (check_vrfb_fb_size(max_frame_size, var))
464 shrink_height(omap_vrfb_max_height(
465 max_frame_size, var->xres_virtual, bytespp) *
466 line_size, var);
467
468 if (check_vrfb_fb_size(max_frame_size, var)) {
469 DBG("cannot fit FB to memory\n");
470 return -EINVAL;
471 }
472
473 return 0;
474 }
475
476 DBG("max frame size %lu, line size %lu\n", max_frame_size, line_size);
477
478 if (line_size * var->yres_virtual > max_frame_size)
479 shrink_height(max_frame_size, var);
480
481 if (line_size * var->yres_virtual > max_frame_size) {
482 shrink_width(max_frame_size, var);
483 line_size = var->xres_virtual * bytespp;
484 }
485
486 if (line_size * var->yres_virtual > max_frame_size) {
487 DBG("cannot fit FB to memory\n");
488 return -EINVAL;
489 }
490
491 return 0;
492}
493
494/*
495 * Consider if VRFB assisted rotation is in use and if the virtual space for
496 * the zero degree view needs to be mapped. The need for mapping also acts as
497 * the trigger for setting up the hardware on the context in question. This
498 * ensures that one does not attempt to access the virtual view before the
499 * hardware is serving the address translations.
500 */
501static int setup_vrfb_rotation(struct fb_info *fbi)
502{
503 struct omapfb_info *ofbi = FB2OFB(fbi);
504 struct omapfb2_mem_region *rg = ofbi->region;
505 struct vrfb *vrfb = &rg->vrfb;
506 struct fb_var_screeninfo *var = &fbi->var;
507 struct fb_fix_screeninfo *fix = &fbi->fix;
508 unsigned bytespp;
509 bool yuv_mode;
510 enum omap_color_mode mode;
511 int r;
512 bool reconf;
513
514 if (!rg->size || ofbi->rotation_type != OMAP_DSS_ROT_VRFB)
515 return 0;
516
517 DBG("setup_vrfb_rotation\n");
518
519 r = fb_mode_to_dss_mode(var, &mode);
520 if (r)
521 return r;
522
523 bytespp = var->bits_per_pixel >> 3;
524
525 yuv_mode = mode == OMAP_DSS_COLOR_YUV2 || mode == OMAP_DSS_COLOR_UYVY;
526
527 /* We need to reconfigure VRFB if the resolution changes, if yuv mode
528 * is enabled/disabled, or if bytes per pixel changes */
529
530 /* XXX we shouldn't allow this when framebuffer is mmapped */
531
532 reconf = false;
533
534 if (yuv_mode != vrfb->yuv_mode)
535 reconf = true;
536 else if (bytespp != vrfb->bytespp)
537 reconf = true;
538 else if (vrfb->xres != var->xres_virtual ||
539 vrfb->yres != var->yres_virtual)
540 reconf = true;
541
542 if (vrfb->vaddr[0] && reconf) {
543 fbi->screen_base = NULL;
544 fix->smem_start = 0;
545 fix->smem_len = 0;
546 iounmap(vrfb->vaddr[0]);
547 vrfb->vaddr[0] = NULL;
548 DBG("setup_vrfb_rotation: reset fb\n");
549 }
550
551 if (vrfb->vaddr[0])
552 return 0;
553
554 omap_vrfb_setup(&rg->vrfb, rg->paddr,
555 var->xres_virtual,
556 var->yres_virtual,
557 bytespp, yuv_mode);
558
559 /* Now one can ioremap the 0 angle view */
560 r = omap_vrfb_map_angle(vrfb, var->yres_virtual, 0);
561 if (r)
562 return r;
563
564 /* used by open/write in fbmem.c */
565 fbi->screen_base = ofbi->region->vrfb.vaddr[0];
566
567 fix->smem_start = ofbi->region->vrfb.paddr[0];
568
569 switch (var->nonstd) {
570 case OMAPFB_COLOR_YUV422:
571 case OMAPFB_COLOR_YUY422:
572 fix->line_length =
573 (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
574 break;
575 default:
576 fix->line_length =
577 (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
578 break;
579 }
580
581 fix->smem_len = var->yres_virtual * fix->line_length;
582
583 return 0;
584}
585
586int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
587 struct fb_var_screeninfo *var)
588{
589 int i;
590
591 for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
592 struct omapfb_colormode *mode = &omapfb_colormodes[i];
593 if (dssmode == mode->dssmode) {
594 assign_colormode_to_var(var, mode);
595 return 0;
596 }
597 }
598 return -ENOENT;
599}
600
601void set_fb_fix(struct fb_info *fbi)
602{
603 struct fb_fix_screeninfo *fix = &fbi->fix;
604 struct fb_var_screeninfo *var = &fbi->var;
605 struct omapfb_info *ofbi = FB2OFB(fbi);
606 struct omapfb2_mem_region *rg = ofbi->region;
607
608 DBG("set_fb_fix\n");
609
610 /* used by open/write in fbmem.c */
611 fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi);
612
613 /* used by mmap in fbmem.c */
614 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
615 switch (var->nonstd) {
616 case OMAPFB_COLOR_YUV422:
617 case OMAPFB_COLOR_YUY422:
618 fix->line_length =
619 (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
620 break;
621 default:
622 fix->line_length =
623 (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
624 break;
625 }
626
627 fix->smem_len = var->yres_virtual * fix->line_length;
628 } else {
629 fix->line_length =
630 (var->xres_virtual * var->bits_per_pixel) >> 3;
631 fix->smem_len = rg->size;
632 }
633
634 fix->smem_start = omapfb_get_region_paddr(ofbi);
635
636 fix->type = FB_TYPE_PACKED_PIXELS;
637
638 if (var->nonstd)
639 fix->visual = FB_VISUAL_PSEUDOCOLOR;
640 else {
641 switch (var->bits_per_pixel) {
642 case 32:
643 case 24:
644 case 16:
645 case 12:
646 fix->visual = FB_VISUAL_TRUECOLOR;
647 /* 12bpp is stored in 16 bits */
648 break;
649 case 1:
650 case 2:
651 case 4:
652 case 8:
653 fix->visual = FB_VISUAL_PSEUDOCOLOR;
654 break;
655 }
656 }
657
658 fix->accel = FB_ACCEL_NONE;
659
660 fix->xpanstep = 1;
661 fix->ypanstep = 1;
662}
663
664/* check new var and possibly modify it to be ok */
665int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
666{
667 struct omapfb_info *ofbi = FB2OFB(fbi);
668 struct omap_dss_device *display = fb2display(fbi);
669 enum omap_color_mode mode = 0;
670 int i;
671 int r;
672
673 DBG("check_fb_var %d\n", ofbi->id);
674
675 WARN_ON(!atomic_read(&ofbi->region->lock_count));
676
677 r = fb_mode_to_dss_mode(var, &mode);
678 if (r) {
679 DBG("cannot convert var to omap dss mode\n");
680 return r;
681 }
682
683 for (i = 0; i < ofbi->num_overlays; ++i) {
684 if ((ofbi->overlays[i]->supported_modes & mode) == 0) {
685 DBG("invalid mode\n");
686 return -EINVAL;
687 }
688 }
689
690 if (var->rotate > 3)
691 return -EINVAL;
692
693 if (check_fb_res_bounds(var))
694 return -EINVAL;
695
696 /* When no memory is allocated ignore the size check */
697 if (ofbi->region->size != 0 && check_fb_size(ofbi, var))
698 return -EINVAL;
699
700 if (var->xres + var->xoffset > var->xres_virtual)
701 var->xoffset = var->xres_virtual - var->xres;
702 if (var->yres + var->yoffset > var->yres_virtual)
703 var->yoffset = var->yres_virtual - var->yres;
704
705 DBG("xres = %d, yres = %d, vxres = %d, vyres = %d\n",
706 var->xres, var->yres,
707 var->xres_virtual, var->yres_virtual);
708
709 if (display && display->driver->get_dimensions) {
710 u32 w, h;
711 display->driver->get_dimensions(display, &w, &h);
712 var->width = DIV_ROUND_CLOSEST(w, 1000);
713 var->height = DIV_ROUND_CLOSEST(h, 1000);
714 } else {
715 var->height = -1;
716 var->width = -1;
717 }
718
719 var->grayscale = 0;
720
721 if (display && display->driver->get_timings) {
722 struct omap_video_timings timings;
723 display->driver->get_timings(display, &timings);
724
725 /* pixclock in ps, the rest in pixclock */
726 var->pixclock = timings.pixelclock != 0 ?
727 KHZ2PICOS(timings.pixelclock / 1000) :
728 0;
729 var->left_margin = timings.hbp;
730 var->right_margin = timings.hfp;
731 var->upper_margin = timings.vbp;
732 var->lower_margin = timings.vfp;
733 var->hsync_len = timings.hsw;
734 var->vsync_len = timings.vsw;
735 var->sync |= timings.hsync_level == OMAPDSS_SIG_ACTIVE_HIGH ?
736 FB_SYNC_HOR_HIGH_ACT : 0;
737 var->sync |= timings.vsync_level == OMAPDSS_SIG_ACTIVE_HIGH ?
738 FB_SYNC_VERT_HIGH_ACT : 0;
739 var->vmode = timings.interlace ?
740 FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
741 } else {
742 var->pixclock = 0;
743 var->left_margin = 0;
744 var->right_margin = 0;
745 var->upper_margin = 0;
746 var->lower_margin = 0;
747 var->hsync_len = 0;
748 var->vsync_len = 0;
749 var->sync = 0;
750 var->vmode = FB_VMODE_NONINTERLACED;
751 }
752
753 return 0;
754}
755
756/*
757 * ---------------------------------------------------------------------------
758 * fbdev framework callbacks
759 * ---------------------------------------------------------------------------
760 */
761static int omapfb_open(struct fb_info *fbi, int user)
762{
763 return 0;
764}
765
766static int omapfb_release(struct fb_info *fbi, int user)
767{
768 return 0;
769}
770
771static unsigned calc_rotation_offset_dma(const struct fb_var_screeninfo *var,
772 const struct fb_fix_screeninfo *fix, int rotation)
773{
774 unsigned offset;
775
776 offset = var->yoffset * fix->line_length +
777 var->xoffset * (var->bits_per_pixel >> 3);
778
779 return offset;
780}
781
782static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,
783 const struct fb_fix_screeninfo *fix, int rotation)
784{
785 unsigned offset;
786
787 if (rotation == FB_ROTATE_UD)
788 offset = (var->yres_virtual - var->yres) *
789 fix->line_length;
790 else if (rotation == FB_ROTATE_CW)
791 offset = (var->yres_virtual - var->yres) *
792 (var->bits_per_pixel >> 3);
793 else
794 offset = 0;
795
796 if (rotation == FB_ROTATE_UR)
797 offset += var->yoffset * fix->line_length +
798 var->xoffset * (var->bits_per_pixel >> 3);
799 else if (rotation == FB_ROTATE_UD)
800 offset -= var->yoffset * fix->line_length +
801 var->xoffset * (var->bits_per_pixel >> 3);
802 else if (rotation == FB_ROTATE_CW)
803 offset -= var->xoffset * fix->line_length +
804 var->yoffset * (var->bits_per_pixel >> 3);
805 else if (rotation == FB_ROTATE_CCW)
806 offset += var->xoffset * fix->line_length +
807 var->yoffset * (var->bits_per_pixel >> 3);
808
809 return offset;
810}
811
812static void omapfb_calc_addr(const struct omapfb_info *ofbi,
813 const struct fb_var_screeninfo *var,
814 const struct fb_fix_screeninfo *fix,
815 int rotation, u32 *paddr)
816{
817 u32 data_start_p;
818 int offset;
819
820 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
821 data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
822 else
823 data_start_p = omapfb_get_region_paddr(ofbi);
824
825 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
826 offset = calc_rotation_offset_vrfb(var, fix, rotation);
827 else
828 offset = calc_rotation_offset_dma(var, fix, rotation);
829
830 data_start_p += offset;
831
832 if (offset)
833 DBG("offset %d, %d = %d\n",
834 var->xoffset, var->yoffset, offset);
835
836 DBG("paddr %x\n", data_start_p);
837
838 *paddr = data_start_p;
839}
840
841/* setup overlay according to the fb */
842int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
843 u16 posx, u16 posy, u16 outw, u16 outh)
844{
845 int r = 0;
846 struct omapfb_info *ofbi = FB2OFB(fbi);
847 struct fb_var_screeninfo *var = &fbi->var;
848 struct fb_fix_screeninfo *fix = &fbi->fix;
849 enum omap_color_mode mode = 0;
850 u32 data_start_p = 0;
851 struct omap_overlay_info info;
852 int xres, yres;
853 int screen_width;
854 int mirror;
855 int rotation = var->rotate;
856 int i;
857
858 WARN_ON(!atomic_read(&ofbi->region->lock_count));
859
860 for (i = 0; i < ofbi->num_overlays; i++) {
861 if (ovl != ofbi->overlays[i])
862 continue;
863
864 rotation = (rotation + ofbi->rotation[i]) % 4;
865 break;
866 }
867
868 DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id,
869 posx, posy, outw, outh);
870
871 if (rotation == FB_ROTATE_CW || rotation == FB_ROTATE_CCW) {
872 xres = var->yres;
873 yres = var->xres;
874 } else {
875 xres = var->xres;
876 yres = var->yres;
877 }
878
879 if (ofbi->region->size)
880 omapfb_calc_addr(ofbi, var, fix, rotation, &data_start_p);
881
882 r = fb_mode_to_dss_mode(var, &mode);
883 if (r) {
884 DBG("fb_mode_to_dss_mode failed");
885 goto err;
886 }
887
888 switch (var->nonstd) {
889 case OMAPFB_COLOR_YUV422:
890 case OMAPFB_COLOR_YUY422:
891 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
892 screen_width = fix->line_length
893 / (var->bits_per_pixel >> 2);
894 break;
895 }
896 default:
897 screen_width = fix->line_length / (var->bits_per_pixel >> 3);
898 break;
899 }
900
901 ovl->get_overlay_info(ovl, &info);
902
903 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
904 mirror = 0;
905 else
906 mirror = ofbi->mirror;
907
908 info.paddr = data_start_p;
909 info.screen_width = screen_width;
910 info.width = xres;
911 info.height = yres;
912 info.color_mode = mode;
913 info.rotation_type = ofbi->rotation_type;
914 info.rotation = rotation;
915 info.mirror = mirror;
916
917 info.pos_x = posx;
918 info.pos_y = posy;
919 info.out_width = outw;
920 info.out_height = outh;
921
922 r = ovl->set_overlay_info(ovl, &info);
923 if (r) {
924 DBG("ovl->setup_overlay_info failed\n");
925 goto err;
926 }
927
928 return 0;
929
930err:
931 DBG("setup_overlay failed\n");
932 return r;
933}
934
935/* apply var to the overlay */
936int omapfb_apply_changes(struct fb_info *fbi, int init)
937{
938 int r = 0;
939 struct omapfb_info *ofbi = FB2OFB(fbi);
940 struct fb_var_screeninfo *var = &fbi->var;
941 struct omap_overlay *ovl;
942 u16 posx, posy;
943 u16 outw, outh;
944 int i;
945
946#ifdef DEBUG
947 if (omapfb_test_pattern)
948 fill_fb(fbi);
949#endif
950
951 WARN_ON(!atomic_read(&ofbi->region->lock_count));
952
953 for (i = 0; i < ofbi->num_overlays; i++) {
954 ovl = ofbi->overlays[i];
955
956 DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id);
957
958 if (ofbi->region->size == 0) {
959 /* the fb is not available. disable the overlay */
960 omapfb_overlay_enable(ovl, 0);
961 if (!init && ovl->manager)
962 ovl->manager->apply(ovl->manager);
963 continue;
964 }
965
966 if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
967 int rotation = (var->rotate + ofbi->rotation[i]) % 4;
968 if (rotation == FB_ROTATE_CW ||
969 rotation == FB_ROTATE_CCW) {
970 outw = var->yres;
971 outh = var->xres;
972 } else {
973 outw = var->xres;
974 outh = var->yres;
975 }
976 } else {
977 struct omap_overlay_info info;
978 ovl->get_overlay_info(ovl, &info);
979 outw = info.out_width;
980 outh = info.out_height;
981 }
982
983 if (init) {
984 posx = 0;
985 posy = 0;
986 } else {
987 struct omap_overlay_info info;
988 ovl->get_overlay_info(ovl, &info);
989 posx = info.pos_x;
990 posy = info.pos_y;
991 }
992
993 r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh);
994 if (r)
995 goto err;
996
997 if (!init && ovl->manager)
998 ovl->manager->apply(ovl->manager);
999 }
1000 return 0;
1001err:
1002 DBG("apply_changes failed\n");
1003 return r;
1004}
1005
1006/* checks var and eventually tweaks it to something supported,
1007 * DO NOT MODIFY PAR */
1008static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
1009{
1010 struct omapfb_info *ofbi = FB2OFB(fbi);
1011 int r;
1012
1013 DBG("check_var(%d)\n", FB2OFB(fbi)->id);
1014
1015 omapfb_get_mem_region(ofbi->region);
1016
1017 r = check_fb_var(fbi, var);
1018
1019 omapfb_put_mem_region(ofbi->region);
1020
1021 return r;
1022}
1023
1024/* set the video mode according to info->var */
1025static int omapfb_set_par(struct fb_info *fbi)
1026{
1027 struct omapfb_info *ofbi = FB2OFB(fbi);
1028 int r;
1029
1030 DBG("set_par(%d)\n", FB2OFB(fbi)->id);
1031
1032 omapfb_get_mem_region(ofbi->region);
1033
1034 set_fb_fix(fbi);
1035
1036 r = setup_vrfb_rotation(fbi);
1037 if (r)
1038 goto out;
1039
1040 r = omapfb_apply_changes(fbi, 0);
1041
1042 out:
1043 omapfb_put_mem_region(ofbi->region);
1044
1045 return r;
1046}
1047
1048static int omapfb_pan_display(struct fb_var_screeninfo *var,
1049 struct fb_info *fbi)
1050{
1051 struct omapfb_info *ofbi = FB2OFB(fbi);
1052 struct fb_var_screeninfo new_var;
1053 int r;
1054
1055 DBG("pan_display(%d)\n", FB2OFB(fbi)->id);
1056
1057 if (var->xoffset == fbi->var.xoffset &&
1058 var->yoffset == fbi->var.yoffset)
1059 return 0;
1060
1061 new_var = fbi->var;
1062 new_var.xoffset = var->xoffset;
1063 new_var.yoffset = var->yoffset;
1064
1065 fbi->var = new_var;
1066
1067 omapfb_get_mem_region(ofbi->region);
1068
1069 r = omapfb_apply_changes(fbi, 0);
1070
1071 omapfb_put_mem_region(ofbi->region);
1072
1073 return r;
1074}
1075
1076static void mmap_user_open(struct vm_area_struct *vma)
1077{
1078 struct omapfb2_mem_region *rg = vma->vm_private_data;
1079
1080 omapfb_get_mem_region(rg);
1081 atomic_inc(&rg->map_count);
1082 omapfb_put_mem_region(rg);
1083}
1084
1085static void mmap_user_close(struct vm_area_struct *vma)
1086{
1087 struct omapfb2_mem_region *rg = vma->vm_private_data;
1088
1089 omapfb_get_mem_region(rg);
1090 atomic_dec(&rg->map_count);
1091 omapfb_put_mem_region(rg);
1092}
1093
1094static struct vm_operations_struct mmap_user_ops = {
1095 .open = mmap_user_open,
1096 .close = mmap_user_close,
1097};
1098
1099static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
1100{
1101 struct omapfb_info *ofbi = FB2OFB(fbi);
1102 struct fb_fix_screeninfo *fix = &fbi->fix;
1103 struct omapfb2_mem_region *rg;
1104 unsigned long start;
1105 u32 len;
1106 int r;
1107
1108 rg = omapfb_get_mem_region(ofbi->region);
1109
1110 start = omapfb_get_region_paddr(ofbi);
1111 len = fix->smem_len;
1112
1113 DBG("user mmap region start %lx, len %d, off %lx\n", start, len,
1114 vma->vm_pgoff << PAGE_SHIFT);
1115
1116 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
1117 vma->vm_ops = &mmap_user_ops;
1118 vma->vm_private_data = rg;
1119
1120 r = vm_iomap_memory(vma, start, len);
1121 if (r)
1122 goto error;
1123
1124 /* vm_ops.open won't be called for mmap itself. */
1125 atomic_inc(&rg->map_count);
1126
1127 omapfb_put_mem_region(rg);
1128
1129 return 0;
1130
1131error:
1132 omapfb_put_mem_region(ofbi->region);
1133
1134 return r;
1135}
1136
1137/* Store a single color palette entry into a pseudo palette or the hardware
1138 * palette if one is available. For now we support only 16bpp and thus store
1139 * the entry only to the pseudo palette.
1140 */
1141static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
1142 u_int blue, u_int transp, int update_hw_pal)
1143{
1144 /*struct omapfb_info *ofbi = FB2OFB(fbi);*/
1145 /*struct omapfb2_device *fbdev = ofbi->fbdev;*/
1146 struct fb_var_screeninfo *var = &fbi->var;
1147 int r = 0;
1148
1149 enum omapfb_color_format mode = OMAPFB_COLOR_RGB24U; /* XXX */
1150
1151 /*switch (plane->color_mode) {*/
1152 switch (mode) {
1153 case OMAPFB_COLOR_YUV422:
1154 case OMAPFB_COLOR_YUV420:
1155 case OMAPFB_COLOR_YUY422:
1156 r = -EINVAL;
1157 break;
1158 case OMAPFB_COLOR_CLUT_8BPP:
1159 case OMAPFB_COLOR_CLUT_4BPP:
1160 case OMAPFB_COLOR_CLUT_2BPP:
1161 case OMAPFB_COLOR_CLUT_1BPP:
1162 /*
1163 if (fbdev->ctrl->setcolreg)
1164 r = fbdev->ctrl->setcolreg(regno, red, green, blue,
1165 transp, update_hw_pal);
1166 */
1167 /* Fallthrough */
1168 r = -EINVAL;
1169 break;
1170 case OMAPFB_COLOR_RGB565:
1171 case OMAPFB_COLOR_RGB444:
1172 case OMAPFB_COLOR_RGB24P:
1173 case OMAPFB_COLOR_RGB24U:
1174 if (r != 0)
1175 break;
1176
1177 if (regno < 16) {
1178 u32 pal;
1179 pal = ((red >> (16 - var->red.length)) <<
1180 var->red.offset) |
1181 ((green >> (16 - var->green.length)) <<
1182 var->green.offset) |
1183 (blue >> (16 - var->blue.length));
1184 ((u32 *)(fbi->pseudo_palette))[regno] = pal;
1185 }
1186 break;
1187 default:
1188 BUG();
1189 }
1190 return r;
1191}
1192
1193static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
1194 u_int transp, struct fb_info *info)
1195{
1196 DBG("setcolreg\n");
1197
1198 return _setcolreg(info, regno, red, green, blue, transp, 1);
1199}
1200
1201static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
1202{
1203 int count, index, r;
1204 u16 *red, *green, *blue, *transp;
1205 u16 trans = 0xffff;
1206
1207 DBG("setcmap\n");
1208
1209 red = cmap->red;
1210 green = cmap->green;
1211 blue = cmap->blue;
1212 transp = cmap->transp;
1213 index = cmap->start;
1214
1215 for (count = 0; count < cmap->len; count++) {
1216 if (transp)
1217 trans = *transp++;
1218 r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
1219 count == cmap->len - 1);
1220 if (r != 0)
1221 return r;
1222 }
1223
1224 return 0;
1225}
1226
1227static int omapfb_blank(int blank, struct fb_info *fbi)
1228{
1229 struct omapfb_info *ofbi = FB2OFB(fbi);
1230 struct omapfb2_device *fbdev = ofbi->fbdev;
1231 struct omap_dss_device *display = fb2display(fbi);
1232 struct omapfb_display_data *d;
1233 int r = 0;
1234
1235 if (!display)
1236 return -EINVAL;
1237
1238 omapfb_lock(fbdev);
1239
1240 d = get_display_data(fbdev, display);
1241
1242 switch (blank) {
1243 case FB_BLANK_UNBLANK:
1244 if (display->state == OMAP_DSS_DISPLAY_ACTIVE)
1245 goto exit;
1246
1247 r = display->driver->enable(display);
1248
1249 if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) &&
1250 d->update_mode == OMAPFB_AUTO_UPDATE &&
1251 !d->auto_update_work_enabled)
1252 omapfb_start_auto_update(fbdev, display);
1253
1254 break;
1255
1256 case FB_BLANK_NORMAL:
1257 /* FB_BLANK_NORMAL could be implemented.
1258 * Needs DSS additions. */
1259 case FB_BLANK_VSYNC_SUSPEND:
1260 case FB_BLANK_HSYNC_SUSPEND:
1261 case FB_BLANK_POWERDOWN:
1262 if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
1263 goto exit;
1264
1265 if (d->auto_update_work_enabled)
1266 omapfb_stop_auto_update(fbdev, display);
1267
1268 display->driver->disable(display);
1269
1270 break;
1271
1272 default:
1273 r = -EINVAL;
1274 }
1275
1276exit:
1277 omapfb_unlock(fbdev);
1278
1279 return r;
1280}
1281
1282#if 0
1283/* XXX fb_read and fb_write are needed for VRFB */
1284ssize_t omapfb_write(struct fb_info *info, const char __user *buf,
1285 size_t count, loff_t *ppos)
1286{
1287 DBG("omapfb_write %d, %lu\n", count, (unsigned long)*ppos);
1288 /* XXX needed for VRFB */
1289 return count;
1290}
1291#endif
1292
1293static struct fb_ops omapfb_ops = {
1294 .owner = THIS_MODULE,
1295 .fb_open = omapfb_open,
1296 .fb_release = omapfb_release,
1297 .fb_fillrect = cfb_fillrect,
1298 .fb_copyarea = cfb_copyarea,
1299 .fb_imageblit = cfb_imageblit,
1300 .fb_blank = omapfb_blank,
1301 .fb_ioctl = omapfb_ioctl,
1302 .fb_check_var = omapfb_check_var,
1303 .fb_set_par = omapfb_set_par,
1304 .fb_pan_display = omapfb_pan_display,
1305 .fb_mmap = omapfb_mmap,
1306 .fb_setcolreg = omapfb_setcolreg,
1307 .fb_setcmap = omapfb_setcmap,
1308 /*.fb_write = omapfb_write,*/
1309};
1310
1311static void omapfb_free_fbmem(struct fb_info *fbi)
1312{
1313 struct omapfb_info *ofbi = FB2OFB(fbi);
1314 struct omapfb2_device *fbdev = ofbi->fbdev;
1315 struct omapfb2_mem_region *rg;
1316
1317 rg = ofbi->region;
1318
1319 if (rg->token == NULL)
1320 return;
1321
1322 WARN_ON(atomic_read(&rg->map_count));
1323
1324 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
1325 /* unmap the 0 angle rotation */
1326 if (rg->vrfb.vaddr[0]) {
1327 iounmap(rg->vrfb.vaddr[0]);
1328 rg->vrfb.vaddr[0] = NULL;
1329 }
1330
1331 omap_vrfb_release_ctx(&rg->vrfb);
1332 }
1333
1334 dma_free_attrs(fbdev->dev, rg->size, rg->token, rg->dma_handle,
1335 &rg->attrs);
1336
1337 rg->token = NULL;
1338 rg->vaddr = NULL;
1339 rg->paddr = 0;
1340 rg->alloc = 0;
1341 rg->size = 0;
1342}
1343
1344static void clear_fb_info(struct fb_info *fbi)
1345{
1346 memset(&fbi->var, 0, sizeof(fbi->var));
1347 memset(&fbi->fix, 0, sizeof(fbi->fix));
1348 strlcpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id));
1349}
1350
1351static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev)
1352{
1353 int i;
1354
1355 DBG("free all fbmem\n");
1356
1357 for (i = 0; i < fbdev->num_fbs; i++) {
1358 struct fb_info *fbi = fbdev->fbs[i];
1359 omapfb_free_fbmem(fbi);
1360 clear_fb_info(fbi);
1361 }
1362
1363 return 0;
1364}
1365
1366static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
1367 unsigned long paddr)
1368{
1369 struct omapfb_info *ofbi = FB2OFB(fbi);
1370 struct omapfb2_device *fbdev = ofbi->fbdev;
1371 struct omapfb2_mem_region *rg;
1372 void *token;
1373 DEFINE_DMA_ATTRS(attrs);
1374 dma_addr_t dma_handle;
1375 int r;
1376
1377 rg = ofbi->region;
1378
1379 rg->paddr = 0;
1380 rg->vaddr = NULL;
1381 memset(&rg->vrfb, 0, sizeof rg->vrfb);
1382 rg->size = 0;
1383 rg->type = 0;
1384 rg->alloc = false;
1385 rg->map = false;
1386
1387 size = PAGE_ALIGN(size);
1388
1389 dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
1390
1391 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
1392 dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
1393
1394 DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
1395
1396 token = dma_alloc_attrs(fbdev->dev, size, &dma_handle,
1397 GFP_KERNEL, &attrs);
1398
1399 if (token == NULL) {
1400 dev_err(fbdev->dev, "failed to allocate framebuffer\n");
1401 return -ENOMEM;
1402 }
1403
1404 DBG("allocated VRAM paddr %lx, vaddr %p\n",
1405 (unsigned long)dma_handle, token);
1406
1407 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
1408 r = omap_vrfb_request_ctx(&rg->vrfb);
1409 if (r) {
1410 dma_free_attrs(fbdev->dev, size, token, dma_handle,
1411 &attrs);
1412 dev_err(fbdev->dev, "vrfb create ctx failed\n");
1413 return r;
1414 }
1415 }
1416
1417 rg->attrs = attrs;
1418 rg->token = token;
1419 rg->dma_handle = dma_handle;
1420
1421 rg->paddr = (unsigned long)dma_handle;
1422 rg->vaddr = (void __iomem *)token;
1423 rg->size = size;
1424 rg->alloc = 1;
1425
1426 return 0;
1427}
1428
1429/* allocate fbmem using display resolution as reference */
1430static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
1431 unsigned long paddr)
1432{
1433 struct omapfb_info *ofbi = FB2OFB(fbi);
1434 struct omapfb2_device *fbdev = ofbi->fbdev;
1435 struct omap_dss_device *display;
1436 int bytespp;
1437
1438 display = fb2display(fbi);
1439
1440 if (!display)
1441 return 0;
1442
1443 switch (omapfb_get_recommended_bpp(fbdev, display)) {
1444 case 16:
1445 bytespp = 2;
1446 break;
1447 case 24:
1448 bytespp = 4;
1449 break;
1450 default:
1451 bytespp = 4;
1452 break;
1453 }
1454
1455 if (!size) {
1456 u16 w, h;
1457
1458 display->driver->get_resolution(display, &w, &h);
1459
1460 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
1461 size = max(omap_vrfb_min_phys_size(w, h, bytespp),
1462 omap_vrfb_min_phys_size(h, w, bytespp));
1463
1464 DBG("adjusting fb mem size for VRFB, %u -> %lu\n",
1465 w * h * bytespp, size);
1466 } else {
1467 size = w * h * bytespp;
1468 }
1469 }
1470
1471 if (!size)
1472 return 0;
1473
1474 return omapfb_alloc_fbmem(fbi, size, paddr);
1475}
1476
1477static int omapfb_parse_vram_param(const char *param, int max_entries,
1478 unsigned long *sizes, unsigned long *paddrs)
1479{
1480 int fbnum;
1481 unsigned long size;
1482 unsigned long paddr = 0;
1483 char *p, *start;
1484
1485 start = (char *)param;
1486
1487 while (1) {
1488 p = start;
1489
1490 fbnum = simple_strtoul(p, &p, 10);
1491
1492 if (p == start)
1493 return -EINVAL;
1494
1495 if (*p != ':')
1496 return -EINVAL;
1497
1498 if (fbnum >= max_entries)
1499 return -EINVAL;
1500
1501 size = memparse(p + 1, &p);
1502
1503 if (!size)
1504 return -EINVAL;
1505
1506 paddr = 0;
1507
1508 if (*p == '@') {
1509 paddr = simple_strtoul(p + 1, &p, 16);
1510
1511 if (!paddr)
1512 return -EINVAL;
1513
1514 }
1515
1516 WARN_ONCE(paddr,
1517 "reserving memory at predefined address not supported\n");
1518
1519 paddrs[fbnum] = paddr;
1520 sizes[fbnum] = size;
1521
1522 if (*p == 0)
1523 break;
1524
1525 if (*p != ',')
1526 return -EINVAL;
1527
1528 ++p;
1529
1530 start = p;
1531 }
1532
1533 return 0;
1534}
1535
1536static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
1537{
1538 int i, r;
1539 unsigned long vram_sizes[10];
1540 unsigned long vram_paddrs[10];
1541
1542 memset(&vram_sizes, 0, sizeof(vram_sizes));
1543 memset(&vram_paddrs, 0, sizeof(vram_paddrs));
1544
1545 if (def_vram && omapfb_parse_vram_param(def_vram, 10,
1546 vram_sizes, vram_paddrs)) {
1547 dev_err(fbdev->dev, "failed to parse vram parameter\n");
1548
1549 memset(&vram_sizes, 0, sizeof(vram_sizes));
1550 memset(&vram_paddrs, 0, sizeof(vram_paddrs));
1551 }
1552
1553 for (i = 0; i < fbdev->num_fbs; i++) {
1554 /* allocate memory automatically only for fb0, or if
1555 * excplicitly defined with vram or plat data option */
1556 if (i == 0 || vram_sizes[i] != 0) {
1557 r = omapfb_alloc_fbmem_display(fbdev->fbs[i],
1558 vram_sizes[i], vram_paddrs[i]);
1559
1560 if (r)
1561 return r;
1562 }
1563 }
1564
1565 for (i = 0; i < fbdev->num_fbs; i++) {
1566 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
1567 struct omapfb2_mem_region *rg;
1568 rg = ofbi->region;
1569
1570 DBG("region%d phys %08x virt %p size=%lu\n",
1571 i,
1572 rg->paddr,
1573 rg->vaddr,
1574 rg->size);
1575 }
1576
1577 return 0;
1578}
1579
1580static void omapfb_clear_fb(struct fb_info *fbi)
1581{
1582 const struct fb_fillrect rect = {
1583 .dx = 0,
1584 .dy = 0,
1585 .width = fbi->var.xres_virtual,
1586 .height = fbi->var.yres_virtual,
1587 .color = 0,
1588 .rop = ROP_COPY,
1589 };
1590
1591 cfb_fillrect(fbi, &rect);
1592}
1593
1594int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
1595{
1596 struct omapfb_info *ofbi = FB2OFB(fbi);
1597 struct omapfb2_device *fbdev = ofbi->fbdev;
1598 struct omapfb2_mem_region *rg = ofbi->region;
1599 unsigned long old_size = rg->size;
1600 unsigned long old_paddr = rg->paddr;
1601 int old_type = rg->type;
1602 int r;
1603
1604 if (type != OMAPFB_MEMTYPE_SDRAM)
1605 return -EINVAL;
1606
1607 size = PAGE_ALIGN(size);
1608
1609 if (old_size == size && old_type == type)
1610 return 0;
1611
1612 omapfb_free_fbmem(fbi);
1613
1614 if (size == 0) {
1615 clear_fb_info(fbi);
1616 return 0;
1617 }
1618
1619 r = omapfb_alloc_fbmem(fbi, size, 0);
1620
1621 if (r) {
1622 if (old_size)
1623 omapfb_alloc_fbmem(fbi, old_size, old_paddr);
1624
1625 if (rg->size == 0)
1626 clear_fb_info(fbi);
1627
1628 return r;
1629 }
1630
1631 if (old_size == size)
1632 return 0;
1633
1634 if (old_size == 0) {
1635 DBG("initializing fb %d\n", ofbi->id);
1636 r = omapfb_fb_init(fbdev, fbi);
1637 if (r) {
1638 DBG("omapfb_fb_init failed\n");
1639 goto err;
1640 }
1641 r = omapfb_apply_changes(fbi, 1);
1642 if (r) {
1643 DBG("omapfb_apply_changes failed\n");
1644 goto err;
1645 }
1646 } else {
1647 struct fb_var_screeninfo new_var;
1648 memcpy(&new_var, &fbi->var, sizeof(new_var));
1649 r = check_fb_var(fbi, &new_var);
1650 if (r)
1651 goto err;
1652 memcpy(&fbi->var, &new_var, sizeof(fbi->var));
1653 set_fb_fix(fbi);
1654 r = setup_vrfb_rotation(fbi);
1655 if (r)
1656 goto err;
1657 }
1658
1659 omapfb_clear_fb(fbi);
1660
1661 return 0;
1662err:
1663 omapfb_free_fbmem(fbi);
1664 clear_fb_info(fbi);
1665 return r;
1666}
1667
1668static void omapfb_auto_update_work(struct work_struct *work)
1669{
1670 struct omap_dss_device *dssdev;
1671 struct omap_dss_driver *dssdrv;
1672 struct omapfb_display_data *d;
1673 u16 w, h;
1674 unsigned int freq;
1675 struct omapfb2_device *fbdev;
1676
1677 d = container_of(work, struct omapfb_display_data,
1678 auto_update_work.work);
1679
1680 dssdev = d->dssdev;
1681 dssdrv = dssdev->driver;
1682 fbdev = d->fbdev;
1683
1684 if (!dssdrv || !dssdrv->update)
1685 return;
1686
1687 if (dssdrv->sync)
1688 dssdrv->sync(dssdev);
1689
1690 dssdrv->get_resolution(dssdev, &w, &h);
1691 dssdrv->update(dssdev, 0, 0, w, h);
1692
1693 freq = auto_update_freq;
1694 if (freq == 0)
1695 freq = 20;
1696 queue_delayed_work(fbdev->auto_update_wq,
1697 &d->auto_update_work, HZ / freq);
1698}
1699
1700void omapfb_start_auto_update(struct omapfb2_device *fbdev,
1701 struct omap_dss_device *display)
1702{
1703 struct omapfb_display_data *d;
1704
1705 if (fbdev->auto_update_wq == NULL) {
1706 struct workqueue_struct *wq;
1707
1708 wq = create_singlethread_workqueue("omapfb_auto_update");
1709
1710 if (wq == NULL) {
1711 dev_err(fbdev->dev, "Failed to create workqueue for "
1712 "auto-update\n");
1713 return;
1714 }
1715
1716 fbdev->auto_update_wq = wq;
1717 }
1718
1719 d = get_display_data(fbdev, display);
1720
1721 INIT_DELAYED_WORK(&d->auto_update_work, omapfb_auto_update_work);
1722
1723 d->auto_update_work_enabled = true;
1724
1725 omapfb_auto_update_work(&d->auto_update_work.work);
1726}
1727
1728void omapfb_stop_auto_update(struct omapfb2_device *fbdev,
1729 struct omap_dss_device *display)
1730{
1731 struct omapfb_display_data *d;
1732
1733 d = get_display_data(fbdev, display);
1734
1735 cancel_delayed_work_sync(&d->auto_update_work);
1736
1737 d->auto_update_work_enabled = false;
1738}
1739
1740/* initialize fb_info, var, fix to something sane based on the display */
1741static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
1742{
1743 struct fb_var_screeninfo *var = &fbi->var;
1744 struct omap_dss_device *display = fb2display(fbi);
1745 struct omapfb_info *ofbi = FB2OFB(fbi);
1746 int r = 0;
1747
1748 fbi->fbops = &omapfb_ops;
1749 fbi->flags = FBINFO_FLAG_DEFAULT;
1750 fbi->pseudo_palette = fbdev->pseudo_palette;
1751
1752 if (ofbi->region->size == 0) {
1753 clear_fb_info(fbi);
1754 return 0;
1755 }
1756
1757 var->nonstd = 0;
1758 var->bits_per_pixel = 0;
1759
1760 var->rotate = def_rotate;
1761
1762 if (display) {
1763 u16 w, h;
1764 int rotation = (var->rotate + ofbi->rotation[0]) % 4;
1765
1766 display->driver->get_resolution(display, &w, &h);
1767
1768 if (rotation == FB_ROTATE_CW ||
1769 rotation == FB_ROTATE_CCW) {
1770 var->xres = h;
1771 var->yres = w;
1772 } else {
1773 var->xres = w;
1774 var->yres = h;
1775 }
1776
1777 var->xres_virtual = var->xres;
1778 var->yres_virtual = var->yres;
1779
1780 if (!var->bits_per_pixel) {
1781 switch (omapfb_get_recommended_bpp(fbdev, display)) {
1782 case 16:
1783 var->bits_per_pixel = 16;
1784 break;
1785 case 24:
1786 var->bits_per_pixel = 32;
1787 break;
1788 default:
1789 dev_err(fbdev->dev, "illegal display "
1790 "bpp\n");
1791 return -EINVAL;
1792 }
1793 }
1794 } else {
1795 /* if there's no display, let's just guess some basic values */
1796 var->xres = 320;
1797 var->yres = 240;
1798 var->xres_virtual = var->xres;
1799 var->yres_virtual = var->yres;
1800 if (!var->bits_per_pixel)
1801 var->bits_per_pixel = 16;
1802 }
1803
1804 r = check_fb_var(fbi, var);
1805 if (r)
1806 goto err;
1807
1808 set_fb_fix(fbi);
1809 r = setup_vrfb_rotation(fbi);
1810 if (r)
1811 goto err;
1812
1813 r = fb_alloc_cmap(&fbi->cmap, 256, 0);
1814 if (r)
1815 dev_err(fbdev->dev, "unable to allocate color map memory\n");
1816
1817err:
1818 return r;
1819}
1820
1821static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi)
1822{
1823 fb_dealloc_cmap(&fbi->cmap);
1824}
1825
1826
1827static void omapfb_free_resources(struct omapfb2_device *fbdev)
1828{
1829 int i;
1830
1831 DBG("free_resources\n");
1832
1833 if (fbdev == NULL)
1834 return;
1835
1836 for (i = 0; i < fbdev->num_fbs; i++) {
1837 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
1838 int j;
1839
1840 for (j = 0; j < ofbi->num_overlays; j++) {
1841 struct omap_overlay *ovl = ofbi->overlays[j];
1842 ovl->disable(ovl);
1843 }
1844 }
1845
1846 for (i = 0; i < fbdev->num_fbs; i++)
1847 unregister_framebuffer(fbdev->fbs[i]);
1848
1849 /* free the reserved fbmem */
1850 omapfb_free_all_fbmem(fbdev);
1851
1852 for (i = 0; i < fbdev->num_fbs; i++) {
1853 fbinfo_cleanup(fbdev, fbdev->fbs[i]);
1854 framebuffer_release(fbdev->fbs[i]);
1855 }
1856
1857 for (i = 0; i < fbdev->num_displays; i++) {
1858 struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
1859
1860 if (fbdev->displays[i].auto_update_work_enabled)
1861 omapfb_stop_auto_update(fbdev, dssdev);
1862
1863 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
1864 dssdev->driver->disable(dssdev);
1865
1866 dssdev->driver->disconnect(dssdev);
1867
1868 omap_dss_put_device(dssdev);
1869 }
1870
1871 if (fbdev->auto_update_wq != NULL) {
1872 flush_workqueue(fbdev->auto_update_wq);
1873 destroy_workqueue(fbdev->auto_update_wq);
1874 fbdev->auto_update_wq = NULL;
1875 }
1876
1877 dev_set_drvdata(fbdev->dev, NULL);
1878}
1879
1880static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
1881{
1882 int r, i;
1883
1884 fbdev->num_fbs = 0;
1885
1886 DBG("create %d framebuffers\n", CONFIG_FB_OMAP2_NUM_FBS);
1887
1888 /* allocate fb_infos */
1889 for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) {
1890 struct fb_info *fbi;
1891 struct omapfb_info *ofbi;
1892
1893 fbi = framebuffer_alloc(sizeof(struct omapfb_info),
1894 fbdev->dev);
1895
1896 if (fbi == NULL) {
1897 dev_err(fbdev->dev,
1898 "unable to allocate memory for plane info\n");
1899 return -ENOMEM;
1900 }
1901
1902 clear_fb_info(fbi);
1903
1904 fbdev->fbs[i] = fbi;
1905
1906 ofbi = FB2OFB(fbi);
1907 ofbi->fbdev = fbdev;
1908 ofbi->id = i;
1909
1910 ofbi->region = &fbdev->regions[i];
1911 ofbi->region->id = i;
1912 init_rwsem(&ofbi->region->lock);
1913
1914 /* assign these early, so that fb alloc can use them */
1915 ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
1916 OMAP_DSS_ROT_DMA;
1917 ofbi->mirror = def_mirror;
1918
1919 fbdev->num_fbs++;
1920 }
1921
1922 DBG("fb_infos allocated\n");
1923
1924 /* assign overlays for the fbs */
1925 for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) {
1926 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
1927
1928 ofbi->overlays[0] = fbdev->overlays[i];
1929 ofbi->num_overlays = 1;
1930 }
1931
1932 /* allocate fb memories */
1933 r = omapfb_allocate_all_fbs(fbdev);
1934 if (r) {
1935 dev_err(fbdev->dev, "failed to allocate fbmem\n");
1936 return r;
1937 }
1938
1939 DBG("fbmems allocated\n");
1940
1941 /* setup fb_infos */
1942 for (i = 0; i < fbdev->num_fbs; i++) {
1943 struct fb_info *fbi = fbdev->fbs[i];
1944 struct omapfb_info *ofbi = FB2OFB(fbi);
1945
1946 omapfb_get_mem_region(ofbi->region);
1947 r = omapfb_fb_init(fbdev, fbi);
1948 omapfb_put_mem_region(ofbi->region);
1949
1950 if (r) {
1951 dev_err(fbdev->dev, "failed to setup fb_info\n");
1952 return r;
1953 }
1954 }
1955
1956 for (i = 0; i < fbdev->num_fbs; i++) {
1957 struct fb_info *fbi = fbdev->fbs[i];
1958 struct omapfb_info *ofbi = FB2OFB(fbi);
1959
1960 if (ofbi->region->size == 0)
1961 continue;
1962
1963 omapfb_clear_fb(fbi);
1964 }
1965
1966 DBG("fb_infos initialized\n");
1967
1968 for (i = 0; i < fbdev->num_fbs; i++) {
1969 r = register_framebuffer(fbdev->fbs[i]);
1970 if (r != 0) {
1971 dev_err(fbdev->dev,
1972 "registering framebuffer %d failed\n", i);
1973 return r;
1974 }
1975 }
1976
1977 DBG("framebuffers registered\n");
1978
1979 for (i = 0; i < fbdev->num_fbs; i++) {
1980 struct fb_info *fbi = fbdev->fbs[i];
1981 struct omapfb_info *ofbi = FB2OFB(fbi);
1982
1983 omapfb_get_mem_region(ofbi->region);
1984 r = omapfb_apply_changes(fbi, 1);
1985 omapfb_put_mem_region(ofbi->region);
1986
1987 if (r) {
1988 dev_err(fbdev->dev, "failed to change mode\n");
1989 return r;
1990 }
1991 }
1992
1993 /* Enable fb0 */
1994 if (fbdev->num_fbs > 0) {
1995 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
1996
1997 if (ofbi->num_overlays > 0) {
1998 struct omap_overlay *ovl = ofbi->overlays[0];
1999
2000 ovl->manager->apply(ovl->manager);
2001
2002 r = omapfb_overlay_enable(ovl, 1);
2003
2004 if (r) {
2005 dev_err(fbdev->dev,
2006 "failed to enable overlay\n");
2007 return r;
2008 }
2009 }
2010 }
2011
2012 DBG("create_framebuffers done\n");
2013
2014 return 0;
2015}
2016
2017static int omapfb_mode_to_timings(const char *mode_str,
2018 struct omap_dss_device *display,
2019 struct omap_video_timings *timings, u8 *bpp)
2020{
2021 struct fb_info *fbi;
2022 struct fb_var_screeninfo *var;
2023 struct fb_ops *fbops;
2024 int r;
2025
2026#ifdef CONFIG_OMAP2_DSS_VENC
2027 if (strcmp(mode_str, "pal") == 0) {
2028 *timings = omap_dss_pal_timings;
2029 *bpp = 24;
2030 return 0;
2031 } else if (strcmp(mode_str, "ntsc") == 0) {
2032 *timings = omap_dss_ntsc_timings;
2033 *bpp = 24;
2034 return 0;
2035 }
2036#endif
2037
2038 /* this is quite a hack, but I wanted to use the modedb and for
2039 * that we need fb_info and var, so we create dummy ones */
2040
2041 *bpp = 0;
2042 fbi = NULL;
2043 var = NULL;
2044 fbops = NULL;
2045
2046 fbi = kzalloc(sizeof(*fbi), GFP_KERNEL);
2047 if (fbi == NULL) {
2048 r = -ENOMEM;
2049 goto err;
2050 }
2051
2052 var = kzalloc(sizeof(*var), GFP_KERNEL);
2053 if (var == NULL) {
2054 r = -ENOMEM;
2055 goto err;
2056 }
2057
2058 fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
2059 if (fbops == NULL) {
2060 r = -ENOMEM;
2061 goto err;
2062 }
2063
2064 fbi->fbops = fbops;
2065
2066 r = fb_find_mode(var, fbi, mode_str, NULL, 0, NULL, 24);
2067 if (r == 0) {
2068 r = -EINVAL;
2069 goto err;
2070 }
2071
2072 if (display->driver->get_timings) {
2073 display->driver->get_timings(display, timings);
2074 } else {
2075 timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
2076 timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
2077 timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
2078 }
2079
2080 timings->pixelclock = PICOS2KHZ(var->pixclock) * 1000;
2081 timings->hbp = var->left_margin;
2082 timings->hfp = var->right_margin;
2083 timings->vbp = var->upper_margin;
2084 timings->vfp = var->lower_margin;
2085 timings->hsw = var->hsync_len;
2086 timings->vsw = var->vsync_len;
2087 timings->x_res = var->xres;
2088 timings->y_res = var->yres;
2089 timings->hsync_level = var->sync & FB_SYNC_HOR_HIGH_ACT ?
2090 OMAPDSS_SIG_ACTIVE_HIGH :
2091 OMAPDSS_SIG_ACTIVE_LOW;
2092 timings->vsync_level = var->sync & FB_SYNC_VERT_HIGH_ACT ?
2093 OMAPDSS_SIG_ACTIVE_HIGH :
2094 OMAPDSS_SIG_ACTIVE_LOW;
2095 timings->interlace = var->vmode & FB_VMODE_INTERLACED;
2096
2097 switch (var->bits_per_pixel) {
2098 case 16:
2099 *bpp = 16;
2100 break;
2101 case 24:
2102 case 32:
2103 default:
2104 *bpp = 24;
2105 break;
2106 }
2107
2108 r = 0;
2109
2110err:
2111 kfree(fbi);
2112 kfree(var);
2113 kfree(fbops);
2114
2115 return r;
2116}
2117
2118static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
2119 struct omap_dss_device *display, char *mode_str)
2120{
2121 int r;
2122 u8 bpp;
2123 struct omap_video_timings timings, temp_timings;
2124 struct omapfb_display_data *d;
2125
2126 r = omapfb_mode_to_timings(mode_str, display, &timings, &bpp);
2127 if (r)
2128 return r;
2129
2130 d = get_display_data(fbdev, display);
2131 d->bpp_override = bpp;
2132
2133 if (display->driver->check_timings) {
2134 r = display->driver->check_timings(display, &timings);
2135 if (r)
2136 return r;
2137 } else {
2138 /* If check_timings is not present compare xres and yres */
2139 if (display->driver->get_timings) {
2140 display->driver->get_timings(display, &temp_timings);
2141
2142 if (temp_timings.x_res != timings.x_res ||
2143 temp_timings.y_res != timings.y_res)
2144 return -EINVAL;
2145 }
2146 }
2147
2148 if (display->driver->set_timings)
2149 display->driver->set_timings(display, &timings);
2150
2151 return 0;
2152}
2153
2154static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
2155 struct omap_dss_device *dssdev)
2156{
2157 struct omapfb_display_data *d;
2158
2159 BUG_ON(dssdev->driver->get_recommended_bpp == NULL);
2160
2161 d = get_display_data(fbdev, dssdev);
2162
2163 if (d->bpp_override != 0)
2164 return d->bpp_override;
2165
2166 return dssdev->driver->get_recommended_bpp(dssdev);
2167}
2168
2169static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
2170{
2171 char *str, *options, *this_opt;
2172 int r = 0;
2173
2174 str = kstrdup(def_mode, GFP_KERNEL);
2175 if (!str)
2176 return -ENOMEM;
2177 options = str;
2178
2179 while (!r && (this_opt = strsep(&options, ",")) != NULL) {
2180 char *p, *display_str, *mode_str;
2181 struct omap_dss_device *display;
2182 int i;
2183
2184 p = strchr(this_opt, ':');
2185 if (!p) {
2186 r = -EINVAL;
2187 break;
2188 }
2189
2190 *p = 0;
2191 display_str = this_opt;
2192 mode_str = p + 1;
2193
2194 display = NULL;
2195 for (i = 0; i < fbdev->num_displays; ++i) {
2196 if (strcmp(fbdev->displays[i].dssdev->name,
2197 display_str) == 0) {
2198 display = fbdev->displays[i].dssdev;
2199 break;
2200 }
2201 }
2202
2203 if (!display) {
2204 r = -EINVAL;
2205 break;
2206 }
2207
2208 r = omapfb_set_def_mode(fbdev, display, mode_str);
2209 if (r)
2210 break;
2211 }
2212
2213 kfree(str);
2214
2215 return r;
2216}
2217
2218static void fb_videomode_to_omap_timings(struct fb_videomode *m,
2219 struct omap_dss_device *display,
2220 struct omap_video_timings *t)
2221{
2222 if (display->driver->get_timings) {
2223 display->driver->get_timings(display, t);
2224 } else {
2225 t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
2226 t->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
2227 t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
2228 }
2229
2230 t->x_res = m->xres;
2231 t->y_res = m->yres;
2232 t->pixelclock = PICOS2KHZ(m->pixclock) * 1000;
2233 t->hsw = m->hsync_len;
2234 t->hfp = m->right_margin;
2235 t->hbp = m->left_margin;
2236 t->vsw = m->vsync_len;
2237 t->vfp = m->lower_margin;
2238 t->vbp = m->upper_margin;
2239 t->hsync_level = m->sync & FB_SYNC_HOR_HIGH_ACT ?
2240 OMAPDSS_SIG_ACTIVE_HIGH :
2241 OMAPDSS_SIG_ACTIVE_LOW;
2242 t->vsync_level = m->sync & FB_SYNC_VERT_HIGH_ACT ?
2243 OMAPDSS_SIG_ACTIVE_HIGH :
2244 OMAPDSS_SIG_ACTIVE_LOW;
2245 t->interlace = m->vmode & FB_VMODE_INTERLACED;
2246}
2247
2248static int omapfb_find_best_mode(struct omap_dss_device *display,
2249 struct omap_video_timings *timings)
2250{
2251 struct fb_monspecs *specs;
2252 u8 *edid;
2253 int r, i, best_idx, len;
2254
2255 if (!display->driver->read_edid)
2256 return -ENODEV;
2257
2258 len = 0x80 * 2;
2259 edid = kmalloc(len, GFP_KERNEL);
2260 if (edid == NULL)
2261 return -ENOMEM;
2262
2263 r = display->driver->read_edid(display, edid, len);
2264 if (r < 0)
2265 goto err1;
2266
2267 specs = kzalloc(sizeof(*specs), GFP_KERNEL);
2268 if (specs == NULL) {
2269 r = -ENOMEM;
2270 goto err1;
2271 }
2272
2273 fb_edid_to_monspecs(edid, specs);
2274
2275 best_idx = -1;
2276
2277 for (i = 0; i < specs->modedb_len; ++i) {
2278 struct fb_videomode *m;
2279 struct omap_video_timings t;
2280
2281 m = &specs->modedb[i];
2282
2283 if (m->pixclock == 0)
2284 continue;
2285
2286 /* skip repeated pixel modes */
2287 if (m->xres == 2880 || m->xres == 1440)
2288 continue;
2289
2290 if (m->vmode & FB_VMODE_INTERLACED ||
2291 m->vmode & FB_VMODE_DOUBLE)
2292 continue;
2293
2294 fb_videomode_to_omap_timings(m, display, &t);
2295
2296 r = display->driver->check_timings(display, &t);
2297 if (r == 0) {
2298 best_idx = i;
2299 break;
2300 }
2301 }
2302
2303 if (best_idx == -1) {
2304 r = -ENOENT;
2305 goto err2;
2306 }
2307
2308 fb_videomode_to_omap_timings(&specs->modedb[best_idx], display,
2309 timings);
2310
2311 r = 0;
2312
2313err2:
2314 fb_destroy_modedb(specs->modedb);
2315 kfree(specs);
2316err1:
2317 kfree(edid);
2318
2319 return r;
2320}
2321
2322static int omapfb_init_display(struct omapfb2_device *fbdev,
2323 struct omap_dss_device *dssdev)
2324{
2325 struct omap_dss_driver *dssdrv = dssdev->driver;
2326 struct omapfb_display_data *d;
2327 int r;
2328
2329 r = dssdrv->enable(dssdev);
2330 if (r) {
2331 dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
2332 dssdev->name);
2333 return r;
2334 }
2335
2336 d = get_display_data(fbdev, dssdev);
2337
2338 d->fbdev = fbdev;
2339
2340 if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
2341 u16 w, h;
2342
2343 if (auto_update) {
2344 omapfb_start_auto_update(fbdev, dssdev);
2345 d->update_mode = OMAPFB_AUTO_UPDATE;
2346 } else {
2347 d->update_mode = OMAPFB_MANUAL_UPDATE;
2348 }
2349
2350 if (dssdrv->enable_te) {
2351 r = dssdrv->enable_te(dssdev, 1);
2352 if (r) {
2353 dev_err(fbdev->dev, "Failed to set TE\n");
2354 return r;
2355 }
2356 }
2357
2358 dssdrv->get_resolution(dssdev, &w, &h);
2359 r = dssdrv->update(dssdev, 0, 0, w, h);
2360 if (r) {
2361 dev_err(fbdev->dev,
2362 "Failed to update display\n");
2363 return r;
2364 }
2365 } else {
2366 d->update_mode = OMAPFB_AUTO_UPDATE;
2367 }
2368
2369 return 0;
2370}
2371
2372static int omapfb_init_connections(struct omapfb2_device *fbdev,
2373 struct omap_dss_device *def_dssdev)
2374{
2375 int i, r;
2376 struct omap_overlay_manager *mgr;
2377
2378 r = def_dssdev->driver->connect(def_dssdev);
2379 if (r) {
2380 dev_err(fbdev->dev, "failed to connect default display\n");
2381 return r;
2382 }
2383
2384 for (i = 0; i < fbdev->num_displays; ++i) {
2385 struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
2386
2387 if (dssdev == def_dssdev)
2388 continue;
2389
2390 /*
2391 * We don't care if the connect succeeds or not. We just want to
2392 * connect as many displays as possible.
2393 */
2394 dssdev->driver->connect(dssdev);
2395 }
2396
2397 mgr = omapdss_find_mgr_from_display(def_dssdev);
2398
2399 if (!mgr) {
2400 dev_err(fbdev->dev, "no ovl manager for the default display\n");
2401 return -EINVAL;
2402 }
2403
2404 for (i = 0; i < fbdev->num_overlays; i++) {
2405 struct omap_overlay *ovl = fbdev->overlays[i];
2406
2407 if (ovl->manager)
2408 ovl->unset_manager(ovl);
2409
2410 r = ovl->set_manager(ovl, mgr);
2411 if (r)
2412 dev_warn(fbdev->dev,
2413 "failed to connect overlay %s to manager %s\n",
2414 ovl->name, mgr->name);
2415 }
2416
2417 return 0;
2418}
2419
2420static struct omap_dss_device *
2421omapfb_find_default_display(struct omapfb2_device *fbdev)
2422{
2423 const char *def_name;
2424 int i;
2425
2426 /*
2427 * Search with the display name from the user or the board file,
2428 * comparing to display names and aliases
2429 */
2430
2431 def_name = omapdss_get_default_display_name();
2432
2433 if (def_name) {
2434 for (i = 0; i < fbdev->num_displays; ++i) {
2435 struct omap_dss_device *dssdev;
2436
2437 dssdev = fbdev->displays[i].dssdev;
2438
2439 if (dssdev->name && strcmp(def_name, dssdev->name) == 0)
2440 return dssdev;
2441
2442 if (strcmp(def_name, dssdev->alias) == 0)
2443 return dssdev;
2444 }
2445
2446 /* def_name given but not found */
2447 return NULL;
2448 }
2449
2450 /* then look for DT alias display0 */
2451 for (i = 0; i < fbdev->num_displays; ++i) {
2452 struct omap_dss_device *dssdev;
2453 int id;
2454
2455 dssdev = fbdev->displays[i].dssdev;
2456
2457 if (dssdev->dev->of_node == NULL)
2458 continue;
2459
2460 id = of_alias_get_id(dssdev->dev->of_node, "display");
2461 if (id == 0)
2462 return dssdev;
2463 }
2464
2465 /* return the first display we have in the list */
2466 return fbdev->displays[0].dssdev;
2467}
2468
2469static int omapfb_probe(struct platform_device *pdev)
2470{
2471 struct omapfb2_device *fbdev = NULL;
2472 int r = 0;
2473 int i;
2474 struct omap_dss_device *def_display;
2475 struct omap_dss_device *dssdev;
2476
2477 DBG("omapfb_probe\n");
2478
2479 if (omapdss_is_initialized() == false)
2480 return -EPROBE_DEFER;
2481
2482 if (pdev->num_resources != 0) {
2483 dev_err(&pdev->dev, "probed for an unknown device\n");
2484 r = -ENODEV;
2485 goto err0;
2486 }
2487
2488 fbdev = devm_kzalloc(&pdev->dev, sizeof(struct omapfb2_device),
2489 GFP_KERNEL);
2490 if (fbdev == NULL) {
2491 r = -ENOMEM;
2492 goto err0;
2493 }
2494
2495 if (def_vrfb && !omap_vrfb_supported()) {
2496 def_vrfb = 0;
2497 dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
2498 "ignoring the module parameter vrfb=y\n");
2499 }
2500
2501 r = omapdss_compat_init();
2502 if (r)
2503 goto err0;
2504
2505 mutex_init(&fbdev->mtx);
2506
2507 fbdev->dev = &pdev->dev;
2508 platform_set_drvdata(pdev, fbdev);
2509
2510 fbdev->num_displays = 0;
2511 dssdev = NULL;
2512 for_each_dss_dev(dssdev) {
2513 struct omapfb_display_data *d;
2514
2515 omap_dss_get_device(dssdev);
2516
2517 if (!dssdev->driver) {
2518 dev_warn(&pdev->dev, "no driver for display: %s\n",
2519 dssdev->name);
2520 omap_dss_put_device(dssdev);
2521 continue;
2522 }
2523
2524 d = &fbdev->displays[fbdev->num_displays++];
2525 d->dssdev = dssdev;
2526 if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
2527 d->update_mode = OMAPFB_MANUAL_UPDATE;
2528 else
2529 d->update_mode = OMAPFB_AUTO_UPDATE;
2530 }
2531
2532 if (fbdev->num_displays == 0) {
2533 dev_err(&pdev->dev, "no displays\n");
2534 r = -EPROBE_DEFER;
2535 goto cleanup;
2536 }
2537
2538 fbdev->num_overlays = omap_dss_get_num_overlays();
2539 for (i = 0; i < fbdev->num_overlays; i++)
2540 fbdev->overlays[i] = omap_dss_get_overlay(i);
2541
2542 fbdev->num_managers = omap_dss_get_num_overlay_managers();
2543 for (i = 0; i < fbdev->num_managers; i++)
2544 fbdev->managers[i] = omap_dss_get_overlay_manager(i);
2545
2546 def_display = omapfb_find_default_display(fbdev);
2547 if (def_display == NULL) {
2548 dev_err(fbdev->dev, "failed to find default display\n");
2549 r = -EPROBE_DEFER;
2550 goto cleanup;
2551 }
2552
2553 r = omapfb_init_connections(fbdev, def_display);
2554 if (r) {
2555 dev_err(fbdev->dev, "failed to init overlay connections\n");
2556 goto cleanup;
2557 }
2558
2559 if (def_mode && strlen(def_mode) > 0) {
2560 if (omapfb_parse_def_modes(fbdev))
2561 dev_warn(&pdev->dev, "cannot parse default modes\n");
2562 } else if (def_display && def_display->driver->set_timings &&
2563 def_display->driver->check_timings) {
2564 struct omap_video_timings t;
2565
2566 r = omapfb_find_best_mode(def_display, &t);
2567
2568 if (r == 0)
2569 def_display->driver->set_timings(def_display, &t);
2570 }
2571
2572 r = omapfb_create_framebuffers(fbdev);
2573 if (r)
2574 goto cleanup;
2575
2576 for (i = 0; i < fbdev->num_managers; i++) {
2577 struct omap_overlay_manager *mgr;
2578 mgr = fbdev->managers[i];
2579 r = mgr->apply(mgr);
2580 if (r)
2581 dev_warn(fbdev->dev, "failed to apply dispc config\n");
2582 }
2583
2584 DBG("mgr->apply'ed\n");
2585
2586 if (def_display) {
2587 r = omapfb_init_display(fbdev, def_display);
2588 if (r) {
2589 dev_err(fbdev->dev,
2590 "failed to initialize default "
2591 "display\n");
2592 goto cleanup;
2593 }
2594 }
2595
2596 DBG("create sysfs for fbs\n");
2597 r = omapfb_create_sysfs(fbdev);
2598 if (r) {
2599 dev_err(fbdev->dev, "failed to create sysfs entries\n");
2600 goto cleanup;
2601 }
2602
2603 if (def_display) {
2604 u16 w, h;
2605
2606 def_display->driver->get_resolution(def_display, &w, &h);
2607
2608 dev_info(fbdev->dev, "using display '%s' mode %dx%d\n",
2609 def_display->name, w, h);
2610 }
2611
2612 return 0;
2613
2614cleanup:
2615 omapfb_free_resources(fbdev);
2616 omapdss_compat_uninit();
2617err0:
2618 dev_err(&pdev->dev, "failed to setup omapfb\n");
2619 return r;
2620}
2621
2622static int __exit omapfb_remove(struct platform_device *pdev)
2623{
2624 struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
2625
2626 /* FIXME: wait till completion of pending events */
2627
2628 omapfb_remove_sysfs(fbdev);
2629
2630 omapfb_free_resources(fbdev);
2631
2632 omapdss_compat_uninit();
2633
2634 return 0;
2635}
2636
2637static struct platform_driver omapfb_driver = {
2638 .probe = omapfb_probe,
2639 .remove = __exit_p(omapfb_remove),
2640 .driver = {
2641 .name = "omapfb",
2642 .owner = THIS_MODULE,
2643 },
2644};
2645
2646module_param_named(mode, def_mode, charp, 0);
2647module_param_named(vram, def_vram, charp, 0);
2648module_param_named(rotate, def_rotate, int, 0);
2649module_param_named(vrfb, def_vrfb, bool, 0);
2650module_param_named(mirror, def_mirror, bool, 0);
2651
2652module_platform_driver(omapfb_driver);
2653
2654MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
2655MODULE_DESCRIPTION("OMAP2/3 Framebuffer");
2656MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
deleted file mode 100644
index 18fa9e1d0033..000000000000
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ /dev/null
@@ -1,605 +0,0 @@
1/*
2 * linux/drivers/video/omap2/omapfb-sysfs.c
3 *
4 * Copyright (C) 2008 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
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/fb.h>
24#include <linux/sysfs.h>
25#include <linux/device.h>
26#include <linux/uaccess.h>
27#include <linux/platform_device.h>
28#include <linux/kernel.h>
29#include <linux/mm.h>
30#include <linux/omapfb.h>
31
32#include <video/omapdss.h>
33#include <video/omapvrfb.h>
34
35#include "omapfb.h"
36
37static ssize_t show_rotate_type(struct device *dev,
38 struct device_attribute *attr, char *buf)
39{
40 struct fb_info *fbi = dev_get_drvdata(dev);
41 struct omapfb_info *ofbi = FB2OFB(fbi);
42
43 return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->rotation_type);
44}
45
46static ssize_t store_rotate_type(struct device *dev,
47 struct device_attribute *attr,
48 const char *buf, size_t count)
49{
50 struct fb_info *fbi = dev_get_drvdata(dev);
51 struct omapfb_info *ofbi = FB2OFB(fbi);
52 struct omapfb2_mem_region *rg;
53 int rot_type;
54 int r;
55
56 r = kstrtoint(buf, 0, &rot_type);
57 if (r)
58 return r;
59
60 if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB)
61 return -EINVAL;
62
63 if (!lock_fb_info(fbi))
64 return -ENODEV;
65
66 r = 0;
67 if (rot_type == ofbi->rotation_type)
68 goto out;
69
70 rg = omapfb_get_mem_region(ofbi->region);
71
72 if (rg->size) {
73 r = -EBUSY;
74 goto put_region;
75 }
76
77 ofbi->rotation_type = rot_type;
78
79 /*
80 * Since the VRAM for this FB is not allocated at the moment we don't
81 * need to do any further parameter checking at this point.
82 */
83put_region:
84 omapfb_put_mem_region(rg);
85out:
86 unlock_fb_info(fbi);
87
88 return r ? r : count;
89}
90
91
92static ssize_t show_mirror(struct device *dev,
93 struct device_attribute *attr, char *buf)
94{
95 struct fb_info *fbi = dev_get_drvdata(dev);
96 struct omapfb_info *ofbi = FB2OFB(fbi);
97
98 return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->mirror);
99}
100
101static ssize_t store_mirror(struct device *dev,
102 struct device_attribute *attr,
103 const char *buf, size_t count)
104{
105 struct fb_info *fbi = dev_get_drvdata(dev);
106 struct omapfb_info *ofbi = FB2OFB(fbi);
107 bool mirror;
108 int r;
109 struct fb_var_screeninfo new_var;
110
111 r = strtobool(buf, &mirror);
112 if (r)
113 return r;
114
115 if (!lock_fb_info(fbi))
116 return -ENODEV;
117
118 ofbi->mirror = mirror;
119
120 omapfb_get_mem_region(ofbi->region);
121
122 memcpy(&new_var, &fbi->var, sizeof(new_var));
123 r = check_fb_var(fbi, &new_var);
124 if (r)
125 goto out;
126 memcpy(&fbi->var, &new_var, sizeof(fbi->var));
127
128 set_fb_fix(fbi);
129
130 r = omapfb_apply_changes(fbi, 0);
131 if (r)
132 goto out;
133
134 r = count;
135out:
136 omapfb_put_mem_region(ofbi->region);
137
138 unlock_fb_info(fbi);
139
140 return r;
141}
142
143static ssize_t show_overlays(struct device *dev,
144 struct device_attribute *attr, char *buf)
145{
146 struct fb_info *fbi = dev_get_drvdata(dev);
147 struct omapfb_info *ofbi = FB2OFB(fbi);
148 struct omapfb2_device *fbdev = ofbi->fbdev;
149 ssize_t l = 0;
150 int t;
151
152 if (!lock_fb_info(fbi))
153 return -ENODEV;
154 omapfb_lock(fbdev);
155
156 for (t = 0; t < ofbi->num_overlays; t++) {
157 struct omap_overlay *ovl = ofbi->overlays[t];
158 int ovlnum;
159
160 for (ovlnum = 0; ovlnum < fbdev->num_overlays; ++ovlnum)
161 if (ovl == fbdev->overlays[ovlnum])
162 break;
163
164 l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
165 t == 0 ? "" : ",", ovlnum);
166 }
167
168 l += snprintf(buf + l, PAGE_SIZE - l, "\n");
169
170 omapfb_unlock(fbdev);
171 unlock_fb_info(fbi);
172
173 return l;
174}
175
176static struct omapfb_info *get_overlay_fb(struct omapfb2_device *fbdev,
177 struct omap_overlay *ovl)
178{
179 int i, t;
180
181 for (i = 0; i < fbdev->num_fbs; i++) {
182 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
183
184 for (t = 0; t < ofbi->num_overlays; t++) {
185 if (ofbi->overlays[t] == ovl)
186 return ofbi;
187 }
188 }
189
190 return NULL;
191}
192
193static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
194 const char *buf, size_t count)
195{
196 struct fb_info *fbi = dev_get_drvdata(dev);
197 struct omapfb_info *ofbi = FB2OFB(fbi);
198 struct omapfb2_device *fbdev = ofbi->fbdev;
199 struct omap_overlay *ovls[OMAPFB_MAX_OVL_PER_FB];
200 struct omap_overlay *ovl;
201 int num_ovls, r, i;
202 int len;
203 bool added = false;
204
205 num_ovls = 0;
206
207 len = strlen(buf);
208 if (buf[len - 1] == '\n')
209 len = len - 1;
210
211 if (!lock_fb_info(fbi))
212 return -ENODEV;
213 omapfb_lock(fbdev);
214
215 if (len > 0) {
216 char *p = (char *)buf;
217 int ovlnum;
218
219 while (p < buf + len) {
220 int found;
221 if (num_ovls == OMAPFB_MAX_OVL_PER_FB) {
222 r = -EINVAL;
223 goto out;
224 }
225
226 ovlnum = simple_strtoul(p, &p, 0);
227 if (ovlnum > fbdev->num_overlays) {
228 r = -EINVAL;
229 goto out;
230 }
231
232 found = 0;
233 for (i = 0; i < num_ovls; ++i) {
234 if (ovls[i] == fbdev->overlays[ovlnum]) {
235 found = 1;
236 break;
237 }
238 }
239
240 if (!found)
241 ovls[num_ovls++] = fbdev->overlays[ovlnum];
242
243 p++;
244 }
245 }
246
247 for (i = 0; i < num_ovls; ++i) {
248 struct omapfb_info *ofbi2 = get_overlay_fb(fbdev, ovls[i]);
249 if (ofbi2 && ofbi2 != ofbi) {
250 dev_err(fbdev->dev, "overlay already in use\n");
251 r = -EINVAL;
252 goto out;
253 }
254 }
255
256 /* detach unused overlays */
257 for (i = 0; i < ofbi->num_overlays; ++i) {
258 int t, found;
259
260 ovl = ofbi->overlays[i];
261
262 found = 0;
263
264 for (t = 0; t < num_ovls; ++t) {
265 if (ovl == ovls[t]) {
266 found = 1;
267 break;
268 }
269 }
270
271 if (found)
272 continue;
273
274 DBG("detaching %d\n", ofbi->overlays[i]->id);
275
276 omapfb_get_mem_region(ofbi->region);
277
278 omapfb_overlay_enable(ovl, 0);
279
280 if (ovl->manager)
281 ovl->manager->apply(ovl->manager);
282
283 omapfb_put_mem_region(ofbi->region);
284
285 for (t = i + 1; t < ofbi->num_overlays; t++) {
286 ofbi->rotation[t-1] = ofbi->rotation[t];
287 ofbi->overlays[t-1] = ofbi->overlays[t];
288 }
289
290 ofbi->num_overlays--;
291 i--;
292 }
293
294 for (i = 0; i < num_ovls; ++i) {
295 int t, found;
296
297 ovl = ovls[i];
298
299 found = 0;
300
301 for (t = 0; t < ofbi->num_overlays; ++t) {
302 if (ovl == ofbi->overlays[t]) {
303 found = 1;
304 break;
305 }
306 }
307
308 if (found)
309 continue;
310 ofbi->rotation[ofbi->num_overlays] = 0;
311 ofbi->overlays[ofbi->num_overlays++] = ovl;
312
313 added = true;
314 }
315
316 if (added) {
317 omapfb_get_mem_region(ofbi->region);
318
319 r = omapfb_apply_changes(fbi, 0);
320
321 omapfb_put_mem_region(ofbi->region);
322
323 if (r)
324 goto out;
325 }
326
327 r = count;
328out:
329 omapfb_unlock(fbdev);
330 unlock_fb_info(fbi);
331
332 return r;
333}
334
335static ssize_t show_overlays_rotate(struct device *dev,
336 struct device_attribute *attr, char *buf)
337{
338 struct fb_info *fbi = dev_get_drvdata(dev);
339 struct omapfb_info *ofbi = FB2OFB(fbi);
340 ssize_t l = 0;
341 int t;
342
343 if (!lock_fb_info(fbi))
344 return -ENODEV;
345
346 for (t = 0; t < ofbi->num_overlays; t++) {
347 l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
348 t == 0 ? "" : ",", ofbi->rotation[t]);
349 }
350
351 l += snprintf(buf + l, PAGE_SIZE - l, "\n");
352
353 unlock_fb_info(fbi);
354
355 return l;
356}
357
358static ssize_t store_overlays_rotate(struct device *dev,
359 struct device_attribute *attr, const char *buf, size_t count)
360{
361 struct fb_info *fbi = dev_get_drvdata(dev);
362 struct omapfb_info *ofbi = FB2OFB(fbi);
363 int num_ovls = 0, r, i;
364 int len;
365 bool changed = false;
366 u8 rotation[OMAPFB_MAX_OVL_PER_FB];
367
368 len = strlen(buf);
369 if (buf[len - 1] == '\n')
370 len = len - 1;
371
372 if (!lock_fb_info(fbi))
373 return -ENODEV;
374
375 if (len > 0) {
376 char *p = (char *)buf;
377
378 while (p < buf + len) {
379 int rot;
380
381 if (num_ovls == ofbi->num_overlays) {
382 r = -EINVAL;
383 goto out;
384 }
385
386 rot = simple_strtoul(p, &p, 0);
387 if (rot < 0 || rot > 3) {
388 r = -EINVAL;
389 goto out;
390 }
391
392 if (ofbi->rotation[num_ovls] != rot)
393 changed = true;
394
395 rotation[num_ovls++] = rot;
396
397 p++;
398 }
399 }
400
401 if (num_ovls != ofbi->num_overlays) {
402 r = -EINVAL;
403 goto out;
404 }
405
406 if (changed) {
407 for (i = 0; i < num_ovls; ++i)
408 ofbi->rotation[i] = rotation[i];
409
410 omapfb_get_mem_region(ofbi->region);
411
412 r = omapfb_apply_changes(fbi, 0);
413
414 omapfb_put_mem_region(ofbi->region);
415
416 if (r)
417 goto out;
418
419 /* FIXME error handling? */
420 }
421
422 r = count;
423out:
424 unlock_fb_info(fbi);
425
426 return r;
427}
428
429static ssize_t show_size(struct device *dev,
430 struct device_attribute *attr, char *buf)
431{
432 struct fb_info *fbi = dev_get_drvdata(dev);
433 struct omapfb_info *ofbi = FB2OFB(fbi);
434
435 return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region->size);
436}
437
438static ssize_t store_size(struct device *dev, struct device_attribute *attr,
439 const char *buf, size_t count)
440{
441 struct fb_info *fbi = dev_get_drvdata(dev);
442 struct omapfb_info *ofbi = FB2OFB(fbi);
443 struct omapfb2_device *fbdev = ofbi->fbdev;
444 struct omap_dss_device *display = fb2display(fbi);
445 struct omapfb2_mem_region *rg;
446 unsigned long size;
447 int r;
448 int i;
449
450 r = kstrtoul(buf, 0, &size);
451 if (r)
452 return r;
453
454 size = PAGE_ALIGN(size);
455
456 if (!lock_fb_info(fbi))
457 return -ENODEV;
458
459 if (display && display->driver->sync)
460 display->driver->sync(display);
461
462 rg = ofbi->region;
463
464 down_write_nested(&rg->lock, rg->id);
465 atomic_inc(&rg->lock_count);
466
467 if (atomic_read(&rg->map_count)) {
468 r = -EBUSY;
469 goto out;
470 }
471
472 for (i = 0; i < fbdev->num_fbs; i++) {
473 struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
474 int j;
475
476 if (ofbi2->region != rg)
477 continue;
478
479 for (j = 0; j < ofbi2->num_overlays; j++) {
480 struct omap_overlay *ovl;
481 ovl = ofbi2->overlays[j];
482 if (ovl->is_enabled(ovl)) {
483 r = -EBUSY;
484 goto out;
485 }
486 }
487 }
488
489 if (size != ofbi->region->size) {
490 r = omapfb_realloc_fbmem(fbi, size, ofbi->region->type);
491 if (r) {
492 dev_err(dev, "realloc fbmem failed\n");
493 goto out;
494 }
495 }
496
497 r = count;
498out:
499 atomic_dec(&rg->lock_count);
500 up_write(&rg->lock);
501
502 unlock_fb_info(fbi);
503
504 return r;
505}
506
507static ssize_t show_phys(struct device *dev,
508 struct device_attribute *attr, char *buf)
509{
510 struct fb_info *fbi = dev_get_drvdata(dev);
511 struct omapfb_info *ofbi = FB2OFB(fbi);
512
513 return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region->paddr);
514}
515
516static ssize_t show_virt(struct device *dev,
517 struct device_attribute *attr, char *buf)
518{
519 struct fb_info *fbi = dev_get_drvdata(dev);
520 struct omapfb_info *ofbi = FB2OFB(fbi);
521
522 return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region->vaddr);
523}
524
525static ssize_t show_upd_mode(struct device *dev,
526 struct device_attribute *attr, char *buf)
527{
528 struct fb_info *fbi = dev_get_drvdata(dev);
529 enum omapfb_update_mode mode;
530 int r;
531
532 r = omapfb_get_update_mode(fbi, &mode);
533
534 if (r)
535 return r;
536
537 return snprintf(buf, PAGE_SIZE, "%u\n", (unsigned)mode);
538}
539
540static ssize_t store_upd_mode(struct device *dev, struct device_attribute *attr,
541 const char *buf, size_t count)
542{
543 struct fb_info *fbi = dev_get_drvdata(dev);
544 unsigned mode;
545 int r;
546
547 r = kstrtouint(buf, 0, &mode);
548 if (r)
549 return r;
550
551 r = omapfb_set_update_mode(fbi, mode);
552 if (r)
553 return r;
554
555 return count;
556}
557
558static struct device_attribute omapfb_attrs[] = {
559 __ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type,
560 store_rotate_type),
561 __ATTR(mirror, S_IRUGO | S_IWUSR, show_mirror, store_mirror),
562 __ATTR(size, S_IRUGO | S_IWUSR, show_size, store_size),
563 __ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays),
564 __ATTR(overlays_rotate, S_IRUGO | S_IWUSR, show_overlays_rotate,
565 store_overlays_rotate),
566 __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
567 __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
568 __ATTR(update_mode, S_IRUGO | S_IWUSR, show_upd_mode, store_upd_mode),
569};
570
571int omapfb_create_sysfs(struct omapfb2_device *fbdev)
572{
573 int i;
574 int r;
575
576 DBG("create sysfs for fbs\n");
577 for (i = 0; i < fbdev->num_fbs; i++) {
578 int t;
579 for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++) {
580 r = device_create_file(fbdev->fbs[i]->dev,
581 &omapfb_attrs[t]);
582
583 if (r) {
584 dev_err(fbdev->dev, "failed to create sysfs "
585 "file\n");
586 return r;
587 }
588 }
589 }
590
591 return 0;
592}
593
594void omapfb_remove_sysfs(struct omapfb2_device *fbdev)
595{
596 int i, t;
597
598 DBG("remove sysfs for fbs\n");
599 for (i = 0; i < fbdev->num_fbs; i++) {
600 for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++)
601 device_remove_file(fbdev->fbs[i]->dev,
602 &omapfb_attrs[t]);
603 }
604}
605
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
deleted file mode 100644
index 623cd872a367..000000000000
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ /dev/null
@@ -1,208 +0,0 @@
1/*
2 * linux/drivers/video/omap2/omapfb.h
3 *
4 * Copyright (C) 2008 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
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#ifndef __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
24#define __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
25
26#ifdef CONFIG_FB_OMAP2_DEBUG_SUPPORT
27#define DEBUG
28#endif
29
30#include <linux/rwsem.h>
31#include <linux/dma-attrs.h>
32#include <linux/dma-mapping.h>
33
34#include <video/omapdss.h>
35
36#ifdef DEBUG
37extern bool omapfb_debug;
38#define DBG(format, ...) \
39 do { \
40 if (omapfb_debug) \
41 printk(KERN_DEBUG "OMAPFB: " format, ## __VA_ARGS__); \
42 } while (0)
43#else
44#define DBG(format, ...)
45#endif
46
47#define FB2OFB(fb_info) ((struct omapfb_info *)(fb_info->par))
48
49/* max number of overlays to which a framebuffer data can be direct */
50#define OMAPFB_MAX_OVL_PER_FB 3
51
52struct omapfb2_mem_region {
53 int id;
54 struct dma_attrs attrs;
55 void *token;
56 dma_addr_t dma_handle;
57 u32 paddr;
58 void __iomem *vaddr;
59 struct vrfb vrfb;
60 unsigned long size;
61 u8 type; /* OMAPFB_PLANE_MEM_* */
62 bool alloc; /* allocated by the driver */
63 bool map; /* kernel mapped by the driver */
64 atomic_t map_count;
65 struct rw_semaphore lock;
66 atomic_t lock_count;
67};
68
69/* appended to fb_info */
70struct omapfb_info {
71 int id;
72 struct omapfb2_mem_region *region;
73 int num_overlays;
74 struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB];
75 struct omapfb2_device *fbdev;
76 enum omap_dss_rotation_type rotation_type;
77 u8 rotation[OMAPFB_MAX_OVL_PER_FB];
78 bool mirror;
79};
80
81struct omapfb_display_data {
82 struct omapfb2_device *fbdev;
83 struct omap_dss_device *dssdev;
84 u8 bpp_override;
85 enum omapfb_update_mode update_mode;
86 bool auto_update_work_enabled;
87 struct delayed_work auto_update_work;
88};
89
90struct omapfb2_device {
91 struct device *dev;
92 struct mutex mtx;
93
94 u32 pseudo_palette[17];
95
96 int state;
97
98 unsigned num_fbs;
99 struct fb_info *fbs[10];
100 struct omapfb2_mem_region regions[10];
101
102 unsigned num_displays;
103 struct omapfb_display_data displays[10];
104 unsigned num_overlays;
105 struct omap_overlay *overlays[10];
106 unsigned num_managers;
107 struct omap_overlay_manager *managers[10];
108
109 struct workqueue_struct *auto_update_wq;
110};
111
112struct omapfb_colormode {
113 enum omap_color_mode dssmode;
114 u32 bits_per_pixel;
115 u32 nonstd;
116 struct fb_bitfield red;
117 struct fb_bitfield green;
118 struct fb_bitfield blue;
119 struct fb_bitfield transp;
120};
121
122void set_fb_fix(struct fb_info *fbi);
123int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var);
124int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type);
125int omapfb_apply_changes(struct fb_info *fbi, int init);
126
127int omapfb_create_sysfs(struct omapfb2_device *fbdev);
128void omapfb_remove_sysfs(struct omapfb2_device *fbdev);
129
130int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
131
132int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
133 struct fb_var_screeninfo *var);
134
135int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
136 u16 posx, u16 posy, u16 outw, u16 outh);
137
138void omapfb_start_auto_update(struct omapfb2_device *fbdev,
139 struct omap_dss_device *display);
140void omapfb_stop_auto_update(struct omapfb2_device *fbdev,
141 struct omap_dss_device *display);
142int omapfb_get_update_mode(struct fb_info *fbi, enum omapfb_update_mode *mode);
143int omapfb_set_update_mode(struct fb_info *fbi, enum omapfb_update_mode mode);
144
145/* find the display connected to this fb, if any */
146static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
147{
148 struct omapfb_info *ofbi = FB2OFB(fbi);
149 struct omap_overlay *ovl;
150
151 /* XXX: returns the display connected to first attached overlay */
152
153 if (ofbi->num_overlays == 0)
154 return NULL;
155
156 ovl = ofbi->overlays[0];
157
158 return ovl->get_device(ovl);
159}
160
161static inline struct omapfb_display_data *get_display_data(
162 struct omapfb2_device *fbdev, struct omap_dss_device *dssdev)
163{
164 int i;
165
166 for (i = 0; i < fbdev->num_displays; ++i)
167 if (fbdev->displays[i].dssdev == dssdev)
168 return &fbdev->displays[i];
169
170 /* This should never happen */
171 BUG();
172 return NULL;
173}
174
175static inline void omapfb_lock(struct omapfb2_device *fbdev)
176{
177 mutex_lock(&fbdev->mtx);
178}
179
180static inline void omapfb_unlock(struct omapfb2_device *fbdev)
181{
182 mutex_unlock(&fbdev->mtx);
183}
184
185static inline int omapfb_overlay_enable(struct omap_overlay *ovl,
186 int enable)
187{
188 if (enable)
189 return ovl->enable(ovl);
190 else
191 return ovl->disable(ovl);
192}
193
194static inline struct omapfb2_mem_region *
195omapfb_get_mem_region(struct omapfb2_mem_region *rg)
196{
197 down_read_nested(&rg->lock, rg->id);
198 atomic_inc(&rg->lock_count);
199 return rg;
200}
201
202static inline void omapfb_put_mem_region(struct omapfb2_mem_region *rg)
203{
204 atomic_dec(&rg->lock_count);
205 up_read(&rg->lock);
206}
207
208#endif
diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c
deleted file mode 100644
index f346b02eee1d..000000000000
--- a/drivers/video/omap2/vrfb.c
+++ /dev/null
@@ -1,399 +0,0 @@
1/*
2 * VRFB Rotation Engine
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.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 version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21/*#define DEBUG*/
22
23#include <linux/err.h>
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/ioport.h>
27#include <linux/io.h>
28#include <linux/bitops.h>
29#include <linux/mutex.h>
30#include <linux/platform_device.h>
31
32#include <video/omapvrfb.h>
33
34#ifdef DEBUG
35#define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__)
36#else
37#define DBG(format, ...)
38#endif
39
40#define SMS_ROT_CONTROL(context) (0x0 + 0x10 * context)
41#define SMS_ROT_SIZE(context) (0x4 + 0x10 * context)
42#define SMS_ROT_PHYSICAL_BA(context) (0x8 + 0x10 * context)
43#define SMS_ROT_VIRT_BASE(rot) (0x1000000 * (rot))
44
45#define OMAP_VRFB_SIZE (2048 * 2048 * 4)
46
47#define VRFB_PAGE_WIDTH_EXP 5 /* Assuming SDRAM pagesize= 1024 */
48#define VRFB_PAGE_HEIGHT_EXP 5 /* 1024 = 2^5 * 2^5 */
49#define VRFB_PAGE_WIDTH (1 << VRFB_PAGE_WIDTH_EXP)
50#define VRFB_PAGE_HEIGHT (1 << VRFB_PAGE_HEIGHT_EXP)
51#define SMS_IMAGEHEIGHT_OFFSET 16
52#define SMS_IMAGEWIDTH_OFFSET 0
53#define SMS_PH_OFFSET 8
54#define SMS_PW_OFFSET 4
55#define SMS_PS_OFFSET 0
56
57/* bitmap of reserved contexts */
58static unsigned long ctx_map;
59
60struct vrfb_ctx {
61 u32 base;
62 u32 physical_ba;
63 u32 control;
64 u32 size;
65};
66
67static DEFINE_MUTEX(ctx_lock);
68
69/*
70 * Access to this happens from client drivers or the PM core after wake-up.
71 * For the first case we require locking at the driver level, for the second
72 * we don't need locking, since no drivers will run until after the wake-up
73 * has finished.
74 */
75
76static void __iomem *vrfb_base;
77
78static int num_ctxs;
79static struct vrfb_ctx *ctxs;
80
81static bool vrfb_loaded;
82
83static void omap2_sms_write_rot_control(u32 val, unsigned ctx)
84{
85 __raw_writel(val, vrfb_base + SMS_ROT_CONTROL(ctx));
86}
87
88static void omap2_sms_write_rot_size(u32 val, unsigned ctx)
89{
90 __raw_writel(val, vrfb_base + SMS_ROT_SIZE(ctx));
91}
92
93static void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx)
94{
95 __raw_writel(val, vrfb_base + SMS_ROT_PHYSICAL_BA(ctx));
96}
97
98static inline void restore_hw_context(int ctx)
99{
100 omap2_sms_write_rot_control(ctxs[ctx].control, ctx);
101 omap2_sms_write_rot_size(ctxs[ctx].size, ctx);
102 omap2_sms_write_rot_physical_ba(ctxs[ctx].physical_ba, ctx);
103}
104
105static u32 get_image_width_roundup(u16 width, u8 bytespp)
106{
107 unsigned long stride = width * bytespp;
108 unsigned long ceil_pages_per_stride = (stride / VRFB_PAGE_WIDTH) +
109 (stride % VRFB_PAGE_WIDTH != 0);
110
111 return ceil_pages_per_stride * VRFB_PAGE_WIDTH / bytespp;
112}
113
114/*
115 * This the extra space needed in the VRFB physical area for VRFB to safely wrap
116 * any memory accesses to the invisible part of the virtual view to the physical
117 * area.
118 */
119static inline u32 get_extra_physical_size(u16 image_width_roundup, u8 bytespp)
120{
121 return (OMAP_VRFB_LINE_LEN - image_width_roundup) * VRFB_PAGE_HEIGHT *
122 bytespp;
123}
124
125void omap_vrfb_restore_context(void)
126{
127 int i;
128 unsigned long map = ctx_map;
129
130 for (i = ffs(map); i; i = ffs(map)) {
131 /* i=1..32 */
132 i--;
133 map &= ~(1 << i);
134 restore_hw_context(i);
135 }
136}
137
138void omap_vrfb_adjust_size(u16 *width, u16 *height,
139 u8 bytespp)
140{
141 *width = ALIGN(*width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
142 *height = ALIGN(*height, VRFB_PAGE_HEIGHT);
143}
144EXPORT_SYMBOL(omap_vrfb_adjust_size);
145
146u32 omap_vrfb_min_phys_size(u16 width, u16 height, u8 bytespp)
147{
148 unsigned long image_width_roundup = get_image_width_roundup(width,
149 bytespp);
150
151 if (image_width_roundup > OMAP_VRFB_LINE_LEN)
152 return 0;
153
154 return (width * height * bytespp) + get_extra_physical_size(
155 image_width_roundup, bytespp);
156}
157EXPORT_SYMBOL(omap_vrfb_min_phys_size);
158
159u16 omap_vrfb_max_height(u32 phys_size, u16 width, u8 bytespp)
160{
161 unsigned long image_width_roundup = get_image_width_roundup(width,
162 bytespp);
163 unsigned long height;
164 unsigned long extra;
165
166 if (image_width_roundup > OMAP_VRFB_LINE_LEN)
167 return 0;
168
169 extra = get_extra_physical_size(image_width_roundup, bytespp);
170
171 if (phys_size < extra)
172 return 0;
173
174 height = (phys_size - extra) / (width * bytespp);
175
176 /* Virtual views provided by VRFB are limited to 2048x2048. */
177 return min_t(unsigned long, height, 2048);
178}
179EXPORT_SYMBOL(omap_vrfb_max_height);
180
181void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
182 u16 width, u16 height,
183 unsigned bytespp, bool yuv_mode)
184{
185 unsigned pixel_size_exp;
186 u16 vrfb_width;
187 u16 vrfb_height;
188 u8 ctx = vrfb->context;
189 u32 size;
190 u32 control;
191
192 DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d, %d)\n", ctx, paddr,
193 width, height, bytespp, yuv_mode);
194
195 /* For YUV2 and UYVY modes VRFB needs to handle pixels a bit
196 * differently. See TRM. */
197 if (yuv_mode) {
198 bytespp *= 2;
199 width /= 2;
200 }
201
202 if (bytespp == 4)
203 pixel_size_exp = 2;
204 else if (bytespp == 2)
205 pixel_size_exp = 1;
206 else {
207 BUG();
208 return;
209 }
210
211 vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
212 vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT);
213
214 DBG("vrfb w %u, h %u bytespp %d\n", vrfb_width, vrfb_height, bytespp);
215
216 size = vrfb_width << SMS_IMAGEWIDTH_OFFSET;
217 size |= vrfb_height << SMS_IMAGEHEIGHT_OFFSET;
218
219 control = pixel_size_exp << SMS_PS_OFFSET;
220 control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET;
221 control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET;
222
223 ctxs[ctx].physical_ba = paddr;
224 ctxs[ctx].size = size;
225 ctxs[ctx].control = control;
226
227 omap2_sms_write_rot_physical_ba(paddr, ctx);
228 omap2_sms_write_rot_size(size, ctx);
229 omap2_sms_write_rot_control(control, ctx);
230
231 DBG("vrfb offset pixels %d, %d\n",
232 vrfb_width - width, vrfb_height - height);
233
234 vrfb->xres = width;
235 vrfb->yres = height;
236 vrfb->xoffset = vrfb_width - width;
237 vrfb->yoffset = vrfb_height - height;
238 vrfb->bytespp = bytespp;
239 vrfb->yuv_mode = yuv_mode;
240}
241EXPORT_SYMBOL(omap_vrfb_setup);
242
243int omap_vrfb_map_angle(struct vrfb *vrfb, u16 height, u8 rot)
244{
245 unsigned long size = height * OMAP_VRFB_LINE_LEN * vrfb->bytespp;
246
247 vrfb->vaddr[rot] = ioremap_wc(vrfb->paddr[rot], size);
248
249 if (!vrfb->vaddr[rot]) {
250 printk(KERN_ERR "vrfb: ioremap failed\n");
251 return -ENOMEM;
252 }
253
254 DBG("ioremapped vrfb area %d of size %lu into %p\n", rot, size,
255 vrfb->vaddr[rot]);
256
257 return 0;
258}
259EXPORT_SYMBOL(omap_vrfb_map_angle);
260
261void omap_vrfb_release_ctx(struct vrfb *vrfb)
262{
263 int rot;
264 int ctx = vrfb->context;
265
266 if (ctx == 0xff)
267 return;
268
269 DBG("release ctx %d\n", ctx);
270
271 mutex_lock(&ctx_lock);
272
273 BUG_ON(!(ctx_map & (1 << ctx)));
274
275 clear_bit(ctx, &ctx_map);
276
277 for (rot = 0; rot < 4; ++rot) {
278 if (vrfb->paddr[rot]) {
279 release_mem_region(vrfb->paddr[rot], OMAP_VRFB_SIZE);
280 vrfb->paddr[rot] = 0;
281 }
282 }
283
284 vrfb->context = 0xff;
285
286 mutex_unlock(&ctx_lock);
287}
288EXPORT_SYMBOL(omap_vrfb_release_ctx);
289
290int omap_vrfb_request_ctx(struct vrfb *vrfb)
291{
292 int rot;
293 u32 paddr;
294 u8 ctx;
295 int r;
296
297 DBG("request ctx\n");
298
299 mutex_lock(&ctx_lock);
300
301 for (ctx = 0; ctx < num_ctxs; ++ctx)
302 if ((ctx_map & (1 << ctx)) == 0)
303 break;
304
305 if (ctx == num_ctxs) {
306 pr_err("vrfb: no free contexts\n");
307 r = -EBUSY;
308 goto out;
309 }
310
311 DBG("found free ctx %d\n", ctx);
312
313 set_bit(ctx, &ctx_map);
314
315 memset(vrfb, 0, sizeof(*vrfb));
316
317 vrfb->context = ctx;
318
319 for (rot = 0; rot < 4; ++rot) {
320 paddr = ctxs[ctx].base + SMS_ROT_VIRT_BASE(rot);
321 if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
322 pr_err("vrfb: failed to reserve VRFB "
323 "area for ctx %d, rotation %d\n",
324 ctx, rot * 90);
325 omap_vrfb_release_ctx(vrfb);
326 r = -ENOMEM;
327 goto out;
328 }
329
330 vrfb->paddr[rot] = paddr;
331
332 DBG("VRFB %d/%d: %lx\n", ctx, rot*90, vrfb->paddr[rot]);
333 }
334
335 r = 0;
336out:
337 mutex_unlock(&ctx_lock);
338 return r;
339}
340EXPORT_SYMBOL(omap_vrfb_request_ctx);
341
342bool omap_vrfb_supported(void)
343{
344 return vrfb_loaded;
345}
346EXPORT_SYMBOL(omap_vrfb_supported);
347
348static int __init vrfb_probe(struct platform_device *pdev)
349{
350 struct resource *mem;
351 int i;
352
353 /* first resource is the register res, the rest are vrfb contexts */
354
355 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
356 vrfb_base = devm_ioremap_resource(&pdev->dev, mem);
357 if (IS_ERR(vrfb_base))
358 return PTR_ERR(vrfb_base);
359
360 num_ctxs = pdev->num_resources - 1;
361
362 ctxs = devm_kzalloc(&pdev->dev,
363 sizeof(struct vrfb_ctx) * num_ctxs,
364 GFP_KERNEL);
365
366 if (!ctxs)
367 return -ENOMEM;
368
369 for (i = 0; i < num_ctxs; ++i) {
370 mem = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
371 if (!mem) {
372 dev_err(&pdev->dev, "can't get vrfb ctx %d address\n",
373 i);
374 return -EINVAL;
375 }
376
377 ctxs[i].base = mem->start;
378 }
379
380 vrfb_loaded = true;
381
382 return 0;
383}
384
385static void __exit vrfb_remove(struct platform_device *pdev)
386{
387 vrfb_loaded = false;
388}
389
390static struct platform_driver vrfb_driver = {
391 .driver.name = "omapvrfb",
392 .remove = __exit_p(vrfb_remove),
393};
394
395module_platform_driver_probe(vrfb_driver, vrfb_probe);
396
397MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
398MODULE_DESCRIPTION("OMAP VRFB");
399MODULE_LICENSE("GPL v2");