diff options
Diffstat (limited to 'drivers/video/omap2/dss')
-rw-r--r-- | drivers/video/omap2/dss/Kconfig | 47 | ||||
-rw-r--r-- | drivers/video/omap2/dss/Makefile | 4 | ||||
-rw-r--r-- | drivers/video/omap2/dss/core.c | 496 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dispc.c | 2467 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dispc.h | 691 | ||||
-rw-r--r-- | drivers/video/omap2/dss/display.c | 81 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dpi.c | 180 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dsi.c | 2938 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss.c | 831 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss.h | 246 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss_features.c | 433 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss_features.h | 96 | ||||
-rw-r--r-- | drivers/video/omap2/dss/hdmi.c | 1763 | ||||
-rw-r--r-- | drivers/video/omap2/dss/hdmi.h | 631 | ||||
-rw-r--r-- | drivers/video/omap2/dss/hdmi_omap4_panel.c | 222 | ||||
-rw-r--r-- | drivers/video/omap2/dss/manager.c | 138 | ||||
-rw-r--r-- | drivers/video/omap2/dss/overlay.c | 128 | ||||
-rw-r--r-- | drivers/video/omap2/dss/rfbi.c | 310 | ||||
-rw-r--r-- | drivers/video/omap2/dss/sdi.c | 86 | ||||
-rw-r--r-- | drivers/video/omap2/dss/venc.c | 151 |
20 files changed, 8950 insertions, 2989 deletions
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index 43b64403eaa4..6b3e2da11419 100644 --- a/drivers/video/omap2/dss/Kconfig +++ b/drivers/video/omap2/dss/Kconfig | |||
@@ -1,8 +1,8 @@ | |||
1 | menuconfig OMAP2_DSS | 1 | menuconfig OMAP2_DSS |
2 | tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)" | 2 | tristate "OMAP2+ Display Subsystem support (EXPERIMENTAL)" |
3 | depends on ARCH_OMAP2 || ARCH_OMAP3 | 3 | depends on ARCH_OMAP2PLUS |
4 | help | 4 | help |
5 | OMAP2/3 Display Subsystem support. | 5 | OMAP2+ Display Subsystem support. |
6 | 6 | ||
7 | if OMAP2_DSS | 7 | if OMAP2_DSS |
8 | 8 | ||
@@ -60,6 +60,14 @@ config OMAP2_DSS_VENC | |||
60 | help | 60 | help |
61 | OMAP Video Encoder support for S-Video and composite TV-out. | 61 | OMAP Video Encoder support for S-Video and composite TV-out. |
62 | 62 | ||
63 | config OMAP4_DSS_HDMI | ||
64 | bool "HDMI support" | ||
65 | depends on ARCH_OMAP4 | ||
66 | default y | ||
67 | help | ||
68 | HDMI Interface. This adds the High Definition Multimedia Interface. | ||
69 | See http://www.hdmi.org/ for HDMI specification. | ||
70 | |||
63 | config OMAP2_DSS_SDI | 71 | config OMAP2_DSS_SDI |
64 | bool "SDI support" | 72 | bool "SDI support" |
65 | depends on ARCH_OMAP3 | 73 | depends on ARCH_OMAP3 |
@@ -72,7 +80,7 @@ config OMAP2_DSS_SDI | |||
72 | 80 | ||
73 | config OMAP2_DSS_DSI | 81 | config OMAP2_DSS_DSI |
74 | bool "DSI support" | 82 | bool "DSI support" |
75 | depends on ARCH_OMAP3 | 83 | depends on ARCH_OMAP3 || ARCH_OMAP4 |
76 | default n | 84 | default n |
77 | help | 85 | help |
78 | MIPI DSI (Display Serial Interface) support. | 86 | MIPI DSI (Display Serial Interface) support. |
@@ -82,14 +90,6 @@ config OMAP2_DSS_DSI | |||
82 | 90 | ||
83 | See http://www.mipi.org/ for DSI spesifications. | 91 | See http://www.mipi.org/ for DSI spesifications. |
84 | 92 | ||
85 | config OMAP2_DSS_USE_DSI_PLL | ||
86 | bool "Use DSI PLL for PCLK (EXPERIMENTAL)" | ||
87 | default n | ||
88 | depends on OMAP2_DSS_DSI | ||
89 | help | ||
90 | Use DSI PLL to generate pixel clock. Currently only for DPI output. | ||
91 | DSI PLL can be used to generate higher and more precise pixel clocks. | ||
92 | |||
93 | config OMAP2_DSS_FAKE_VSYNC | 93 | config OMAP2_DSS_FAKE_VSYNC |
94 | bool "Fake VSYNC irq from manual update displays" | 94 | bool "Fake VSYNC irq from manual update displays" |
95 | default n | 95 | default n |
@@ -117,4 +117,27 @@ config OMAP2_DSS_MIN_FCK_PER_PCK | |||
117 | Max FCK is 173MHz, so this doesn't work if your PCK | 117 | Max FCK is 173MHz, so this doesn't work if your PCK |
118 | is very high. | 118 | is very high. |
119 | 119 | ||
120 | config OMAP2_DSS_SLEEP_BEFORE_RESET | ||
121 | bool "Sleep 50ms before DSS reset" | ||
122 | default y | ||
123 | help | ||
124 | For some unknown reason we may get SYNC_LOST errors from the display | ||
125 | subsystem at initialization time if we don't sleep before resetting | ||
126 | the DSS. See the source (dss.c) for more comments. | ||
127 | |||
128 | However, 50ms is quite long time to sleep, and with some | ||
129 | configurations the SYNC_LOST may never happen, so the sleep can | ||
130 | be disabled here. | ||
131 | |||
132 | config OMAP2_DSS_SLEEP_AFTER_VENC_RESET | ||
133 | bool "Sleep 20ms after VENC reset" | ||
134 | default y | ||
135 | help | ||
136 | There is a 20ms sleep after VENC reset which seemed to fix the | ||
137 | reset. The reason for the bug is unclear, and it's also unclear | ||
138 | on what platforms this happens. | ||
139 | |||
140 | This option enables the sleep, and is enabled by default. You can | ||
141 | disable the sleep if it doesn't cause problems on your platform. | ||
142 | |||
120 | endif | 143 | endif |
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile index d71b5d9d71b1..10d9d3bb3e24 100644 --- a/drivers/video/omap2/dss/Makefile +++ b/drivers/video/omap2/dss/Makefile | |||
@@ -1,7 +1,9 @@ | |||
1 | obj-$(CONFIG_OMAP2_DSS) += omapdss.o | 1 | obj-$(CONFIG_OMAP2_DSS) += omapdss.o |
2 | omapdss-y := core.o dss.o dispc.o display.o manager.o overlay.o | 2 | omapdss-y := core.o dss.o dss_features.o dispc.o display.o manager.o overlay.o |
3 | omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o | 3 | omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o |
4 | omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o | 4 | omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o |
5 | omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o | 5 | omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o |
6 | omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o | 6 | omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o |
7 | omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o | 7 | omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o |
8 | omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ | ||
9 | hdmi_omap4_panel.o | ||
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index b3a498f22d36..3da426719dd6 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c | |||
@@ -33,331 +33,29 @@ | |||
33 | #include <linux/device.h> | 33 | #include <linux/device.h> |
34 | #include <linux/regulator/consumer.h> | 34 | #include <linux/regulator/consumer.h> |
35 | 35 | ||
36 | #include <plat/display.h> | 36 | #include <video/omapdss.h> |
37 | #include <plat/clock.h> | ||
38 | 37 | ||
39 | #include "dss.h" | 38 | #include "dss.h" |
39 | #include "dss_features.h" | ||
40 | 40 | ||
41 | static struct { | 41 | static struct { |
42 | struct platform_device *pdev; | 42 | struct platform_device *pdev; |
43 | int ctx_id; | ||
44 | |||
45 | struct clk *dss_ick; | ||
46 | struct clk *dss1_fck; | ||
47 | struct clk *dss2_fck; | ||
48 | struct clk *dss_54m_fck; | ||
49 | struct clk *dss_96m_fck; | ||
50 | unsigned num_clks_enabled; | ||
51 | 43 | ||
52 | struct regulator *vdds_dsi_reg; | 44 | struct regulator *vdds_dsi_reg; |
53 | struct regulator *vdds_sdi_reg; | 45 | struct regulator *vdds_sdi_reg; |
54 | struct regulator *vdda_dac_reg; | ||
55 | } core; | 46 | } core; |
56 | 47 | ||
57 | static void dss_clk_enable_all_no_ctx(void); | ||
58 | static void dss_clk_disable_all_no_ctx(void); | ||
59 | static void dss_clk_enable_no_ctx(enum dss_clock clks); | ||
60 | static void dss_clk_disable_no_ctx(enum dss_clock clks); | ||
61 | |||
62 | static char *def_disp_name; | 48 | static char *def_disp_name; |
63 | module_param_named(def_disp, def_disp_name, charp, 0); | 49 | module_param_named(def_disp, def_disp_name, charp, 0); |
64 | MODULE_PARM_DESC(def_disp_name, "default display name"); | 50 | MODULE_PARM_DESC(def_disp, "default display name"); |
65 | 51 | ||
66 | #ifdef DEBUG | 52 | #ifdef DEBUG |
67 | unsigned int dss_debug; | 53 | unsigned int dss_debug; |
68 | module_param_named(debug, dss_debug, bool, 0644); | 54 | module_param_named(debug, dss_debug, bool, 0644); |
69 | #endif | 55 | #endif |
70 | 56 | ||
71 | /* CONTEXT */ | 57 | static int omap_dss_register_device(struct omap_dss_device *); |
72 | static int dss_get_ctx_id(void) | 58 | static void omap_dss_unregister_device(struct omap_dss_device *); |
73 | { | ||
74 | struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; | ||
75 | int r; | ||
76 | |||
77 | if (!pdata->get_last_off_on_transaction_id) | ||
78 | return 0; | ||
79 | r = pdata->get_last_off_on_transaction_id(&core.pdev->dev); | ||
80 | if (r < 0) { | ||
81 | dev_err(&core.pdev->dev, "getting transaction ID failed, " | ||
82 | "will force context restore\n"); | ||
83 | r = -1; | ||
84 | } | ||
85 | return r; | ||
86 | } | ||
87 | |||
88 | int dss_need_ctx_restore(void) | ||
89 | { | ||
90 | int id = dss_get_ctx_id(); | ||
91 | |||
92 | if (id < 0 || id != core.ctx_id) { | ||
93 | DSSDBG("ctx id %d -> id %d\n", | ||
94 | core.ctx_id, id); | ||
95 | core.ctx_id = id; | ||
96 | return 1; | ||
97 | } else { | ||
98 | return 0; | ||
99 | } | ||
100 | } | ||
101 | |||
102 | static void save_all_ctx(void) | ||
103 | { | ||
104 | DSSDBG("save context\n"); | ||
105 | |||
106 | dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); | ||
107 | |||
108 | dss_save_context(); | ||
109 | dispc_save_context(); | ||
110 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
111 | dsi_save_context(); | ||
112 | #endif | ||
113 | |||
114 | dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); | ||
115 | } | ||
116 | |||
117 | static void restore_all_ctx(void) | ||
118 | { | ||
119 | DSSDBG("restore context\n"); | ||
120 | |||
121 | dss_clk_enable_all_no_ctx(); | ||
122 | |||
123 | dss_restore_context(); | ||
124 | dispc_restore_context(); | ||
125 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
126 | dsi_restore_context(); | ||
127 | #endif | ||
128 | |||
129 | dss_clk_disable_all_no_ctx(); | ||
130 | } | ||
131 | |||
132 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | ||
133 | /* CLOCKS */ | ||
134 | static void core_dump_clocks(struct seq_file *s) | ||
135 | { | ||
136 | int i; | ||
137 | struct clk *clocks[5] = { | ||
138 | core.dss_ick, | ||
139 | core.dss1_fck, | ||
140 | core.dss2_fck, | ||
141 | core.dss_54m_fck, | ||
142 | core.dss_96m_fck | ||
143 | }; | ||
144 | |||
145 | seq_printf(s, "- CORE -\n"); | ||
146 | |||
147 | seq_printf(s, "internal clk count\t\t%u\n", core.num_clks_enabled); | ||
148 | |||
149 | for (i = 0; i < 5; i++) { | ||
150 | if (!clocks[i]) | ||
151 | continue; | ||
152 | seq_printf(s, "%-15s\t%lu\t%d\n", | ||
153 | clocks[i]->name, | ||
154 | clk_get_rate(clocks[i]), | ||
155 | clocks[i]->usecount); | ||
156 | } | ||
157 | } | ||
158 | #endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */ | ||
159 | |||
160 | static int dss_get_clock(struct clk **clock, const char *clk_name) | ||
161 | { | ||
162 | struct clk *clk; | ||
163 | |||
164 | clk = clk_get(&core.pdev->dev, clk_name); | ||
165 | |||
166 | if (IS_ERR(clk)) { | ||
167 | DSSERR("can't get clock %s", clk_name); | ||
168 | return PTR_ERR(clk); | ||
169 | } | ||
170 | |||
171 | *clock = clk; | ||
172 | |||
173 | DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk)); | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static int dss_get_clocks(void) | ||
179 | { | ||
180 | int r; | ||
181 | |||
182 | core.dss_ick = NULL; | ||
183 | core.dss1_fck = NULL; | ||
184 | core.dss2_fck = NULL; | ||
185 | core.dss_54m_fck = NULL; | ||
186 | core.dss_96m_fck = NULL; | ||
187 | |||
188 | r = dss_get_clock(&core.dss_ick, "ick"); | ||
189 | if (r) | ||
190 | goto err; | ||
191 | |||
192 | r = dss_get_clock(&core.dss1_fck, "dss1_fck"); | ||
193 | if (r) | ||
194 | goto err; | ||
195 | |||
196 | r = dss_get_clock(&core.dss2_fck, "dss2_fck"); | ||
197 | if (r) | ||
198 | goto err; | ||
199 | |||
200 | r = dss_get_clock(&core.dss_54m_fck, "tv_fck"); | ||
201 | if (r) | ||
202 | goto err; | ||
203 | |||
204 | r = dss_get_clock(&core.dss_96m_fck, "video_fck"); | ||
205 | if (r) | ||
206 | goto err; | ||
207 | |||
208 | return 0; | ||
209 | |||
210 | err: | ||
211 | if (core.dss_ick) | ||
212 | clk_put(core.dss_ick); | ||
213 | if (core.dss1_fck) | ||
214 | clk_put(core.dss1_fck); | ||
215 | if (core.dss2_fck) | ||
216 | clk_put(core.dss2_fck); | ||
217 | if (core.dss_54m_fck) | ||
218 | clk_put(core.dss_54m_fck); | ||
219 | if (core.dss_96m_fck) | ||
220 | clk_put(core.dss_96m_fck); | ||
221 | |||
222 | return r; | ||
223 | } | ||
224 | |||
225 | static void dss_put_clocks(void) | ||
226 | { | ||
227 | if (core.dss_96m_fck) | ||
228 | clk_put(core.dss_96m_fck); | ||
229 | clk_put(core.dss_54m_fck); | ||
230 | clk_put(core.dss1_fck); | ||
231 | clk_put(core.dss2_fck); | ||
232 | clk_put(core.dss_ick); | ||
233 | } | ||
234 | |||
235 | unsigned long dss_clk_get_rate(enum dss_clock clk) | ||
236 | { | ||
237 | switch (clk) { | ||
238 | case DSS_CLK_ICK: | ||
239 | return clk_get_rate(core.dss_ick); | ||
240 | case DSS_CLK_FCK1: | ||
241 | return clk_get_rate(core.dss1_fck); | ||
242 | case DSS_CLK_FCK2: | ||
243 | return clk_get_rate(core.dss2_fck); | ||
244 | case DSS_CLK_54M: | ||
245 | return clk_get_rate(core.dss_54m_fck); | ||
246 | case DSS_CLK_96M: | ||
247 | return clk_get_rate(core.dss_96m_fck); | ||
248 | } | ||
249 | |||
250 | BUG(); | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static unsigned count_clk_bits(enum dss_clock clks) | ||
255 | { | ||
256 | unsigned num_clks = 0; | ||
257 | |||
258 | if (clks & DSS_CLK_ICK) | ||
259 | ++num_clks; | ||
260 | if (clks & DSS_CLK_FCK1) | ||
261 | ++num_clks; | ||
262 | if (clks & DSS_CLK_FCK2) | ||
263 | ++num_clks; | ||
264 | if (clks & DSS_CLK_54M) | ||
265 | ++num_clks; | ||
266 | if (clks & DSS_CLK_96M) | ||
267 | ++num_clks; | ||
268 | |||
269 | return num_clks; | ||
270 | } | ||
271 | |||
272 | static void dss_clk_enable_no_ctx(enum dss_clock clks) | ||
273 | { | ||
274 | unsigned num_clks = count_clk_bits(clks); | ||
275 | |||
276 | if (clks & DSS_CLK_ICK) | ||
277 | clk_enable(core.dss_ick); | ||
278 | if (clks & DSS_CLK_FCK1) | ||
279 | clk_enable(core.dss1_fck); | ||
280 | if (clks & DSS_CLK_FCK2) | ||
281 | clk_enable(core.dss2_fck); | ||
282 | if (clks & DSS_CLK_54M) | ||
283 | clk_enable(core.dss_54m_fck); | ||
284 | if (clks & DSS_CLK_96M) | ||
285 | clk_enable(core.dss_96m_fck); | ||
286 | |||
287 | core.num_clks_enabled += num_clks; | ||
288 | } | ||
289 | |||
290 | void dss_clk_enable(enum dss_clock clks) | ||
291 | { | ||
292 | bool check_ctx = core.num_clks_enabled == 0; | ||
293 | |||
294 | dss_clk_enable_no_ctx(clks); | ||
295 | |||
296 | if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore()) | ||
297 | restore_all_ctx(); | ||
298 | } | ||
299 | |||
300 | static void dss_clk_disable_no_ctx(enum dss_clock clks) | ||
301 | { | ||
302 | unsigned num_clks = count_clk_bits(clks); | ||
303 | |||
304 | if (clks & DSS_CLK_ICK) | ||
305 | clk_disable(core.dss_ick); | ||
306 | if (clks & DSS_CLK_FCK1) | ||
307 | clk_disable(core.dss1_fck); | ||
308 | if (clks & DSS_CLK_FCK2) | ||
309 | clk_disable(core.dss2_fck); | ||
310 | if (clks & DSS_CLK_54M) | ||
311 | clk_disable(core.dss_54m_fck); | ||
312 | if (clks & DSS_CLK_96M) | ||
313 | clk_disable(core.dss_96m_fck); | ||
314 | |||
315 | core.num_clks_enabled -= num_clks; | ||
316 | } | ||
317 | |||
318 | void dss_clk_disable(enum dss_clock clks) | ||
319 | { | ||
320 | if (cpu_is_omap34xx()) { | ||
321 | unsigned num_clks = count_clk_bits(clks); | ||
322 | |||
323 | BUG_ON(core.num_clks_enabled < num_clks); | ||
324 | |||
325 | if (core.num_clks_enabled == num_clks) | ||
326 | save_all_ctx(); | ||
327 | } | ||
328 | |||
329 | dss_clk_disable_no_ctx(clks); | ||
330 | } | ||
331 | |||
332 | static void dss_clk_enable_all_no_ctx(void) | ||
333 | { | ||
334 | enum dss_clock clks; | ||
335 | |||
336 | clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; | ||
337 | if (cpu_is_omap34xx()) | ||
338 | clks |= DSS_CLK_96M; | ||
339 | dss_clk_enable_no_ctx(clks); | ||
340 | } | ||
341 | |||
342 | static void dss_clk_disable_all_no_ctx(void) | ||
343 | { | ||
344 | enum dss_clock clks; | ||
345 | |||
346 | clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; | ||
347 | if (cpu_is_omap34xx()) | ||
348 | clks |= DSS_CLK_96M; | ||
349 | dss_clk_disable_no_ctx(clks); | ||
350 | } | ||
351 | |||
352 | static void dss_clk_disable_all(void) | ||
353 | { | ||
354 | enum dss_clock clks; | ||
355 | |||
356 | clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; | ||
357 | if (cpu_is_omap34xx()) | ||
358 | clks |= DSS_CLK_96M; | ||
359 | dss_clk_disable(clks); | ||
360 | } | ||
361 | 59 | ||
362 | /* REGULATORS */ | 60 | /* REGULATORS */ |
363 | 61 | ||
@@ -389,32 +87,7 @@ struct regulator *dss_get_vdds_sdi(void) | |||
389 | return reg; | 87 | return reg; |
390 | } | 88 | } |
391 | 89 | ||
392 | struct regulator *dss_get_vdda_dac(void) | ||
393 | { | ||
394 | struct regulator *reg; | ||
395 | |||
396 | if (core.vdda_dac_reg != NULL) | ||
397 | return core.vdda_dac_reg; | ||
398 | |||
399 | reg = regulator_get(&core.pdev->dev, "vdda_dac"); | ||
400 | if (!IS_ERR(reg)) | ||
401 | core.vdda_dac_reg = reg; | ||
402 | |||
403 | return reg; | ||
404 | } | ||
405 | |||
406 | /* DEBUGFS */ | ||
407 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | 90 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) |
408 | static void dss_debug_dump_clocks(struct seq_file *s) | ||
409 | { | ||
410 | core_dump_clocks(s); | ||
411 | dss_dump_clocks(s); | ||
412 | dispc_dump_clocks(s); | ||
413 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
414 | dsi_dump_clocks(s); | ||
415 | #endif | ||
416 | } | ||
417 | |||
418 | static int dss_debug_show(struct seq_file *s, void *unused) | 91 | static int dss_debug_show(struct seq_file *s, void *unused) |
419 | { | 92 | { |
420 | void (*func)(struct seq_file *) = s->private; | 93 | void (*func)(struct seq_file *) = s->private; |
@@ -454,8 +127,7 @@ static int dss_initialize_debugfs(void) | |||
454 | #endif | 127 | #endif |
455 | 128 | ||
456 | #if defined(CONFIG_OMAP2_DSS_DSI) && defined(CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS) | 129 | #if defined(CONFIG_OMAP2_DSS_DSI) && defined(CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS) |
457 | debugfs_create_file("dsi_irq", S_IRUGO, dss_debugfs_dir, | 130 | dsi_create_debugfs_files_irq(dss_debugfs_dir, &dss_debug_fops); |
458 | &dsi_dump_irqs, &dss_debug_fops); | ||
459 | #endif | 131 | #endif |
460 | 132 | ||
461 | debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir, | 133 | debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir, |
@@ -467,8 +139,7 @@ static int dss_initialize_debugfs(void) | |||
467 | &rfbi_dump_regs, &dss_debug_fops); | 139 | &rfbi_dump_regs, &dss_debug_fops); |
468 | #endif | 140 | #endif |
469 | #ifdef CONFIG_OMAP2_DSS_DSI | 141 | #ifdef CONFIG_OMAP2_DSS_DSI |
470 | debugfs_create_file("dsi", S_IRUGO, dss_debugfs_dir, | 142 | dsi_create_debugfs_files_reg(dss_debugfs_dir, &dss_debug_fops); |
471 | &dsi_dump_regs, &dss_debug_fops); | ||
472 | #endif | 143 | #endif |
473 | #ifdef CONFIG_OMAP2_DSS_VENC | 144 | #ifdef CONFIG_OMAP2_DSS_VENC |
474 | debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir, | 145 | debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir, |
@@ -496,72 +167,53 @@ static inline void dss_uninitialize_debugfs(void) | |||
496 | static int omap_dss_probe(struct platform_device *pdev) | 167 | static int omap_dss_probe(struct platform_device *pdev) |
497 | { | 168 | { |
498 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | 169 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; |
499 | int skip_init = 0; | ||
500 | int r; | 170 | int r; |
501 | int i; | 171 | int i; |
502 | 172 | ||
503 | core.pdev = pdev; | 173 | core.pdev = pdev; |
504 | 174 | ||
175 | dss_features_init(); | ||
176 | |||
505 | dss_init_overlay_managers(pdev); | 177 | dss_init_overlay_managers(pdev); |
506 | dss_init_overlays(pdev); | 178 | dss_init_overlays(pdev); |
507 | 179 | ||
508 | r = dss_get_clocks(); | 180 | r = dss_init_platform_driver(); |
509 | if (r) | ||
510 | goto err_clocks; | ||
511 | |||
512 | dss_clk_enable_all_no_ctx(); | ||
513 | |||
514 | core.ctx_id = dss_get_ctx_id(); | ||
515 | DSSDBG("initial ctx id %u\n", core.ctx_id); | ||
516 | |||
517 | #ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT | ||
518 | /* DISPC_CONTROL */ | ||
519 | if (omap_readl(0x48050440) & 1) /* LCD enabled? */ | ||
520 | skip_init = 1; | ||
521 | #endif | ||
522 | |||
523 | r = dss_init(skip_init); | ||
524 | if (r) { | 181 | if (r) { |
525 | DSSERR("Failed to initialize DSS\n"); | 182 | DSSERR("Failed to initialize DSS platform driver\n"); |
526 | goto err_dss; | 183 | goto err_dss; |
527 | } | 184 | } |
528 | 185 | ||
529 | r = rfbi_init(); | 186 | /* keep clocks enabled to prevent context saves/restores during init */ |
530 | if (r) { | 187 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
531 | DSSERR("Failed to initialize rfbi\n"); | ||
532 | goto err_rfbi; | ||
533 | } | ||
534 | 188 | ||
535 | r = dpi_init(pdev); | 189 | r = rfbi_init_platform_driver(); |
536 | if (r) { | 190 | if (r) { |
537 | DSSERR("Failed to initialize dpi\n"); | 191 | DSSERR("Failed to initialize rfbi platform driver\n"); |
538 | goto err_dpi; | 192 | goto err_rfbi; |
539 | } | 193 | } |
540 | 194 | ||
541 | r = dispc_init(); | 195 | r = dispc_init_platform_driver(); |
542 | if (r) { | 196 | if (r) { |
543 | DSSERR("Failed to initialize dispc\n"); | 197 | DSSERR("Failed to initialize dispc platform driver\n"); |
544 | goto err_dispc; | 198 | goto err_dispc; |
545 | } | 199 | } |
546 | 200 | ||
547 | r = venc_init(pdev); | 201 | r = venc_init_platform_driver(); |
548 | if (r) { | 202 | if (r) { |
549 | DSSERR("Failed to initialize venc\n"); | 203 | DSSERR("Failed to initialize venc platform driver\n"); |
550 | goto err_venc; | 204 | goto err_venc; |
551 | } | 205 | } |
552 | 206 | ||
553 | if (cpu_is_omap34xx()) { | 207 | r = dsi_init_platform_driver(); |
554 | r = sdi_init(skip_init); | 208 | if (r) { |
555 | if (r) { | 209 | DSSERR("Failed to initialize DSI platform driver\n"); |
556 | DSSERR("Failed to initialize SDI\n"); | 210 | goto err_dsi; |
557 | goto err_sdi; | 211 | } |
558 | } | ||
559 | 212 | ||
560 | r = dsi_init(pdev); | 213 | r = hdmi_init_platform_driver(); |
561 | if (r) { | 214 | if (r) { |
562 | DSSERR("Failed to initialize DSI\n"); | 215 | DSSERR("Failed to initialize hdmi\n"); |
563 | goto err_dsi; | 216 | goto err_hdmi; |
564 | } | ||
565 | } | 217 | } |
566 | 218 | ||
567 | r = dss_initialize_debugfs(); | 219 | r = dss_initialize_debugfs(); |
@@ -586,32 +238,25 @@ static int omap_dss_probe(struct platform_device *pdev) | |||
586 | pdata->default_device = dssdev; | 238 | pdata->default_device = dssdev; |
587 | } | 239 | } |
588 | 240 | ||
589 | dss_clk_disable_all(); | 241 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
590 | 242 | ||
591 | return 0; | 243 | return 0; |
592 | 244 | ||
593 | err_register: | 245 | err_register: |
594 | dss_uninitialize_debugfs(); | 246 | dss_uninitialize_debugfs(); |
595 | err_debugfs: | 247 | err_debugfs: |
596 | if (cpu_is_omap34xx()) | 248 | hdmi_uninit_platform_driver(); |
597 | dsi_exit(); | 249 | err_hdmi: |
250 | dsi_uninit_platform_driver(); | ||
598 | err_dsi: | 251 | err_dsi: |
599 | if (cpu_is_omap34xx()) | 252 | venc_uninit_platform_driver(); |
600 | sdi_exit(); | ||
601 | err_sdi: | ||
602 | venc_exit(); | ||
603 | err_venc: | 253 | err_venc: |
604 | dispc_exit(); | 254 | dispc_uninit_platform_driver(); |
605 | err_dispc: | 255 | err_dispc: |
606 | dpi_exit(); | 256 | rfbi_uninit_platform_driver(); |
607 | err_dpi: | ||
608 | rfbi_exit(); | ||
609 | err_rfbi: | 257 | err_rfbi: |
610 | dss_exit(); | 258 | dss_uninit_platform_driver(); |
611 | err_dss: | 259 | err_dss: |
612 | dss_clk_disable_all_no_ctx(); | ||
613 | dss_put_clocks(); | ||
614 | err_clocks: | ||
615 | 260 | ||
616 | return r; | 261 | return r; |
617 | } | 262 | } |
@@ -620,61 +265,15 @@ static int omap_dss_remove(struct platform_device *pdev) | |||
620 | { | 265 | { |
621 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | 266 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; |
622 | int i; | 267 | int i; |
623 | int c; | ||
624 | 268 | ||
625 | dss_uninitialize_debugfs(); | 269 | dss_uninitialize_debugfs(); |
626 | 270 | ||
627 | venc_exit(); | 271 | venc_uninit_platform_driver(); |
628 | dispc_exit(); | 272 | dispc_uninit_platform_driver(); |
629 | dpi_exit(); | 273 | rfbi_uninit_platform_driver(); |
630 | rfbi_exit(); | 274 | dsi_uninit_platform_driver(); |
631 | if (cpu_is_omap34xx()) { | 275 | hdmi_uninit_platform_driver(); |
632 | dsi_exit(); | 276 | dss_uninit_platform_driver(); |
633 | sdi_exit(); | ||
634 | } | ||
635 | |||
636 | dss_exit(); | ||
637 | |||
638 | /* these should be removed at some point */ | ||
639 | c = core.dss_ick->usecount; | ||
640 | if (c > 0) { | ||
641 | DSSERR("warning: dss_ick usecount %d, disabling\n", c); | ||
642 | while (c-- > 0) | ||
643 | clk_disable(core.dss_ick); | ||
644 | } | ||
645 | |||
646 | c = core.dss1_fck->usecount; | ||
647 | if (c > 0) { | ||
648 | DSSERR("warning: dss1_fck usecount %d, disabling\n", c); | ||
649 | while (c-- > 0) | ||
650 | clk_disable(core.dss1_fck); | ||
651 | } | ||
652 | |||
653 | c = core.dss2_fck->usecount; | ||
654 | if (c > 0) { | ||
655 | DSSERR("warning: dss2_fck usecount %d, disabling\n", c); | ||
656 | while (c-- > 0) | ||
657 | clk_disable(core.dss2_fck); | ||
658 | } | ||
659 | |||
660 | c = core.dss_54m_fck->usecount; | ||
661 | if (c > 0) { | ||
662 | DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c); | ||
663 | while (c-- > 0) | ||
664 | clk_disable(core.dss_54m_fck); | ||
665 | } | ||
666 | |||
667 | if (core.dss_96m_fck) { | ||
668 | c = core.dss_96m_fck->usecount; | ||
669 | if (c > 0) { | ||
670 | DSSERR("warning: dss_96m_fck usecount %d, disabling\n", | ||
671 | c); | ||
672 | while (c-- > 0) | ||
673 | clk_disable(core.dss_96m_fck); | ||
674 | } | ||
675 | } | ||
676 | |||
677 | dss_put_clocks(); | ||
678 | 277 | ||
679 | dss_uninit_overlays(pdev); | 278 | dss_uninit_overlays(pdev); |
680 | dss_uninit_overlay_managers(pdev); | 279 | dss_uninit_overlay_managers(pdev); |
@@ -882,7 +481,7 @@ static void omap_dss_dev_release(struct device *dev) | |||
882 | reset_device(dev, 0); | 481 | reset_device(dev, 0); |
883 | } | 482 | } |
884 | 483 | ||
885 | int omap_dss_register_device(struct omap_dss_device *dssdev) | 484 | static int omap_dss_register_device(struct omap_dss_device *dssdev) |
886 | { | 485 | { |
887 | static int dev_num; | 486 | static int dev_num; |
888 | 487 | ||
@@ -896,7 +495,7 @@ int omap_dss_register_device(struct omap_dss_device *dssdev) | |||
896 | return device_register(&dssdev->dev); | 495 | return device_register(&dssdev->dev); |
897 | } | 496 | } |
898 | 497 | ||
899 | void omap_dss_unregister_device(struct omap_dss_device *dssdev) | 498 | static void omap_dss_unregister_device(struct omap_dss_device *dssdev) |
900 | { | 499 | { |
901 | device_unregister(&dssdev->dev); | 500 | device_unregister(&dssdev->dev); |
902 | } | 501 | } |
@@ -962,11 +561,6 @@ static void __exit omap_dss_exit(void) | |||
962 | core.vdds_sdi_reg = NULL; | 561 | core.vdds_sdi_reg = NULL; |
963 | } | 562 | } |
964 | 563 | ||
965 | if (core.vdda_dac_reg != NULL) { | ||
966 | regulator_put(core.vdda_dac_reg); | ||
967 | core.vdda_dac_reg = NULL; | ||
968 | } | ||
969 | |||
970 | platform_driver_unregister(&omap_dss_driver); | 564 | platform_driver_unregister(&omap_dss_driver); |
971 | 565 | ||
972 | omap_dss_bus_unregister(); | 566 | omap_dss_bus_unregister(); |
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 5ecdc0004094..7a9a2e7d9685 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c | |||
@@ -32,97 +32,19 @@ | |||
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/workqueue.h> | 33 | #include <linux/workqueue.h> |
34 | #include <linux/hardirq.h> | 34 | #include <linux/hardirq.h> |
35 | #include <linux/interrupt.h> | ||
35 | 36 | ||
36 | #include <plat/sram.h> | 37 | #include <plat/sram.h> |
37 | #include <plat/clock.h> | 38 | #include <plat/clock.h> |
38 | 39 | ||
39 | #include <plat/display.h> | 40 | #include <video/omapdss.h> |
40 | 41 | ||
41 | #include "dss.h" | 42 | #include "dss.h" |
43 | #include "dss_features.h" | ||
44 | #include "dispc.h" | ||
42 | 45 | ||
43 | /* DISPC */ | 46 | /* DISPC */ |
44 | #define DISPC_BASE 0x48050400 | 47 | #define DISPC_SZ_REGS SZ_4K |
45 | |||
46 | #define DISPC_SZ_REGS SZ_1K | ||
47 | |||
48 | struct dispc_reg { u16 idx; }; | ||
49 | |||
50 | #define DISPC_REG(idx) ((const struct dispc_reg) { idx }) | ||
51 | |||
52 | /* DISPC common */ | ||
53 | #define DISPC_REVISION DISPC_REG(0x0000) | ||
54 | #define DISPC_SYSCONFIG DISPC_REG(0x0010) | ||
55 | #define DISPC_SYSSTATUS DISPC_REG(0x0014) | ||
56 | #define DISPC_IRQSTATUS DISPC_REG(0x0018) | ||
57 | #define DISPC_IRQENABLE DISPC_REG(0x001C) | ||
58 | #define DISPC_CONTROL DISPC_REG(0x0040) | ||
59 | #define DISPC_CONFIG DISPC_REG(0x0044) | ||
60 | #define DISPC_CAPABLE DISPC_REG(0x0048) | ||
61 | #define DISPC_DEFAULT_COLOR0 DISPC_REG(0x004C) | ||
62 | #define DISPC_DEFAULT_COLOR1 DISPC_REG(0x0050) | ||
63 | #define DISPC_TRANS_COLOR0 DISPC_REG(0x0054) | ||
64 | #define DISPC_TRANS_COLOR1 DISPC_REG(0x0058) | ||
65 | #define DISPC_LINE_STATUS DISPC_REG(0x005C) | ||
66 | #define DISPC_LINE_NUMBER DISPC_REG(0x0060) | ||
67 | #define DISPC_TIMING_H DISPC_REG(0x0064) | ||
68 | #define DISPC_TIMING_V DISPC_REG(0x0068) | ||
69 | #define DISPC_POL_FREQ DISPC_REG(0x006C) | ||
70 | #define DISPC_DIVISOR DISPC_REG(0x0070) | ||
71 | #define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074) | ||
72 | #define DISPC_SIZE_DIG DISPC_REG(0x0078) | ||
73 | #define DISPC_SIZE_LCD DISPC_REG(0x007C) | ||
74 | |||
75 | /* DISPC GFX plane */ | ||
76 | #define DISPC_GFX_BA0 DISPC_REG(0x0080) | ||
77 | #define DISPC_GFX_BA1 DISPC_REG(0x0084) | ||
78 | #define DISPC_GFX_POSITION DISPC_REG(0x0088) | ||
79 | #define DISPC_GFX_SIZE DISPC_REG(0x008C) | ||
80 | #define DISPC_GFX_ATTRIBUTES DISPC_REG(0x00A0) | ||
81 | #define DISPC_GFX_FIFO_THRESHOLD DISPC_REG(0x00A4) | ||
82 | #define DISPC_GFX_FIFO_SIZE_STATUS DISPC_REG(0x00A8) | ||
83 | #define DISPC_GFX_ROW_INC DISPC_REG(0x00AC) | ||
84 | #define DISPC_GFX_PIXEL_INC DISPC_REG(0x00B0) | ||
85 | #define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4) | ||
86 | #define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8) | ||
87 | |||
88 | #define DISPC_DATA_CYCLE1 DISPC_REG(0x01D4) | ||
89 | #define DISPC_DATA_CYCLE2 DISPC_REG(0x01D8) | ||
90 | #define DISPC_DATA_CYCLE3 DISPC_REG(0x01DC) | ||
91 | |||
92 | #define DISPC_CPR_COEF_R DISPC_REG(0x0220) | ||
93 | #define DISPC_CPR_COEF_G DISPC_REG(0x0224) | ||
94 | #define DISPC_CPR_COEF_B DISPC_REG(0x0228) | ||
95 | |||
96 | #define DISPC_GFX_PRELOAD DISPC_REG(0x022C) | ||
97 | |||
98 | /* DISPC Video plane, n = 0 for VID1 and n = 1 for VID2 */ | ||
99 | #define DISPC_VID_REG(n, idx) DISPC_REG(0x00BC + (n)*0x90 + idx) | ||
100 | |||
101 | #define DISPC_VID_BA0(n) DISPC_VID_REG(n, 0x0000) | ||
102 | #define DISPC_VID_BA1(n) DISPC_VID_REG(n, 0x0004) | ||
103 | #define DISPC_VID_POSITION(n) DISPC_VID_REG(n, 0x0008) | ||
104 | #define DISPC_VID_SIZE(n) DISPC_VID_REG(n, 0x000C) | ||
105 | #define DISPC_VID_ATTRIBUTES(n) DISPC_VID_REG(n, 0x0010) | ||
106 | #define DISPC_VID_FIFO_THRESHOLD(n) DISPC_VID_REG(n, 0x0014) | ||
107 | #define DISPC_VID_FIFO_SIZE_STATUS(n) DISPC_VID_REG(n, 0x0018) | ||
108 | #define DISPC_VID_ROW_INC(n) DISPC_VID_REG(n, 0x001C) | ||
109 | #define DISPC_VID_PIXEL_INC(n) DISPC_VID_REG(n, 0x0020) | ||
110 | #define DISPC_VID_FIR(n) DISPC_VID_REG(n, 0x0024) | ||
111 | #define DISPC_VID_PICTURE_SIZE(n) DISPC_VID_REG(n, 0x0028) | ||
112 | #define DISPC_VID_ACCU0(n) DISPC_VID_REG(n, 0x002C) | ||
113 | #define DISPC_VID_ACCU1(n) DISPC_VID_REG(n, 0x0030) | ||
114 | |||
115 | /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ | ||
116 | #define DISPC_VID_FIR_COEF_H(n, i) DISPC_REG(0x00F0 + (n)*0x90 + (i)*0x8) | ||
117 | /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ | ||
118 | #define DISPC_VID_FIR_COEF_HV(n, i) DISPC_REG(0x00F4 + (n)*0x90 + (i)*0x8) | ||
119 | /* coef index i = {0, 1, 2, 3, 4} */ | ||
120 | #define DISPC_VID_CONV_COEF(n, i) DISPC_REG(0x0130 + (n)*0x90 + (i)*0x4) | ||
121 | /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ | ||
122 | #define DISPC_VID_FIR_COEF_V(n, i) DISPC_REG(0x01E0 + (n)*0x20 + (i)*0x4) | ||
123 | |||
124 | #define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04) | ||
125 | |||
126 | 48 | ||
127 | #define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \ | 49 | #define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \ |
128 | DISPC_IRQ_OCP_ERR | \ | 50 | DISPC_IRQ_OCP_ERR | \ |
@@ -139,16 +61,28 @@ struct omap_dispc_isr_data { | |||
139 | u32 mask; | 61 | u32 mask; |
140 | }; | 62 | }; |
141 | 63 | ||
64 | struct dispc_h_coef { | ||
65 | s8 hc4; | ||
66 | s8 hc3; | ||
67 | u8 hc2; | ||
68 | s8 hc1; | ||
69 | s8 hc0; | ||
70 | }; | ||
71 | |||
72 | struct dispc_v_coef { | ||
73 | s8 vc22; | ||
74 | s8 vc2; | ||
75 | u8 vc1; | ||
76 | s8 vc0; | ||
77 | s8 vc00; | ||
78 | }; | ||
79 | |||
142 | #define REG_GET(idx, start, end) \ | 80 | #define REG_GET(idx, start, end) \ |
143 | FLD_GET(dispc_read_reg(idx), start, end) | 81 | FLD_GET(dispc_read_reg(idx), start, end) |
144 | 82 | ||
145 | #define REG_FLD_MOD(idx, val, start, end) \ | 83 | #define REG_FLD_MOD(idx, val, start, end) \ |
146 | dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end)) | 84 | dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end)) |
147 | 85 | ||
148 | static const struct dispc_reg dispc_reg_att[] = { DISPC_GFX_ATTRIBUTES, | ||
149 | DISPC_VID_ATTRIBUTES(0), | ||
150 | DISPC_VID_ATTRIBUTES(1) }; | ||
151 | |||
152 | struct dispc_irq_stats { | 86 | struct dispc_irq_stats { |
153 | unsigned long last_reset; | 87 | unsigned long last_reset; |
154 | unsigned irq_count; | 88 | unsigned irq_count; |
@@ -156,7 +90,9 @@ struct dispc_irq_stats { | |||
156 | }; | 90 | }; |
157 | 91 | ||
158 | static struct { | 92 | static struct { |
93 | struct platform_device *pdev; | ||
159 | void __iomem *base; | 94 | void __iomem *base; |
95 | int irq; | ||
160 | 96 | ||
161 | u32 fifo_size[3]; | 97 | u32 fifo_size[3]; |
162 | 98 | ||
@@ -174,25 +110,38 @@ static struct { | |||
174 | #endif | 110 | #endif |
175 | } dispc; | 111 | } dispc; |
176 | 112 | ||
113 | enum omap_color_component { | ||
114 | /* used for all color formats for OMAP3 and earlier | ||
115 | * and for RGB and Y color component on OMAP4 | ||
116 | */ | ||
117 | DISPC_COLOR_COMPONENT_RGB_Y = 1 << 0, | ||
118 | /* used for UV component for | ||
119 | * OMAP_DSS_COLOR_YUV2, OMAP_DSS_COLOR_UYVY, OMAP_DSS_COLOR_NV12 | ||
120 | * color formats on OMAP4 | ||
121 | */ | ||
122 | DISPC_COLOR_COMPONENT_UV = 1 << 1, | ||
123 | }; | ||
124 | |||
177 | static void _omap_dispc_set_irqs(void); | 125 | static void _omap_dispc_set_irqs(void); |
178 | 126 | ||
179 | static inline void dispc_write_reg(const struct dispc_reg idx, u32 val) | 127 | static inline void dispc_write_reg(const u16 idx, u32 val) |
180 | { | 128 | { |
181 | __raw_writel(val, dispc.base + idx.idx); | 129 | __raw_writel(val, dispc.base + idx); |
182 | } | 130 | } |
183 | 131 | ||
184 | static inline u32 dispc_read_reg(const struct dispc_reg idx) | 132 | static inline u32 dispc_read_reg(const u16 idx) |
185 | { | 133 | { |
186 | return __raw_readl(dispc.base + idx.idx); | 134 | return __raw_readl(dispc.base + idx); |
187 | } | 135 | } |
188 | 136 | ||
189 | #define SR(reg) \ | 137 | #define SR(reg) \ |
190 | dispc.ctx[(DISPC_##reg).idx / sizeof(u32)] = dispc_read_reg(DISPC_##reg) | 138 | dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg) |
191 | #define RR(reg) \ | 139 | #define RR(reg) \ |
192 | dispc_write_reg(DISPC_##reg, dispc.ctx[(DISPC_##reg).idx / sizeof(u32)]) | 140 | dispc_write_reg(DISPC_##reg, dispc.ctx[DISPC_##reg / sizeof(u32)]) |
193 | 141 | ||
194 | void dispc_save_context(void) | 142 | void dispc_save_context(void) |
195 | { | 143 | { |
144 | int i; | ||
196 | if (cpu_is_omap24xx()) | 145 | if (cpu_is_omap24xx()) |
197 | return; | 146 | return; |
198 | 147 | ||
@@ -200,280 +149,320 @@ void dispc_save_context(void) | |||
200 | SR(IRQENABLE); | 149 | SR(IRQENABLE); |
201 | SR(CONTROL); | 150 | SR(CONTROL); |
202 | SR(CONFIG); | 151 | SR(CONFIG); |
203 | SR(DEFAULT_COLOR0); | 152 | SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD)); |
204 | SR(DEFAULT_COLOR1); | 153 | SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT)); |
205 | SR(TRANS_COLOR0); | 154 | SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD)); |
206 | SR(TRANS_COLOR1); | 155 | SR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT)); |
207 | SR(LINE_NUMBER); | 156 | SR(LINE_NUMBER); |
208 | SR(TIMING_H); | 157 | SR(TIMING_H(OMAP_DSS_CHANNEL_LCD)); |
209 | SR(TIMING_V); | 158 | SR(TIMING_V(OMAP_DSS_CHANNEL_LCD)); |
210 | SR(POL_FREQ); | 159 | SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD)); |
211 | SR(DIVISOR); | 160 | SR(DIVISORo(OMAP_DSS_CHANNEL_LCD)); |
212 | SR(GLOBAL_ALPHA); | 161 | SR(GLOBAL_ALPHA); |
213 | SR(SIZE_DIG); | 162 | SR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); |
214 | SR(SIZE_LCD); | 163 | SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD)); |
215 | 164 | if (dss_has_feature(FEAT_MGR_LCD2)) { | |
216 | SR(GFX_BA0); | 165 | SR(CONTROL2); |
217 | SR(GFX_BA1); | 166 | SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2)); |
218 | SR(GFX_POSITION); | 167 | SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2)); |
219 | SR(GFX_SIZE); | 168 | SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2)); |
220 | SR(GFX_ATTRIBUTES); | 169 | SR(TIMING_H(OMAP_DSS_CHANNEL_LCD2)); |
221 | SR(GFX_FIFO_THRESHOLD); | 170 | SR(TIMING_V(OMAP_DSS_CHANNEL_LCD2)); |
222 | SR(GFX_ROW_INC); | 171 | SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2)); |
223 | SR(GFX_PIXEL_INC); | 172 | SR(DIVISORo(OMAP_DSS_CHANNEL_LCD2)); |
224 | SR(GFX_WINDOW_SKIP); | 173 | SR(CONFIG2); |
225 | SR(GFX_TABLE_BA); | 174 | } |
226 | 175 | ||
227 | SR(DATA_CYCLE1); | 176 | SR(OVL_BA0(OMAP_DSS_GFX)); |
228 | SR(DATA_CYCLE2); | 177 | SR(OVL_BA1(OMAP_DSS_GFX)); |
229 | SR(DATA_CYCLE3); | 178 | SR(OVL_POSITION(OMAP_DSS_GFX)); |
230 | 179 | SR(OVL_SIZE(OMAP_DSS_GFX)); | |
231 | SR(CPR_COEF_R); | 180 | SR(OVL_ATTRIBUTES(OMAP_DSS_GFX)); |
232 | SR(CPR_COEF_G); | 181 | SR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX)); |
233 | SR(CPR_COEF_B); | 182 | SR(OVL_ROW_INC(OMAP_DSS_GFX)); |
234 | 183 | SR(OVL_PIXEL_INC(OMAP_DSS_GFX)); | |
235 | SR(GFX_PRELOAD); | 184 | SR(OVL_WINDOW_SKIP(OMAP_DSS_GFX)); |
185 | SR(OVL_TABLE_BA(OMAP_DSS_GFX)); | ||
186 | |||
187 | SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD)); | ||
188 | SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); | ||
189 | SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); | ||
190 | |||
191 | SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); | ||
192 | SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); | ||
193 | SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); | ||
194 | if (dss_has_feature(FEAT_MGR_LCD2)) { | ||
195 | SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); | ||
196 | SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); | ||
197 | SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); | ||
198 | |||
199 | SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); | ||
200 | SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); | ||
201 | SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); | ||
202 | } | ||
203 | |||
204 | SR(OVL_PRELOAD(OMAP_DSS_GFX)); | ||
236 | 205 | ||
237 | /* VID1 */ | 206 | /* VID1 */ |
238 | SR(VID_BA0(0)); | 207 | SR(OVL_BA0(OMAP_DSS_VIDEO1)); |
239 | SR(VID_BA1(0)); | 208 | SR(OVL_BA1(OMAP_DSS_VIDEO1)); |
240 | SR(VID_POSITION(0)); | 209 | SR(OVL_POSITION(OMAP_DSS_VIDEO1)); |
241 | SR(VID_SIZE(0)); | 210 | SR(OVL_SIZE(OMAP_DSS_VIDEO1)); |
242 | SR(VID_ATTRIBUTES(0)); | 211 | SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1)); |
243 | SR(VID_FIFO_THRESHOLD(0)); | 212 | SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1)); |
244 | SR(VID_ROW_INC(0)); | 213 | SR(OVL_ROW_INC(OMAP_DSS_VIDEO1)); |
245 | SR(VID_PIXEL_INC(0)); | 214 | SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1)); |
246 | SR(VID_FIR(0)); | 215 | SR(OVL_FIR(OMAP_DSS_VIDEO1)); |
247 | SR(VID_PICTURE_SIZE(0)); | 216 | SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1)); |
248 | SR(VID_ACCU0(0)); | 217 | SR(OVL_ACCU0(OMAP_DSS_VIDEO1)); |
249 | SR(VID_ACCU1(0)); | 218 | SR(OVL_ACCU1(OMAP_DSS_VIDEO1)); |
250 | 219 | ||
251 | SR(VID_FIR_COEF_H(0, 0)); | 220 | for (i = 0; i < 8; i++) |
252 | SR(VID_FIR_COEF_H(0, 1)); | 221 | SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i)); |
253 | SR(VID_FIR_COEF_H(0, 2)); | 222 | |
254 | SR(VID_FIR_COEF_H(0, 3)); | 223 | for (i = 0; i < 8; i++) |
255 | SR(VID_FIR_COEF_H(0, 4)); | 224 | SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i)); |
256 | SR(VID_FIR_COEF_H(0, 5)); | 225 | |
257 | SR(VID_FIR_COEF_H(0, 6)); | 226 | for (i = 0; i < 5; i++) |
258 | SR(VID_FIR_COEF_H(0, 7)); | 227 | SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i)); |
259 | 228 | ||
260 | SR(VID_FIR_COEF_HV(0, 0)); | 229 | for (i = 0; i < 8; i++) |
261 | SR(VID_FIR_COEF_HV(0, 1)); | 230 | SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i)); |
262 | SR(VID_FIR_COEF_HV(0, 2)); | 231 | |
263 | SR(VID_FIR_COEF_HV(0, 3)); | 232 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { |
264 | SR(VID_FIR_COEF_HV(0, 4)); | 233 | SR(OVL_BA0_UV(OMAP_DSS_VIDEO1)); |
265 | SR(VID_FIR_COEF_HV(0, 5)); | 234 | SR(OVL_BA1_UV(OMAP_DSS_VIDEO1)); |
266 | SR(VID_FIR_COEF_HV(0, 6)); | 235 | SR(OVL_FIR2(OMAP_DSS_VIDEO1)); |
267 | SR(VID_FIR_COEF_HV(0, 7)); | 236 | SR(OVL_ACCU2_0(OMAP_DSS_VIDEO1)); |
268 | 237 | SR(OVL_ACCU2_1(OMAP_DSS_VIDEO1)); | |
269 | SR(VID_CONV_COEF(0, 0)); | 238 | |
270 | SR(VID_CONV_COEF(0, 1)); | 239 | for (i = 0; i < 8; i++) |
271 | SR(VID_CONV_COEF(0, 2)); | 240 | SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i)); |
272 | SR(VID_CONV_COEF(0, 3)); | 241 | |
273 | SR(VID_CONV_COEF(0, 4)); | 242 | for (i = 0; i < 8; i++) |
274 | 243 | SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i)); | |
275 | SR(VID_FIR_COEF_V(0, 0)); | 244 | |
276 | SR(VID_FIR_COEF_V(0, 1)); | 245 | for (i = 0; i < 8; i++) |
277 | SR(VID_FIR_COEF_V(0, 2)); | 246 | SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i)); |
278 | SR(VID_FIR_COEF_V(0, 3)); | 247 | } |
279 | SR(VID_FIR_COEF_V(0, 4)); | 248 | if (dss_has_feature(FEAT_ATTR2)) |
280 | SR(VID_FIR_COEF_V(0, 5)); | 249 | SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1)); |
281 | SR(VID_FIR_COEF_V(0, 6)); | 250 | |
282 | SR(VID_FIR_COEF_V(0, 7)); | 251 | SR(OVL_PRELOAD(OMAP_DSS_VIDEO1)); |
283 | |||
284 | SR(VID_PRELOAD(0)); | ||
285 | 252 | ||
286 | /* VID2 */ | 253 | /* VID2 */ |
287 | SR(VID_BA0(1)); | 254 | SR(OVL_BA0(OMAP_DSS_VIDEO2)); |
288 | SR(VID_BA1(1)); | 255 | SR(OVL_BA1(OMAP_DSS_VIDEO2)); |
289 | SR(VID_POSITION(1)); | 256 | SR(OVL_POSITION(OMAP_DSS_VIDEO2)); |
290 | SR(VID_SIZE(1)); | 257 | SR(OVL_SIZE(OMAP_DSS_VIDEO2)); |
291 | SR(VID_ATTRIBUTES(1)); | 258 | SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2)); |
292 | SR(VID_FIFO_THRESHOLD(1)); | 259 | SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2)); |
293 | SR(VID_ROW_INC(1)); | 260 | SR(OVL_ROW_INC(OMAP_DSS_VIDEO2)); |
294 | SR(VID_PIXEL_INC(1)); | 261 | SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2)); |
295 | SR(VID_FIR(1)); | 262 | SR(OVL_FIR(OMAP_DSS_VIDEO2)); |
296 | SR(VID_PICTURE_SIZE(1)); | 263 | SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2)); |
297 | SR(VID_ACCU0(1)); | 264 | SR(OVL_ACCU0(OMAP_DSS_VIDEO2)); |
298 | SR(VID_ACCU1(1)); | 265 | SR(OVL_ACCU1(OMAP_DSS_VIDEO2)); |
299 | 266 | ||
300 | SR(VID_FIR_COEF_H(1, 0)); | 267 | for (i = 0; i < 8; i++) |
301 | SR(VID_FIR_COEF_H(1, 1)); | 268 | SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i)); |
302 | SR(VID_FIR_COEF_H(1, 2)); | 269 | |
303 | SR(VID_FIR_COEF_H(1, 3)); | 270 | for (i = 0; i < 8; i++) |
304 | SR(VID_FIR_COEF_H(1, 4)); | 271 | SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i)); |
305 | SR(VID_FIR_COEF_H(1, 5)); | 272 | |
306 | SR(VID_FIR_COEF_H(1, 6)); | 273 | for (i = 0; i < 5; i++) |
307 | SR(VID_FIR_COEF_H(1, 7)); | 274 | SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i)); |
308 | 275 | ||
309 | SR(VID_FIR_COEF_HV(1, 0)); | 276 | for (i = 0; i < 8; i++) |
310 | SR(VID_FIR_COEF_HV(1, 1)); | 277 | SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); |
311 | SR(VID_FIR_COEF_HV(1, 2)); | 278 | |
312 | SR(VID_FIR_COEF_HV(1, 3)); | 279 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { |
313 | SR(VID_FIR_COEF_HV(1, 4)); | 280 | SR(OVL_BA0_UV(OMAP_DSS_VIDEO2)); |
314 | SR(VID_FIR_COEF_HV(1, 5)); | 281 | SR(OVL_BA1_UV(OMAP_DSS_VIDEO2)); |
315 | SR(VID_FIR_COEF_HV(1, 6)); | 282 | SR(OVL_FIR2(OMAP_DSS_VIDEO2)); |
316 | SR(VID_FIR_COEF_HV(1, 7)); | 283 | SR(OVL_ACCU2_0(OMAP_DSS_VIDEO2)); |
317 | 284 | SR(OVL_ACCU2_1(OMAP_DSS_VIDEO2)); | |
318 | SR(VID_CONV_COEF(1, 0)); | 285 | |
319 | SR(VID_CONV_COEF(1, 1)); | 286 | for (i = 0; i < 8; i++) |
320 | SR(VID_CONV_COEF(1, 2)); | 287 | SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i)); |
321 | SR(VID_CONV_COEF(1, 3)); | 288 | |
322 | SR(VID_CONV_COEF(1, 4)); | 289 | for (i = 0; i < 8; i++) |
323 | 290 | SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i)); | |
324 | SR(VID_FIR_COEF_V(1, 0)); | 291 | |
325 | SR(VID_FIR_COEF_V(1, 1)); | 292 | for (i = 0; i < 8; i++) |
326 | SR(VID_FIR_COEF_V(1, 2)); | 293 | SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i)); |
327 | SR(VID_FIR_COEF_V(1, 3)); | 294 | } |
328 | SR(VID_FIR_COEF_V(1, 4)); | 295 | if (dss_has_feature(FEAT_ATTR2)) |
329 | SR(VID_FIR_COEF_V(1, 5)); | 296 | SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); |
330 | SR(VID_FIR_COEF_V(1, 6)); | 297 | |
331 | SR(VID_FIR_COEF_V(1, 7)); | 298 | SR(OVL_PRELOAD(OMAP_DSS_VIDEO2)); |
332 | 299 | ||
333 | SR(VID_PRELOAD(1)); | 300 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) |
301 | SR(DIVISOR); | ||
334 | } | 302 | } |
335 | 303 | ||
336 | void dispc_restore_context(void) | 304 | void dispc_restore_context(void) |
337 | { | 305 | { |
306 | int i; | ||
338 | RR(SYSCONFIG); | 307 | RR(SYSCONFIG); |
339 | /*RR(IRQENABLE);*/ | 308 | /*RR(IRQENABLE);*/ |
340 | /*RR(CONTROL);*/ | 309 | /*RR(CONTROL);*/ |
341 | RR(CONFIG); | 310 | RR(CONFIG); |
342 | RR(DEFAULT_COLOR0); | 311 | RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD)); |
343 | RR(DEFAULT_COLOR1); | 312 | RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT)); |
344 | RR(TRANS_COLOR0); | 313 | RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD)); |
345 | RR(TRANS_COLOR1); | 314 | RR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT)); |
346 | RR(LINE_NUMBER); | 315 | RR(LINE_NUMBER); |
347 | RR(TIMING_H); | 316 | RR(TIMING_H(OMAP_DSS_CHANNEL_LCD)); |
348 | RR(TIMING_V); | 317 | RR(TIMING_V(OMAP_DSS_CHANNEL_LCD)); |
349 | RR(POL_FREQ); | 318 | RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD)); |
350 | RR(DIVISOR); | 319 | RR(DIVISORo(OMAP_DSS_CHANNEL_LCD)); |
351 | RR(GLOBAL_ALPHA); | 320 | RR(GLOBAL_ALPHA); |
352 | RR(SIZE_DIG); | 321 | RR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); |
353 | RR(SIZE_LCD); | 322 | RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD)); |
354 | 323 | if (dss_has_feature(FEAT_MGR_LCD2)) { | |
355 | RR(GFX_BA0); | 324 | RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2)); |
356 | RR(GFX_BA1); | 325 | RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2)); |
357 | RR(GFX_POSITION); | 326 | RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2)); |
358 | RR(GFX_SIZE); | 327 | RR(TIMING_H(OMAP_DSS_CHANNEL_LCD2)); |
359 | RR(GFX_ATTRIBUTES); | 328 | RR(TIMING_V(OMAP_DSS_CHANNEL_LCD2)); |
360 | RR(GFX_FIFO_THRESHOLD); | 329 | RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2)); |
361 | RR(GFX_ROW_INC); | 330 | RR(DIVISORo(OMAP_DSS_CHANNEL_LCD2)); |
362 | RR(GFX_PIXEL_INC); | 331 | RR(CONFIG2); |
363 | RR(GFX_WINDOW_SKIP); | 332 | } |
364 | RR(GFX_TABLE_BA); | 333 | |
365 | 334 | RR(OVL_BA0(OMAP_DSS_GFX)); | |
366 | RR(DATA_CYCLE1); | 335 | RR(OVL_BA1(OMAP_DSS_GFX)); |
367 | RR(DATA_CYCLE2); | 336 | RR(OVL_POSITION(OMAP_DSS_GFX)); |
368 | RR(DATA_CYCLE3); | 337 | RR(OVL_SIZE(OMAP_DSS_GFX)); |
369 | 338 | RR(OVL_ATTRIBUTES(OMAP_DSS_GFX)); | |
370 | RR(CPR_COEF_R); | 339 | RR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX)); |
371 | RR(CPR_COEF_G); | 340 | RR(OVL_ROW_INC(OMAP_DSS_GFX)); |
372 | RR(CPR_COEF_B); | 341 | RR(OVL_PIXEL_INC(OMAP_DSS_GFX)); |
373 | 342 | RR(OVL_WINDOW_SKIP(OMAP_DSS_GFX)); | |
374 | RR(GFX_PRELOAD); | 343 | RR(OVL_TABLE_BA(OMAP_DSS_GFX)); |
344 | |||
345 | |||
346 | RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD)); | ||
347 | RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); | ||
348 | RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); | ||
349 | |||
350 | RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); | ||
351 | RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); | ||
352 | RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); | ||
353 | if (dss_has_feature(FEAT_MGR_LCD2)) { | ||
354 | RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); | ||
355 | RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); | ||
356 | RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); | ||
357 | |||
358 | RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); | ||
359 | RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); | ||
360 | RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); | ||
361 | } | ||
362 | |||
363 | RR(OVL_PRELOAD(OMAP_DSS_GFX)); | ||
375 | 364 | ||
376 | /* VID1 */ | 365 | /* VID1 */ |
377 | RR(VID_BA0(0)); | 366 | RR(OVL_BA0(OMAP_DSS_VIDEO1)); |
378 | RR(VID_BA1(0)); | 367 | RR(OVL_BA1(OMAP_DSS_VIDEO1)); |
379 | RR(VID_POSITION(0)); | 368 | RR(OVL_POSITION(OMAP_DSS_VIDEO1)); |
380 | RR(VID_SIZE(0)); | 369 | RR(OVL_SIZE(OMAP_DSS_VIDEO1)); |
381 | RR(VID_ATTRIBUTES(0)); | 370 | RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1)); |
382 | RR(VID_FIFO_THRESHOLD(0)); | 371 | RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1)); |
383 | RR(VID_ROW_INC(0)); | 372 | RR(OVL_ROW_INC(OMAP_DSS_VIDEO1)); |
384 | RR(VID_PIXEL_INC(0)); | 373 | RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1)); |
385 | RR(VID_FIR(0)); | 374 | RR(OVL_FIR(OMAP_DSS_VIDEO1)); |
386 | RR(VID_PICTURE_SIZE(0)); | 375 | RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1)); |
387 | RR(VID_ACCU0(0)); | 376 | RR(OVL_ACCU0(OMAP_DSS_VIDEO1)); |
388 | RR(VID_ACCU1(0)); | 377 | RR(OVL_ACCU1(OMAP_DSS_VIDEO1)); |
389 | 378 | ||
390 | RR(VID_FIR_COEF_H(0, 0)); | 379 | for (i = 0; i < 8; i++) |
391 | RR(VID_FIR_COEF_H(0, 1)); | 380 | RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i)); |
392 | RR(VID_FIR_COEF_H(0, 2)); | 381 | |
393 | RR(VID_FIR_COEF_H(0, 3)); | 382 | for (i = 0; i < 8; i++) |
394 | RR(VID_FIR_COEF_H(0, 4)); | 383 | RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i)); |
395 | RR(VID_FIR_COEF_H(0, 5)); | 384 | |
396 | RR(VID_FIR_COEF_H(0, 6)); | 385 | for (i = 0; i < 5; i++) |
397 | RR(VID_FIR_COEF_H(0, 7)); | 386 | RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i)); |
398 | 387 | ||
399 | RR(VID_FIR_COEF_HV(0, 0)); | 388 | for (i = 0; i < 8; i++) |
400 | RR(VID_FIR_COEF_HV(0, 1)); | 389 | RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i)); |
401 | RR(VID_FIR_COEF_HV(0, 2)); | 390 | |
402 | RR(VID_FIR_COEF_HV(0, 3)); | 391 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { |
403 | RR(VID_FIR_COEF_HV(0, 4)); | 392 | RR(OVL_BA0_UV(OMAP_DSS_VIDEO1)); |
404 | RR(VID_FIR_COEF_HV(0, 5)); | 393 | RR(OVL_BA1_UV(OMAP_DSS_VIDEO1)); |
405 | RR(VID_FIR_COEF_HV(0, 6)); | 394 | RR(OVL_FIR2(OMAP_DSS_VIDEO1)); |
406 | RR(VID_FIR_COEF_HV(0, 7)); | 395 | RR(OVL_ACCU2_0(OMAP_DSS_VIDEO1)); |
407 | 396 | RR(OVL_ACCU2_1(OMAP_DSS_VIDEO1)); | |
408 | RR(VID_CONV_COEF(0, 0)); | 397 | |
409 | RR(VID_CONV_COEF(0, 1)); | 398 | for (i = 0; i < 8; i++) |
410 | RR(VID_CONV_COEF(0, 2)); | 399 | RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i)); |
411 | RR(VID_CONV_COEF(0, 3)); | 400 | |
412 | RR(VID_CONV_COEF(0, 4)); | 401 | for (i = 0; i < 8; i++) |
413 | 402 | RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i)); | |
414 | RR(VID_FIR_COEF_V(0, 0)); | 403 | |
415 | RR(VID_FIR_COEF_V(0, 1)); | 404 | for (i = 0; i < 8; i++) |
416 | RR(VID_FIR_COEF_V(0, 2)); | 405 | RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i)); |
417 | RR(VID_FIR_COEF_V(0, 3)); | 406 | } |
418 | RR(VID_FIR_COEF_V(0, 4)); | 407 | if (dss_has_feature(FEAT_ATTR2)) |
419 | RR(VID_FIR_COEF_V(0, 5)); | 408 | RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1)); |
420 | RR(VID_FIR_COEF_V(0, 6)); | 409 | |
421 | RR(VID_FIR_COEF_V(0, 7)); | 410 | RR(OVL_PRELOAD(OMAP_DSS_VIDEO1)); |
422 | |||
423 | RR(VID_PRELOAD(0)); | ||
424 | 411 | ||
425 | /* VID2 */ | 412 | /* VID2 */ |
426 | RR(VID_BA0(1)); | 413 | RR(OVL_BA0(OMAP_DSS_VIDEO2)); |
427 | RR(VID_BA1(1)); | 414 | RR(OVL_BA1(OMAP_DSS_VIDEO2)); |
428 | RR(VID_POSITION(1)); | 415 | RR(OVL_POSITION(OMAP_DSS_VIDEO2)); |
429 | RR(VID_SIZE(1)); | 416 | RR(OVL_SIZE(OMAP_DSS_VIDEO2)); |
430 | RR(VID_ATTRIBUTES(1)); | 417 | RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2)); |
431 | RR(VID_FIFO_THRESHOLD(1)); | 418 | RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2)); |
432 | RR(VID_ROW_INC(1)); | 419 | RR(OVL_ROW_INC(OMAP_DSS_VIDEO2)); |
433 | RR(VID_PIXEL_INC(1)); | 420 | RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2)); |
434 | RR(VID_FIR(1)); | 421 | RR(OVL_FIR(OMAP_DSS_VIDEO2)); |
435 | RR(VID_PICTURE_SIZE(1)); | 422 | RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2)); |
436 | RR(VID_ACCU0(1)); | 423 | RR(OVL_ACCU0(OMAP_DSS_VIDEO2)); |
437 | RR(VID_ACCU1(1)); | 424 | RR(OVL_ACCU1(OMAP_DSS_VIDEO2)); |
438 | 425 | ||
439 | RR(VID_FIR_COEF_H(1, 0)); | 426 | for (i = 0; i < 8; i++) |
440 | RR(VID_FIR_COEF_H(1, 1)); | 427 | RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i)); |
441 | RR(VID_FIR_COEF_H(1, 2)); | 428 | |
442 | RR(VID_FIR_COEF_H(1, 3)); | 429 | for (i = 0; i < 8; i++) |
443 | RR(VID_FIR_COEF_H(1, 4)); | 430 | RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i)); |
444 | RR(VID_FIR_COEF_H(1, 5)); | 431 | |
445 | RR(VID_FIR_COEF_H(1, 6)); | 432 | for (i = 0; i < 5; i++) |
446 | RR(VID_FIR_COEF_H(1, 7)); | 433 | RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i)); |
447 | 434 | ||
448 | RR(VID_FIR_COEF_HV(1, 0)); | 435 | for (i = 0; i < 8; i++) |
449 | RR(VID_FIR_COEF_HV(1, 1)); | 436 | RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); |
450 | RR(VID_FIR_COEF_HV(1, 2)); | 437 | |
451 | RR(VID_FIR_COEF_HV(1, 3)); | 438 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { |
452 | RR(VID_FIR_COEF_HV(1, 4)); | 439 | RR(OVL_BA0_UV(OMAP_DSS_VIDEO2)); |
453 | RR(VID_FIR_COEF_HV(1, 5)); | 440 | RR(OVL_BA1_UV(OMAP_DSS_VIDEO2)); |
454 | RR(VID_FIR_COEF_HV(1, 6)); | 441 | RR(OVL_FIR2(OMAP_DSS_VIDEO2)); |
455 | RR(VID_FIR_COEF_HV(1, 7)); | 442 | RR(OVL_ACCU2_0(OMAP_DSS_VIDEO2)); |
456 | 443 | RR(OVL_ACCU2_1(OMAP_DSS_VIDEO2)); | |
457 | RR(VID_CONV_COEF(1, 0)); | 444 | |
458 | RR(VID_CONV_COEF(1, 1)); | 445 | for (i = 0; i < 8; i++) |
459 | RR(VID_CONV_COEF(1, 2)); | 446 | RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i)); |
460 | RR(VID_CONV_COEF(1, 3)); | 447 | |
461 | RR(VID_CONV_COEF(1, 4)); | 448 | for (i = 0; i < 8; i++) |
462 | 449 | RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i)); | |
463 | RR(VID_FIR_COEF_V(1, 0)); | 450 | |
464 | RR(VID_FIR_COEF_V(1, 1)); | 451 | for (i = 0; i < 8; i++) |
465 | RR(VID_FIR_COEF_V(1, 2)); | 452 | RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i)); |
466 | RR(VID_FIR_COEF_V(1, 3)); | 453 | } |
467 | RR(VID_FIR_COEF_V(1, 4)); | 454 | if (dss_has_feature(FEAT_ATTR2)) |
468 | RR(VID_FIR_COEF_V(1, 5)); | 455 | RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); |
469 | RR(VID_FIR_COEF_V(1, 6)); | 456 | |
470 | RR(VID_FIR_COEF_V(1, 7)); | 457 | RR(OVL_PRELOAD(OMAP_DSS_VIDEO2)); |
471 | 458 | ||
472 | RR(VID_PRELOAD(1)); | 459 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) |
460 | RR(DIVISOR); | ||
473 | 461 | ||
474 | /* enable last, because LCD & DIGIT enable are here */ | 462 | /* enable last, because LCD & DIGIT enable are here */ |
475 | RR(CONTROL); | 463 | RR(CONTROL); |
476 | 464 | if (dss_has_feature(FEAT_MGR_LCD2)) | |
465 | RR(CONTROL2); | ||
477 | /* clear spurious SYNC_LOST_DIGIT interrupts */ | 466 | /* clear spurious SYNC_LOST_DIGIT interrupts */ |
478 | dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); | 467 | dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); |
479 | 468 | ||
@@ -490,180 +479,188 @@ void dispc_restore_context(void) | |||
490 | static inline void enable_clocks(bool enable) | 479 | static inline void enable_clocks(bool enable) |
491 | { | 480 | { |
492 | if (enable) | 481 | if (enable) |
493 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 482 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
494 | else | 483 | else |
495 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 484 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
496 | } | 485 | } |
497 | 486 | ||
498 | bool dispc_go_busy(enum omap_channel channel) | 487 | bool dispc_go_busy(enum omap_channel channel) |
499 | { | 488 | { |
500 | int bit; | 489 | int bit; |
501 | 490 | ||
502 | if (channel == OMAP_DSS_CHANNEL_LCD) | 491 | if (channel == OMAP_DSS_CHANNEL_LCD || |
492 | channel == OMAP_DSS_CHANNEL_LCD2) | ||
503 | bit = 5; /* GOLCD */ | 493 | bit = 5; /* GOLCD */ |
504 | else | 494 | else |
505 | bit = 6; /* GODIGIT */ | 495 | bit = 6; /* GODIGIT */ |
506 | 496 | ||
507 | return REG_GET(DISPC_CONTROL, bit, bit) == 1; | 497 | if (channel == OMAP_DSS_CHANNEL_LCD2) |
498 | return REG_GET(DISPC_CONTROL2, bit, bit) == 1; | ||
499 | else | ||
500 | return REG_GET(DISPC_CONTROL, bit, bit) == 1; | ||
508 | } | 501 | } |
509 | 502 | ||
510 | void dispc_go(enum omap_channel channel) | 503 | void dispc_go(enum omap_channel channel) |
511 | { | 504 | { |
512 | int bit; | 505 | int bit; |
506 | bool enable_bit, go_bit; | ||
513 | 507 | ||
514 | enable_clocks(1); | 508 | enable_clocks(1); |
515 | 509 | ||
516 | if (channel == OMAP_DSS_CHANNEL_LCD) | 510 | if (channel == OMAP_DSS_CHANNEL_LCD || |
511 | channel == OMAP_DSS_CHANNEL_LCD2) | ||
517 | bit = 0; /* LCDENABLE */ | 512 | bit = 0; /* LCDENABLE */ |
518 | else | 513 | else |
519 | bit = 1; /* DIGITALENABLE */ | 514 | bit = 1; /* DIGITALENABLE */ |
520 | 515 | ||
521 | /* if the channel is not enabled, we don't need GO */ | 516 | /* if the channel is not enabled, we don't need GO */ |
522 | if (REG_GET(DISPC_CONTROL, bit, bit) == 0) | 517 | if (channel == OMAP_DSS_CHANNEL_LCD2) |
518 | enable_bit = REG_GET(DISPC_CONTROL2, bit, bit) == 1; | ||
519 | else | ||
520 | enable_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1; | ||
521 | |||
522 | if (!enable_bit) | ||
523 | goto end; | 523 | goto end; |
524 | 524 | ||
525 | if (channel == OMAP_DSS_CHANNEL_LCD) | 525 | if (channel == OMAP_DSS_CHANNEL_LCD || |
526 | channel == OMAP_DSS_CHANNEL_LCD2) | ||
526 | bit = 5; /* GOLCD */ | 527 | bit = 5; /* GOLCD */ |
527 | else | 528 | else |
528 | bit = 6; /* GODIGIT */ | 529 | bit = 6; /* GODIGIT */ |
529 | 530 | ||
530 | if (REG_GET(DISPC_CONTROL, bit, bit) == 1) { | 531 | if (channel == OMAP_DSS_CHANNEL_LCD2) |
532 | go_bit = REG_GET(DISPC_CONTROL2, bit, bit) == 1; | ||
533 | else | ||
534 | go_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1; | ||
535 | |||
536 | if (go_bit) { | ||
531 | DSSERR("GO bit not down for channel %d\n", channel); | 537 | DSSERR("GO bit not down for channel %d\n", channel); |
532 | goto end; | 538 | goto end; |
533 | } | 539 | } |
534 | 540 | ||
535 | DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : "DIGIT"); | 541 | DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : |
542 | (channel == OMAP_DSS_CHANNEL_LCD2 ? "LCD2" : "DIGIT")); | ||
536 | 543 | ||
537 | REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); | 544 | if (channel == OMAP_DSS_CHANNEL_LCD2) |
545 | REG_FLD_MOD(DISPC_CONTROL2, 1, bit, bit); | ||
546 | else | ||
547 | REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); | ||
538 | end: | 548 | end: |
539 | enable_clocks(0); | 549 | enable_clocks(0); |
540 | } | 550 | } |
541 | 551 | ||
542 | static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value) | 552 | static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value) |
543 | { | 553 | { |
554 | dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value); | ||
555 | } | ||
556 | |||
557 | static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value) | ||
558 | { | ||
559 | dispc_write_reg(DISPC_OVL_FIR_COEF_HV(plane, reg), value); | ||
560 | } | ||
561 | |||
562 | static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value) | ||
563 | { | ||
564 | dispc_write_reg(DISPC_OVL_FIR_COEF_V(plane, reg), value); | ||
565 | } | ||
566 | |||
567 | static void _dispc_write_firh2_reg(enum omap_plane plane, int reg, u32 value) | ||
568 | { | ||
544 | BUG_ON(plane == OMAP_DSS_GFX); | 569 | BUG_ON(plane == OMAP_DSS_GFX); |
545 | 570 | ||
546 | dispc_write_reg(DISPC_VID_FIR_COEF_H(plane-1, reg), value); | 571 | dispc_write_reg(DISPC_OVL_FIR_COEF_H2(plane, reg), value); |
547 | } | 572 | } |
548 | 573 | ||
549 | static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value) | 574 | static void _dispc_write_firhv2_reg(enum omap_plane plane, int reg, u32 value) |
550 | { | 575 | { |
551 | BUG_ON(plane == OMAP_DSS_GFX); | 576 | BUG_ON(plane == OMAP_DSS_GFX); |
552 | 577 | ||
553 | dispc_write_reg(DISPC_VID_FIR_COEF_HV(plane-1, reg), value); | 578 | dispc_write_reg(DISPC_OVL_FIR_COEF_HV2(plane, reg), value); |
554 | } | 579 | } |
555 | 580 | ||
556 | static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value) | 581 | static void _dispc_write_firv2_reg(enum omap_plane plane, int reg, u32 value) |
557 | { | 582 | { |
558 | BUG_ON(plane == OMAP_DSS_GFX); | 583 | BUG_ON(plane == OMAP_DSS_GFX); |
559 | 584 | ||
560 | dispc_write_reg(DISPC_VID_FIR_COEF_V(plane-1, reg), value); | 585 | dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value); |
561 | } | 586 | } |
562 | 587 | ||
563 | static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, | 588 | static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, |
564 | int vscaleup, int five_taps) | 589 | int vscaleup, int five_taps, |
590 | enum omap_color_component color_comp) | ||
565 | { | 591 | { |
566 | /* Coefficients for horizontal up-sampling */ | 592 | /* Coefficients for horizontal up-sampling */ |
567 | static const u32 coef_hup[8] = { | 593 | static const struct dispc_h_coef coef_hup[8] = { |
568 | 0x00800000, | 594 | { 0, 0, 128, 0, 0 }, |
569 | 0x0D7CF800, | 595 | { -1, 13, 124, -8, 0 }, |
570 | 0x1E70F5FF, | 596 | { -2, 30, 112, -11, -1 }, |
571 | 0x335FF5FE, | 597 | { -5, 51, 95, -11, -2 }, |
572 | 0xF74949F7, | 598 | { 0, -9, 73, 73, -9 }, |
573 | 0xF55F33FB, | 599 | { -2, -11, 95, 51, -5 }, |
574 | 0xF5701EFE, | 600 | { -1, -11, 112, 30, -2 }, |
575 | 0xF87C0DFF, | 601 | { 0, -8, 124, 13, -1 }, |
576 | }; | 602 | }; |
577 | 603 | ||
578 | /* Coefficients for horizontal down-sampling */ | 604 | /* Coefficients for vertical up-sampling */ |
579 | static const u32 coef_hdown[8] = { | 605 | static const struct dispc_v_coef coef_vup_3tap[8] = { |
580 | 0x24382400, | 606 | { 0, 0, 128, 0, 0 }, |
581 | 0x28371FFE, | 607 | { 0, 3, 123, 2, 0 }, |
582 | 0x2C361BFB, | 608 | { 0, 12, 111, 5, 0 }, |
583 | 0x303516F9, | 609 | { 0, 32, 89, 7, 0 }, |
584 | 0x11343311, | 610 | { 0, 0, 64, 64, 0 }, |
585 | 0x1635300C, | 611 | { 0, 7, 89, 32, 0 }, |
586 | 0x1B362C08, | 612 | { 0, 5, 111, 12, 0 }, |
587 | 0x1F372804, | 613 | { 0, 2, 123, 3, 0 }, |
588 | }; | 614 | }; |
589 | 615 | ||
590 | /* Coefficients for horizontal and vertical up-sampling */ | 616 | static const struct dispc_v_coef coef_vup_5tap[8] = { |
591 | static const u32 coef_hvup[2][8] = { | 617 | { 0, 0, 128, 0, 0 }, |
592 | { | 618 | { -1, 13, 124, -8, 0 }, |
593 | 0x00800000, | 619 | { -2, 30, 112, -11, -1 }, |
594 | 0x037B02FF, | 620 | { -5, 51, 95, -11, -2 }, |
595 | 0x0C6F05FE, | 621 | { 0, -9, 73, 73, -9 }, |
596 | 0x205907FB, | 622 | { -2, -11, 95, 51, -5 }, |
597 | 0x00404000, | 623 | { -1, -11, 112, 30, -2 }, |
598 | 0x075920FE, | 624 | { 0, -8, 124, 13, -1 }, |
599 | 0x056F0CFF, | ||
600 | 0x027B0300, | ||
601 | }, | ||
602 | { | ||
603 | 0x00800000, | ||
604 | 0x0D7CF8FF, | ||
605 | 0x1E70F5FE, | ||
606 | 0x335FF5FB, | ||
607 | 0xF7404000, | ||
608 | 0xF55F33FE, | ||
609 | 0xF5701EFF, | ||
610 | 0xF87C0D00, | ||
611 | }, | ||
612 | }; | 625 | }; |
613 | 626 | ||
614 | /* Coefficients for horizontal and vertical down-sampling */ | 627 | /* Coefficients for horizontal down-sampling */ |
615 | static const u32 coef_hvdown[2][8] = { | 628 | static const struct dispc_h_coef coef_hdown[8] = { |
616 | { | 629 | { 0, 36, 56, 36, 0 }, |
617 | 0x24382400, | 630 | { 4, 40, 55, 31, -2 }, |
618 | 0x28391F04, | 631 | { 8, 44, 54, 27, -5 }, |
619 | 0x2D381B08, | 632 | { 12, 48, 53, 22, -7 }, |
620 | 0x3237170C, | 633 | { -9, 17, 52, 51, 17 }, |
621 | 0x123737F7, | 634 | { -7, 22, 53, 48, 12 }, |
622 | 0x173732F9, | 635 | { -5, 27, 54, 44, 8 }, |
623 | 0x1B382DFB, | 636 | { -2, 31, 55, 40, 4 }, |
624 | 0x1F3928FE, | ||
625 | }, | ||
626 | { | ||
627 | 0x24382400, | ||
628 | 0x28371F04, | ||
629 | 0x2C361B08, | ||
630 | 0x3035160C, | ||
631 | 0x113433F7, | ||
632 | 0x163530F9, | ||
633 | 0x1B362CFB, | ||
634 | 0x1F3728FE, | ||
635 | }, | ||
636 | }; | 637 | }; |
637 | 638 | ||
638 | /* Coefficients for vertical up-sampling */ | 639 | /* Coefficients for vertical down-sampling */ |
639 | static const u32 coef_vup[8] = { | 640 | static const struct dispc_v_coef coef_vdown_3tap[8] = { |
640 | 0x00000000, | 641 | { 0, 36, 56, 36, 0 }, |
641 | 0x0000FF00, | 642 | { 0, 40, 57, 31, 0 }, |
642 | 0x0000FEFF, | 643 | { 0, 45, 56, 27, 0 }, |
643 | 0x0000FBFE, | 644 | { 0, 50, 55, 23, 0 }, |
644 | 0x000000F7, | 645 | { 0, 18, 55, 55, 0 }, |
645 | 0x0000FEFB, | 646 | { 0, 23, 55, 50, 0 }, |
646 | 0x0000FFFE, | 647 | { 0, 27, 56, 45, 0 }, |
647 | 0x000000FF, | 648 | { 0, 31, 57, 40, 0 }, |
648 | }; | 649 | }; |
649 | 650 | ||
650 | 651 | static const struct dispc_v_coef coef_vdown_5tap[8] = { | |
651 | /* Coefficients for vertical down-sampling */ | 652 | { 0, 36, 56, 36, 0 }, |
652 | static const u32 coef_vdown[8] = { | 653 | { 4, 40, 55, 31, -2 }, |
653 | 0x00000000, | 654 | { 8, 44, 54, 27, -5 }, |
654 | 0x000004FE, | 655 | { 12, 48, 53, 22, -7 }, |
655 | 0x000008FB, | 656 | { -9, 17, 52, 51, 17 }, |
656 | 0x00000CF9, | 657 | { -7, 22, 53, 48, 12 }, |
657 | 0x0000F711, | 658 | { -5, 27, 54, 44, 8 }, |
658 | 0x0000F90C, | 659 | { -2, 31, 55, 40, 4 }, |
659 | 0x0000FB08, | ||
660 | 0x0000FE04, | ||
661 | }; | 660 | }; |
662 | 661 | ||
663 | const u32 *h_coef; | 662 | const struct dispc_h_coef *h_coef; |
664 | const u32 *hv_coef; | 663 | const struct dispc_v_coef *v_coef; |
665 | const u32 *hv_coef_mod; | ||
666 | const u32 *v_coef; | ||
667 | int i; | 664 | int i; |
668 | 665 | ||
669 | if (hscaleup) | 666 | if (hscaleup) |
@@ -671,47 +668,43 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, | |||
671 | else | 668 | else |
672 | h_coef = coef_hdown; | 669 | h_coef = coef_hdown; |
673 | 670 | ||
674 | if (vscaleup) { | 671 | if (vscaleup) |
675 | hv_coef = coef_hvup[five_taps]; | 672 | v_coef = five_taps ? coef_vup_5tap : coef_vup_3tap; |
676 | v_coef = coef_vup; | 673 | else |
677 | 674 | v_coef = five_taps ? coef_vdown_5tap : coef_vdown_3tap; | |
678 | if (hscaleup) | ||
679 | hv_coef_mod = NULL; | ||
680 | else | ||
681 | hv_coef_mod = coef_hvdown[five_taps]; | ||
682 | } else { | ||
683 | hv_coef = coef_hvdown[five_taps]; | ||
684 | v_coef = coef_vdown; | ||
685 | |||
686 | if (hscaleup) | ||
687 | hv_coef_mod = coef_hvup[five_taps]; | ||
688 | else | ||
689 | hv_coef_mod = NULL; | ||
690 | } | ||
691 | 675 | ||
692 | for (i = 0; i < 8; i++) { | 676 | for (i = 0; i < 8; i++) { |
693 | u32 h, hv; | 677 | u32 h, hv; |
694 | 678 | ||
695 | h = h_coef[i]; | 679 | h = FLD_VAL(h_coef[i].hc0, 7, 0) |
696 | 680 | | FLD_VAL(h_coef[i].hc1, 15, 8) | |
697 | hv = hv_coef[i]; | 681 | | FLD_VAL(h_coef[i].hc2, 23, 16) |
698 | 682 | | FLD_VAL(h_coef[i].hc3, 31, 24); | |
699 | if (hv_coef_mod) { | 683 | hv = FLD_VAL(h_coef[i].hc4, 7, 0) |
700 | hv &= 0xffffff00; | 684 | | FLD_VAL(v_coef[i].vc0, 15, 8) |
701 | hv |= (hv_coef_mod[i] & 0xff); | 685 | | FLD_VAL(v_coef[i].vc1, 23, 16) |
686 | | FLD_VAL(v_coef[i].vc2, 31, 24); | ||
687 | |||
688 | if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) { | ||
689 | _dispc_write_firh_reg(plane, i, h); | ||
690 | _dispc_write_firhv_reg(plane, i, hv); | ||
691 | } else { | ||
692 | _dispc_write_firh2_reg(plane, i, h); | ||
693 | _dispc_write_firhv2_reg(plane, i, hv); | ||
702 | } | 694 | } |
703 | 695 | ||
704 | _dispc_write_firh_reg(plane, i, h); | ||
705 | _dispc_write_firhv_reg(plane, i, hv); | ||
706 | } | 696 | } |
707 | 697 | ||
708 | if (!five_taps) | 698 | if (five_taps) { |
709 | return; | 699 | for (i = 0; i < 8; i++) { |
710 | 700 | u32 v; | |
711 | for (i = 0; i < 8; i++) { | 701 | v = FLD_VAL(v_coef[i].vc00, 7, 0) |
712 | u32 v; | 702 | | FLD_VAL(v_coef[i].vc22, 15, 8); |
713 | v = v_coef[i]; | 703 | if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) |
714 | _dispc_write_firv_reg(plane, i, v); | 704 | _dispc_write_firv_reg(plane, i, v); |
705 | else | ||
706 | _dispc_write_firv2_reg(plane, i, v); | ||
707 | } | ||
715 | } | 708 | } |
716 | } | 709 | } |
717 | 710 | ||
@@ -730,80 +723,104 @@ static void _dispc_setup_color_conv_coef(void) | |||
730 | 723 | ||
731 | ct = &ctbl_bt601_5; | 724 | ct = &ctbl_bt601_5; |
732 | 725 | ||
733 | dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct->rcr, ct->ry)); | 726 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0), |
734 | dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct->gy, ct->rcb)); | 727 | CVAL(ct->rcr, ct->ry)); |
735 | dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct->gcb, ct->gcr)); | 728 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1), |
736 | dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct->bcr, ct->by)); | 729 | CVAL(ct->gy, ct->rcb)); |
737 | dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0, ct->bcb)); | 730 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2), |
738 | 731 | CVAL(ct->gcb, ct->gcr)); | |
739 | dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct->rcr, ct->ry)); | 732 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3), |
740 | dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct->gy, ct->rcb)); | 733 | CVAL(ct->bcr, ct->by)); |
741 | dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct->gcb, ct->gcr)); | 734 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4), |
742 | dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct->bcr, ct->by)); | 735 | CVAL(0, ct->bcb)); |
743 | dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0, ct->bcb)); | 736 | |
737 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0), | ||
738 | CVAL(ct->rcr, ct->ry)); | ||
739 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1), | ||
740 | CVAL(ct->gy, ct->rcb)); | ||
741 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2), | ||
742 | CVAL(ct->gcb, ct->gcr)); | ||
743 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3), | ||
744 | CVAL(ct->bcr, ct->by)); | ||
745 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4), | ||
746 | CVAL(0, ct->bcb)); | ||
744 | 747 | ||
745 | #undef CVAL | 748 | #undef CVAL |
746 | 749 | ||
747 | REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct->full_range, 11, 11); | 750 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1), |
748 | REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct->full_range, 11, 11); | 751 | ct->full_range, 11, 11); |
752 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2), | ||
753 | ct->full_range, 11, 11); | ||
749 | } | 754 | } |
750 | 755 | ||
751 | 756 | ||
752 | static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr) | 757 | static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr) |
753 | { | 758 | { |
754 | const struct dispc_reg ba0_reg[] = { DISPC_GFX_BA0, | 759 | dispc_write_reg(DISPC_OVL_BA0(plane), paddr); |
755 | DISPC_VID_BA0(0), | ||
756 | DISPC_VID_BA0(1) }; | ||
757 | |||
758 | dispc_write_reg(ba0_reg[plane], paddr); | ||
759 | } | 760 | } |
760 | 761 | ||
761 | static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr) | 762 | static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr) |
762 | { | 763 | { |
763 | const struct dispc_reg ba1_reg[] = { DISPC_GFX_BA1, | 764 | dispc_write_reg(DISPC_OVL_BA1(plane), paddr); |
764 | DISPC_VID_BA1(0), | 765 | } |
765 | DISPC_VID_BA1(1) }; | ||
766 | 766 | ||
767 | dispc_write_reg(ba1_reg[plane], paddr); | 767 | static void _dispc_set_plane_ba0_uv(enum omap_plane plane, u32 paddr) |
768 | { | ||
769 | dispc_write_reg(DISPC_OVL_BA0_UV(plane), paddr); | ||
768 | } | 770 | } |
769 | 771 | ||
770 | static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y) | 772 | static void _dispc_set_plane_ba1_uv(enum omap_plane plane, u32 paddr) |
771 | { | 773 | { |
772 | const struct dispc_reg pos_reg[] = { DISPC_GFX_POSITION, | 774 | dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr); |
773 | DISPC_VID_POSITION(0), | 775 | } |
774 | DISPC_VID_POSITION(1) }; | ||
775 | 776 | ||
777 | static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y) | ||
778 | { | ||
776 | u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); | 779 | u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); |
777 | dispc_write_reg(pos_reg[plane], val); | 780 | |
781 | dispc_write_reg(DISPC_OVL_POSITION(plane), val); | ||
778 | } | 782 | } |
779 | 783 | ||
780 | static void _dispc_set_pic_size(enum omap_plane plane, int width, int height) | 784 | static void _dispc_set_pic_size(enum omap_plane plane, int width, int height) |
781 | { | 785 | { |
782 | const struct dispc_reg siz_reg[] = { DISPC_GFX_SIZE, | ||
783 | DISPC_VID_PICTURE_SIZE(0), | ||
784 | DISPC_VID_PICTURE_SIZE(1) }; | ||
785 | u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); | 786 | u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); |
786 | dispc_write_reg(siz_reg[plane], val); | 787 | |
788 | if (plane == OMAP_DSS_GFX) | ||
789 | dispc_write_reg(DISPC_OVL_SIZE(plane), val); | ||
790 | else | ||
791 | dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val); | ||
787 | } | 792 | } |
788 | 793 | ||
789 | static void _dispc_set_vid_size(enum omap_plane plane, int width, int height) | 794 | static void _dispc_set_vid_size(enum omap_plane plane, int width, int height) |
790 | { | 795 | { |
791 | u32 val; | 796 | u32 val; |
792 | const struct dispc_reg vsi_reg[] = { DISPC_VID_SIZE(0), | ||
793 | DISPC_VID_SIZE(1) }; | ||
794 | 797 | ||
795 | BUG_ON(plane == OMAP_DSS_GFX); | 798 | BUG_ON(plane == OMAP_DSS_GFX); |
796 | 799 | ||
797 | val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); | 800 | val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); |
798 | dispc_write_reg(vsi_reg[plane-1], val); | 801 | |
802 | dispc_write_reg(DISPC_OVL_SIZE(plane), val); | ||
799 | } | 803 | } |
800 | 804 | ||
801 | static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha) | 805 | static void _dispc_set_pre_mult_alpha(enum omap_plane plane, bool enable) |
802 | { | 806 | { |
807 | if (!dss_has_feature(FEAT_PRE_MULT_ALPHA)) | ||
808 | return; | ||
803 | 809 | ||
804 | BUG_ON(plane == OMAP_DSS_VIDEO1); | 810 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && |
811 | plane == OMAP_DSS_VIDEO1) | ||
812 | return; | ||
805 | 813 | ||
806 | if (cpu_is_omap24xx()) | 814 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28); |
815 | } | ||
816 | |||
817 | static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha) | ||
818 | { | ||
819 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) | ||
820 | return; | ||
821 | |||
822 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && | ||
823 | plane == OMAP_DSS_VIDEO1) | ||
807 | return; | 824 | return; |
808 | 825 | ||
809 | if (plane == OMAP_DSS_GFX) | 826 | if (plane == OMAP_DSS_GFX) |
@@ -814,61 +831,93 @@ static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha) | |||
814 | 831 | ||
815 | static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc) | 832 | static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc) |
816 | { | 833 | { |
817 | const struct dispc_reg ri_reg[] = { DISPC_GFX_PIXEL_INC, | 834 | dispc_write_reg(DISPC_OVL_PIXEL_INC(plane), inc); |
818 | DISPC_VID_PIXEL_INC(0), | ||
819 | DISPC_VID_PIXEL_INC(1) }; | ||
820 | |||
821 | dispc_write_reg(ri_reg[plane], inc); | ||
822 | } | 835 | } |
823 | 836 | ||
824 | static void _dispc_set_row_inc(enum omap_plane plane, s32 inc) | 837 | static void _dispc_set_row_inc(enum omap_plane plane, s32 inc) |
825 | { | 838 | { |
826 | const struct dispc_reg ri_reg[] = { DISPC_GFX_ROW_INC, | 839 | dispc_write_reg(DISPC_OVL_ROW_INC(plane), inc); |
827 | DISPC_VID_ROW_INC(0), | ||
828 | DISPC_VID_ROW_INC(1) }; | ||
829 | |||
830 | dispc_write_reg(ri_reg[plane], inc); | ||
831 | } | 840 | } |
832 | 841 | ||
833 | static void _dispc_set_color_mode(enum omap_plane plane, | 842 | static void _dispc_set_color_mode(enum omap_plane plane, |
834 | enum omap_color_mode color_mode) | 843 | enum omap_color_mode color_mode) |
835 | { | 844 | { |
836 | u32 m = 0; | 845 | u32 m = 0; |
837 | 846 | if (plane != OMAP_DSS_GFX) { | |
838 | switch (color_mode) { | 847 | switch (color_mode) { |
839 | case OMAP_DSS_COLOR_CLUT1: | 848 | case OMAP_DSS_COLOR_NV12: |
840 | m = 0x0; break; | 849 | m = 0x0; break; |
841 | case OMAP_DSS_COLOR_CLUT2: | 850 | case OMAP_DSS_COLOR_RGB12U: |
842 | m = 0x1; break; | 851 | m = 0x1; break; |
843 | case OMAP_DSS_COLOR_CLUT4: | 852 | case OMAP_DSS_COLOR_RGBA16: |
844 | m = 0x2; break; | 853 | m = 0x2; break; |
845 | case OMAP_DSS_COLOR_CLUT8: | 854 | case OMAP_DSS_COLOR_RGBX16: |
846 | m = 0x3; break; | 855 | m = 0x4; break; |
847 | case OMAP_DSS_COLOR_RGB12U: | 856 | case OMAP_DSS_COLOR_ARGB16: |
848 | m = 0x4; break; | 857 | m = 0x5; break; |
849 | case OMAP_DSS_COLOR_ARGB16: | 858 | case OMAP_DSS_COLOR_RGB16: |
850 | m = 0x5; break; | 859 | m = 0x6; break; |
851 | case OMAP_DSS_COLOR_RGB16: | 860 | case OMAP_DSS_COLOR_ARGB16_1555: |
852 | m = 0x6; break; | 861 | m = 0x7; break; |
853 | case OMAP_DSS_COLOR_RGB24U: | 862 | case OMAP_DSS_COLOR_RGB24U: |
854 | m = 0x8; break; | 863 | m = 0x8; break; |
855 | case OMAP_DSS_COLOR_RGB24P: | 864 | case OMAP_DSS_COLOR_RGB24P: |
856 | m = 0x9; break; | 865 | m = 0x9; break; |
857 | case OMAP_DSS_COLOR_YUV2: | 866 | case OMAP_DSS_COLOR_YUV2: |
858 | m = 0xa; break; | 867 | m = 0xa; break; |
859 | case OMAP_DSS_COLOR_UYVY: | 868 | case OMAP_DSS_COLOR_UYVY: |
860 | m = 0xb; break; | 869 | m = 0xb; break; |
861 | case OMAP_DSS_COLOR_ARGB32: | 870 | case OMAP_DSS_COLOR_ARGB32: |
862 | m = 0xc; break; | 871 | m = 0xc; break; |
863 | case OMAP_DSS_COLOR_RGBA32: | 872 | case OMAP_DSS_COLOR_RGBA32: |
864 | m = 0xd; break; | 873 | m = 0xd; break; |
865 | case OMAP_DSS_COLOR_RGBX32: | 874 | case OMAP_DSS_COLOR_RGBX32: |
866 | m = 0xe; break; | 875 | m = 0xe; break; |
867 | default: | 876 | case OMAP_DSS_COLOR_XRGB16_1555: |
868 | BUG(); break; | 877 | m = 0xf; break; |
878 | default: | ||
879 | BUG(); break; | ||
880 | } | ||
881 | } else { | ||
882 | switch (color_mode) { | ||
883 | case OMAP_DSS_COLOR_CLUT1: | ||
884 | m = 0x0; break; | ||
885 | case OMAP_DSS_COLOR_CLUT2: | ||
886 | m = 0x1; break; | ||
887 | case OMAP_DSS_COLOR_CLUT4: | ||
888 | m = 0x2; break; | ||
889 | case OMAP_DSS_COLOR_CLUT8: | ||
890 | m = 0x3; break; | ||
891 | case OMAP_DSS_COLOR_RGB12U: | ||
892 | m = 0x4; break; | ||
893 | case OMAP_DSS_COLOR_ARGB16: | ||
894 | m = 0x5; break; | ||
895 | case OMAP_DSS_COLOR_RGB16: | ||
896 | m = 0x6; break; | ||
897 | case OMAP_DSS_COLOR_ARGB16_1555: | ||
898 | m = 0x7; break; | ||
899 | case OMAP_DSS_COLOR_RGB24U: | ||
900 | m = 0x8; break; | ||
901 | case OMAP_DSS_COLOR_RGB24P: | ||
902 | m = 0x9; break; | ||
903 | case OMAP_DSS_COLOR_YUV2: | ||
904 | m = 0xa; break; | ||
905 | case OMAP_DSS_COLOR_UYVY: | ||
906 | m = 0xb; break; | ||
907 | case OMAP_DSS_COLOR_ARGB32: | ||
908 | m = 0xc; break; | ||
909 | case OMAP_DSS_COLOR_RGBA32: | ||
910 | m = 0xd; break; | ||
911 | case OMAP_DSS_COLOR_RGBX32: | ||
912 | m = 0xe; break; | ||
913 | case OMAP_DSS_COLOR_XRGB16_1555: | ||
914 | m = 0xf; break; | ||
915 | default: | ||
916 | BUG(); break; | ||
917 | } | ||
869 | } | 918 | } |
870 | 919 | ||
871 | REG_FLD_MOD(dispc_reg_att[plane], m, 4, 1); | 920 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); |
872 | } | 921 | } |
873 | 922 | ||
874 | static void _dispc_set_channel_out(enum omap_plane plane, | 923 | static void _dispc_set_channel_out(enum omap_plane plane, |
@@ -876,6 +925,7 @@ static void _dispc_set_channel_out(enum omap_plane plane, | |||
876 | { | 925 | { |
877 | int shift; | 926 | int shift; |
878 | u32 val; | 927 | u32 val; |
928 | int chan = 0, chan2 = 0; | ||
879 | 929 | ||
880 | switch (plane) { | 930 | switch (plane) { |
881 | case OMAP_DSS_GFX: | 931 | case OMAP_DSS_GFX: |
@@ -890,9 +940,31 @@ static void _dispc_set_channel_out(enum omap_plane plane, | |||
890 | return; | 940 | return; |
891 | } | 941 | } |
892 | 942 | ||
893 | val = dispc_read_reg(dispc_reg_att[plane]); | 943 | val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); |
894 | val = FLD_MOD(val, channel, shift, shift); | 944 | if (dss_has_feature(FEAT_MGR_LCD2)) { |
895 | dispc_write_reg(dispc_reg_att[plane], val); | 945 | switch (channel) { |
946 | case OMAP_DSS_CHANNEL_LCD: | ||
947 | chan = 0; | ||
948 | chan2 = 0; | ||
949 | break; | ||
950 | case OMAP_DSS_CHANNEL_DIGIT: | ||
951 | chan = 1; | ||
952 | chan2 = 0; | ||
953 | break; | ||
954 | case OMAP_DSS_CHANNEL_LCD2: | ||
955 | chan = 0; | ||
956 | chan2 = 1; | ||
957 | break; | ||
958 | default: | ||
959 | BUG(); | ||
960 | } | ||
961 | |||
962 | val = FLD_MOD(val, chan, shift, shift); | ||
963 | val = FLD_MOD(val, chan2, 31, 30); | ||
964 | } else { | ||
965 | val = FLD_MOD(val, channel, shift, shift); | ||
966 | } | ||
967 | dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); | ||
896 | } | 968 | } |
897 | 969 | ||
898 | void dispc_set_burst_size(enum omap_plane plane, | 970 | void dispc_set_burst_size(enum omap_plane plane, |
@@ -916,22 +988,36 @@ void dispc_set_burst_size(enum omap_plane plane, | |||
916 | return; | 988 | return; |
917 | } | 989 | } |
918 | 990 | ||
919 | val = dispc_read_reg(dispc_reg_att[plane]); | 991 | val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); |
920 | val = FLD_MOD(val, burst_size, shift+1, shift); | 992 | val = FLD_MOD(val, burst_size, shift+1, shift); |
921 | dispc_write_reg(dispc_reg_att[plane], val); | 993 | dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); |
922 | 994 | ||
923 | enable_clocks(0); | 995 | enable_clocks(0); |
924 | } | 996 | } |
925 | 997 | ||
998 | void dispc_enable_gamma_table(bool enable) | ||
999 | { | ||
1000 | /* | ||
1001 | * This is partially implemented to support only disabling of | ||
1002 | * the gamma table. | ||
1003 | */ | ||
1004 | if (enable) { | ||
1005 | DSSWARN("Gamma table enabling for TV not yet supported"); | ||
1006 | return; | ||
1007 | } | ||
1008 | |||
1009 | REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9); | ||
1010 | } | ||
1011 | |||
926 | static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) | 1012 | static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) |
927 | { | 1013 | { |
928 | u32 val; | 1014 | u32 val; |
929 | 1015 | ||
930 | BUG_ON(plane == OMAP_DSS_GFX); | 1016 | BUG_ON(plane == OMAP_DSS_GFX); |
931 | 1017 | ||
932 | val = dispc_read_reg(dispc_reg_att[plane]); | 1018 | val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); |
933 | val = FLD_MOD(val, enable, 9, 9); | 1019 | val = FLD_MOD(val, enable, 9, 9); |
934 | dispc_write_reg(dispc_reg_att[plane], val); | 1020 | dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); |
935 | } | 1021 | } |
936 | 1022 | ||
937 | void dispc_enable_replication(enum omap_plane plane, bool enable) | 1023 | void dispc_enable_replication(enum omap_plane plane, bool enable) |
@@ -944,17 +1030,17 @@ void dispc_enable_replication(enum omap_plane plane, bool enable) | |||
944 | bit = 10; | 1030 | bit = 10; |
945 | 1031 | ||
946 | enable_clocks(1); | 1032 | enable_clocks(1); |
947 | REG_FLD_MOD(dispc_reg_att[plane], enable, bit, bit); | 1033 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit); |
948 | enable_clocks(0); | 1034 | enable_clocks(0); |
949 | } | 1035 | } |
950 | 1036 | ||
951 | void dispc_set_lcd_size(u16 width, u16 height) | 1037 | void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height) |
952 | { | 1038 | { |
953 | u32 val; | 1039 | u32 val; |
954 | BUG_ON((width > (1 << 11)) || (height > (1 << 11))); | 1040 | BUG_ON((width > (1 << 11)) || (height > (1 << 11))); |
955 | val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); | 1041 | val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); |
956 | enable_clocks(1); | 1042 | enable_clocks(1); |
957 | dispc_write_reg(DISPC_SIZE_LCD, val); | 1043 | dispc_write_reg(DISPC_SIZE_MGR(channel), val); |
958 | enable_clocks(0); | 1044 | enable_clocks(0); |
959 | } | 1045 | } |
960 | 1046 | ||
@@ -964,28 +1050,23 @@ void dispc_set_digit_size(u16 width, u16 height) | |||
964 | BUG_ON((width > (1 << 11)) || (height > (1 << 11))); | 1050 | BUG_ON((width > (1 << 11)) || (height > (1 << 11))); |
965 | val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); | 1051 | val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); |
966 | enable_clocks(1); | 1052 | enable_clocks(1); |
967 | dispc_write_reg(DISPC_SIZE_DIG, val); | 1053 | dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val); |
968 | enable_clocks(0); | 1054 | enable_clocks(0); |
969 | } | 1055 | } |
970 | 1056 | ||
971 | static void dispc_read_plane_fifo_sizes(void) | 1057 | static void dispc_read_plane_fifo_sizes(void) |
972 | { | 1058 | { |
973 | const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS, | ||
974 | DISPC_VID_FIFO_SIZE_STATUS(0), | ||
975 | DISPC_VID_FIFO_SIZE_STATUS(1) }; | ||
976 | u32 size; | 1059 | u32 size; |
977 | int plane; | 1060 | int plane; |
1061 | u8 start, end; | ||
978 | 1062 | ||
979 | enable_clocks(1); | 1063 | enable_clocks(1); |
980 | 1064 | ||
981 | for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) { | 1065 | dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); |
982 | if (cpu_is_omap24xx()) | ||
983 | size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0); | ||
984 | else if (cpu_is_omap34xx()) | ||
985 | size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0); | ||
986 | else | ||
987 | BUG(); | ||
988 | 1066 | ||
1067 | for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) { | ||
1068 | size = FLD_GET(dispc_read_reg(DISPC_OVL_FIFO_SIZE_STATUS(plane)), | ||
1069 | start, end); | ||
989 | dispc.fifo_size[plane] = size; | 1070 | dispc.fifo_size[plane] = size; |
990 | } | 1071 | } |
991 | 1072 | ||
@@ -999,23 +1080,24 @@ u32 dispc_get_plane_fifo_size(enum omap_plane plane) | |||
999 | 1080 | ||
1000 | void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high) | 1081 | void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high) |
1001 | { | 1082 | { |
1002 | const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD, | 1083 | u8 hi_start, hi_end, lo_start, lo_end; |
1003 | DISPC_VID_FIFO_THRESHOLD(0), | 1084 | |
1004 | DISPC_VID_FIFO_THRESHOLD(1) }; | 1085 | dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end); |
1086 | dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end); | ||
1087 | |||
1005 | enable_clocks(1); | 1088 | enable_clocks(1); |
1006 | 1089 | ||
1007 | DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n", | 1090 | DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n", |
1008 | plane, | 1091 | plane, |
1009 | REG_GET(ftrs_reg[plane], 11, 0), | 1092 | REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane), |
1010 | REG_GET(ftrs_reg[plane], 27, 16), | 1093 | lo_start, lo_end), |
1094 | REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane), | ||
1095 | hi_start, hi_end), | ||
1011 | low, high); | 1096 | low, high); |
1012 | 1097 | ||
1013 | if (cpu_is_omap24xx()) | 1098 | dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane), |
1014 | dispc_write_reg(ftrs_reg[plane], | 1099 | FLD_VAL(high, hi_start, hi_end) | |
1015 | FLD_VAL(high, 24, 16) | FLD_VAL(low, 8, 0)); | 1100 | FLD_VAL(low, lo_start, lo_end)); |
1016 | else | ||
1017 | dispc_write_reg(ftrs_reg[plane], | ||
1018 | FLD_VAL(high, 27, 16) | FLD_VAL(low, 11, 0)); | ||
1019 | 1101 | ||
1020 | enable_clocks(0); | 1102 | enable_clocks(0); |
1021 | } | 1103 | } |
@@ -1030,91 +1112,129 @@ void dispc_enable_fifomerge(bool enable) | |||
1030 | enable_clocks(0); | 1112 | enable_clocks(0); |
1031 | } | 1113 | } |
1032 | 1114 | ||
1033 | static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc) | 1115 | static void _dispc_set_fir(enum omap_plane plane, |
1116 | int hinc, int vinc, | ||
1117 | enum omap_color_component color_comp) | ||
1034 | { | 1118 | { |
1035 | u32 val; | 1119 | u32 val; |
1036 | const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0), | ||
1037 | DISPC_VID_FIR(1) }; | ||
1038 | 1120 | ||
1039 | BUG_ON(plane == OMAP_DSS_GFX); | 1121 | if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) { |
1122 | u8 hinc_start, hinc_end, vinc_start, vinc_end; | ||
1040 | 1123 | ||
1041 | if (cpu_is_omap24xx()) | 1124 | dss_feat_get_reg_field(FEAT_REG_FIRHINC, |
1042 | val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0); | 1125 | &hinc_start, &hinc_end); |
1043 | else | 1126 | dss_feat_get_reg_field(FEAT_REG_FIRVINC, |
1127 | &vinc_start, &vinc_end); | ||
1128 | val = FLD_VAL(vinc, vinc_start, vinc_end) | | ||
1129 | FLD_VAL(hinc, hinc_start, hinc_end); | ||
1130 | |||
1131 | dispc_write_reg(DISPC_OVL_FIR(plane), val); | ||
1132 | } else { | ||
1044 | val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0); | 1133 | val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0); |
1045 | dispc_write_reg(fir_reg[plane-1], val); | 1134 | dispc_write_reg(DISPC_OVL_FIR2(plane), val); |
1135 | } | ||
1046 | } | 1136 | } |
1047 | 1137 | ||
1048 | static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) | 1138 | static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) |
1049 | { | 1139 | { |
1050 | u32 val; | 1140 | u32 val; |
1051 | const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0), | 1141 | u8 hor_start, hor_end, vert_start, vert_end; |
1052 | DISPC_VID_ACCU0(1) }; | ||
1053 | 1142 | ||
1054 | BUG_ON(plane == OMAP_DSS_GFX); | 1143 | dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); |
1144 | dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); | ||
1145 | |||
1146 | val = FLD_VAL(vaccu, vert_start, vert_end) | | ||
1147 | FLD_VAL(haccu, hor_start, hor_end); | ||
1055 | 1148 | ||
1056 | val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0); | 1149 | dispc_write_reg(DISPC_OVL_ACCU0(plane), val); |
1057 | dispc_write_reg(ac0_reg[plane-1], val); | ||
1058 | } | 1150 | } |
1059 | 1151 | ||
1060 | static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) | 1152 | static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) |
1061 | { | 1153 | { |
1062 | u32 val; | 1154 | u32 val; |
1063 | const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0), | 1155 | u8 hor_start, hor_end, vert_start, vert_end; |
1064 | DISPC_VID_ACCU1(1) }; | ||
1065 | 1156 | ||
1066 | BUG_ON(plane == OMAP_DSS_GFX); | 1157 | dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); |
1158 | dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); | ||
1159 | |||
1160 | val = FLD_VAL(vaccu, vert_start, vert_end) | | ||
1161 | FLD_VAL(haccu, hor_start, hor_end); | ||
1067 | 1162 | ||
1068 | val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0); | 1163 | dispc_write_reg(DISPC_OVL_ACCU1(plane), val); |
1069 | dispc_write_reg(ac1_reg[plane-1], val); | ||
1070 | } | 1164 | } |
1071 | 1165 | ||
1166 | static void _dispc_set_vid_accu2_0(enum omap_plane plane, int haccu, int vaccu) | ||
1167 | { | ||
1168 | u32 val; | ||
1072 | 1169 | ||
1073 | static void _dispc_set_scaling(enum omap_plane plane, | 1170 | val = FLD_VAL(vaccu, 26, 16) | FLD_VAL(haccu, 10, 0); |
1171 | dispc_write_reg(DISPC_OVL_ACCU2_0(plane), val); | ||
1172 | } | ||
1173 | |||
1174 | static void _dispc_set_vid_accu2_1(enum omap_plane plane, int haccu, int vaccu) | ||
1175 | { | ||
1176 | u32 val; | ||
1177 | |||
1178 | val = FLD_VAL(vaccu, 26, 16) | FLD_VAL(haccu, 10, 0); | ||
1179 | dispc_write_reg(DISPC_OVL_ACCU2_1(plane), val); | ||
1180 | } | ||
1181 | |||
1182 | static void _dispc_set_scale_param(enum omap_plane plane, | ||
1074 | u16 orig_width, u16 orig_height, | 1183 | u16 orig_width, u16 orig_height, |
1075 | u16 out_width, u16 out_height, | 1184 | u16 out_width, u16 out_height, |
1076 | bool ilace, bool five_taps, | 1185 | bool five_taps, u8 rotation, |
1077 | bool fieldmode) | 1186 | enum omap_color_component color_comp) |
1078 | { | 1187 | { |
1079 | int fir_hinc; | 1188 | int fir_hinc, fir_vinc; |
1080 | int fir_vinc; | ||
1081 | int hscaleup, vscaleup; | 1189 | int hscaleup, vscaleup; |
1082 | int accu0 = 0; | ||
1083 | int accu1 = 0; | ||
1084 | u32 l; | ||
1085 | |||
1086 | BUG_ON(plane == OMAP_DSS_GFX); | ||
1087 | 1190 | ||
1088 | hscaleup = orig_width <= out_width; | 1191 | hscaleup = orig_width <= out_width; |
1089 | vscaleup = orig_height <= out_height; | 1192 | vscaleup = orig_height <= out_height; |
1090 | 1193 | ||
1091 | _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps); | 1194 | _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps, color_comp); |
1092 | 1195 | ||
1093 | if (!orig_width || orig_width == out_width) | 1196 | fir_hinc = 1024 * orig_width / out_width; |
1094 | fir_hinc = 0; | 1197 | fir_vinc = 1024 * orig_height / out_height; |
1095 | else | ||
1096 | fir_hinc = 1024 * orig_width / out_width; | ||
1097 | 1198 | ||
1098 | if (!orig_height || orig_height == out_height) | 1199 | _dispc_set_fir(plane, fir_hinc, fir_vinc, color_comp); |
1099 | fir_vinc = 0; | 1200 | } |
1100 | else | ||
1101 | fir_vinc = 1024 * orig_height / out_height; | ||
1102 | 1201 | ||
1103 | _dispc_set_fir(plane, fir_hinc, fir_vinc); | 1202 | static void _dispc_set_scaling_common(enum omap_plane plane, |
1203 | u16 orig_width, u16 orig_height, | ||
1204 | u16 out_width, u16 out_height, | ||
1205 | bool ilace, bool five_taps, | ||
1206 | bool fieldmode, enum omap_color_mode color_mode, | ||
1207 | u8 rotation) | ||
1208 | { | ||
1209 | int accu0 = 0; | ||
1210 | int accu1 = 0; | ||
1211 | u32 l; | ||
1104 | 1212 | ||
1105 | l = dispc_read_reg(dispc_reg_att[plane]); | 1213 | _dispc_set_scale_param(plane, orig_width, orig_height, |
1106 | l &= ~((0x0f << 5) | (0x3 << 21)); | 1214 | out_width, out_height, five_taps, |
1215 | rotation, DISPC_COLOR_COMPONENT_RGB_Y); | ||
1216 | l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); | ||
1107 | 1217 | ||
1108 | l |= fir_hinc ? (1 << 5) : 0; | 1218 | /* RESIZEENABLE and VERTICALTAPS */ |
1109 | l |= fir_vinc ? (1 << 6) : 0; | 1219 | l &= ~((0x3 << 5) | (0x1 << 21)); |
1220 | l |= (orig_width != out_width) ? (1 << 5) : 0; | ||
1221 | l |= (orig_height != out_height) ? (1 << 6) : 0; | ||
1222 | l |= five_taps ? (1 << 21) : 0; | ||
1110 | 1223 | ||
1111 | l |= hscaleup ? 0 : (1 << 7); | 1224 | /* VRESIZECONF and HRESIZECONF */ |
1112 | l |= vscaleup ? 0 : (1 << 8); | 1225 | if (dss_has_feature(FEAT_RESIZECONF)) { |
1226 | l &= ~(0x3 << 7); | ||
1227 | l |= (orig_width <= out_width) ? 0 : (1 << 7); | ||
1228 | l |= (orig_height <= out_height) ? 0 : (1 << 8); | ||
1229 | } | ||
1113 | 1230 | ||
1114 | l |= five_taps ? (1 << 21) : 0; | 1231 | /* LINEBUFFERSPLIT */ |
1115 | l |= five_taps ? (1 << 22) : 0; | 1232 | if (dss_has_feature(FEAT_LINEBUFFERSPLIT)) { |
1233 | l &= ~(0x1 << 22); | ||
1234 | l |= five_taps ? (1 << 22) : 0; | ||
1235 | } | ||
1116 | 1236 | ||
1117 | dispc_write_reg(dispc_reg_att[plane], l); | 1237 | dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), l); |
1118 | 1238 | ||
1119 | /* | 1239 | /* |
1120 | * field 0 = even field = bottom field | 1240 | * field 0 = even field = bottom field |
@@ -1122,7 +1242,7 @@ static void _dispc_set_scaling(enum omap_plane plane, | |||
1122 | */ | 1242 | */ |
1123 | if (ilace && !fieldmode) { | 1243 | if (ilace && !fieldmode) { |
1124 | accu1 = 0; | 1244 | accu1 = 0; |
1125 | accu0 = (fir_vinc / 2) & 0x3ff; | 1245 | accu0 = ((1024 * orig_height / out_height) / 2) & 0x3ff; |
1126 | if (accu0 >= 1024/2) { | 1246 | if (accu0 >= 1024/2) { |
1127 | accu1 = 1024/2; | 1247 | accu1 = 1024/2; |
1128 | accu0 -= accu1; | 1248 | accu0 -= accu1; |
@@ -1133,12 +1253,101 @@ static void _dispc_set_scaling(enum omap_plane plane, | |||
1133 | _dispc_set_vid_accu1(plane, 0, accu1); | 1253 | _dispc_set_vid_accu1(plane, 0, accu1); |
1134 | } | 1254 | } |
1135 | 1255 | ||
1256 | static void _dispc_set_scaling_uv(enum omap_plane plane, | ||
1257 | u16 orig_width, u16 orig_height, | ||
1258 | u16 out_width, u16 out_height, | ||
1259 | bool ilace, bool five_taps, | ||
1260 | bool fieldmode, enum omap_color_mode color_mode, | ||
1261 | u8 rotation) | ||
1262 | { | ||
1263 | int scale_x = out_width != orig_width; | ||
1264 | int scale_y = out_height != orig_height; | ||
1265 | |||
1266 | if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) | ||
1267 | return; | ||
1268 | if ((color_mode != OMAP_DSS_COLOR_YUV2 && | ||
1269 | color_mode != OMAP_DSS_COLOR_UYVY && | ||
1270 | color_mode != OMAP_DSS_COLOR_NV12)) { | ||
1271 | /* reset chroma resampling for RGB formats */ | ||
1272 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8); | ||
1273 | return; | ||
1274 | } | ||
1275 | switch (color_mode) { | ||
1276 | case OMAP_DSS_COLOR_NV12: | ||
1277 | /* UV is subsampled by 2 vertically*/ | ||
1278 | orig_height >>= 1; | ||
1279 | /* UV is subsampled by 2 horz.*/ | ||
1280 | orig_width >>= 1; | ||
1281 | break; | ||
1282 | case OMAP_DSS_COLOR_YUV2: | ||
1283 | case OMAP_DSS_COLOR_UYVY: | ||
1284 | /*For YUV422 with 90/270 rotation, | ||
1285 | *we don't upsample chroma | ||
1286 | */ | ||
1287 | if (rotation == OMAP_DSS_ROT_0 || | ||
1288 | rotation == OMAP_DSS_ROT_180) | ||
1289 | /* UV is subsampled by 2 hrz*/ | ||
1290 | orig_width >>= 1; | ||
1291 | /* must use FIR for YUV422 if rotated */ | ||
1292 | if (rotation != OMAP_DSS_ROT_0) | ||
1293 | scale_x = scale_y = true; | ||
1294 | break; | ||
1295 | default: | ||
1296 | BUG(); | ||
1297 | } | ||
1298 | |||
1299 | if (out_width != orig_width) | ||
1300 | scale_x = true; | ||
1301 | if (out_height != orig_height) | ||
1302 | scale_y = true; | ||
1303 | |||
1304 | _dispc_set_scale_param(plane, orig_width, orig_height, | ||
1305 | out_width, out_height, five_taps, | ||
1306 | rotation, DISPC_COLOR_COMPONENT_UV); | ||
1307 | |||
1308 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), | ||
1309 | (scale_x || scale_y) ? 1 : 0, 8, 8); | ||
1310 | /* set H scaling */ | ||
1311 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5); | ||
1312 | /* set V scaling */ | ||
1313 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6); | ||
1314 | |||
1315 | _dispc_set_vid_accu2_0(plane, 0x80, 0); | ||
1316 | _dispc_set_vid_accu2_1(plane, 0x80, 0); | ||
1317 | } | ||
1318 | |||
1319 | static void _dispc_set_scaling(enum omap_plane plane, | ||
1320 | u16 orig_width, u16 orig_height, | ||
1321 | u16 out_width, u16 out_height, | ||
1322 | bool ilace, bool five_taps, | ||
1323 | bool fieldmode, enum omap_color_mode color_mode, | ||
1324 | u8 rotation) | ||
1325 | { | ||
1326 | BUG_ON(plane == OMAP_DSS_GFX); | ||
1327 | |||
1328 | _dispc_set_scaling_common(plane, | ||
1329 | orig_width, orig_height, | ||
1330 | out_width, out_height, | ||
1331 | ilace, five_taps, | ||
1332 | fieldmode, color_mode, | ||
1333 | rotation); | ||
1334 | |||
1335 | _dispc_set_scaling_uv(plane, | ||
1336 | orig_width, orig_height, | ||
1337 | out_width, out_height, | ||
1338 | ilace, five_taps, | ||
1339 | fieldmode, color_mode, | ||
1340 | rotation); | ||
1341 | } | ||
1342 | |||
1136 | static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, | 1343 | static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, |
1137 | bool mirroring, enum omap_color_mode color_mode) | 1344 | bool mirroring, enum omap_color_mode color_mode) |
1138 | { | 1345 | { |
1346 | bool row_repeat = false; | ||
1347 | int vidrot = 0; | ||
1348 | |||
1139 | if (color_mode == OMAP_DSS_COLOR_YUV2 || | 1349 | if (color_mode == OMAP_DSS_COLOR_YUV2 || |
1140 | color_mode == OMAP_DSS_COLOR_UYVY) { | 1350 | color_mode == OMAP_DSS_COLOR_UYVY) { |
1141 | int vidrot = 0; | ||
1142 | 1351 | ||
1143 | if (mirroring) { | 1352 | if (mirroring) { |
1144 | switch (rotation) { | 1353 | switch (rotation) { |
@@ -1172,16 +1381,16 @@ static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, | |||
1172 | } | 1381 | } |
1173 | } | 1382 | } |
1174 | 1383 | ||
1175 | REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12); | ||
1176 | |||
1177 | if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270) | 1384 | if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270) |
1178 | REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18); | 1385 | row_repeat = true; |
1179 | else | 1386 | else |
1180 | REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18); | 1387 | row_repeat = false; |
1181 | } else { | ||
1182 | REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12); | ||
1183 | REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18); | ||
1184 | } | 1388 | } |
1389 | |||
1390 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12); | ||
1391 | if (dss_has_feature(FEAT_ROWREPEATENABLE)) | ||
1392 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), | ||
1393 | row_repeat ? 1 : 0, 18, 18); | ||
1185 | } | 1394 | } |
1186 | 1395 | ||
1187 | static int color_mode_to_bpp(enum omap_color_mode color_mode) | 1396 | static int color_mode_to_bpp(enum omap_color_mode color_mode) |
@@ -1194,12 +1403,17 @@ static int color_mode_to_bpp(enum omap_color_mode color_mode) | |||
1194 | case OMAP_DSS_COLOR_CLUT4: | 1403 | case OMAP_DSS_COLOR_CLUT4: |
1195 | return 4; | 1404 | return 4; |
1196 | case OMAP_DSS_COLOR_CLUT8: | 1405 | case OMAP_DSS_COLOR_CLUT8: |
1406 | case OMAP_DSS_COLOR_NV12: | ||
1197 | return 8; | 1407 | return 8; |
1198 | case OMAP_DSS_COLOR_RGB12U: | 1408 | case OMAP_DSS_COLOR_RGB12U: |
1199 | case OMAP_DSS_COLOR_RGB16: | 1409 | case OMAP_DSS_COLOR_RGB16: |
1200 | case OMAP_DSS_COLOR_ARGB16: | 1410 | case OMAP_DSS_COLOR_ARGB16: |
1201 | case OMAP_DSS_COLOR_YUV2: | 1411 | case OMAP_DSS_COLOR_YUV2: |
1202 | case OMAP_DSS_COLOR_UYVY: | 1412 | case OMAP_DSS_COLOR_UYVY: |
1413 | case OMAP_DSS_COLOR_RGBA16: | ||
1414 | case OMAP_DSS_COLOR_RGBX16: | ||
1415 | case OMAP_DSS_COLOR_ARGB16_1555: | ||
1416 | case OMAP_DSS_COLOR_XRGB16_1555: | ||
1203 | return 16; | 1417 | return 16; |
1204 | case OMAP_DSS_COLOR_RGB24P: | 1418 | case OMAP_DSS_COLOR_RGB24P: |
1205 | return 24; | 1419 | return 24; |
@@ -1449,12 +1663,13 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, | |||
1449 | } | 1663 | } |
1450 | } | 1664 | } |
1451 | 1665 | ||
1452 | static unsigned long calc_fclk_five_taps(u16 width, u16 height, | 1666 | static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width, |
1453 | u16 out_width, u16 out_height, enum omap_color_mode color_mode) | 1667 | u16 height, u16 out_width, u16 out_height, |
1668 | enum omap_color_mode color_mode) | ||
1454 | { | 1669 | { |
1455 | u32 fclk = 0; | 1670 | u32 fclk = 0; |
1456 | /* FIXME venc pclk? */ | 1671 | /* FIXME venc pclk? */ |
1457 | u64 tmp, pclk = dispc_pclk_rate(); | 1672 | u64 tmp, pclk = dispc_pclk_rate(channel); |
1458 | 1673 | ||
1459 | if (height > out_height) { | 1674 | if (height > out_height) { |
1460 | /* FIXME get real display PPL */ | 1675 | /* FIXME get real display PPL */ |
@@ -1486,8 +1701,8 @@ static unsigned long calc_fclk_five_taps(u16 width, u16 height, | |||
1486 | return fclk; | 1701 | return fclk; |
1487 | } | 1702 | } |
1488 | 1703 | ||
1489 | static unsigned long calc_fclk(u16 width, u16 height, | 1704 | static unsigned long calc_fclk(enum omap_channel channel, u16 width, |
1490 | u16 out_width, u16 out_height) | 1705 | u16 height, u16 out_width, u16 out_height) |
1491 | { | 1706 | { |
1492 | unsigned int hf, vf; | 1707 | unsigned int hf, vf; |
1493 | 1708 | ||
@@ -1511,7 +1726,7 @@ static unsigned long calc_fclk(u16 width, u16 height, | |||
1511 | vf = 1; | 1726 | vf = 1; |
1512 | 1727 | ||
1513 | /* FIXME venc pclk? */ | 1728 | /* FIXME venc pclk? */ |
1514 | return dispc_pclk_rate() * vf * hf; | 1729 | return dispc_pclk_rate(channel) * vf * hf; |
1515 | } | 1730 | } |
1516 | 1731 | ||
1517 | void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out) | 1732 | void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out) |
@@ -1530,7 +1745,8 @@ static int _dispc_setup_plane(enum omap_plane plane, | |||
1530 | bool ilace, | 1745 | bool ilace, |
1531 | enum omap_dss_rotation_type rotation_type, | 1746 | enum omap_dss_rotation_type rotation_type, |
1532 | u8 rotation, int mirror, | 1747 | u8 rotation, int mirror, |
1533 | u8 global_alpha) | 1748 | u8 global_alpha, u8 pre_mult_alpha, |
1749 | enum omap_channel channel, u32 puv_addr) | ||
1534 | { | 1750 | { |
1535 | const int maxdownscale = cpu_is_omap34xx() ? 4 : 2; | 1751 | const int maxdownscale = cpu_is_omap34xx() ? 4 : 2; |
1536 | bool five_taps = 0; | 1752 | bool five_taps = 0; |
@@ -1559,27 +1775,12 @@ static int _dispc_setup_plane(enum omap_plane plane, | |||
1559 | height, pos_y, out_height); | 1775 | height, pos_y, out_height); |
1560 | } | 1776 | } |
1561 | 1777 | ||
1778 | if (!dss_feat_color_mode_supported(plane, color_mode)) | ||
1779 | return -EINVAL; | ||
1780 | |||
1562 | if (plane == OMAP_DSS_GFX) { | 1781 | if (plane == OMAP_DSS_GFX) { |
1563 | if (width != out_width || height != out_height) | 1782 | if (width != out_width || height != out_height) |
1564 | return -EINVAL; | 1783 | return -EINVAL; |
1565 | |||
1566 | switch (color_mode) { | ||
1567 | case OMAP_DSS_COLOR_ARGB16: | ||
1568 | case OMAP_DSS_COLOR_ARGB32: | ||
1569 | case OMAP_DSS_COLOR_RGBA32: | ||
1570 | case OMAP_DSS_COLOR_RGBX32: | ||
1571 | if (cpu_is_omap24xx()) | ||
1572 | return -EINVAL; | ||
1573 | /* fall through */ | ||
1574 | case OMAP_DSS_COLOR_RGB12U: | ||
1575 | case OMAP_DSS_COLOR_RGB16: | ||
1576 | case OMAP_DSS_COLOR_RGB24P: | ||
1577 | case OMAP_DSS_COLOR_RGB24U: | ||
1578 | break; | ||
1579 | |||
1580 | default: | ||
1581 | return -EINVAL; | ||
1582 | } | ||
1583 | } else { | 1784 | } else { |
1584 | /* video plane */ | 1785 | /* video plane */ |
1585 | 1786 | ||
@@ -1593,41 +1794,17 @@ static int _dispc_setup_plane(enum omap_plane plane, | |||
1593 | out_height > height * 8) | 1794 | out_height > height * 8) |
1594 | return -EINVAL; | 1795 | return -EINVAL; |
1595 | 1796 | ||
1596 | switch (color_mode) { | 1797 | if (color_mode == OMAP_DSS_COLOR_YUV2 || |
1597 | case OMAP_DSS_COLOR_RGBX32: | 1798 | color_mode == OMAP_DSS_COLOR_UYVY || |
1598 | case OMAP_DSS_COLOR_RGB12U: | 1799 | color_mode == OMAP_DSS_COLOR_NV12) |
1599 | if (cpu_is_omap24xx()) | ||
1600 | return -EINVAL; | ||
1601 | /* fall through */ | ||
1602 | case OMAP_DSS_COLOR_RGB16: | ||
1603 | case OMAP_DSS_COLOR_RGB24P: | ||
1604 | case OMAP_DSS_COLOR_RGB24U: | ||
1605 | break; | ||
1606 | |||
1607 | case OMAP_DSS_COLOR_ARGB16: | ||
1608 | case OMAP_DSS_COLOR_ARGB32: | ||
1609 | case OMAP_DSS_COLOR_RGBA32: | ||
1610 | if (cpu_is_omap24xx()) | ||
1611 | return -EINVAL; | ||
1612 | if (plane == OMAP_DSS_VIDEO1) | ||
1613 | return -EINVAL; | ||
1614 | break; | ||
1615 | |||
1616 | case OMAP_DSS_COLOR_YUV2: | ||
1617 | case OMAP_DSS_COLOR_UYVY: | ||
1618 | cconv = 1; | 1800 | cconv = 1; |
1619 | break; | ||
1620 | |||
1621 | default: | ||
1622 | return -EINVAL; | ||
1623 | } | ||
1624 | 1801 | ||
1625 | /* Must use 5-tap filter? */ | 1802 | /* Must use 5-tap filter? */ |
1626 | five_taps = height > out_height * 2; | 1803 | five_taps = height > out_height * 2; |
1627 | 1804 | ||
1628 | if (!five_taps) { | 1805 | if (!five_taps) { |
1629 | fclk = calc_fclk(width, height, | 1806 | fclk = calc_fclk(channel, width, height, out_width, |
1630 | out_width, out_height); | 1807 | out_height); |
1631 | 1808 | ||
1632 | /* Try 5-tap filter if 3-tap fclk is too high */ | 1809 | /* Try 5-tap filter if 3-tap fclk is too high */ |
1633 | if (cpu_is_omap34xx() && height > out_height && | 1810 | if (cpu_is_omap34xx() && height > out_height && |
@@ -1641,7 +1818,7 @@ static int _dispc_setup_plane(enum omap_plane plane, | |||
1641 | } | 1818 | } |
1642 | 1819 | ||
1643 | if (five_taps) | 1820 | if (five_taps) |
1644 | fclk = calc_fclk_five_taps(width, height, | 1821 | fclk = calc_fclk_five_taps(channel, width, height, |
1645 | out_width, out_height, color_mode); | 1822 | out_width, out_height, color_mode); |
1646 | 1823 | ||
1647 | DSSDBG("required fclk rate = %lu Hz\n", fclk); | 1824 | DSSDBG("required fclk rate = %lu Hz\n", fclk); |
@@ -1693,6 +1870,12 @@ static int _dispc_setup_plane(enum omap_plane plane, | |||
1693 | _dispc_set_plane_ba0(plane, paddr + offset0); | 1870 | _dispc_set_plane_ba0(plane, paddr + offset0); |
1694 | _dispc_set_plane_ba1(plane, paddr + offset1); | 1871 | _dispc_set_plane_ba1(plane, paddr + offset1); |
1695 | 1872 | ||
1873 | if (OMAP_DSS_COLOR_NV12 == color_mode) { | ||
1874 | _dispc_set_plane_ba0_uv(plane, puv_addr + offset0); | ||
1875 | _dispc_set_plane_ba1_uv(plane, puv_addr + offset1); | ||
1876 | } | ||
1877 | |||
1878 | |||
1696 | _dispc_set_row_inc(plane, row_inc); | 1879 | _dispc_set_row_inc(plane, row_inc); |
1697 | _dispc_set_pix_inc(plane, pix_inc); | 1880 | _dispc_set_pix_inc(plane, pix_inc); |
1698 | 1881 | ||
@@ -1706,22 +1889,23 @@ static int _dispc_setup_plane(enum omap_plane plane, | |||
1706 | if (plane != OMAP_DSS_GFX) { | 1889 | if (plane != OMAP_DSS_GFX) { |
1707 | _dispc_set_scaling(plane, width, height, | 1890 | _dispc_set_scaling(plane, width, height, |
1708 | out_width, out_height, | 1891 | out_width, out_height, |
1709 | ilace, five_taps, fieldmode); | 1892 | ilace, five_taps, fieldmode, |
1893 | color_mode, rotation); | ||
1710 | _dispc_set_vid_size(plane, out_width, out_height); | 1894 | _dispc_set_vid_size(plane, out_width, out_height); |
1711 | _dispc_set_vid_color_conv(plane, cconv); | 1895 | _dispc_set_vid_color_conv(plane, cconv); |
1712 | } | 1896 | } |
1713 | 1897 | ||
1714 | _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode); | 1898 | _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode); |
1715 | 1899 | ||
1716 | if (plane != OMAP_DSS_VIDEO1) | 1900 | _dispc_set_pre_mult_alpha(plane, pre_mult_alpha); |
1717 | _dispc_setup_global_alpha(plane, global_alpha); | 1901 | _dispc_setup_global_alpha(plane, global_alpha); |
1718 | 1902 | ||
1719 | return 0; | 1903 | return 0; |
1720 | } | 1904 | } |
1721 | 1905 | ||
1722 | static void _dispc_enable_plane(enum omap_plane plane, bool enable) | 1906 | static void _dispc_enable_plane(enum omap_plane plane, bool enable) |
1723 | { | 1907 | { |
1724 | REG_FLD_MOD(dispc_reg_att[plane], enable ? 1 : 0, 0, 0); | 1908 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0); |
1725 | } | 1909 | } |
1726 | 1910 | ||
1727 | static void dispc_disable_isr(void *data, u32 mask) | 1911 | static void dispc_disable_isr(void *data, u32 mask) |
@@ -1730,36 +1914,44 @@ static void dispc_disable_isr(void *data, u32 mask) | |||
1730 | complete(compl); | 1914 | complete(compl); |
1731 | } | 1915 | } |
1732 | 1916 | ||
1733 | static void _enable_lcd_out(bool enable) | 1917 | static void _enable_lcd_out(enum omap_channel channel, bool enable) |
1734 | { | 1918 | { |
1735 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0); | 1919 | if (channel == OMAP_DSS_CHANNEL_LCD2) |
1920 | REG_FLD_MOD(DISPC_CONTROL2, enable ? 1 : 0, 0, 0); | ||
1921 | else | ||
1922 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0); | ||
1736 | } | 1923 | } |
1737 | 1924 | ||
1738 | static void dispc_enable_lcd_out(bool enable) | 1925 | static void dispc_enable_lcd_out(enum omap_channel channel, bool enable) |
1739 | { | 1926 | { |
1740 | struct completion frame_done_completion; | 1927 | struct completion frame_done_completion; |
1741 | bool is_on; | 1928 | bool is_on; |
1742 | int r; | 1929 | int r; |
1930 | u32 irq; | ||
1743 | 1931 | ||
1744 | enable_clocks(1); | 1932 | enable_clocks(1); |
1745 | 1933 | ||
1746 | /* When we disable LCD output, we need to wait until frame is done. | 1934 | /* When we disable LCD output, we need to wait until frame is done. |
1747 | * Otherwise the DSS is still working, and turning off the clocks | 1935 | * Otherwise the DSS is still working, and turning off the clocks |
1748 | * prevents DSS from going to OFF mode */ | 1936 | * prevents DSS from going to OFF mode */ |
1749 | is_on = REG_GET(DISPC_CONTROL, 0, 0); | 1937 | is_on = channel == OMAP_DSS_CHANNEL_LCD2 ? |
1938 | REG_GET(DISPC_CONTROL2, 0, 0) : | ||
1939 | REG_GET(DISPC_CONTROL, 0, 0); | ||
1940 | |||
1941 | irq = channel == OMAP_DSS_CHANNEL_LCD2 ? DISPC_IRQ_FRAMEDONE2 : | ||
1942 | DISPC_IRQ_FRAMEDONE; | ||
1750 | 1943 | ||
1751 | if (!enable && is_on) { | 1944 | if (!enable && is_on) { |
1752 | init_completion(&frame_done_completion); | 1945 | init_completion(&frame_done_completion); |
1753 | 1946 | ||
1754 | r = omap_dispc_register_isr(dispc_disable_isr, | 1947 | r = omap_dispc_register_isr(dispc_disable_isr, |
1755 | &frame_done_completion, | 1948 | &frame_done_completion, irq); |
1756 | DISPC_IRQ_FRAMEDONE); | ||
1757 | 1949 | ||
1758 | if (r) | 1950 | if (r) |
1759 | DSSERR("failed to register FRAMEDONE isr\n"); | 1951 | DSSERR("failed to register FRAMEDONE isr\n"); |
1760 | } | 1952 | } |
1761 | 1953 | ||
1762 | _enable_lcd_out(enable); | 1954 | _enable_lcd_out(channel, enable); |
1763 | 1955 | ||
1764 | if (!enable && is_on) { | 1956 | if (!enable && is_on) { |
1765 | if (!wait_for_completion_timeout(&frame_done_completion, | 1957 | if (!wait_for_completion_timeout(&frame_done_completion, |
@@ -1767,8 +1959,7 @@ static void dispc_enable_lcd_out(bool enable) | |||
1767 | DSSERR("timeout waiting for FRAME DONE\n"); | 1959 | DSSERR("timeout waiting for FRAME DONE\n"); |
1768 | 1960 | ||
1769 | r = omap_dispc_unregister_isr(dispc_disable_isr, | 1961 | r = omap_dispc_unregister_isr(dispc_disable_isr, |
1770 | &frame_done_completion, | 1962 | &frame_done_completion, irq); |
1771 | DISPC_IRQ_FRAMEDONE); | ||
1772 | 1963 | ||
1773 | if (r) | 1964 | if (r) |
1774 | DSSERR("failed to unregister FRAMEDONE isr\n"); | 1965 | DSSERR("failed to unregister FRAMEDONE isr\n"); |
@@ -1838,6 +2029,8 @@ static void dispc_enable_digit_out(bool enable) | |||
1838 | unsigned long flags; | 2029 | unsigned long flags; |
1839 | spin_lock_irqsave(&dispc.irq_lock, flags); | 2030 | spin_lock_irqsave(&dispc.irq_lock, flags); |
1840 | dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; | 2031 | dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; |
2032 | if (dss_has_feature(FEAT_MGR_LCD2)) | ||
2033 | dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2; | ||
1841 | dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); | 2034 | dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); |
1842 | _omap_dispc_set_irqs(); | 2035 | _omap_dispc_set_irqs(); |
1843 | spin_unlock_irqrestore(&dispc.irq_lock, flags); | 2036 | spin_unlock_irqrestore(&dispc.irq_lock, flags); |
@@ -1852,14 +2045,17 @@ bool dispc_is_channel_enabled(enum omap_channel channel) | |||
1852 | return !!REG_GET(DISPC_CONTROL, 0, 0); | 2045 | return !!REG_GET(DISPC_CONTROL, 0, 0); |
1853 | else if (channel == OMAP_DSS_CHANNEL_DIGIT) | 2046 | else if (channel == OMAP_DSS_CHANNEL_DIGIT) |
1854 | return !!REG_GET(DISPC_CONTROL, 1, 1); | 2047 | return !!REG_GET(DISPC_CONTROL, 1, 1); |
2048 | else if (channel == OMAP_DSS_CHANNEL_LCD2) | ||
2049 | return !!REG_GET(DISPC_CONTROL2, 0, 0); | ||
1855 | else | 2050 | else |
1856 | BUG(); | 2051 | BUG(); |
1857 | } | 2052 | } |
1858 | 2053 | ||
1859 | void dispc_enable_channel(enum omap_channel channel, bool enable) | 2054 | void dispc_enable_channel(enum omap_channel channel, bool enable) |
1860 | { | 2055 | { |
1861 | if (channel == OMAP_DSS_CHANNEL_LCD) | 2056 | if (channel == OMAP_DSS_CHANNEL_LCD || |
1862 | dispc_enable_lcd_out(enable); | 2057 | channel == OMAP_DSS_CHANNEL_LCD2) |
2058 | dispc_enable_lcd_out(channel, enable); | ||
1863 | else if (channel == OMAP_DSS_CHANNEL_DIGIT) | 2059 | else if (channel == OMAP_DSS_CHANNEL_DIGIT) |
1864 | dispc_enable_digit_out(enable); | 2060 | dispc_enable_digit_out(enable); |
1865 | else | 2061 | else |
@@ -1868,6 +2064,9 @@ void dispc_enable_channel(enum omap_channel channel, bool enable) | |||
1868 | 2064 | ||
1869 | void dispc_lcd_enable_signal_polarity(bool act_high) | 2065 | void dispc_lcd_enable_signal_polarity(bool act_high) |
1870 | { | 2066 | { |
2067 | if (!dss_has_feature(FEAT_LCDENABLEPOL)) | ||
2068 | return; | ||
2069 | |||
1871 | enable_clocks(1); | 2070 | enable_clocks(1); |
1872 | REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29); | 2071 | REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29); |
1873 | enable_clocks(0); | 2072 | enable_clocks(0); |
@@ -1875,6 +2074,9 @@ void dispc_lcd_enable_signal_polarity(bool act_high) | |||
1875 | 2074 | ||
1876 | void dispc_lcd_enable_signal(bool enable) | 2075 | void dispc_lcd_enable_signal(bool enable) |
1877 | { | 2076 | { |
2077 | if (!dss_has_feature(FEAT_LCDENABLESIGNAL)) | ||
2078 | return; | ||
2079 | |||
1878 | enable_clocks(1); | 2080 | enable_clocks(1); |
1879 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28); | 2081 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28); |
1880 | enable_clocks(0); | 2082 | enable_clocks(0); |
@@ -1882,20 +2084,27 @@ void dispc_lcd_enable_signal(bool enable) | |||
1882 | 2084 | ||
1883 | void dispc_pck_free_enable(bool enable) | 2085 | void dispc_pck_free_enable(bool enable) |
1884 | { | 2086 | { |
2087 | if (!dss_has_feature(FEAT_PCKFREEENABLE)) | ||
2088 | return; | ||
2089 | |||
1885 | enable_clocks(1); | 2090 | enable_clocks(1); |
1886 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); | 2091 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); |
1887 | enable_clocks(0); | 2092 | enable_clocks(0); |
1888 | } | 2093 | } |
1889 | 2094 | ||
1890 | void dispc_enable_fifohandcheck(bool enable) | 2095 | void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable) |
1891 | { | 2096 | { |
1892 | enable_clocks(1); | 2097 | enable_clocks(1); |
1893 | REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16); | 2098 | if (channel == OMAP_DSS_CHANNEL_LCD2) |
2099 | REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16); | ||
2100 | else | ||
2101 | REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16); | ||
1894 | enable_clocks(0); | 2102 | enable_clocks(0); |
1895 | } | 2103 | } |
1896 | 2104 | ||
1897 | 2105 | ||
1898 | void dispc_set_lcd_display_type(enum omap_lcd_display_type type) | 2106 | void dispc_set_lcd_display_type(enum omap_channel channel, |
2107 | enum omap_lcd_display_type type) | ||
1899 | { | 2108 | { |
1900 | int mode; | 2109 | int mode; |
1901 | 2110 | ||
@@ -1914,7 +2123,10 @@ void dispc_set_lcd_display_type(enum omap_lcd_display_type type) | |||
1914 | } | 2123 | } |
1915 | 2124 | ||
1916 | enable_clocks(1); | 2125 | enable_clocks(1); |
1917 | REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3); | 2126 | if (channel == OMAP_DSS_CHANNEL_LCD2) |
2127 | REG_FLD_MOD(DISPC_CONTROL2, mode, 3, 3); | ||
2128 | else | ||
2129 | REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3); | ||
1918 | enable_clocks(0); | 2130 | enable_clocks(0); |
1919 | } | 2131 | } |
1920 | 2132 | ||
@@ -1928,25 +2140,21 @@ void dispc_set_loadmode(enum omap_dss_load_mode mode) | |||
1928 | 2140 | ||
1929 | void dispc_set_default_color(enum omap_channel channel, u32 color) | 2141 | void dispc_set_default_color(enum omap_channel channel, u32 color) |
1930 | { | 2142 | { |
1931 | const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0, | ||
1932 | DISPC_DEFAULT_COLOR1 }; | ||
1933 | |||
1934 | enable_clocks(1); | 2143 | enable_clocks(1); |
1935 | dispc_write_reg(def_reg[channel], color); | 2144 | dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color); |
1936 | enable_clocks(0); | 2145 | enable_clocks(0); |
1937 | } | 2146 | } |
1938 | 2147 | ||
1939 | u32 dispc_get_default_color(enum omap_channel channel) | 2148 | u32 dispc_get_default_color(enum omap_channel channel) |
1940 | { | 2149 | { |
1941 | const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0, | ||
1942 | DISPC_DEFAULT_COLOR1 }; | ||
1943 | u32 l; | 2150 | u32 l; |
1944 | 2151 | ||
1945 | BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT && | 2152 | BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT && |
1946 | channel != OMAP_DSS_CHANNEL_LCD); | 2153 | channel != OMAP_DSS_CHANNEL_LCD && |
2154 | channel != OMAP_DSS_CHANNEL_LCD2); | ||
1947 | 2155 | ||
1948 | enable_clocks(1); | 2156 | enable_clocks(1); |
1949 | l = dispc_read_reg(def_reg[channel]); | 2157 | l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel)); |
1950 | enable_clocks(0); | 2158 | enable_clocks(0); |
1951 | 2159 | ||
1952 | return l; | 2160 | return l; |
@@ -1956,16 +2164,15 @@ void dispc_set_trans_key(enum omap_channel ch, | |||
1956 | enum omap_dss_trans_key_type type, | 2164 | enum omap_dss_trans_key_type type, |
1957 | u32 trans_key) | 2165 | u32 trans_key) |
1958 | { | 2166 | { |
1959 | const struct dispc_reg tr_reg[] = { | ||
1960 | DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 }; | ||
1961 | |||
1962 | enable_clocks(1); | 2167 | enable_clocks(1); |
1963 | if (ch == OMAP_DSS_CHANNEL_LCD) | 2168 | if (ch == OMAP_DSS_CHANNEL_LCD) |
1964 | REG_FLD_MOD(DISPC_CONFIG, type, 11, 11); | 2169 | REG_FLD_MOD(DISPC_CONFIG, type, 11, 11); |
1965 | else /* OMAP_DSS_CHANNEL_DIGIT */ | 2170 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) |
1966 | REG_FLD_MOD(DISPC_CONFIG, type, 13, 13); | 2171 | REG_FLD_MOD(DISPC_CONFIG, type, 13, 13); |
2172 | else /* OMAP_DSS_CHANNEL_LCD2 */ | ||
2173 | REG_FLD_MOD(DISPC_CONFIG2, type, 11, 11); | ||
1967 | 2174 | ||
1968 | dispc_write_reg(tr_reg[ch], trans_key); | 2175 | dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key); |
1969 | enable_clocks(0); | 2176 | enable_clocks(0); |
1970 | } | 2177 | } |
1971 | 2178 | ||
@@ -1973,21 +2180,20 @@ void dispc_get_trans_key(enum omap_channel ch, | |||
1973 | enum omap_dss_trans_key_type *type, | 2180 | enum omap_dss_trans_key_type *type, |
1974 | u32 *trans_key) | 2181 | u32 *trans_key) |
1975 | { | 2182 | { |
1976 | const struct dispc_reg tr_reg[] = { | ||
1977 | DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 }; | ||
1978 | |||
1979 | enable_clocks(1); | 2183 | enable_clocks(1); |
1980 | if (type) { | 2184 | if (type) { |
1981 | if (ch == OMAP_DSS_CHANNEL_LCD) | 2185 | if (ch == OMAP_DSS_CHANNEL_LCD) |
1982 | *type = REG_GET(DISPC_CONFIG, 11, 11); | 2186 | *type = REG_GET(DISPC_CONFIG, 11, 11); |
1983 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) | 2187 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) |
1984 | *type = REG_GET(DISPC_CONFIG, 13, 13); | 2188 | *type = REG_GET(DISPC_CONFIG, 13, 13); |
2189 | else if (ch == OMAP_DSS_CHANNEL_LCD2) | ||
2190 | *type = REG_GET(DISPC_CONFIG2, 11, 11); | ||
1985 | else | 2191 | else |
1986 | BUG(); | 2192 | BUG(); |
1987 | } | 2193 | } |
1988 | 2194 | ||
1989 | if (trans_key) | 2195 | if (trans_key) |
1990 | *trans_key = dispc_read_reg(tr_reg[ch]); | 2196 | *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch)); |
1991 | enable_clocks(0); | 2197 | enable_clocks(0); |
1992 | } | 2198 | } |
1993 | 2199 | ||
@@ -1996,40 +2202,45 @@ void dispc_enable_trans_key(enum omap_channel ch, bool enable) | |||
1996 | enable_clocks(1); | 2202 | enable_clocks(1); |
1997 | if (ch == OMAP_DSS_CHANNEL_LCD) | 2203 | if (ch == OMAP_DSS_CHANNEL_LCD) |
1998 | REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); | 2204 | REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); |
1999 | else /* OMAP_DSS_CHANNEL_DIGIT */ | 2205 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) |
2000 | REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12); | 2206 | REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12); |
2207 | else /* OMAP_DSS_CHANNEL_LCD2 */ | ||
2208 | REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10); | ||
2001 | enable_clocks(0); | 2209 | enable_clocks(0); |
2002 | } | 2210 | } |
2003 | void dispc_enable_alpha_blending(enum omap_channel ch, bool enable) | 2211 | void dispc_enable_alpha_blending(enum omap_channel ch, bool enable) |
2004 | { | 2212 | { |
2005 | if (cpu_is_omap24xx()) | 2213 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) |
2006 | return; | 2214 | return; |
2007 | 2215 | ||
2008 | enable_clocks(1); | 2216 | enable_clocks(1); |
2009 | if (ch == OMAP_DSS_CHANNEL_LCD) | 2217 | if (ch == OMAP_DSS_CHANNEL_LCD) |
2010 | REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18); | 2218 | REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18); |
2011 | else /* OMAP_DSS_CHANNEL_DIGIT */ | 2219 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) |
2012 | REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); | 2220 | REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); |
2221 | else /* OMAP_DSS_CHANNEL_LCD2 */ | ||
2222 | REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18); | ||
2013 | enable_clocks(0); | 2223 | enable_clocks(0); |
2014 | } | 2224 | } |
2015 | bool dispc_alpha_blending_enabled(enum omap_channel ch) | 2225 | bool dispc_alpha_blending_enabled(enum omap_channel ch) |
2016 | { | 2226 | { |
2017 | bool enabled; | 2227 | bool enabled; |
2018 | 2228 | ||
2019 | if (cpu_is_omap24xx()) | 2229 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) |
2020 | return false; | 2230 | return false; |
2021 | 2231 | ||
2022 | enable_clocks(1); | 2232 | enable_clocks(1); |
2023 | if (ch == OMAP_DSS_CHANNEL_LCD) | 2233 | if (ch == OMAP_DSS_CHANNEL_LCD) |
2024 | enabled = REG_GET(DISPC_CONFIG, 18, 18); | 2234 | enabled = REG_GET(DISPC_CONFIG, 18, 18); |
2025 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) | 2235 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) |
2026 | enabled = REG_GET(DISPC_CONFIG, 18, 18); | 2236 | enabled = REG_GET(DISPC_CONFIG, 19, 19); |
2237 | else if (ch == OMAP_DSS_CHANNEL_LCD2) | ||
2238 | enabled = REG_GET(DISPC_CONFIG2, 18, 18); | ||
2027 | else | 2239 | else |
2028 | BUG(); | 2240 | BUG(); |
2029 | enable_clocks(0); | 2241 | enable_clocks(0); |
2030 | 2242 | ||
2031 | return enabled; | 2243 | return enabled; |
2032 | |||
2033 | } | 2244 | } |
2034 | 2245 | ||
2035 | 2246 | ||
@@ -2042,6 +2253,8 @@ bool dispc_trans_key_enabled(enum omap_channel ch) | |||
2042 | enabled = REG_GET(DISPC_CONFIG, 10, 10); | 2253 | enabled = REG_GET(DISPC_CONFIG, 10, 10); |
2043 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) | 2254 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) |
2044 | enabled = REG_GET(DISPC_CONFIG, 12, 12); | 2255 | enabled = REG_GET(DISPC_CONFIG, 12, 12); |
2256 | else if (ch == OMAP_DSS_CHANNEL_LCD2) | ||
2257 | enabled = REG_GET(DISPC_CONFIG2, 10, 10); | ||
2045 | else | 2258 | else |
2046 | BUG(); | 2259 | BUG(); |
2047 | enable_clocks(0); | 2260 | enable_clocks(0); |
@@ -2050,7 +2263,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch) | |||
2050 | } | 2263 | } |
2051 | 2264 | ||
2052 | 2265 | ||
2053 | void dispc_set_tft_data_lines(u8 data_lines) | 2266 | void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines) |
2054 | { | 2267 | { |
2055 | int code; | 2268 | int code; |
2056 | 2269 | ||
@@ -2073,11 +2286,15 @@ void dispc_set_tft_data_lines(u8 data_lines) | |||
2073 | } | 2286 | } |
2074 | 2287 | ||
2075 | enable_clocks(1); | 2288 | enable_clocks(1); |
2076 | REG_FLD_MOD(DISPC_CONTROL, code, 9, 8); | 2289 | if (channel == OMAP_DSS_CHANNEL_LCD2) |
2290 | REG_FLD_MOD(DISPC_CONTROL2, code, 9, 8); | ||
2291 | else | ||
2292 | REG_FLD_MOD(DISPC_CONTROL, code, 9, 8); | ||
2077 | enable_clocks(0); | 2293 | enable_clocks(0); |
2078 | } | 2294 | } |
2079 | 2295 | ||
2080 | void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode) | 2296 | void dispc_set_parallel_interface_mode(enum omap_channel channel, |
2297 | enum omap_parallel_interface_mode mode) | ||
2081 | { | 2298 | { |
2082 | u32 l; | 2299 | u32 l; |
2083 | int stallmode; | 2300 | int stallmode; |
@@ -2107,13 +2324,17 @@ void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode) | |||
2107 | 2324 | ||
2108 | enable_clocks(1); | 2325 | enable_clocks(1); |
2109 | 2326 | ||
2110 | l = dispc_read_reg(DISPC_CONTROL); | 2327 | if (channel == OMAP_DSS_CHANNEL_LCD2) { |
2111 | 2328 | l = dispc_read_reg(DISPC_CONTROL2); | |
2112 | l = FLD_MOD(l, stallmode, 11, 11); | 2329 | l = FLD_MOD(l, stallmode, 11, 11); |
2113 | l = FLD_MOD(l, gpout0, 15, 15); | 2330 | dispc_write_reg(DISPC_CONTROL2, l); |
2114 | l = FLD_MOD(l, gpout1, 16, 16); | 2331 | } else { |
2115 | 2332 | l = dispc_read_reg(DISPC_CONTROL); | |
2116 | dispc_write_reg(DISPC_CONTROL, l); | 2333 | l = FLD_MOD(l, stallmode, 11, 11); |
2334 | l = FLD_MOD(l, gpout0, 15, 15); | ||
2335 | l = FLD_MOD(l, gpout1, 16, 16); | ||
2336 | dispc_write_reg(DISPC_CONTROL, l); | ||
2337 | } | ||
2117 | 2338 | ||
2118 | enable_clocks(0); | 2339 | enable_clocks(0); |
2119 | } | 2340 | } |
@@ -2149,8 +2370,8 @@ bool dispc_lcd_timings_ok(struct omap_video_timings *timings) | |||
2149 | timings->vfp, timings->vbp); | 2370 | timings->vfp, timings->vbp); |
2150 | } | 2371 | } |
2151 | 2372 | ||
2152 | static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp, | 2373 | static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw, |
2153 | int vsw, int vfp, int vbp) | 2374 | int hfp, int hbp, int vsw, int vfp, int vbp) |
2154 | { | 2375 | { |
2155 | u32 timing_h, timing_v; | 2376 | u32 timing_h, timing_v; |
2156 | 2377 | ||
@@ -2169,13 +2390,14 @@ static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp, | |||
2169 | } | 2390 | } |
2170 | 2391 | ||
2171 | enable_clocks(1); | 2392 | enable_clocks(1); |
2172 | dispc_write_reg(DISPC_TIMING_H, timing_h); | 2393 | dispc_write_reg(DISPC_TIMING_H(channel), timing_h); |
2173 | dispc_write_reg(DISPC_TIMING_V, timing_v); | 2394 | dispc_write_reg(DISPC_TIMING_V(channel), timing_v); |
2174 | enable_clocks(0); | 2395 | enable_clocks(0); |
2175 | } | 2396 | } |
2176 | 2397 | ||
2177 | /* change name to mode? */ | 2398 | /* change name to mode? */ |
2178 | void dispc_set_lcd_timings(struct omap_video_timings *timings) | 2399 | void dispc_set_lcd_timings(enum omap_channel channel, |
2400 | struct omap_video_timings *timings) | ||
2179 | { | 2401 | { |
2180 | unsigned xtot, ytot; | 2402 | unsigned xtot, ytot; |
2181 | unsigned long ht, vt; | 2403 | unsigned long ht, vt; |
@@ -2185,10 +2407,11 @@ void dispc_set_lcd_timings(struct omap_video_timings *timings) | |||
2185 | timings->vfp, timings->vbp)) | 2407 | timings->vfp, timings->vbp)) |
2186 | BUG(); | 2408 | BUG(); |
2187 | 2409 | ||
2188 | _dispc_set_lcd_timings(timings->hsw, timings->hfp, timings->hbp, | 2410 | _dispc_set_lcd_timings(channel, timings->hsw, timings->hfp, |
2189 | timings->vsw, timings->vfp, timings->vbp); | 2411 | timings->hbp, timings->vsw, timings->vfp, |
2412 | timings->vbp); | ||
2190 | 2413 | ||
2191 | dispc_set_lcd_size(timings->x_res, timings->y_res); | 2414 | dispc_set_lcd_size(channel, timings->x_res, timings->y_res); |
2192 | 2415 | ||
2193 | xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp; | 2416 | xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp; |
2194 | ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp; | 2417 | ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp; |
@@ -2196,7 +2419,8 @@ void dispc_set_lcd_timings(struct omap_video_timings *timings) | |||
2196 | ht = (timings->pixel_clock * 1000) / xtot; | 2419 | ht = (timings->pixel_clock * 1000) / xtot; |
2197 | vt = (timings->pixel_clock * 1000) / xtot / ytot; | 2420 | vt = (timings->pixel_clock * 1000) / xtot / ytot; |
2198 | 2421 | ||
2199 | DSSDBG("xres %u yres %u\n", timings->x_res, timings->y_res); | 2422 | DSSDBG("channel %d xres %u yres %u\n", channel, timings->x_res, |
2423 | timings->y_res); | ||
2200 | DSSDBG("pck %u\n", timings->pixel_clock); | 2424 | DSSDBG("pck %u\n", timings->pixel_clock); |
2201 | DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", | 2425 | DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", |
2202 | timings->hsw, timings->hfp, timings->hbp, | 2426 | timings->hsw, timings->hfp, timings->hbp, |
@@ -2205,89 +2429,151 @@ void dispc_set_lcd_timings(struct omap_video_timings *timings) | |||
2205 | DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); | 2429 | DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); |
2206 | } | 2430 | } |
2207 | 2431 | ||
2208 | static void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div) | 2432 | static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div, |
2433 | u16 pck_div) | ||
2209 | { | 2434 | { |
2210 | BUG_ON(lck_div < 1); | 2435 | BUG_ON(lck_div < 1); |
2211 | BUG_ON(pck_div < 2); | 2436 | BUG_ON(pck_div < 2); |
2212 | 2437 | ||
2213 | enable_clocks(1); | 2438 | enable_clocks(1); |
2214 | dispc_write_reg(DISPC_DIVISOR, | 2439 | dispc_write_reg(DISPC_DIVISORo(channel), |
2215 | FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); | 2440 | FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); |
2216 | enable_clocks(0); | 2441 | enable_clocks(0); |
2217 | } | 2442 | } |
2218 | 2443 | ||
2219 | static void dispc_get_lcd_divisor(int *lck_div, int *pck_div) | 2444 | static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div, |
2445 | int *pck_div) | ||
2220 | { | 2446 | { |
2221 | u32 l; | 2447 | u32 l; |
2222 | l = dispc_read_reg(DISPC_DIVISOR); | 2448 | l = dispc_read_reg(DISPC_DIVISORo(channel)); |
2223 | *lck_div = FLD_GET(l, 23, 16); | 2449 | *lck_div = FLD_GET(l, 23, 16); |
2224 | *pck_div = FLD_GET(l, 7, 0); | 2450 | *pck_div = FLD_GET(l, 7, 0); |
2225 | } | 2451 | } |
2226 | 2452 | ||
2227 | unsigned long dispc_fclk_rate(void) | 2453 | unsigned long dispc_fclk_rate(void) |
2228 | { | 2454 | { |
2455 | struct platform_device *dsidev; | ||
2229 | unsigned long r = 0; | 2456 | unsigned long r = 0; |
2230 | 2457 | ||
2231 | if (dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK) | 2458 | switch (dss_get_dispc_clk_source()) { |
2232 | r = dss_clk_get_rate(DSS_CLK_FCK1); | 2459 | case OMAP_DSS_CLK_SRC_FCK: |
2233 | else | 2460 | r = dss_clk_get_rate(DSS_CLK_FCK); |
2234 | #ifdef CONFIG_OMAP2_DSS_DSI | 2461 | break; |
2235 | r = dsi_get_dsi1_pll_rate(); | 2462 | case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: |
2236 | #else | 2463 | dsidev = dsi_get_dsidev_from_id(0); |
2237 | BUG(); | 2464 | r = dsi_get_pll_hsdiv_dispc_rate(dsidev); |
2238 | #endif | 2465 | break; |
2466 | case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: | ||
2467 | dsidev = dsi_get_dsidev_from_id(1); | ||
2468 | r = dsi_get_pll_hsdiv_dispc_rate(dsidev); | ||
2469 | break; | ||
2470 | default: | ||
2471 | BUG(); | ||
2472 | } | ||
2473 | |||
2239 | return r; | 2474 | return r; |
2240 | } | 2475 | } |
2241 | 2476 | ||
2242 | unsigned long dispc_lclk_rate(void) | 2477 | unsigned long dispc_lclk_rate(enum omap_channel channel) |
2243 | { | 2478 | { |
2479 | struct platform_device *dsidev; | ||
2244 | int lcd; | 2480 | int lcd; |
2245 | unsigned long r; | 2481 | unsigned long r; |
2246 | u32 l; | 2482 | u32 l; |
2247 | 2483 | ||
2248 | l = dispc_read_reg(DISPC_DIVISOR); | 2484 | l = dispc_read_reg(DISPC_DIVISORo(channel)); |
2249 | 2485 | ||
2250 | lcd = FLD_GET(l, 23, 16); | 2486 | lcd = FLD_GET(l, 23, 16); |
2251 | 2487 | ||
2252 | r = dispc_fclk_rate(); | 2488 | switch (dss_get_lcd_clk_source(channel)) { |
2489 | case OMAP_DSS_CLK_SRC_FCK: | ||
2490 | r = dss_clk_get_rate(DSS_CLK_FCK); | ||
2491 | break; | ||
2492 | case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: | ||
2493 | dsidev = dsi_get_dsidev_from_id(0); | ||
2494 | r = dsi_get_pll_hsdiv_dispc_rate(dsidev); | ||
2495 | break; | ||
2496 | case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: | ||
2497 | dsidev = dsi_get_dsidev_from_id(1); | ||
2498 | r = dsi_get_pll_hsdiv_dispc_rate(dsidev); | ||
2499 | break; | ||
2500 | default: | ||
2501 | BUG(); | ||
2502 | } | ||
2253 | 2503 | ||
2254 | return r / lcd; | 2504 | return r / lcd; |
2255 | } | 2505 | } |
2256 | 2506 | ||
2257 | unsigned long dispc_pclk_rate(void) | 2507 | unsigned long dispc_pclk_rate(enum omap_channel channel) |
2258 | { | 2508 | { |
2259 | int lcd, pcd; | 2509 | int pcd; |
2260 | unsigned long r; | 2510 | unsigned long r; |
2261 | u32 l; | 2511 | u32 l; |
2262 | 2512 | ||
2263 | l = dispc_read_reg(DISPC_DIVISOR); | 2513 | l = dispc_read_reg(DISPC_DIVISORo(channel)); |
2264 | 2514 | ||
2265 | lcd = FLD_GET(l, 23, 16); | ||
2266 | pcd = FLD_GET(l, 7, 0); | 2515 | pcd = FLD_GET(l, 7, 0); |
2267 | 2516 | ||
2268 | r = dispc_fclk_rate(); | 2517 | r = dispc_lclk_rate(channel); |
2269 | 2518 | ||
2270 | return r / lcd / pcd; | 2519 | return r / pcd; |
2271 | } | 2520 | } |
2272 | 2521 | ||
2273 | void dispc_dump_clocks(struct seq_file *s) | 2522 | void dispc_dump_clocks(struct seq_file *s) |
2274 | { | 2523 | { |
2275 | int lcd, pcd; | 2524 | int lcd, pcd; |
2525 | u32 l; | ||
2526 | enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source(); | ||
2527 | enum omap_dss_clk_source lcd_clk_src; | ||
2276 | 2528 | ||
2277 | enable_clocks(1); | 2529 | enable_clocks(1); |
2278 | 2530 | ||
2279 | dispc_get_lcd_divisor(&lcd, &pcd); | ||
2280 | |||
2281 | seq_printf(s, "- DISPC -\n"); | 2531 | seq_printf(s, "- DISPC -\n"); |
2282 | 2532 | ||
2283 | seq_printf(s, "dispc fclk source = %s\n", | 2533 | seq_printf(s, "dispc fclk source = %s (%s)\n", |
2284 | dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? | 2534 | dss_get_generic_clk_source_name(dispc_clk_src), |
2285 | "dss1_alwon_fclk" : "dsi1_pll_fclk"); | 2535 | dss_feat_get_clk_source_name(dispc_clk_src)); |
2286 | 2536 | ||
2287 | seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate()); | 2537 | seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate()); |
2288 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", dispc_lclk_rate(), lcd); | ||
2289 | seq_printf(s, "pck\t\t%-16lupck div\t%u\n", dispc_pclk_rate(), pcd); | ||
2290 | 2538 | ||
2539 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) { | ||
2540 | seq_printf(s, "- DISPC-CORE-CLK -\n"); | ||
2541 | l = dispc_read_reg(DISPC_DIVISOR); | ||
2542 | lcd = FLD_GET(l, 23, 16); | ||
2543 | |||
2544 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", | ||
2545 | (dispc_fclk_rate()/lcd), lcd); | ||
2546 | } | ||
2547 | seq_printf(s, "- LCD1 -\n"); | ||
2548 | |||
2549 | lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD); | ||
2550 | |||
2551 | seq_printf(s, "lcd1_clk source = %s (%s)\n", | ||
2552 | dss_get_generic_clk_source_name(lcd_clk_src), | ||
2553 | dss_feat_get_clk_source_name(lcd_clk_src)); | ||
2554 | |||
2555 | dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd); | ||
2556 | |||
2557 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", | ||
2558 | dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD), lcd); | ||
2559 | seq_printf(s, "pck\t\t%-16lupck div\t%u\n", | ||
2560 | dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD), pcd); | ||
2561 | if (dss_has_feature(FEAT_MGR_LCD2)) { | ||
2562 | seq_printf(s, "- LCD2 -\n"); | ||
2563 | |||
2564 | lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD2); | ||
2565 | |||
2566 | seq_printf(s, "lcd2_clk source = %s (%s)\n", | ||
2567 | dss_get_generic_clk_source_name(lcd_clk_src), | ||
2568 | dss_feat_get_clk_source_name(lcd_clk_src)); | ||
2569 | |||
2570 | dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd); | ||
2571 | |||
2572 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", | ||
2573 | dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD2), lcd); | ||
2574 | seq_printf(s, "pck\t\t%-16lupck div\t%u\n", | ||
2575 | dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd); | ||
2576 | } | ||
2291 | enable_clocks(0); | 2577 | enable_clocks(0); |
2292 | } | 2578 | } |
2293 | 2579 | ||
@@ -2329,15 +2615,21 @@ void dispc_dump_irqs(struct seq_file *s) | |||
2329 | PIS(SYNC_LOST); | 2615 | PIS(SYNC_LOST); |
2330 | PIS(SYNC_LOST_DIGIT); | 2616 | PIS(SYNC_LOST_DIGIT); |
2331 | PIS(WAKEUP); | 2617 | PIS(WAKEUP); |
2618 | if (dss_has_feature(FEAT_MGR_LCD2)) { | ||
2619 | PIS(FRAMEDONE2); | ||
2620 | PIS(VSYNC2); | ||
2621 | PIS(ACBIAS_COUNT_STAT2); | ||
2622 | PIS(SYNC_LOST2); | ||
2623 | } | ||
2332 | #undef PIS | 2624 | #undef PIS |
2333 | } | 2625 | } |
2334 | #endif | 2626 | #endif |
2335 | 2627 | ||
2336 | void dispc_dump_regs(struct seq_file *s) | 2628 | void dispc_dump_regs(struct seq_file *s) |
2337 | { | 2629 | { |
2338 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r)) | 2630 | #define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r)) |
2339 | 2631 | ||
2340 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 2632 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
2341 | 2633 | ||
2342 | DUMPREG(DISPC_REVISION); | 2634 | DUMPREG(DISPC_REVISION); |
2343 | DUMPREG(DISPC_SYSCONFIG); | 2635 | DUMPREG(DISPC_SYSCONFIG); |
@@ -2347,139 +2639,234 @@ void dispc_dump_regs(struct seq_file *s) | |||
2347 | DUMPREG(DISPC_CONTROL); | 2639 | DUMPREG(DISPC_CONTROL); |
2348 | DUMPREG(DISPC_CONFIG); | 2640 | DUMPREG(DISPC_CONFIG); |
2349 | DUMPREG(DISPC_CAPABLE); | 2641 | DUMPREG(DISPC_CAPABLE); |
2350 | DUMPREG(DISPC_DEFAULT_COLOR0); | 2642 | DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD)); |
2351 | DUMPREG(DISPC_DEFAULT_COLOR1); | 2643 | DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT)); |
2352 | DUMPREG(DISPC_TRANS_COLOR0); | 2644 | DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD)); |
2353 | DUMPREG(DISPC_TRANS_COLOR1); | 2645 | DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT)); |
2354 | DUMPREG(DISPC_LINE_STATUS); | 2646 | DUMPREG(DISPC_LINE_STATUS); |
2355 | DUMPREG(DISPC_LINE_NUMBER); | 2647 | DUMPREG(DISPC_LINE_NUMBER); |
2356 | DUMPREG(DISPC_TIMING_H); | 2648 | DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD)); |
2357 | DUMPREG(DISPC_TIMING_V); | 2649 | DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD)); |
2358 | DUMPREG(DISPC_POL_FREQ); | 2650 | DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD)); |
2359 | DUMPREG(DISPC_DIVISOR); | 2651 | DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD)); |
2360 | DUMPREG(DISPC_GLOBAL_ALPHA); | 2652 | DUMPREG(DISPC_GLOBAL_ALPHA); |
2361 | DUMPREG(DISPC_SIZE_DIG); | 2653 | DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); |
2362 | DUMPREG(DISPC_SIZE_LCD); | 2654 | DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD)); |
2363 | 2655 | if (dss_has_feature(FEAT_MGR_LCD2)) { | |
2364 | DUMPREG(DISPC_GFX_BA0); | 2656 | DUMPREG(DISPC_CONTROL2); |
2365 | DUMPREG(DISPC_GFX_BA1); | 2657 | DUMPREG(DISPC_CONFIG2); |
2366 | DUMPREG(DISPC_GFX_POSITION); | 2658 | DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2)); |
2367 | DUMPREG(DISPC_GFX_SIZE); | 2659 | DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2)); |
2368 | DUMPREG(DISPC_GFX_ATTRIBUTES); | 2660 | DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD2)); |
2369 | DUMPREG(DISPC_GFX_FIFO_THRESHOLD); | 2661 | DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD2)); |
2370 | DUMPREG(DISPC_GFX_FIFO_SIZE_STATUS); | 2662 | DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD2)); |
2371 | DUMPREG(DISPC_GFX_ROW_INC); | 2663 | DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD2)); |
2372 | DUMPREG(DISPC_GFX_PIXEL_INC); | 2664 | DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD2)); |
2373 | DUMPREG(DISPC_GFX_WINDOW_SKIP); | 2665 | } |
2374 | DUMPREG(DISPC_GFX_TABLE_BA); | 2666 | |
2375 | 2667 | DUMPREG(DISPC_OVL_BA0(OMAP_DSS_GFX)); | |
2376 | DUMPREG(DISPC_DATA_CYCLE1); | 2668 | DUMPREG(DISPC_OVL_BA1(OMAP_DSS_GFX)); |
2377 | DUMPREG(DISPC_DATA_CYCLE2); | 2669 | DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_GFX)); |
2378 | DUMPREG(DISPC_DATA_CYCLE3); | 2670 | DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_GFX)); |
2379 | 2671 | DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_GFX)); | |
2380 | DUMPREG(DISPC_CPR_COEF_R); | 2672 | DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_GFX)); |
2381 | DUMPREG(DISPC_CPR_COEF_G); | 2673 | DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_GFX)); |
2382 | DUMPREG(DISPC_CPR_COEF_B); | 2674 | DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_GFX)); |
2383 | 2675 | DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_GFX)); | |
2384 | DUMPREG(DISPC_GFX_PRELOAD); | 2676 | DUMPREG(DISPC_OVL_WINDOW_SKIP(OMAP_DSS_GFX)); |
2385 | 2677 | DUMPREG(DISPC_OVL_TABLE_BA(OMAP_DSS_GFX)); | |
2386 | DUMPREG(DISPC_VID_BA0(0)); | 2678 | |
2387 | DUMPREG(DISPC_VID_BA1(0)); | 2679 | DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD)); |
2388 | DUMPREG(DISPC_VID_POSITION(0)); | 2680 | DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); |
2389 | DUMPREG(DISPC_VID_SIZE(0)); | 2681 | DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); |
2390 | DUMPREG(DISPC_VID_ATTRIBUTES(0)); | 2682 | |
2391 | DUMPREG(DISPC_VID_FIFO_THRESHOLD(0)); | 2683 | DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); |
2392 | DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(0)); | 2684 | DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); |
2393 | DUMPREG(DISPC_VID_ROW_INC(0)); | 2685 | DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); |
2394 | DUMPREG(DISPC_VID_PIXEL_INC(0)); | 2686 | if (dss_has_feature(FEAT_MGR_LCD2)) { |
2395 | DUMPREG(DISPC_VID_FIR(0)); | 2687 | DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); |
2396 | DUMPREG(DISPC_VID_PICTURE_SIZE(0)); | 2688 | DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); |
2397 | DUMPREG(DISPC_VID_ACCU0(0)); | 2689 | DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); |
2398 | DUMPREG(DISPC_VID_ACCU1(0)); | 2690 | |
2399 | 2691 | DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); | |
2400 | DUMPREG(DISPC_VID_BA0(1)); | 2692 | DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); |
2401 | DUMPREG(DISPC_VID_BA1(1)); | 2693 | DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); |
2402 | DUMPREG(DISPC_VID_POSITION(1)); | 2694 | } |
2403 | DUMPREG(DISPC_VID_SIZE(1)); | 2695 | |
2404 | DUMPREG(DISPC_VID_ATTRIBUTES(1)); | 2696 | DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX)); |
2405 | DUMPREG(DISPC_VID_FIFO_THRESHOLD(1)); | 2697 | |
2406 | DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(1)); | 2698 | DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO1)); |
2407 | DUMPREG(DISPC_VID_ROW_INC(1)); | 2699 | DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO1)); |
2408 | DUMPREG(DISPC_VID_PIXEL_INC(1)); | 2700 | DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO1)); |
2409 | DUMPREG(DISPC_VID_FIR(1)); | 2701 | DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO1)); |
2410 | DUMPREG(DISPC_VID_PICTURE_SIZE(1)); | 2702 | DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1)); |
2411 | DUMPREG(DISPC_VID_ACCU0(1)); | 2703 | DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1)); |
2412 | DUMPREG(DISPC_VID_ACCU1(1)); | 2704 | DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO1)); |
2413 | 2705 | DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO1)); | |
2414 | DUMPREG(DISPC_VID_FIR_COEF_H(0, 0)); | 2706 | DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO1)); |
2415 | DUMPREG(DISPC_VID_FIR_COEF_H(0, 1)); | 2707 | DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO1)); |
2416 | DUMPREG(DISPC_VID_FIR_COEF_H(0, 2)); | 2708 | DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1)); |
2417 | DUMPREG(DISPC_VID_FIR_COEF_H(0, 3)); | 2709 | DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO1)); |
2418 | DUMPREG(DISPC_VID_FIR_COEF_H(0, 4)); | 2710 | DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO1)); |
2419 | DUMPREG(DISPC_VID_FIR_COEF_H(0, 5)); | 2711 | |
2420 | DUMPREG(DISPC_VID_FIR_COEF_H(0, 6)); | 2712 | DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO2)); |
2421 | DUMPREG(DISPC_VID_FIR_COEF_H(0, 7)); | 2713 | DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO2)); |
2422 | DUMPREG(DISPC_VID_FIR_COEF_HV(0, 0)); | 2714 | DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO2)); |
2423 | DUMPREG(DISPC_VID_FIR_COEF_HV(0, 1)); | 2715 | DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO2)); |
2424 | DUMPREG(DISPC_VID_FIR_COEF_HV(0, 2)); | 2716 | DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2)); |
2425 | DUMPREG(DISPC_VID_FIR_COEF_HV(0, 3)); | 2717 | DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2)); |
2426 | DUMPREG(DISPC_VID_FIR_COEF_HV(0, 4)); | 2718 | DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO2)); |
2427 | DUMPREG(DISPC_VID_FIR_COEF_HV(0, 5)); | 2719 | DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO2)); |
2428 | DUMPREG(DISPC_VID_FIR_COEF_HV(0, 6)); | 2720 | DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO2)); |
2429 | DUMPREG(DISPC_VID_FIR_COEF_HV(0, 7)); | 2721 | DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO2)); |
2430 | DUMPREG(DISPC_VID_CONV_COEF(0, 0)); | 2722 | DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2)); |
2431 | DUMPREG(DISPC_VID_CONV_COEF(0, 1)); | 2723 | DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO2)); |
2432 | DUMPREG(DISPC_VID_CONV_COEF(0, 2)); | 2724 | DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO2)); |
2433 | DUMPREG(DISPC_VID_CONV_COEF(0, 3)); | 2725 | |
2434 | DUMPREG(DISPC_VID_CONV_COEF(0, 4)); | 2726 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 0)); |
2435 | DUMPREG(DISPC_VID_FIR_COEF_V(0, 0)); | 2727 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 1)); |
2436 | DUMPREG(DISPC_VID_FIR_COEF_V(0, 1)); | 2728 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 2)); |
2437 | DUMPREG(DISPC_VID_FIR_COEF_V(0, 2)); | 2729 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 3)); |
2438 | DUMPREG(DISPC_VID_FIR_COEF_V(0, 3)); | 2730 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 4)); |
2439 | DUMPREG(DISPC_VID_FIR_COEF_V(0, 4)); | 2731 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 5)); |
2440 | DUMPREG(DISPC_VID_FIR_COEF_V(0, 5)); | 2732 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 6)); |
2441 | DUMPREG(DISPC_VID_FIR_COEF_V(0, 6)); | 2733 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 7)); |
2442 | DUMPREG(DISPC_VID_FIR_COEF_V(0, 7)); | 2734 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 0)); |
2443 | 2735 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 1)); | |
2444 | DUMPREG(DISPC_VID_FIR_COEF_H(1, 0)); | 2736 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 2)); |
2445 | DUMPREG(DISPC_VID_FIR_COEF_H(1, 1)); | 2737 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 3)); |
2446 | DUMPREG(DISPC_VID_FIR_COEF_H(1, 2)); | 2738 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 4)); |
2447 | DUMPREG(DISPC_VID_FIR_COEF_H(1, 3)); | 2739 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 5)); |
2448 | DUMPREG(DISPC_VID_FIR_COEF_H(1, 4)); | 2740 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 6)); |
2449 | DUMPREG(DISPC_VID_FIR_COEF_H(1, 5)); | 2741 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 7)); |
2450 | DUMPREG(DISPC_VID_FIR_COEF_H(1, 6)); | 2742 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0)); |
2451 | DUMPREG(DISPC_VID_FIR_COEF_H(1, 7)); | 2743 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1)); |
2452 | DUMPREG(DISPC_VID_FIR_COEF_HV(1, 0)); | 2744 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2)); |
2453 | DUMPREG(DISPC_VID_FIR_COEF_HV(1, 1)); | 2745 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3)); |
2454 | DUMPREG(DISPC_VID_FIR_COEF_HV(1, 2)); | 2746 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4)); |
2455 | DUMPREG(DISPC_VID_FIR_COEF_HV(1, 3)); | 2747 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0)); |
2456 | DUMPREG(DISPC_VID_FIR_COEF_HV(1, 4)); | 2748 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1)); |
2457 | DUMPREG(DISPC_VID_FIR_COEF_HV(1, 5)); | 2749 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2)); |
2458 | DUMPREG(DISPC_VID_FIR_COEF_HV(1, 6)); | 2750 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3)); |
2459 | DUMPREG(DISPC_VID_FIR_COEF_HV(1, 7)); | 2751 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4)); |
2460 | DUMPREG(DISPC_VID_CONV_COEF(1, 0)); | 2752 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5)); |
2461 | DUMPREG(DISPC_VID_CONV_COEF(1, 1)); | 2753 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6)); |
2462 | DUMPREG(DISPC_VID_CONV_COEF(1, 2)); | 2754 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7)); |
2463 | DUMPREG(DISPC_VID_CONV_COEF(1, 3)); | 2755 | |
2464 | DUMPREG(DISPC_VID_CONV_COEF(1, 4)); | 2756 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { |
2465 | DUMPREG(DISPC_VID_FIR_COEF_V(1, 0)); | 2757 | DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO1)); |
2466 | DUMPREG(DISPC_VID_FIR_COEF_V(1, 1)); | 2758 | DUMPREG(DISPC_OVL_BA1_UV(OMAP_DSS_VIDEO1)); |
2467 | DUMPREG(DISPC_VID_FIR_COEF_V(1, 2)); | 2759 | DUMPREG(DISPC_OVL_FIR2(OMAP_DSS_VIDEO1)); |
2468 | DUMPREG(DISPC_VID_FIR_COEF_V(1, 3)); | 2760 | DUMPREG(DISPC_OVL_ACCU2_0(OMAP_DSS_VIDEO1)); |
2469 | DUMPREG(DISPC_VID_FIR_COEF_V(1, 4)); | 2761 | DUMPREG(DISPC_OVL_ACCU2_1(OMAP_DSS_VIDEO1)); |
2470 | DUMPREG(DISPC_VID_FIR_COEF_V(1, 5)); | 2762 | |
2471 | DUMPREG(DISPC_VID_FIR_COEF_V(1, 6)); | 2763 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 0)); |
2472 | DUMPREG(DISPC_VID_FIR_COEF_V(1, 7)); | 2764 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 1)); |
2473 | 2765 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 2)); | |
2474 | DUMPREG(DISPC_VID_PRELOAD(0)); | 2766 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 3)); |
2475 | DUMPREG(DISPC_VID_PRELOAD(1)); | 2767 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 4)); |
2476 | 2768 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 5)); | |
2477 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 2769 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 6)); |
2770 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 7)); | ||
2771 | |||
2772 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 0)); | ||
2773 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 1)); | ||
2774 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 2)); | ||
2775 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 3)); | ||
2776 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 4)); | ||
2777 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 5)); | ||
2778 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 6)); | ||
2779 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 7)); | ||
2780 | |||
2781 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 0)); | ||
2782 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 1)); | ||
2783 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 2)); | ||
2784 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 3)); | ||
2785 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 4)); | ||
2786 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 5)); | ||
2787 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 6)); | ||
2788 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 7)); | ||
2789 | } | ||
2790 | if (dss_has_feature(FEAT_ATTR2)) | ||
2791 | DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1)); | ||
2792 | |||
2793 | |||
2794 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 0)); | ||
2795 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 1)); | ||
2796 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 2)); | ||
2797 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 3)); | ||
2798 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 4)); | ||
2799 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 5)); | ||
2800 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 6)); | ||
2801 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 7)); | ||
2802 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 0)); | ||
2803 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 1)); | ||
2804 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 2)); | ||
2805 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 3)); | ||
2806 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 4)); | ||
2807 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 5)); | ||
2808 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 6)); | ||
2809 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 7)); | ||
2810 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0)); | ||
2811 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1)); | ||
2812 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2)); | ||
2813 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3)); | ||
2814 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4)); | ||
2815 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0)); | ||
2816 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1)); | ||
2817 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2)); | ||
2818 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3)); | ||
2819 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4)); | ||
2820 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5)); | ||
2821 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6)); | ||
2822 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7)); | ||
2823 | |||
2824 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { | ||
2825 | DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO2)); | ||
2826 | DUMPREG(DISPC_OVL_BA1_UV(OMAP_DSS_VIDEO2)); | ||
2827 | DUMPREG(DISPC_OVL_FIR2(OMAP_DSS_VIDEO2)); | ||
2828 | DUMPREG(DISPC_OVL_ACCU2_0(OMAP_DSS_VIDEO2)); | ||
2829 | DUMPREG(DISPC_OVL_ACCU2_1(OMAP_DSS_VIDEO2)); | ||
2830 | |||
2831 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 0)); | ||
2832 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 1)); | ||
2833 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 2)); | ||
2834 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 3)); | ||
2835 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 4)); | ||
2836 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 5)); | ||
2837 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 6)); | ||
2838 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 7)); | ||
2839 | |||
2840 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 0)); | ||
2841 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 1)); | ||
2842 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 2)); | ||
2843 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 3)); | ||
2844 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 4)); | ||
2845 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 5)); | ||
2846 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 6)); | ||
2847 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 7)); | ||
2848 | |||
2849 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 0)); | ||
2850 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 1)); | ||
2851 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 2)); | ||
2852 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 3)); | ||
2853 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 4)); | ||
2854 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 5)); | ||
2855 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 6)); | ||
2856 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 7)); | ||
2857 | } | ||
2858 | if (dss_has_feature(FEAT_ATTR2)) | ||
2859 | DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); | ||
2860 | |||
2861 | DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1)); | ||
2862 | DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2)); | ||
2863 | |||
2864 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); | ||
2478 | #undef DUMPREG | 2865 | #undef DUMPREG |
2479 | } | 2866 | } |
2480 | 2867 | ||
2481 | static void _dispc_set_pol_freq(bool onoff, bool rf, bool ieo, bool ipc, | 2868 | static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf, |
2482 | bool ihs, bool ivs, u8 acbi, u8 acb) | 2869 | bool ieo, bool ipc, bool ihs, bool ivs, u8 acbi, u8 acb) |
2483 | { | 2870 | { |
2484 | u32 l = 0; | 2871 | u32 l = 0; |
2485 | 2872 | ||
@@ -2496,13 +2883,14 @@ static void _dispc_set_pol_freq(bool onoff, bool rf, bool ieo, bool ipc, | |||
2496 | l |= FLD_VAL(acb, 7, 0); | 2883 | l |= FLD_VAL(acb, 7, 0); |
2497 | 2884 | ||
2498 | enable_clocks(1); | 2885 | enable_clocks(1); |
2499 | dispc_write_reg(DISPC_POL_FREQ, l); | 2886 | dispc_write_reg(DISPC_POL_FREQ(channel), l); |
2500 | enable_clocks(0); | 2887 | enable_clocks(0); |
2501 | } | 2888 | } |
2502 | 2889 | ||
2503 | void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb) | 2890 | void dispc_set_pol_freq(enum omap_channel channel, |
2891 | enum omap_panel_config config, u8 acbi, u8 acb) | ||
2504 | { | 2892 | { |
2505 | _dispc_set_pol_freq((config & OMAP_DSS_LCD_ONOFF) != 0, | 2893 | _dispc_set_pol_freq(channel, (config & OMAP_DSS_LCD_ONOFF) != 0, |
2506 | (config & OMAP_DSS_LCD_RF) != 0, | 2894 | (config & OMAP_DSS_LCD_RF) != 0, |
2507 | (config & OMAP_DSS_LCD_IEO) != 0, | 2895 | (config & OMAP_DSS_LCD_IEO) != 0, |
2508 | (config & OMAP_DSS_LCD_IPC) != 0, | 2896 | (config & OMAP_DSS_LCD_IPC) != 0, |
@@ -2571,24 +2959,26 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, | |||
2571 | return 0; | 2959 | return 0; |
2572 | } | 2960 | } |
2573 | 2961 | ||
2574 | int dispc_set_clock_div(struct dispc_clock_info *cinfo) | 2962 | int dispc_set_clock_div(enum omap_channel channel, |
2963 | struct dispc_clock_info *cinfo) | ||
2575 | { | 2964 | { |
2576 | DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div); | 2965 | DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div); |
2577 | DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div); | 2966 | DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div); |
2578 | 2967 | ||
2579 | dispc_set_lcd_divisor(cinfo->lck_div, cinfo->pck_div); | 2968 | dispc_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div); |
2580 | 2969 | ||
2581 | return 0; | 2970 | return 0; |
2582 | } | 2971 | } |
2583 | 2972 | ||
2584 | int dispc_get_clock_div(struct dispc_clock_info *cinfo) | 2973 | int dispc_get_clock_div(enum omap_channel channel, |
2974 | struct dispc_clock_info *cinfo) | ||
2585 | { | 2975 | { |
2586 | unsigned long fck; | 2976 | unsigned long fck; |
2587 | 2977 | ||
2588 | fck = dispc_fclk_rate(); | 2978 | fck = dispc_fclk_rate(); |
2589 | 2979 | ||
2590 | cinfo->lck_div = REG_GET(DISPC_DIVISOR, 23, 16); | 2980 | cinfo->lck_div = REG_GET(DISPC_DIVISORo(channel), 23, 16); |
2591 | cinfo->pck_div = REG_GET(DISPC_DIVISOR, 7, 0); | 2981 | cinfo->pck_div = REG_GET(DISPC_DIVISORo(channel), 7, 0); |
2592 | 2982 | ||
2593 | cinfo->lck = fck / cinfo->lck_div; | 2983 | cinfo->lck = fck / cinfo->lck_div; |
2594 | cinfo->pck = cinfo->lck / cinfo->pck_div; | 2984 | cinfo->pck = cinfo->lck / cinfo->pck_div; |
@@ -2665,6 +3055,9 @@ int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask) | |||
2665 | break; | 3055 | break; |
2666 | } | 3056 | } |
2667 | 3057 | ||
3058 | if (ret) | ||
3059 | goto err; | ||
3060 | |||
2668 | _omap_dispc_set_irqs(); | 3061 | _omap_dispc_set_irqs(); |
2669 | 3062 | ||
2670 | spin_unlock_irqrestore(&dispc.irq_lock, flags); | 3063 | spin_unlock_irqrestore(&dispc.irq_lock, flags); |
@@ -2728,6 +3121,8 @@ static void print_irq_status(u32 status) | |||
2728 | PIS(VID2_FIFO_UNDERFLOW); | 3121 | PIS(VID2_FIFO_UNDERFLOW); |
2729 | PIS(SYNC_LOST); | 3122 | PIS(SYNC_LOST); |
2730 | PIS(SYNC_LOST_DIGIT); | 3123 | PIS(SYNC_LOST_DIGIT); |
3124 | if (dss_has_feature(FEAT_MGR_LCD2)) | ||
3125 | PIS(SYNC_LOST2); | ||
2731 | #undef PIS | 3126 | #undef PIS |
2732 | 3127 | ||
2733 | printk("\n"); | 3128 | printk("\n"); |
@@ -2738,10 +3133,10 @@ static void print_irq_status(u32 status) | |||
2738 | * but we presume they are on because we got an IRQ. However, | 3133 | * but we presume they are on because we got an IRQ. However, |
2739 | * an irq handler may turn the clocks off, so we may not have | 3134 | * an irq handler may turn the clocks off, so we may not have |
2740 | * clock later in the function. */ | 3135 | * clock later in the function. */ |
2741 | void dispc_irq_handler(void) | 3136 | static irqreturn_t omap_dispc_irq_handler(int irq, void *arg) |
2742 | { | 3137 | { |
2743 | int i; | 3138 | int i; |
2744 | u32 irqstatus; | 3139 | u32 irqstatus, irqenable; |
2745 | u32 handledirqs = 0; | 3140 | u32 handledirqs = 0; |
2746 | u32 unhandled_errors; | 3141 | u32 unhandled_errors; |
2747 | struct omap_dispc_isr_data *isr_data; | 3142 | struct omap_dispc_isr_data *isr_data; |
@@ -2750,6 +3145,13 @@ void dispc_irq_handler(void) | |||
2750 | spin_lock(&dispc.irq_lock); | 3145 | spin_lock(&dispc.irq_lock); |
2751 | 3146 | ||
2752 | irqstatus = dispc_read_reg(DISPC_IRQSTATUS); | 3147 | irqstatus = dispc_read_reg(DISPC_IRQSTATUS); |
3148 | irqenable = dispc_read_reg(DISPC_IRQENABLE); | ||
3149 | |||
3150 | /* IRQ is not for us */ | ||
3151 | if (!(irqstatus & irqenable)) { | ||
3152 | spin_unlock(&dispc.irq_lock); | ||
3153 | return IRQ_NONE; | ||
3154 | } | ||
2753 | 3155 | ||
2754 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 3156 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS |
2755 | spin_lock(&dispc.irq_stats_lock); | 3157 | spin_lock(&dispc.irq_stats_lock); |
@@ -2801,6 +3203,8 @@ void dispc_irq_handler(void) | |||
2801 | } | 3203 | } |
2802 | 3204 | ||
2803 | spin_unlock(&dispc.irq_lock); | 3205 | spin_unlock(&dispc.irq_lock); |
3206 | |||
3207 | return IRQ_HANDLED; | ||
2804 | } | 3208 | } |
2805 | 3209 | ||
2806 | static void dispc_error_worker(struct work_struct *work) | 3210 | static void dispc_error_worker(struct work_struct *work) |
@@ -2946,6 +3350,45 @@ static void dispc_error_worker(struct work_struct *work) | |||
2946 | } | 3350 | } |
2947 | } | 3351 | } |
2948 | 3352 | ||
3353 | if (errors & DISPC_IRQ_SYNC_LOST2) { | ||
3354 | struct omap_overlay_manager *manager = NULL; | ||
3355 | bool enable = false; | ||
3356 | |||
3357 | DSSERR("SYNC_LOST for LCD2, disabling LCD2\n"); | ||
3358 | |||
3359 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { | ||
3360 | struct omap_overlay_manager *mgr; | ||
3361 | mgr = omap_dss_get_overlay_manager(i); | ||
3362 | |||
3363 | if (mgr->id == OMAP_DSS_CHANNEL_LCD2) { | ||
3364 | manager = mgr; | ||
3365 | enable = mgr->device->state == | ||
3366 | OMAP_DSS_DISPLAY_ACTIVE; | ||
3367 | mgr->device->driver->disable(mgr->device); | ||
3368 | break; | ||
3369 | } | ||
3370 | } | ||
3371 | |||
3372 | if (manager) { | ||
3373 | struct omap_dss_device *dssdev = manager->device; | ||
3374 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) { | ||
3375 | struct omap_overlay *ovl; | ||
3376 | ovl = omap_dss_get_overlay(i); | ||
3377 | |||
3378 | if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) | ||
3379 | continue; | ||
3380 | |||
3381 | if (ovl->id != 0 && ovl->manager == manager) | ||
3382 | dispc_enable_plane(ovl->id, 0); | ||
3383 | } | ||
3384 | |||
3385 | dispc_go(manager->id); | ||
3386 | mdelay(50); | ||
3387 | if (enable) | ||
3388 | dssdev->driver->enable(dssdev); | ||
3389 | } | ||
3390 | } | ||
3391 | |||
2949 | if (errors & DISPC_IRQ_OCP_ERR) { | 3392 | if (errors & DISPC_IRQ_OCP_ERR) { |
2950 | DSSERR("OCP_ERR\n"); | 3393 | DSSERR("OCP_ERR\n"); |
2951 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { | 3394 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { |
@@ -3053,6 +3496,8 @@ static void _omap_dispc_initialize_irq(void) | |||
3053 | memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr)); | 3496 | memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr)); |
3054 | 3497 | ||
3055 | dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; | 3498 | dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; |
3499 | if (dss_has_feature(FEAT_MGR_LCD2)) | ||
3500 | dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2; | ||
3056 | 3501 | ||
3057 | /* there's SYNC_LOST_DIGIT waiting after enabling the DSS, | 3502 | /* there's SYNC_LOST_DIGIT waiting after enabling the DSS, |
3058 | * so clear it */ | 3503 | * so clear it */ |
@@ -3084,8 +3529,18 @@ static void _omap_dispc_initial_config(void) | |||
3084 | l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */ | 3529 | l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */ |
3085 | dispc_write_reg(DISPC_SYSCONFIG, l); | 3530 | dispc_write_reg(DISPC_SYSCONFIG, l); |
3086 | 3531 | ||
3532 | /* Exclusively enable DISPC_CORE_CLK and set divider to 1 */ | ||
3533 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) { | ||
3534 | l = dispc_read_reg(DISPC_DIVISOR); | ||
3535 | /* Use DISPC_DIVISOR.LCD, instead of DISPC_DIVISOR1.LCD */ | ||
3536 | l = FLD_MOD(l, 1, 0, 0); | ||
3537 | l = FLD_MOD(l, 1, 23, 16); | ||
3538 | dispc_write_reg(DISPC_DIVISOR, l); | ||
3539 | } | ||
3540 | |||
3087 | /* FUNCGATED */ | 3541 | /* FUNCGATED */ |
3088 | REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); | 3542 | if (dss_has_feature(FEAT_FUNCGATED)) |
3543 | REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); | ||
3089 | 3544 | ||
3090 | /* L3 firewall setting: enable access to OCM RAM */ | 3545 | /* L3 firewall setting: enable access to OCM RAM */ |
3091 | /* XXX this should be somewhere in plat-omap */ | 3546 | /* XXX this should be somewhere in plat-omap */ |
@@ -3099,47 +3554,6 @@ static void _omap_dispc_initial_config(void) | |||
3099 | dispc_read_plane_fifo_sizes(); | 3554 | dispc_read_plane_fifo_sizes(); |
3100 | } | 3555 | } |
3101 | 3556 | ||
3102 | int dispc_init(void) | ||
3103 | { | ||
3104 | u32 rev; | ||
3105 | |||
3106 | spin_lock_init(&dispc.irq_lock); | ||
3107 | |||
3108 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
3109 | spin_lock_init(&dispc.irq_stats_lock); | ||
3110 | dispc.irq_stats.last_reset = jiffies; | ||
3111 | #endif | ||
3112 | |||
3113 | INIT_WORK(&dispc.error_work, dispc_error_worker); | ||
3114 | |||
3115 | dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS); | ||
3116 | if (!dispc.base) { | ||
3117 | DSSERR("can't ioremap DISPC\n"); | ||
3118 | return -ENOMEM; | ||
3119 | } | ||
3120 | |||
3121 | enable_clocks(1); | ||
3122 | |||
3123 | _omap_dispc_initial_config(); | ||
3124 | |||
3125 | _omap_dispc_initialize_irq(); | ||
3126 | |||
3127 | dispc_save_context(); | ||
3128 | |||
3129 | rev = dispc_read_reg(DISPC_REVISION); | ||
3130 | printk(KERN_INFO "OMAP DISPC rev %d.%d\n", | ||
3131 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | ||
3132 | |||
3133 | enable_clocks(0); | ||
3134 | |||
3135 | return 0; | ||
3136 | } | ||
3137 | |||
3138 | void dispc_exit(void) | ||
3139 | { | ||
3140 | iounmap(dispc.base); | ||
3141 | } | ||
3142 | |||
3143 | int dispc_enable_plane(enum omap_plane plane, bool enable) | 3557 | int dispc_enable_plane(enum omap_plane plane, bool enable) |
3144 | { | 3558 | { |
3145 | DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); | 3559 | DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); |
@@ -3159,17 +3573,19 @@ int dispc_setup_plane(enum omap_plane plane, | |||
3159 | enum omap_color_mode color_mode, | 3573 | enum omap_color_mode color_mode, |
3160 | bool ilace, | 3574 | bool ilace, |
3161 | enum omap_dss_rotation_type rotation_type, | 3575 | enum omap_dss_rotation_type rotation_type, |
3162 | u8 rotation, bool mirror, u8 global_alpha) | 3576 | u8 rotation, bool mirror, u8 global_alpha, |
3577 | u8 pre_mult_alpha, enum omap_channel channel, | ||
3578 | u32 puv_addr) | ||
3163 | { | 3579 | { |
3164 | int r = 0; | 3580 | int r = 0; |
3165 | 3581 | ||
3166 | DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> " | 3582 | DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d, %d, %dx%d -> " |
3167 | "%dx%d, ilace %d, cmode %x, rot %d, mir %d\n", | 3583 | "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n", |
3168 | plane, paddr, screen_width, pos_x, pos_y, | 3584 | plane, paddr, screen_width, pos_x, pos_y, |
3169 | width, height, | 3585 | width, height, |
3170 | out_width, out_height, | 3586 | out_width, out_height, |
3171 | ilace, color_mode, | 3587 | ilace, color_mode, |
3172 | rotation, mirror); | 3588 | rotation, mirror, channel); |
3173 | 3589 | ||
3174 | enable_clocks(1); | 3590 | enable_clocks(1); |
3175 | 3591 | ||
@@ -3181,9 +3597,102 @@ int dispc_setup_plane(enum omap_plane plane, | |||
3181 | color_mode, ilace, | 3597 | color_mode, ilace, |
3182 | rotation_type, | 3598 | rotation_type, |
3183 | rotation, mirror, | 3599 | rotation, mirror, |
3184 | global_alpha); | 3600 | global_alpha, |
3601 | pre_mult_alpha, | ||
3602 | channel, puv_addr); | ||
3185 | 3603 | ||
3186 | enable_clocks(0); | 3604 | enable_clocks(0); |
3187 | 3605 | ||
3188 | return r; | 3606 | return r; |
3189 | } | 3607 | } |
3608 | |||
3609 | /* DISPC HW IP initialisation */ | ||
3610 | static int omap_dispchw_probe(struct platform_device *pdev) | ||
3611 | { | ||
3612 | u32 rev; | ||
3613 | int r = 0; | ||
3614 | struct resource *dispc_mem; | ||
3615 | |||
3616 | dispc.pdev = pdev; | ||
3617 | |||
3618 | spin_lock_init(&dispc.irq_lock); | ||
3619 | |||
3620 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
3621 | spin_lock_init(&dispc.irq_stats_lock); | ||
3622 | dispc.irq_stats.last_reset = jiffies; | ||
3623 | #endif | ||
3624 | |||
3625 | INIT_WORK(&dispc.error_work, dispc_error_worker); | ||
3626 | |||
3627 | dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0); | ||
3628 | if (!dispc_mem) { | ||
3629 | DSSERR("can't get IORESOURCE_MEM DISPC\n"); | ||
3630 | r = -EINVAL; | ||
3631 | goto fail0; | ||
3632 | } | ||
3633 | dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem)); | ||
3634 | if (!dispc.base) { | ||
3635 | DSSERR("can't ioremap DISPC\n"); | ||
3636 | r = -ENOMEM; | ||
3637 | goto fail0; | ||
3638 | } | ||
3639 | dispc.irq = platform_get_irq(dispc.pdev, 0); | ||
3640 | if (dispc.irq < 0) { | ||
3641 | DSSERR("platform_get_irq failed\n"); | ||
3642 | r = -ENODEV; | ||
3643 | goto fail1; | ||
3644 | } | ||
3645 | |||
3646 | r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED, | ||
3647 | "OMAP DISPC", dispc.pdev); | ||
3648 | if (r < 0) { | ||
3649 | DSSERR("request_irq failed\n"); | ||
3650 | goto fail1; | ||
3651 | } | ||
3652 | |||
3653 | enable_clocks(1); | ||
3654 | |||
3655 | _omap_dispc_initial_config(); | ||
3656 | |||
3657 | _omap_dispc_initialize_irq(); | ||
3658 | |||
3659 | dispc_save_context(); | ||
3660 | |||
3661 | rev = dispc_read_reg(DISPC_REVISION); | ||
3662 | dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n", | ||
3663 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | ||
3664 | |||
3665 | enable_clocks(0); | ||
3666 | |||
3667 | return 0; | ||
3668 | fail1: | ||
3669 | iounmap(dispc.base); | ||
3670 | fail0: | ||
3671 | return r; | ||
3672 | } | ||
3673 | |||
3674 | static int omap_dispchw_remove(struct platform_device *pdev) | ||
3675 | { | ||
3676 | free_irq(dispc.irq, dispc.pdev); | ||
3677 | iounmap(dispc.base); | ||
3678 | return 0; | ||
3679 | } | ||
3680 | |||
3681 | static struct platform_driver omap_dispchw_driver = { | ||
3682 | .probe = omap_dispchw_probe, | ||
3683 | .remove = omap_dispchw_remove, | ||
3684 | .driver = { | ||
3685 | .name = "omapdss_dispc", | ||
3686 | .owner = THIS_MODULE, | ||
3687 | }, | ||
3688 | }; | ||
3689 | |||
3690 | int dispc_init_platform_driver(void) | ||
3691 | { | ||
3692 | return platform_driver_register(&omap_dispchw_driver); | ||
3693 | } | ||
3694 | |||
3695 | void dispc_uninit_platform_driver(void) | ||
3696 | { | ||
3697 | return platform_driver_unregister(&omap_dispchw_driver); | ||
3698 | } | ||
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h new file mode 100644 index 000000000000..6c9ee0a0efb3 --- /dev/null +++ b/drivers/video/omap2/dss/dispc.h | |||
@@ -0,0 +1,691 @@ | |||
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 | |||
40 | /* DISPC overlay registers */ | ||
41 | #define DISPC_OVL_BA0(n) (DISPC_OVL_BASE(n) + \ | ||
42 | DISPC_BA0_OFFSET(n)) | ||
43 | #define DISPC_OVL_BA1(n) (DISPC_OVL_BASE(n) + \ | ||
44 | DISPC_BA1_OFFSET(n)) | ||
45 | #define DISPC_OVL_BA0_UV(n) (DISPC_OVL_BASE(n) + \ | ||
46 | DISPC_BA0_UV_OFFSET(n)) | ||
47 | #define DISPC_OVL_BA1_UV(n) (DISPC_OVL_BASE(n) + \ | ||
48 | DISPC_BA1_UV_OFFSET(n)) | ||
49 | #define DISPC_OVL_POSITION(n) (DISPC_OVL_BASE(n) + \ | ||
50 | DISPC_POS_OFFSET(n)) | ||
51 | #define DISPC_OVL_SIZE(n) (DISPC_OVL_BASE(n) + \ | ||
52 | DISPC_SIZE_OFFSET(n)) | ||
53 | #define DISPC_OVL_ATTRIBUTES(n) (DISPC_OVL_BASE(n) + \ | ||
54 | DISPC_ATTR_OFFSET(n)) | ||
55 | #define DISPC_OVL_ATTRIBUTES2(n) (DISPC_OVL_BASE(n) + \ | ||
56 | DISPC_ATTR2_OFFSET(n)) | ||
57 | #define DISPC_OVL_FIFO_THRESHOLD(n) (DISPC_OVL_BASE(n) + \ | ||
58 | DISPC_FIFO_THRESH_OFFSET(n)) | ||
59 | #define DISPC_OVL_FIFO_SIZE_STATUS(n) (DISPC_OVL_BASE(n) + \ | ||
60 | DISPC_FIFO_SIZE_STATUS_OFFSET(n)) | ||
61 | #define DISPC_OVL_ROW_INC(n) (DISPC_OVL_BASE(n) + \ | ||
62 | DISPC_ROW_INC_OFFSET(n)) | ||
63 | #define DISPC_OVL_PIXEL_INC(n) (DISPC_OVL_BASE(n) + \ | ||
64 | DISPC_PIX_INC_OFFSET(n)) | ||
65 | #define DISPC_OVL_WINDOW_SKIP(n) (DISPC_OVL_BASE(n) + \ | ||
66 | DISPC_WINDOW_SKIP_OFFSET(n)) | ||
67 | #define DISPC_OVL_TABLE_BA(n) (DISPC_OVL_BASE(n) + \ | ||
68 | DISPC_TABLE_BA_OFFSET(n)) | ||
69 | #define DISPC_OVL_FIR(n) (DISPC_OVL_BASE(n) + \ | ||
70 | DISPC_FIR_OFFSET(n)) | ||
71 | #define DISPC_OVL_FIR2(n) (DISPC_OVL_BASE(n) + \ | ||
72 | DISPC_FIR2_OFFSET(n)) | ||
73 | #define DISPC_OVL_PICTURE_SIZE(n) (DISPC_OVL_BASE(n) + \ | ||
74 | DISPC_PIC_SIZE_OFFSET(n)) | ||
75 | #define DISPC_OVL_ACCU0(n) (DISPC_OVL_BASE(n) + \ | ||
76 | DISPC_ACCU0_OFFSET(n)) | ||
77 | #define DISPC_OVL_ACCU1(n) (DISPC_OVL_BASE(n) + \ | ||
78 | DISPC_ACCU1_OFFSET(n)) | ||
79 | #define DISPC_OVL_ACCU2_0(n) (DISPC_OVL_BASE(n) + \ | ||
80 | DISPC_ACCU2_0_OFFSET(n)) | ||
81 | #define DISPC_OVL_ACCU2_1(n) (DISPC_OVL_BASE(n) + \ | ||
82 | DISPC_ACCU2_1_OFFSET(n)) | ||
83 | #define DISPC_OVL_FIR_COEF_H(n, i) (DISPC_OVL_BASE(n) + \ | ||
84 | DISPC_FIR_COEF_H_OFFSET(n, i)) | ||
85 | #define DISPC_OVL_FIR_COEF_HV(n, i) (DISPC_OVL_BASE(n) + \ | ||
86 | DISPC_FIR_COEF_HV_OFFSET(n, i)) | ||
87 | #define DISPC_OVL_FIR_COEF_H2(n, i) (DISPC_OVL_BASE(n) + \ | ||
88 | DISPC_FIR_COEF_H2_OFFSET(n, i)) | ||
89 | #define DISPC_OVL_FIR_COEF_HV2(n, i) (DISPC_OVL_BASE(n) + \ | ||
90 | DISPC_FIR_COEF_HV2_OFFSET(n, i)) | ||
91 | #define DISPC_OVL_CONV_COEF(n, i) (DISPC_OVL_BASE(n) + \ | ||
92 | DISPC_CONV_COEF_OFFSET(n, i)) | ||
93 | #define DISPC_OVL_FIR_COEF_V(n, i) (DISPC_OVL_BASE(n) + \ | ||
94 | DISPC_FIR_COEF_V_OFFSET(n, i)) | ||
95 | #define DISPC_OVL_FIR_COEF_V2(n, i) (DISPC_OVL_BASE(n) + \ | ||
96 | DISPC_FIR_COEF_V2_OFFSET(n, i)) | ||
97 | #define DISPC_OVL_PRELOAD(n) (DISPC_OVL_BASE(n) + \ | ||
98 | DISPC_PRELOAD_OFFSET(n)) | ||
99 | |||
100 | /* DISPC manager/channel specific registers */ | ||
101 | static inline u16 DISPC_DEFAULT_COLOR(enum omap_channel channel) | ||
102 | { | ||
103 | switch (channel) { | ||
104 | case OMAP_DSS_CHANNEL_LCD: | ||
105 | return 0x004C; | ||
106 | case OMAP_DSS_CHANNEL_DIGIT: | ||
107 | return 0x0050; | ||
108 | case OMAP_DSS_CHANNEL_LCD2: | ||
109 | return 0x03AC; | ||
110 | default: | ||
111 | BUG(); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | static inline u16 DISPC_TRANS_COLOR(enum omap_channel channel) | ||
116 | { | ||
117 | switch (channel) { | ||
118 | case OMAP_DSS_CHANNEL_LCD: | ||
119 | return 0x0054; | ||
120 | case OMAP_DSS_CHANNEL_DIGIT: | ||
121 | return 0x0058; | ||
122 | case OMAP_DSS_CHANNEL_LCD2: | ||
123 | return 0x03B0; | ||
124 | default: | ||
125 | BUG(); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | static inline u16 DISPC_TIMING_H(enum omap_channel channel) | ||
130 | { | ||
131 | switch (channel) { | ||
132 | case OMAP_DSS_CHANNEL_LCD: | ||
133 | return 0x0064; | ||
134 | case OMAP_DSS_CHANNEL_DIGIT: | ||
135 | BUG(); | ||
136 | case OMAP_DSS_CHANNEL_LCD2: | ||
137 | return 0x0400; | ||
138 | default: | ||
139 | BUG(); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | static inline u16 DISPC_TIMING_V(enum omap_channel channel) | ||
144 | { | ||
145 | switch (channel) { | ||
146 | case OMAP_DSS_CHANNEL_LCD: | ||
147 | return 0x0068; | ||
148 | case OMAP_DSS_CHANNEL_DIGIT: | ||
149 | BUG(); | ||
150 | case OMAP_DSS_CHANNEL_LCD2: | ||
151 | return 0x0404; | ||
152 | default: | ||
153 | BUG(); | ||
154 | } | ||
155 | } | ||
156 | |||
157 | static inline u16 DISPC_POL_FREQ(enum omap_channel channel) | ||
158 | { | ||
159 | switch (channel) { | ||
160 | case OMAP_DSS_CHANNEL_LCD: | ||
161 | return 0x006C; | ||
162 | case OMAP_DSS_CHANNEL_DIGIT: | ||
163 | BUG(); | ||
164 | case OMAP_DSS_CHANNEL_LCD2: | ||
165 | return 0x0408; | ||
166 | default: | ||
167 | BUG(); | ||
168 | } | ||
169 | } | ||
170 | |||
171 | static inline u16 DISPC_DIVISORo(enum omap_channel channel) | ||
172 | { | ||
173 | switch (channel) { | ||
174 | case OMAP_DSS_CHANNEL_LCD: | ||
175 | return 0x0070; | ||
176 | case OMAP_DSS_CHANNEL_DIGIT: | ||
177 | BUG(); | ||
178 | case OMAP_DSS_CHANNEL_LCD2: | ||
179 | return 0x040C; | ||
180 | default: | ||
181 | BUG(); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | /* Named as DISPC_SIZE_LCD, DISPC_SIZE_DIGIT and DISPC_SIZE_LCD2 in TRM */ | ||
186 | static inline u16 DISPC_SIZE_MGR(enum omap_channel channel) | ||
187 | { | ||
188 | switch (channel) { | ||
189 | case OMAP_DSS_CHANNEL_LCD: | ||
190 | return 0x007C; | ||
191 | case OMAP_DSS_CHANNEL_DIGIT: | ||
192 | return 0x0078; | ||
193 | case OMAP_DSS_CHANNEL_LCD2: | ||
194 | return 0x03CC; | ||
195 | default: | ||
196 | BUG(); | ||
197 | } | ||
198 | } | ||
199 | |||
200 | static inline u16 DISPC_DATA_CYCLE1(enum omap_channel channel) | ||
201 | { | ||
202 | switch (channel) { | ||
203 | case OMAP_DSS_CHANNEL_LCD: | ||
204 | return 0x01D4; | ||
205 | case OMAP_DSS_CHANNEL_DIGIT: | ||
206 | BUG(); | ||
207 | case OMAP_DSS_CHANNEL_LCD2: | ||
208 | return 0x03C0; | ||
209 | default: | ||
210 | BUG(); | ||
211 | } | ||
212 | } | ||
213 | |||
214 | static inline u16 DISPC_DATA_CYCLE2(enum omap_channel channel) | ||
215 | { | ||
216 | switch (channel) { | ||
217 | case OMAP_DSS_CHANNEL_LCD: | ||
218 | return 0x01D8; | ||
219 | case OMAP_DSS_CHANNEL_DIGIT: | ||
220 | BUG(); | ||
221 | case OMAP_DSS_CHANNEL_LCD2: | ||
222 | return 0x03C4; | ||
223 | default: | ||
224 | BUG(); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | static inline u16 DISPC_DATA_CYCLE3(enum omap_channel channel) | ||
229 | { | ||
230 | switch (channel) { | ||
231 | case OMAP_DSS_CHANNEL_LCD: | ||
232 | return 0x01DC; | ||
233 | case OMAP_DSS_CHANNEL_DIGIT: | ||
234 | BUG(); | ||
235 | case OMAP_DSS_CHANNEL_LCD2: | ||
236 | return 0x03C8; | ||
237 | default: | ||
238 | BUG(); | ||
239 | } | ||
240 | } | ||
241 | |||
242 | static inline u16 DISPC_CPR_COEF_R(enum omap_channel channel) | ||
243 | { | ||
244 | switch (channel) { | ||
245 | case OMAP_DSS_CHANNEL_LCD: | ||
246 | return 0x0220; | ||
247 | case OMAP_DSS_CHANNEL_DIGIT: | ||
248 | BUG(); | ||
249 | case OMAP_DSS_CHANNEL_LCD2: | ||
250 | return 0x03BC; | ||
251 | default: | ||
252 | BUG(); | ||
253 | } | ||
254 | } | ||
255 | |||
256 | static inline u16 DISPC_CPR_COEF_G(enum omap_channel channel) | ||
257 | { | ||
258 | switch (channel) { | ||
259 | case OMAP_DSS_CHANNEL_LCD: | ||
260 | return 0x0224; | ||
261 | case OMAP_DSS_CHANNEL_DIGIT: | ||
262 | BUG(); | ||
263 | case OMAP_DSS_CHANNEL_LCD2: | ||
264 | return 0x03B8; | ||
265 | default: | ||
266 | BUG(); | ||
267 | } | ||
268 | } | ||
269 | |||
270 | static inline u16 DISPC_CPR_COEF_B(enum omap_channel channel) | ||
271 | { | ||
272 | switch (channel) { | ||
273 | case OMAP_DSS_CHANNEL_LCD: | ||
274 | return 0x0228; | ||
275 | case OMAP_DSS_CHANNEL_DIGIT: | ||
276 | BUG(); | ||
277 | case OMAP_DSS_CHANNEL_LCD2: | ||
278 | return 0x03B4; | ||
279 | default: | ||
280 | BUG(); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | /* DISPC overlay register base addresses */ | ||
285 | static inline u16 DISPC_OVL_BASE(enum omap_plane plane) | ||
286 | { | ||
287 | switch (plane) { | ||
288 | case OMAP_DSS_GFX: | ||
289 | return 0x0080; | ||
290 | case OMAP_DSS_VIDEO1: | ||
291 | return 0x00BC; | ||
292 | case OMAP_DSS_VIDEO2: | ||
293 | return 0x014C; | ||
294 | default: | ||
295 | BUG(); | ||
296 | } | ||
297 | } | ||
298 | |||
299 | /* DISPC overlay register offsets */ | ||
300 | static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane) | ||
301 | { | ||
302 | switch (plane) { | ||
303 | case OMAP_DSS_GFX: | ||
304 | case OMAP_DSS_VIDEO1: | ||
305 | case OMAP_DSS_VIDEO2: | ||
306 | return 0x0000; | ||
307 | default: | ||
308 | BUG(); | ||
309 | } | ||
310 | } | ||
311 | |||
312 | static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane) | ||
313 | { | ||
314 | switch (plane) { | ||
315 | case OMAP_DSS_GFX: | ||
316 | case OMAP_DSS_VIDEO1: | ||
317 | case OMAP_DSS_VIDEO2: | ||
318 | return 0x0004; | ||
319 | default: | ||
320 | BUG(); | ||
321 | } | ||
322 | } | ||
323 | |||
324 | static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane) | ||
325 | { | ||
326 | switch (plane) { | ||
327 | case OMAP_DSS_GFX: | ||
328 | BUG(); | ||
329 | case OMAP_DSS_VIDEO1: | ||
330 | return 0x0544; | ||
331 | case OMAP_DSS_VIDEO2: | ||
332 | return 0x04BC; | ||
333 | default: | ||
334 | BUG(); | ||
335 | } | ||
336 | } | ||
337 | |||
338 | static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane) | ||
339 | { | ||
340 | switch (plane) { | ||
341 | case OMAP_DSS_GFX: | ||
342 | BUG(); | ||
343 | case OMAP_DSS_VIDEO1: | ||
344 | return 0x0548; | ||
345 | case OMAP_DSS_VIDEO2: | ||
346 | return 0x04C0; | ||
347 | default: | ||
348 | BUG(); | ||
349 | } | ||
350 | } | ||
351 | |||
352 | static inline u16 DISPC_POS_OFFSET(enum omap_plane plane) | ||
353 | { | ||
354 | switch (plane) { | ||
355 | case OMAP_DSS_GFX: | ||
356 | case OMAP_DSS_VIDEO1: | ||
357 | case OMAP_DSS_VIDEO2: | ||
358 | return 0x0008; | ||
359 | default: | ||
360 | BUG(); | ||
361 | } | ||
362 | } | ||
363 | |||
364 | static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane) | ||
365 | { | ||
366 | switch (plane) { | ||
367 | case OMAP_DSS_GFX: | ||
368 | case OMAP_DSS_VIDEO1: | ||
369 | case OMAP_DSS_VIDEO2: | ||
370 | return 0x000C; | ||
371 | default: | ||
372 | BUG(); | ||
373 | } | ||
374 | } | ||
375 | |||
376 | static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane) | ||
377 | { | ||
378 | switch (plane) { | ||
379 | case OMAP_DSS_GFX: | ||
380 | return 0x0020; | ||
381 | case OMAP_DSS_VIDEO1: | ||
382 | case OMAP_DSS_VIDEO2: | ||
383 | return 0x0010; | ||
384 | default: | ||
385 | BUG(); | ||
386 | } | ||
387 | } | ||
388 | |||
389 | static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane) | ||
390 | { | ||
391 | switch (plane) { | ||
392 | case OMAP_DSS_GFX: | ||
393 | BUG(); | ||
394 | case OMAP_DSS_VIDEO1: | ||
395 | return 0x0568; | ||
396 | case OMAP_DSS_VIDEO2: | ||
397 | return 0x04DC; | ||
398 | default: | ||
399 | BUG(); | ||
400 | } | ||
401 | } | ||
402 | |||
403 | static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane) | ||
404 | { | ||
405 | switch (plane) { | ||
406 | case OMAP_DSS_GFX: | ||
407 | return 0x0024; | ||
408 | case OMAP_DSS_VIDEO1: | ||
409 | case OMAP_DSS_VIDEO2: | ||
410 | return 0x0014; | ||
411 | default: | ||
412 | BUG(); | ||
413 | } | ||
414 | } | ||
415 | |||
416 | static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane) | ||
417 | { | ||
418 | switch (plane) { | ||
419 | case OMAP_DSS_GFX: | ||
420 | return 0x0028; | ||
421 | case OMAP_DSS_VIDEO1: | ||
422 | case OMAP_DSS_VIDEO2: | ||
423 | return 0x0018; | ||
424 | default: | ||
425 | BUG(); | ||
426 | } | ||
427 | } | ||
428 | |||
429 | static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane) | ||
430 | { | ||
431 | switch (plane) { | ||
432 | case OMAP_DSS_GFX: | ||
433 | return 0x002C; | ||
434 | case OMAP_DSS_VIDEO1: | ||
435 | case OMAP_DSS_VIDEO2: | ||
436 | return 0x001C; | ||
437 | default: | ||
438 | BUG(); | ||
439 | } | ||
440 | } | ||
441 | |||
442 | static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane) | ||
443 | { | ||
444 | switch (plane) { | ||
445 | case OMAP_DSS_GFX: | ||
446 | return 0x0030; | ||
447 | case OMAP_DSS_VIDEO1: | ||
448 | case OMAP_DSS_VIDEO2: | ||
449 | return 0x0020; | ||
450 | default: | ||
451 | BUG(); | ||
452 | } | ||
453 | } | ||
454 | |||
455 | static inline u16 DISPC_WINDOW_SKIP_OFFSET(enum omap_plane plane) | ||
456 | { | ||
457 | switch (plane) { | ||
458 | case OMAP_DSS_GFX: | ||
459 | return 0x0034; | ||
460 | case OMAP_DSS_VIDEO1: | ||
461 | case OMAP_DSS_VIDEO2: | ||
462 | BUG(); | ||
463 | default: | ||
464 | BUG(); | ||
465 | } | ||
466 | } | ||
467 | |||
468 | static inline u16 DISPC_TABLE_BA_OFFSET(enum omap_plane plane) | ||
469 | { | ||
470 | switch (plane) { | ||
471 | case OMAP_DSS_GFX: | ||
472 | return 0x0038; | ||
473 | case OMAP_DSS_VIDEO1: | ||
474 | case OMAP_DSS_VIDEO2: | ||
475 | BUG(); | ||
476 | default: | ||
477 | BUG(); | ||
478 | } | ||
479 | } | ||
480 | |||
481 | static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane) | ||
482 | { | ||
483 | switch (plane) { | ||
484 | case OMAP_DSS_GFX: | ||
485 | BUG(); | ||
486 | case OMAP_DSS_VIDEO1: | ||
487 | case OMAP_DSS_VIDEO2: | ||
488 | return 0x0024; | ||
489 | default: | ||
490 | BUG(); | ||
491 | } | ||
492 | } | ||
493 | |||
494 | static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane) | ||
495 | { | ||
496 | switch (plane) { | ||
497 | case OMAP_DSS_GFX: | ||
498 | BUG(); | ||
499 | case OMAP_DSS_VIDEO1: | ||
500 | return 0x0580; | ||
501 | case OMAP_DSS_VIDEO2: | ||
502 | return 0x055C; | ||
503 | default: | ||
504 | BUG(); | ||
505 | } | ||
506 | } | ||
507 | |||
508 | static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane) | ||
509 | { | ||
510 | switch (plane) { | ||
511 | case OMAP_DSS_GFX: | ||
512 | BUG(); | ||
513 | case OMAP_DSS_VIDEO1: | ||
514 | case OMAP_DSS_VIDEO2: | ||
515 | return 0x0028; | ||
516 | default: | ||
517 | BUG(); | ||
518 | } | ||
519 | } | ||
520 | |||
521 | |||
522 | static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane) | ||
523 | { | ||
524 | switch (plane) { | ||
525 | case OMAP_DSS_GFX: | ||
526 | BUG(); | ||
527 | case OMAP_DSS_VIDEO1: | ||
528 | case OMAP_DSS_VIDEO2: | ||
529 | return 0x002C; | ||
530 | default: | ||
531 | BUG(); | ||
532 | } | ||
533 | } | ||
534 | |||
535 | static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane) | ||
536 | { | ||
537 | switch (plane) { | ||
538 | case OMAP_DSS_GFX: | ||
539 | BUG(); | ||
540 | case OMAP_DSS_VIDEO1: | ||
541 | return 0x0584; | ||
542 | case OMAP_DSS_VIDEO2: | ||
543 | return 0x0560; | ||
544 | default: | ||
545 | BUG(); | ||
546 | } | ||
547 | } | ||
548 | |||
549 | static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane) | ||
550 | { | ||
551 | switch (plane) { | ||
552 | case OMAP_DSS_GFX: | ||
553 | BUG(); | ||
554 | case OMAP_DSS_VIDEO1: | ||
555 | case OMAP_DSS_VIDEO2: | ||
556 | return 0x0030; | ||
557 | default: | ||
558 | BUG(); | ||
559 | } | ||
560 | } | ||
561 | |||
562 | static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane) | ||
563 | { | ||
564 | switch (plane) { | ||
565 | case OMAP_DSS_GFX: | ||
566 | BUG(); | ||
567 | case OMAP_DSS_VIDEO1: | ||
568 | return 0x0588; | ||
569 | case OMAP_DSS_VIDEO2: | ||
570 | return 0x0564; | ||
571 | default: | ||
572 | BUG(); | ||
573 | } | ||
574 | } | ||
575 | |||
576 | /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ | ||
577 | static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i) | ||
578 | { | ||
579 | switch (plane) { | ||
580 | case OMAP_DSS_GFX: | ||
581 | BUG(); | ||
582 | case OMAP_DSS_VIDEO1: | ||
583 | case OMAP_DSS_VIDEO2: | ||
584 | return 0x0034 + i * 0x8; | ||
585 | default: | ||
586 | BUG(); | ||
587 | } | ||
588 | } | ||
589 | |||
590 | /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ | ||
591 | static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i) | ||
592 | { | ||
593 | switch (plane) { | ||
594 | case OMAP_DSS_GFX: | ||
595 | BUG(); | ||
596 | case OMAP_DSS_VIDEO1: | ||
597 | return 0x058C + i * 0x8; | ||
598 | case OMAP_DSS_VIDEO2: | ||
599 | return 0x0568 + i * 0x8; | ||
600 | default: | ||
601 | BUG(); | ||
602 | } | ||
603 | } | ||
604 | |||
605 | /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ | ||
606 | static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i) | ||
607 | { | ||
608 | switch (plane) { | ||
609 | case OMAP_DSS_GFX: | ||
610 | BUG(); | ||
611 | case OMAP_DSS_VIDEO1: | ||
612 | case OMAP_DSS_VIDEO2: | ||
613 | return 0x0038 + i * 0x8; | ||
614 | default: | ||
615 | BUG(); | ||
616 | } | ||
617 | } | ||
618 | |||
619 | /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ | ||
620 | static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i) | ||
621 | { | ||
622 | switch (plane) { | ||
623 | case OMAP_DSS_GFX: | ||
624 | BUG(); | ||
625 | case OMAP_DSS_VIDEO1: | ||
626 | return 0x0590 + i * 8; | ||
627 | case OMAP_DSS_VIDEO2: | ||
628 | return 0x056C + i * 0x8; | ||
629 | default: | ||
630 | BUG(); | ||
631 | } | ||
632 | } | ||
633 | |||
634 | /* coef index i = {0, 1, 2, 3, 4,} */ | ||
635 | static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i) | ||
636 | { | ||
637 | switch (plane) { | ||
638 | case OMAP_DSS_GFX: | ||
639 | BUG(); | ||
640 | case OMAP_DSS_VIDEO1: | ||
641 | case OMAP_DSS_VIDEO2: | ||
642 | return 0x0074 + i * 0x4; | ||
643 | default: | ||
644 | BUG(); | ||
645 | } | ||
646 | } | ||
647 | |||
648 | /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ | ||
649 | static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i) | ||
650 | { | ||
651 | switch (plane) { | ||
652 | case OMAP_DSS_GFX: | ||
653 | BUG(); | ||
654 | case OMAP_DSS_VIDEO1: | ||
655 | return 0x0124 + i * 0x4; | ||
656 | case OMAP_DSS_VIDEO2: | ||
657 | return 0x00B4 + i * 0x4; | ||
658 | default: | ||
659 | BUG(); | ||
660 | } | ||
661 | } | ||
662 | |||
663 | /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ | ||
664 | static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i) | ||
665 | { | ||
666 | switch (plane) { | ||
667 | case OMAP_DSS_GFX: | ||
668 | BUG(); | ||
669 | case OMAP_DSS_VIDEO1: | ||
670 | return 0x05CC + i * 0x4; | ||
671 | case OMAP_DSS_VIDEO2: | ||
672 | return 0x05A8 + i * 0x4; | ||
673 | default: | ||
674 | BUG(); | ||
675 | } | ||
676 | } | ||
677 | |||
678 | static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane) | ||
679 | { | ||
680 | switch (plane) { | ||
681 | case OMAP_DSS_GFX: | ||
682 | return 0x01AC; | ||
683 | case OMAP_DSS_VIDEO1: | ||
684 | return 0x0174; | ||
685 | case OMAP_DSS_VIDEO2: | ||
686 | return 0x00E8; | ||
687 | default: | ||
688 | BUG(); | ||
689 | } | ||
690 | } | ||
691 | #endif | ||
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index 22dd7a474f79..c2dfc8c50057 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c | |||
@@ -25,14 +25,11 @@ | |||
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/jiffies.h> | 27 | #include <linux/jiffies.h> |
28 | #include <linux/list.h> | ||
29 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
30 | 29 | ||
31 | #include <plat/display.h> | 30 | #include <video/omapdss.h> |
32 | #include "dss.h" | 31 | #include "dss.h" |
33 | 32 | ||
34 | static LIST_HEAD(display_list); | ||
35 | |||
36 | static ssize_t display_enabled_show(struct device *dev, | 33 | static ssize_t display_enabled_show(struct device *dev, |
37 | struct device_attribute *attr, char *buf) | 34 | struct device_attribute *attr, char *buf) |
38 | { | 35 | { |
@@ -47,9 +44,13 @@ static ssize_t display_enabled_store(struct device *dev, | |||
47 | const char *buf, size_t size) | 44 | const char *buf, size_t size) |
48 | { | 45 | { |
49 | struct omap_dss_device *dssdev = to_dss_device(dev); | 46 | struct omap_dss_device *dssdev = to_dss_device(dev); |
50 | bool enabled, r; | 47 | int r, enabled; |
48 | |||
49 | r = kstrtoint(buf, 0, &enabled); | ||
50 | if (r) | ||
51 | return r; | ||
51 | 52 | ||
52 | enabled = simple_strtoul(buf, NULL, 10); | 53 | enabled = !!enabled; |
53 | 54 | ||
54 | if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) { | 55 | if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) { |
55 | if (enabled) { | 56 | if (enabled) { |
@@ -85,7 +86,9 @@ static ssize_t display_upd_mode_store(struct device *dev, | |||
85 | if (!dssdev->driver->set_update_mode) | 86 | if (!dssdev->driver->set_update_mode) |
86 | return -EINVAL; | 87 | return -EINVAL; |
87 | 88 | ||
88 | val = simple_strtoul(buf, NULL, 10); | 89 | r = kstrtoint(buf, 0, &val); |
90 | if (r) | ||
91 | return r; | ||
89 | 92 | ||
90 | switch (val) { | 93 | switch (val) { |
91 | case OMAP_DSS_UPDATE_DISABLED: | 94 | case OMAP_DSS_UPDATE_DISABLED: |
@@ -117,13 +120,16 @@ static ssize_t display_tear_store(struct device *dev, | |||
117 | struct device_attribute *attr, const char *buf, size_t size) | 120 | struct device_attribute *attr, const char *buf, size_t size) |
118 | { | 121 | { |
119 | struct omap_dss_device *dssdev = to_dss_device(dev); | 122 | struct omap_dss_device *dssdev = to_dss_device(dev); |
120 | unsigned long te; | 123 | int te, r; |
121 | int r; | ||
122 | 124 | ||
123 | if (!dssdev->driver->enable_te || !dssdev->driver->get_te) | 125 | if (!dssdev->driver->enable_te || !dssdev->driver->get_te) |
124 | return -ENOENT; | 126 | return -ENOENT; |
125 | 127 | ||
126 | te = simple_strtoul(buf, NULL, 0); | 128 | r = kstrtoint(buf, 0, &te); |
129 | if (r) | ||
130 | return r; | ||
131 | |||
132 | te = !!te; | ||
127 | 133 | ||
128 | r = dssdev->driver->enable_te(dssdev, te); | 134 | r = dssdev->driver->enable_te(dssdev, te); |
129 | if (r) | 135 | if (r) |
@@ -199,13 +205,14 @@ static ssize_t display_rotate_store(struct device *dev, | |||
199 | struct device_attribute *attr, const char *buf, size_t size) | 205 | struct device_attribute *attr, const char *buf, size_t size) |
200 | { | 206 | { |
201 | struct omap_dss_device *dssdev = to_dss_device(dev); | 207 | struct omap_dss_device *dssdev = to_dss_device(dev); |
202 | unsigned long rot; | 208 | int rot, r; |
203 | int r; | ||
204 | 209 | ||
205 | if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate) | 210 | if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate) |
206 | return -ENOENT; | 211 | return -ENOENT; |
207 | 212 | ||
208 | rot = simple_strtoul(buf, NULL, 0); | 213 | r = kstrtoint(buf, 0, &rot); |
214 | if (r) | ||
215 | return r; | ||
209 | 216 | ||
210 | r = dssdev->driver->set_rotate(dssdev, rot); | 217 | r = dssdev->driver->set_rotate(dssdev, rot); |
211 | if (r) | 218 | if (r) |
@@ -229,13 +236,16 @@ static ssize_t display_mirror_store(struct device *dev, | |||
229 | struct device_attribute *attr, const char *buf, size_t size) | 236 | struct device_attribute *attr, const char *buf, size_t size) |
230 | { | 237 | { |
231 | struct omap_dss_device *dssdev = to_dss_device(dev); | 238 | struct omap_dss_device *dssdev = to_dss_device(dev); |
232 | unsigned long mirror; | 239 | int mirror, r; |
233 | int r; | ||
234 | 240 | ||
235 | if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) | 241 | if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) |
236 | return -ENOENT; | 242 | return -ENOENT; |
237 | 243 | ||
238 | mirror = simple_strtoul(buf, NULL, 0); | 244 | r = kstrtoint(buf, 0, &mirror); |
245 | if (r) | ||
246 | return r; | ||
247 | |||
248 | mirror = !!mirror; | ||
239 | 249 | ||
240 | r = dssdev->driver->set_mirror(dssdev, mirror); | 250 | r = dssdev->driver->set_mirror(dssdev, mirror); |
241 | if (r) | 251 | if (r) |
@@ -262,14 +272,15 @@ static ssize_t display_wss_store(struct device *dev, | |||
262 | struct device_attribute *attr, const char *buf, size_t size) | 272 | struct device_attribute *attr, const char *buf, size_t size) |
263 | { | 273 | { |
264 | struct omap_dss_device *dssdev = to_dss_device(dev); | 274 | struct omap_dss_device *dssdev = to_dss_device(dev); |
265 | unsigned long wss; | 275 | u32 wss; |
266 | int r; | 276 | int r; |
267 | 277 | ||
268 | if (!dssdev->driver->get_wss || !dssdev->driver->set_wss) | 278 | if (!dssdev->driver->get_wss || !dssdev->driver->set_wss) |
269 | return -ENOENT; | 279 | return -ENOENT; |
270 | 280 | ||
271 | if (strict_strtoul(buf, 0, &wss)) | 281 | r = kstrtou32(buf, 0, &wss); |
272 | return -EINVAL; | 282 | if (r) |
283 | return r; | ||
273 | 284 | ||
274 | if (wss > 0xfffff) | 285 | if (wss > 0xfffff) |
275 | return -EINVAL; | 286 | return -EINVAL; |
@@ -345,6 +356,7 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev) | |||
345 | return 16; | 356 | return 16; |
346 | case OMAP_DISPLAY_TYPE_VENC: | 357 | case OMAP_DISPLAY_TYPE_VENC: |
347 | case OMAP_DISPLAY_TYPE_SDI: | 358 | case OMAP_DISPLAY_TYPE_SDI: |
359 | case OMAP_DISPLAY_TYPE_HDMI: | ||
348 | return 24; | 360 | return 24; |
349 | default: | 361 | default: |
350 | BUG(); | 362 | BUG(); |
@@ -371,6 +383,7 @@ bool dss_use_replication(struct omap_dss_device *dssdev, | |||
371 | case OMAP_DISPLAY_TYPE_DPI: | 383 | case OMAP_DISPLAY_TYPE_DPI: |
372 | bpp = dssdev->phy.dpi.data_lines; | 384 | bpp = dssdev->phy.dpi.data_lines; |
373 | break; | 385 | break; |
386 | case OMAP_DISPLAY_TYPE_HDMI: | ||
374 | case OMAP_DISPLAY_TYPE_VENC: | 387 | case OMAP_DISPLAY_TYPE_VENC: |
375 | case OMAP_DISPLAY_TYPE_SDI: | 388 | case OMAP_DISPLAY_TYPE_SDI: |
376 | bpp = 24; | 389 | bpp = 24; |
@@ -396,29 +409,6 @@ void dss_init_device(struct platform_device *pdev, | |||
396 | switch (dssdev->type) { | 409 | switch (dssdev->type) { |
397 | #ifdef CONFIG_OMAP2_DSS_DPI | 410 | #ifdef CONFIG_OMAP2_DSS_DPI |
398 | case OMAP_DISPLAY_TYPE_DPI: | 411 | case OMAP_DISPLAY_TYPE_DPI: |
399 | #endif | ||
400 | #ifdef CONFIG_OMAP2_DSS_RFBI | ||
401 | case OMAP_DISPLAY_TYPE_DBI: | ||
402 | #endif | ||
403 | #ifdef CONFIG_OMAP2_DSS_SDI | ||
404 | case OMAP_DISPLAY_TYPE_SDI: | ||
405 | #endif | ||
406 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
407 | case OMAP_DISPLAY_TYPE_DSI: | ||
408 | #endif | ||
409 | #ifdef CONFIG_OMAP2_DSS_VENC | ||
410 | case OMAP_DISPLAY_TYPE_VENC: | ||
411 | #endif | ||
412 | break; | ||
413 | default: | ||
414 | DSSERR("Support for display '%s' not compiled in.\n", | ||
415 | dssdev->name); | ||
416 | return; | ||
417 | } | ||
418 | |||
419 | switch (dssdev->type) { | ||
420 | #ifdef CONFIG_OMAP2_DSS_DPI | ||
421 | case OMAP_DISPLAY_TYPE_DPI: | ||
422 | r = dpi_init_display(dssdev); | 412 | r = dpi_init_display(dssdev); |
423 | break; | 413 | break; |
424 | #endif | 414 | #endif |
@@ -442,8 +432,13 @@ void dss_init_device(struct platform_device *pdev, | |||
442 | r = dsi_init_display(dssdev); | 432 | r = dsi_init_display(dssdev); |
443 | break; | 433 | break; |
444 | #endif | 434 | #endif |
435 | case OMAP_DISPLAY_TYPE_HDMI: | ||
436 | r = hdmi_init_display(dssdev); | ||
437 | break; | ||
445 | default: | 438 | default: |
446 | BUG(); | 439 | DSSERR("Support for display '%s' not compiled in.\n", |
440 | dssdev->name); | ||
441 | return; | ||
447 | } | 442 | } |
448 | 443 | ||
449 | if (r) { | 444 | if (r) { |
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 960e977a8bf0..ff6bd30132df 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c | |||
@@ -30,47 +30,73 @@ | |||
30 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
31 | #include <linux/regulator/consumer.h> | 31 | #include <linux/regulator/consumer.h> |
32 | 32 | ||
33 | #include <plat/display.h> | 33 | #include <video/omapdss.h> |
34 | #include <plat/cpu.h> | 34 | #include <plat/cpu.h> |
35 | 35 | ||
36 | #include "dss.h" | 36 | #include "dss.h" |
37 | 37 | ||
38 | static struct { | 38 | static struct { |
39 | struct regulator *vdds_dsi_reg; | 39 | struct regulator *vdds_dsi_reg; |
40 | struct platform_device *dsidev; | ||
40 | } dpi; | 41 | } dpi; |
41 | 42 | ||
42 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 43 | static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk) |
43 | static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req, | 44 | { |
44 | unsigned long *fck, int *lck_div, int *pck_div) | 45 | int dsi_module; |
46 | |||
47 | dsi_module = clk == OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ? 0 : 1; | ||
48 | |||
49 | return dsi_get_dsidev_from_id(dsi_module); | ||
50 | } | ||
51 | |||
52 | static bool dpi_use_dsi_pll(struct omap_dss_device *dssdev) | ||
53 | { | ||
54 | if (dssdev->clocks.dispc.dispc_fclk_src == | ||
55 | OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC || | ||
56 | dssdev->clocks.dispc.dispc_fclk_src == | ||
57 | OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC || | ||
58 | dssdev->clocks.dispc.channel.lcd_clk_src == | ||
59 | OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC || | ||
60 | dssdev->clocks.dispc.channel.lcd_clk_src == | ||
61 | OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC) | ||
62 | return true; | ||
63 | else | ||
64 | return false; | ||
65 | } | ||
66 | |||
67 | static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft, | ||
68 | unsigned long pck_req, unsigned long *fck, int *lck_div, | ||
69 | int *pck_div) | ||
45 | { | 70 | { |
46 | struct dsi_clock_info dsi_cinfo; | 71 | struct dsi_clock_info dsi_cinfo; |
47 | struct dispc_clock_info dispc_cinfo; | 72 | struct dispc_clock_info dispc_cinfo; |
48 | int r; | 73 | int r; |
49 | 74 | ||
50 | r = dsi_pll_calc_clock_div_pck(is_tft, pck_req, &dsi_cinfo, | 75 | r = dsi_pll_calc_clock_div_pck(dpi.dsidev, is_tft, pck_req, |
51 | &dispc_cinfo); | 76 | &dsi_cinfo, &dispc_cinfo); |
52 | if (r) | 77 | if (r) |
53 | return r; | 78 | return r; |
54 | 79 | ||
55 | r = dsi_pll_set_clock_div(&dsi_cinfo); | 80 | r = dsi_pll_set_clock_div(dpi.dsidev, &dsi_cinfo); |
56 | if (r) | 81 | if (r) |
57 | return r; | 82 | return r; |
58 | 83 | ||
59 | dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK); | 84 | dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); |
60 | 85 | ||
61 | r = dispc_set_clock_div(&dispc_cinfo); | 86 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); |
62 | if (r) | 87 | if (r) |
63 | return r; | 88 | return r; |
64 | 89 | ||
65 | *fck = dsi_cinfo.dsi1_pll_fclk; | 90 | *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; |
66 | *lck_div = dispc_cinfo.lck_div; | 91 | *lck_div = dispc_cinfo.lck_div; |
67 | *pck_div = dispc_cinfo.pck_div; | 92 | *pck_div = dispc_cinfo.pck_div; |
68 | 93 | ||
69 | return 0; | 94 | return 0; |
70 | } | 95 | } |
71 | #else | 96 | |
72 | static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req, | 97 | static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, bool is_tft, |
73 | unsigned long *fck, int *lck_div, int *pck_div) | 98 | unsigned long pck_req, unsigned long *fck, int *lck_div, |
99 | int *pck_div) | ||
74 | { | 100 | { |
75 | struct dss_clock_info dss_cinfo; | 101 | struct dss_clock_info dss_cinfo; |
76 | struct dispc_clock_info dispc_cinfo; | 102 | struct dispc_clock_info dispc_cinfo; |
@@ -84,7 +110,7 @@ static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req, | |||
84 | if (r) | 110 | if (r) |
85 | return r; | 111 | return r; |
86 | 112 | ||
87 | r = dispc_set_clock_div(&dispc_cinfo); | 113 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); |
88 | if (r) | 114 | if (r) |
89 | return r; | 115 | return r; |
90 | 116 | ||
@@ -94,31 +120,29 @@ static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req, | |||
94 | 120 | ||
95 | return 0; | 121 | return 0; |
96 | } | 122 | } |
97 | #endif | ||
98 | 123 | ||
99 | static int dpi_set_mode(struct omap_dss_device *dssdev) | 124 | static int dpi_set_mode(struct omap_dss_device *dssdev) |
100 | { | 125 | { |
101 | struct omap_video_timings *t = &dssdev->panel.timings; | 126 | struct omap_video_timings *t = &dssdev->panel.timings; |
102 | int lck_div, pck_div; | 127 | int lck_div = 0, pck_div = 0; |
103 | unsigned long fck; | 128 | unsigned long fck = 0; |
104 | unsigned long pck; | 129 | unsigned long pck; |
105 | bool is_tft; | 130 | bool is_tft; |
106 | int r = 0; | 131 | int r = 0; |
107 | 132 | ||
108 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 133 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
109 | 134 | ||
110 | dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi, | 135 | dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, |
111 | dssdev->panel.acb); | 136 | dssdev->panel.acbi, dssdev->panel.acb); |
112 | 137 | ||
113 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; | 138 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; |
114 | 139 | ||
115 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 140 | if (dpi_use_dsi_pll(dssdev)) |
116 | r = dpi_set_dsi_clk(is_tft, t->pixel_clock * 1000, | 141 | r = dpi_set_dsi_clk(dssdev, is_tft, t->pixel_clock * 1000, |
117 | &fck, &lck_div, &pck_div); | 142 | &fck, &lck_div, &pck_div); |
118 | #else | 143 | else |
119 | r = dpi_set_dispc_clk(is_tft, t->pixel_clock * 1000, | 144 | r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000, |
120 | &fck, &lck_div, &pck_div); | 145 | &fck, &lck_div, &pck_div); |
121 | #endif | ||
122 | if (r) | 146 | if (r) |
123 | goto err0; | 147 | goto err0; |
124 | 148 | ||
@@ -132,10 +156,10 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) | |||
132 | t->pixel_clock = pck; | 156 | t->pixel_clock = pck; |
133 | } | 157 | } |
134 | 158 | ||
135 | dispc_set_lcd_timings(t); | 159 | dispc_set_lcd_timings(dssdev->manager->id, t); |
136 | 160 | ||
137 | err0: | 161 | err0: |
138 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 162 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
139 | return r; | 163 | return r; |
140 | } | 164 | } |
141 | 165 | ||
@@ -145,10 +169,12 @@ static int dpi_basic_init(struct omap_dss_device *dssdev) | |||
145 | 169 | ||
146 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; | 170 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; |
147 | 171 | ||
148 | dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS); | 172 | dispc_set_parallel_interface_mode(dssdev->manager->id, |
149 | dispc_set_lcd_display_type(is_tft ? OMAP_DSS_LCD_DISPLAY_TFT : | 173 | OMAP_DSS_PARALLELMODE_BYPASS); |
150 | OMAP_DSS_LCD_DISPLAY_STN); | 174 | dispc_set_lcd_display_type(dssdev->manager->id, is_tft ? |
151 | dispc_set_tft_data_lines(dssdev->phy.dpi.data_lines); | 175 | OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN); |
176 | dispc_set_tft_data_lines(dssdev->manager->id, | ||
177 | dssdev->phy.dpi.data_lines); | ||
152 | 178 | ||
153 | return 0; | 179 | return 0; |
154 | } | 180 | } |
@@ -169,18 +195,19 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) | |||
169 | goto err1; | 195 | goto err1; |
170 | } | 196 | } |
171 | 197 | ||
172 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 198 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
173 | 199 | ||
174 | r = dpi_basic_init(dssdev); | 200 | r = dpi_basic_init(dssdev); |
175 | if (r) | 201 | if (r) |
176 | goto err2; | 202 | goto err2; |
177 | 203 | ||
178 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 204 | if (dpi_use_dsi_pll(dssdev)) { |
179 | dss_clk_enable(DSS_CLK_FCK2); | 205 | dss_clk_enable(DSS_CLK_SYSCK); |
180 | r = dsi_pll_init(dssdev, 0, 1); | 206 | r = dsi_pll_init(dpi.dsidev, 0, 1); |
181 | if (r) | 207 | if (r) |
182 | goto err3; | 208 | goto err3; |
183 | #endif | 209 | } |
210 | |||
184 | r = dpi_set_mode(dssdev); | 211 | r = dpi_set_mode(dssdev); |
185 | if (r) | 212 | if (r) |
186 | goto err4; | 213 | goto err4; |
@@ -192,13 +219,13 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) | |||
192 | return 0; | 219 | return 0; |
193 | 220 | ||
194 | err4: | 221 | err4: |
195 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 222 | if (dpi_use_dsi_pll(dssdev)) |
196 | dsi_pll_uninit(); | 223 | dsi_pll_uninit(dpi.dsidev, true); |
197 | err3: | 224 | err3: |
198 | dss_clk_disable(DSS_CLK_FCK2); | 225 | if (dpi_use_dsi_pll(dssdev)) |
199 | #endif | 226 | dss_clk_disable(DSS_CLK_SYSCK); |
200 | err2: | 227 | err2: |
201 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 228 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
202 | if (cpu_is_omap34xx()) | 229 | if (cpu_is_omap34xx()) |
203 | regulator_disable(dpi.vdds_dsi_reg); | 230 | regulator_disable(dpi.vdds_dsi_reg); |
204 | err1: | 231 | err1: |
@@ -212,13 +239,13 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) | |||
212 | { | 239 | { |
213 | dssdev->manager->disable(dssdev->manager); | 240 | dssdev->manager->disable(dssdev->manager); |
214 | 241 | ||
215 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 242 | if (dpi_use_dsi_pll(dssdev)) { |
216 | dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 243 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); |
217 | dsi_pll_uninit(); | 244 | dsi_pll_uninit(dpi.dsidev, true); |
218 | dss_clk_disable(DSS_CLK_FCK2); | 245 | dss_clk_disable(DSS_CLK_SYSCK); |
219 | #endif | 246 | } |
220 | 247 | ||
221 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 248 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
222 | 249 | ||
223 | if (cpu_is_omap34xx()) | 250 | if (cpu_is_omap34xx()) |
224 | regulator_disable(dpi.vdds_dsi_reg); | 251 | regulator_disable(dpi.vdds_dsi_reg); |
@@ -234,7 +261,7 @@ void dpi_set_timings(struct omap_dss_device *dssdev, | |||
234 | dssdev->panel.timings = *timings; | 261 | dssdev->panel.timings = *timings; |
235 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { | 262 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { |
236 | dpi_set_mode(dssdev); | 263 | dpi_set_mode(dssdev); |
237 | dispc_go(OMAP_DSS_CHANNEL_LCD); | 264 | dispc_go(dssdev->manager->id); |
238 | } | 265 | } |
239 | } | 266 | } |
240 | EXPORT_SYMBOL(dpi_set_timings); | 267 | EXPORT_SYMBOL(dpi_set_timings); |
@@ -247,6 +274,7 @@ int dpi_check_timings(struct omap_dss_device *dssdev, | |||
247 | int lck_div, pck_div; | 274 | int lck_div, pck_div; |
248 | unsigned long fck; | 275 | unsigned long fck; |
249 | unsigned long pck; | 276 | unsigned long pck; |
277 | struct dispc_clock_info dispc_cinfo; | ||
250 | 278 | ||
251 | if (!dispc_lcd_timings_ok(timings)) | 279 | if (!dispc_lcd_timings_ok(timings)) |
252 | return -EINVAL; | 280 | return -EINVAL; |
@@ -256,25 +284,18 @@ int dpi_check_timings(struct omap_dss_device *dssdev, | |||
256 | 284 | ||
257 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; | 285 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; |
258 | 286 | ||
259 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 287 | if (dpi_use_dsi_pll(dssdev)) { |
260 | { | ||
261 | struct dsi_clock_info dsi_cinfo; | 288 | struct dsi_clock_info dsi_cinfo; |
262 | struct dispc_clock_info dispc_cinfo; | 289 | r = dsi_pll_calc_clock_div_pck(dpi.dsidev, is_tft, |
263 | r = dsi_pll_calc_clock_div_pck(is_tft, | ||
264 | timings->pixel_clock * 1000, | 290 | timings->pixel_clock * 1000, |
265 | &dsi_cinfo, &dispc_cinfo); | 291 | &dsi_cinfo, &dispc_cinfo); |
266 | 292 | ||
267 | if (r) | 293 | if (r) |
268 | return r; | 294 | return r; |
269 | 295 | ||
270 | fck = dsi_cinfo.dsi1_pll_fclk; | 296 | fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; |
271 | lck_div = dispc_cinfo.lck_div; | 297 | } else { |
272 | pck_div = dispc_cinfo.pck_div; | ||
273 | } | ||
274 | #else | ||
275 | { | ||
276 | struct dss_clock_info dss_cinfo; | 298 | struct dss_clock_info dss_cinfo; |
277 | struct dispc_clock_info dispc_cinfo; | ||
278 | r = dss_calc_clock_div(is_tft, timings->pixel_clock * 1000, | 299 | r = dss_calc_clock_div(is_tft, timings->pixel_clock * 1000, |
279 | &dss_cinfo, &dispc_cinfo); | 300 | &dss_cinfo, &dispc_cinfo); |
280 | 301 | ||
@@ -282,10 +303,10 @@ int dpi_check_timings(struct omap_dss_device *dssdev, | |||
282 | return r; | 303 | return r; |
283 | 304 | ||
284 | fck = dss_cinfo.fck; | 305 | fck = dss_cinfo.fck; |
285 | lck_div = dispc_cinfo.lck_div; | ||
286 | pck_div = dispc_cinfo.pck_div; | ||
287 | } | 306 | } |
288 | #endif | 307 | |
308 | lck_div = dispc_cinfo.lck_div; | ||
309 | pck_div = dispc_cinfo.pck_div; | ||
289 | 310 | ||
290 | pck = fck / lck_div / pck_div / 1000; | 311 | pck = fck / lck_div / pck_div / 1000; |
291 | 312 | ||
@@ -299,22 +320,33 @@ int dpi_init_display(struct omap_dss_device *dssdev) | |||
299 | { | 320 | { |
300 | DSSDBG("init_display\n"); | 321 | DSSDBG("init_display\n"); |
301 | 322 | ||
302 | return 0; | 323 | if (cpu_is_omap34xx() && dpi.vdds_dsi_reg == NULL) { |
303 | } | 324 | struct regulator *vdds_dsi; |
304 | 325 | ||
305 | int dpi_init(struct platform_device *pdev) | 326 | vdds_dsi = dss_get_vdds_dsi(); |
306 | { | 327 | |
307 | if (cpu_is_omap34xx()) { | 328 | if (IS_ERR(vdds_dsi)) { |
308 | dpi.vdds_dsi_reg = dss_get_vdds_dsi(); | ||
309 | if (IS_ERR(dpi.vdds_dsi_reg)) { | ||
310 | DSSERR("can't get VDDS_DSI regulator\n"); | 329 | DSSERR("can't get VDDS_DSI regulator\n"); |
311 | return PTR_ERR(dpi.vdds_dsi_reg); | 330 | return PTR_ERR(vdds_dsi); |
312 | } | 331 | } |
332 | |||
333 | dpi.vdds_dsi_reg = vdds_dsi; | ||
334 | } | ||
335 | |||
336 | if (dpi_use_dsi_pll(dssdev)) { | ||
337 | enum omap_dss_clk_source dispc_fclk_src = | ||
338 | dssdev->clocks.dispc.dispc_fclk_src; | ||
339 | dpi.dsidev = dpi_get_dsidev(dispc_fclk_src); | ||
313 | } | 340 | } |
314 | 341 | ||
315 | return 0; | 342 | return 0; |
316 | } | 343 | } |
317 | 344 | ||
345 | int dpi_init(void) | ||
346 | { | ||
347 | return 0; | ||
348 | } | ||
349 | |||
318 | void dpi_exit(void) | 350 | void dpi_exit(void) |
319 | { | 351 | { |
320 | } | 352 | } |
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index b3fa3a7db911..345757cfcbee 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c | |||
@@ -33,17 +33,19 @@ | |||
33 | #include <linux/regulator/consumer.h> | 33 | #include <linux/regulator/consumer.h> |
34 | #include <linux/wait.h> | 34 | #include <linux/wait.h> |
35 | #include <linux/workqueue.h> | 35 | #include <linux/workqueue.h> |
36 | #include <linux/sched.h> | ||
37 | #include <linux/slab.h> | ||
38 | #include <linux/debugfs.h> | ||
36 | 39 | ||
37 | #include <plat/display.h> | 40 | #include <video/omapdss.h> |
38 | #include <plat/clock.h> | 41 | #include <plat/clock.h> |
39 | 42 | ||
40 | #include "dss.h" | 43 | #include "dss.h" |
44 | #include "dss_features.h" | ||
41 | 45 | ||
42 | /*#define VERBOSE_IRQ*/ | 46 | /*#define VERBOSE_IRQ*/ |
43 | #define DSI_CATCH_MISSING_TE | 47 | #define DSI_CATCH_MISSING_TE |
44 | 48 | ||
45 | #define DSI_BASE 0x4804FC00 | ||
46 | |||
47 | struct dsi_reg { u16 idx; }; | 49 | struct dsi_reg { u16 idx; }; |
48 | 50 | ||
49 | #define DSI_REG(idx) ((const struct dsi_reg) { idx }) | 51 | #define DSI_REG(idx) ((const struct dsi_reg) { idx }) |
@@ -57,6 +59,7 @@ struct dsi_reg { u16 idx; }; | |||
57 | #define DSI_IRQSTATUS DSI_REG(0x0018) | 59 | #define DSI_IRQSTATUS DSI_REG(0x0018) |
58 | #define DSI_IRQENABLE DSI_REG(0x001C) | 60 | #define DSI_IRQENABLE DSI_REG(0x001C) |
59 | #define DSI_CTRL DSI_REG(0x0040) | 61 | #define DSI_CTRL DSI_REG(0x0040) |
62 | #define DSI_GNQ DSI_REG(0x0044) | ||
60 | #define DSI_COMPLEXIO_CFG1 DSI_REG(0x0048) | 63 | #define DSI_COMPLEXIO_CFG1 DSI_REG(0x0048) |
61 | #define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(0x004C) | 64 | #define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(0x004C) |
62 | #define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(0x0050) | 65 | #define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(0x0050) |
@@ -91,6 +94,7 @@ struct dsi_reg { u16 idx; }; | |||
91 | #define DSI_DSIPHY_CFG1 DSI_REG(0x200 + 0x0004) | 94 | #define DSI_DSIPHY_CFG1 DSI_REG(0x200 + 0x0004) |
92 | #define DSI_DSIPHY_CFG2 DSI_REG(0x200 + 0x0008) | 95 | #define DSI_DSIPHY_CFG2 DSI_REG(0x200 + 0x0008) |
93 | #define DSI_DSIPHY_CFG5 DSI_REG(0x200 + 0x0014) | 96 | #define DSI_DSIPHY_CFG5 DSI_REG(0x200 + 0x0014) |
97 | #define DSI_DSIPHY_CFG10 DSI_REG(0x200 + 0x0028) | ||
94 | 98 | ||
95 | /* DSI_PLL_CTRL_SCP */ | 99 | /* DSI_PLL_CTRL_SCP */ |
96 | 100 | ||
@@ -100,11 +104,11 @@ struct dsi_reg { u16 idx; }; | |||
100 | #define DSI_PLL_CONFIGURATION1 DSI_REG(0x300 + 0x000C) | 104 | #define DSI_PLL_CONFIGURATION1 DSI_REG(0x300 + 0x000C) |
101 | #define DSI_PLL_CONFIGURATION2 DSI_REG(0x300 + 0x0010) | 105 | #define DSI_PLL_CONFIGURATION2 DSI_REG(0x300 + 0x0010) |
102 | 106 | ||
103 | #define REG_GET(idx, start, end) \ | 107 | #define REG_GET(dsidev, idx, start, end) \ |
104 | FLD_GET(dsi_read_reg(idx), start, end) | 108 | FLD_GET(dsi_read_reg(dsidev, idx), start, end) |
105 | 109 | ||
106 | #define REG_FLD_MOD(idx, val, start, end) \ | 110 | #define REG_FLD_MOD(dsidev, idx, val, start, end) \ |
107 | dsi_write_reg(idx, FLD_MOD(dsi_read_reg(idx), val, start, end)) | 111 | dsi_write_reg(dsidev, idx, FLD_MOD(dsi_read_reg(dsidev, idx), val, start, end)) |
108 | 112 | ||
109 | /* Global interrupts */ | 113 | /* Global interrupts */ |
110 | #define DSI_IRQ_VC0 (1 << 0) | 114 | #define DSI_IRQ_VC0 (1 << 0) |
@@ -148,31 +152,50 @@ struct dsi_reg { u16 idx; }; | |||
148 | #define DSI_CIO_IRQ_ERRSYNCESC1 (1 << 0) | 152 | #define DSI_CIO_IRQ_ERRSYNCESC1 (1 << 0) |
149 | #define DSI_CIO_IRQ_ERRSYNCESC2 (1 << 1) | 153 | #define DSI_CIO_IRQ_ERRSYNCESC2 (1 << 1) |
150 | #define DSI_CIO_IRQ_ERRSYNCESC3 (1 << 2) | 154 | #define DSI_CIO_IRQ_ERRSYNCESC3 (1 << 2) |
155 | #define DSI_CIO_IRQ_ERRSYNCESC4 (1 << 3) | ||
156 | #define DSI_CIO_IRQ_ERRSYNCESC5 (1 << 4) | ||
151 | #define DSI_CIO_IRQ_ERRESC1 (1 << 5) | 157 | #define DSI_CIO_IRQ_ERRESC1 (1 << 5) |
152 | #define DSI_CIO_IRQ_ERRESC2 (1 << 6) | 158 | #define DSI_CIO_IRQ_ERRESC2 (1 << 6) |
153 | #define DSI_CIO_IRQ_ERRESC3 (1 << 7) | 159 | #define DSI_CIO_IRQ_ERRESC3 (1 << 7) |
160 | #define DSI_CIO_IRQ_ERRESC4 (1 << 8) | ||
161 | #define DSI_CIO_IRQ_ERRESC5 (1 << 9) | ||
154 | #define DSI_CIO_IRQ_ERRCONTROL1 (1 << 10) | 162 | #define DSI_CIO_IRQ_ERRCONTROL1 (1 << 10) |
155 | #define DSI_CIO_IRQ_ERRCONTROL2 (1 << 11) | 163 | #define DSI_CIO_IRQ_ERRCONTROL2 (1 << 11) |
156 | #define DSI_CIO_IRQ_ERRCONTROL3 (1 << 12) | 164 | #define DSI_CIO_IRQ_ERRCONTROL3 (1 << 12) |
165 | #define DSI_CIO_IRQ_ERRCONTROL4 (1 << 13) | ||
166 | #define DSI_CIO_IRQ_ERRCONTROL5 (1 << 14) | ||
157 | #define DSI_CIO_IRQ_STATEULPS1 (1 << 15) | 167 | #define DSI_CIO_IRQ_STATEULPS1 (1 << 15) |
158 | #define DSI_CIO_IRQ_STATEULPS2 (1 << 16) | 168 | #define DSI_CIO_IRQ_STATEULPS2 (1 << 16) |
159 | #define DSI_CIO_IRQ_STATEULPS3 (1 << 17) | 169 | #define DSI_CIO_IRQ_STATEULPS3 (1 << 17) |
170 | #define DSI_CIO_IRQ_STATEULPS4 (1 << 18) | ||
171 | #define DSI_CIO_IRQ_STATEULPS5 (1 << 19) | ||
160 | #define DSI_CIO_IRQ_ERRCONTENTIONLP0_1 (1 << 20) | 172 | #define DSI_CIO_IRQ_ERRCONTENTIONLP0_1 (1 << 20) |
161 | #define DSI_CIO_IRQ_ERRCONTENTIONLP1_1 (1 << 21) | 173 | #define DSI_CIO_IRQ_ERRCONTENTIONLP1_1 (1 << 21) |
162 | #define DSI_CIO_IRQ_ERRCONTENTIONLP0_2 (1 << 22) | 174 | #define DSI_CIO_IRQ_ERRCONTENTIONLP0_2 (1 << 22) |
163 | #define DSI_CIO_IRQ_ERRCONTENTIONLP1_2 (1 << 23) | 175 | #define DSI_CIO_IRQ_ERRCONTENTIONLP1_2 (1 << 23) |
164 | #define DSI_CIO_IRQ_ERRCONTENTIONLP0_3 (1 << 24) | 176 | #define DSI_CIO_IRQ_ERRCONTENTIONLP0_3 (1 << 24) |
165 | #define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25) | 177 | #define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25) |
178 | #define DSI_CIO_IRQ_ERRCONTENTIONLP0_4 (1 << 26) | ||
179 | #define DSI_CIO_IRQ_ERRCONTENTIONLP1_4 (1 << 27) | ||
180 | #define DSI_CIO_IRQ_ERRCONTENTIONLP0_5 (1 << 28) | ||
181 | #define DSI_CIO_IRQ_ERRCONTENTIONLP1_5 (1 << 29) | ||
166 | #define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30) | 182 | #define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30) |
167 | #define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31) | 183 | #define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31) |
168 | #define DSI_CIO_IRQ_ERROR_MASK \ | 184 | #define DSI_CIO_IRQ_ERROR_MASK \ |
169 | (DSI_CIO_IRQ_ERRSYNCESC1 | DSI_CIO_IRQ_ERRSYNCESC2 | \ | 185 | (DSI_CIO_IRQ_ERRSYNCESC1 | DSI_CIO_IRQ_ERRSYNCESC2 | \ |
170 | DSI_CIO_IRQ_ERRSYNCESC3 | DSI_CIO_IRQ_ERRESC1 | DSI_CIO_IRQ_ERRESC2 | \ | 186 | DSI_CIO_IRQ_ERRSYNCESC3 | DSI_CIO_IRQ_ERRSYNCESC4 | \ |
171 | DSI_CIO_IRQ_ERRESC3 | DSI_CIO_IRQ_ERRCONTROL1 | \ | 187 | DSI_CIO_IRQ_ERRSYNCESC5 | \ |
172 | DSI_CIO_IRQ_ERRCONTROL2 | DSI_CIO_IRQ_ERRCONTROL3 | \ | 188 | DSI_CIO_IRQ_ERRESC1 | DSI_CIO_IRQ_ERRESC2 | \ |
189 | DSI_CIO_IRQ_ERRESC3 | DSI_CIO_IRQ_ERRESC4 | \ | ||
190 | DSI_CIO_IRQ_ERRESC5 | \ | ||
191 | DSI_CIO_IRQ_ERRCONTROL1 | DSI_CIO_IRQ_ERRCONTROL2 | \ | ||
192 | DSI_CIO_IRQ_ERRCONTROL3 | DSI_CIO_IRQ_ERRCONTROL4 | \ | ||
193 | DSI_CIO_IRQ_ERRCONTROL5 | \ | ||
173 | DSI_CIO_IRQ_ERRCONTENTIONLP0_1 | DSI_CIO_IRQ_ERRCONTENTIONLP1_1 | \ | 194 | DSI_CIO_IRQ_ERRCONTENTIONLP0_1 | DSI_CIO_IRQ_ERRCONTENTIONLP1_1 | \ |
174 | DSI_CIO_IRQ_ERRCONTENTIONLP0_2 | DSI_CIO_IRQ_ERRCONTENTIONLP1_2 | \ | 195 | DSI_CIO_IRQ_ERRCONTENTIONLP0_2 | DSI_CIO_IRQ_ERRCONTENTIONLP1_2 | \ |
175 | DSI_CIO_IRQ_ERRCONTENTIONLP0_3 | DSI_CIO_IRQ_ERRCONTENTIONLP1_3) | 196 | DSI_CIO_IRQ_ERRCONTENTIONLP0_3 | DSI_CIO_IRQ_ERRCONTENTIONLP1_3 | \ |
197 | DSI_CIO_IRQ_ERRCONTENTIONLP0_4 | DSI_CIO_IRQ_ERRCONTENTIONLP1_4 | \ | ||
198 | DSI_CIO_IRQ_ERRCONTENTIONLP0_5 | DSI_CIO_IRQ_ERRCONTENTIONLP1_5) | ||
176 | 199 | ||
177 | #define DSI_DT_DCS_SHORT_WRITE_0 0x05 | 200 | #define DSI_DT_DCS_SHORT_WRITE_0 0x05 |
178 | #define DSI_DT_DCS_SHORT_WRITE_1 0x15 | 201 | #define DSI_DT_DCS_SHORT_WRITE_1 0x15 |
@@ -186,13 +209,15 @@ struct dsi_reg { u16 idx; }; | |||
186 | #define DSI_DT_RX_SHORT_READ_1 0x21 | 209 | #define DSI_DT_RX_SHORT_READ_1 0x21 |
187 | #define DSI_DT_RX_SHORT_READ_2 0x22 | 210 | #define DSI_DT_RX_SHORT_READ_2 0x22 |
188 | 211 | ||
189 | #define FINT_MAX 2100000 | 212 | typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); |
190 | #define FINT_MIN 750000 | 213 | |
191 | #define REGN_MAX (1 << 7) | 214 | #define DSI_MAX_NR_ISRS 2 |
192 | #define REGM_MAX ((1 << 11) - 1) | 215 | |
193 | #define REGM3_MAX (1 << 4) | 216 | struct dsi_isr_data { |
194 | #define REGM4_MAX (1 << 4) | 217 | omap_dsi_isr_t isr; |
195 | #define LP_DIV_MAX ((1 << 13) - 1) | 218 | void *arg; |
219 | u32 mask; | ||
220 | }; | ||
196 | 221 | ||
197 | enum fifo_size { | 222 | enum fifo_size { |
198 | DSI_FIFO_SIZE_0 = 0, | 223 | DSI_FIFO_SIZE_0 = 0, |
@@ -207,6 +232,19 @@ enum dsi_vc_mode { | |||
207 | DSI_VC_MODE_VP, | 232 | DSI_VC_MODE_VP, |
208 | }; | 233 | }; |
209 | 234 | ||
235 | enum dsi_lane { | ||
236 | DSI_CLK_P = 1 << 0, | ||
237 | DSI_CLK_N = 1 << 1, | ||
238 | DSI_DATA1_P = 1 << 2, | ||
239 | DSI_DATA1_N = 1 << 3, | ||
240 | DSI_DATA2_P = 1 << 4, | ||
241 | DSI_DATA2_N = 1 << 5, | ||
242 | DSI_DATA3_P = 1 << 6, | ||
243 | DSI_DATA3_N = 1 << 7, | ||
244 | DSI_DATA4_P = 1 << 8, | ||
245 | DSI_DATA4_N = 1 << 9, | ||
246 | }; | ||
247 | |||
210 | struct dsi_update_region { | 248 | struct dsi_update_region { |
211 | u16 x, y, w, h; | 249 | u16 x, y, w, h; |
212 | struct omap_dss_device *device; | 250 | struct omap_dss_device *device; |
@@ -220,18 +258,29 @@ struct dsi_irq_stats { | |||
220 | unsigned cio_irqs[32]; | 258 | unsigned cio_irqs[32]; |
221 | }; | 259 | }; |
222 | 260 | ||
223 | static struct | 261 | struct dsi_isr_tables { |
224 | { | 262 | struct dsi_isr_data isr_table[DSI_MAX_NR_ISRS]; |
263 | struct dsi_isr_data isr_table_vc[4][DSI_MAX_NR_ISRS]; | ||
264 | struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS]; | ||
265 | }; | ||
266 | |||
267 | struct dsi_data { | ||
268 | struct platform_device *pdev; | ||
225 | void __iomem *base; | 269 | void __iomem *base; |
270 | int irq; | ||
271 | |||
272 | void (*dsi_mux_pads)(bool enable); | ||
226 | 273 | ||
227 | struct dsi_clock_info current_cinfo; | 274 | struct dsi_clock_info current_cinfo; |
228 | 275 | ||
276 | bool vdds_dsi_enabled; | ||
229 | struct regulator *vdds_dsi_reg; | 277 | struct regulator *vdds_dsi_reg; |
230 | 278 | ||
231 | struct { | 279 | struct { |
232 | enum dsi_vc_mode mode; | 280 | enum dsi_vc_mode mode; |
233 | struct omap_dss_device *dssdev; | 281 | struct omap_dss_device *dssdev; |
234 | enum fifo_size fifo_size; | 282 | enum fifo_size fifo_size; |
283 | int vc_id; | ||
235 | } vc[4]; | 284 | } vc[4]; |
236 | 285 | ||
237 | struct mutex lock; | 286 | struct mutex lock; |
@@ -239,15 +288,16 @@ static struct | |||
239 | 288 | ||
240 | unsigned pll_locked; | 289 | unsigned pll_locked; |
241 | 290 | ||
242 | struct completion bta_completion; | 291 | spinlock_t irq_lock; |
243 | void (*bta_callback)(void); | 292 | struct dsi_isr_tables isr_tables; |
293 | /* space for a copy used by the interrupt handler */ | ||
294 | struct dsi_isr_tables isr_tables_copy; | ||
244 | 295 | ||
245 | int update_channel; | 296 | int update_channel; |
246 | struct dsi_update_region update_region; | 297 | struct dsi_update_region update_region; |
247 | 298 | ||
248 | bool te_enabled; | 299 | bool te_enabled; |
249 | 300 | bool ulps_enabled; | |
250 | struct workqueue_struct *workqueue; | ||
251 | 301 | ||
252 | void (*framedone_callback)(int, void *); | 302 | void (*framedone_callback)(int, void *); |
253 | void *framedone_data; | 303 | void *framedone_data; |
@@ -275,21 +325,68 @@ static struct | |||
275 | spinlock_t irq_stats_lock; | 325 | spinlock_t irq_stats_lock; |
276 | struct dsi_irq_stats irq_stats; | 326 | struct dsi_irq_stats irq_stats; |
277 | #endif | 327 | #endif |
278 | } dsi; | 328 | /* DSI PLL Parameter Ranges */ |
329 | unsigned long regm_max, regn_max; | ||
330 | unsigned long regm_dispc_max, regm_dsi_max; | ||
331 | unsigned long fint_min, fint_max; | ||
332 | unsigned long lpdiv_max; | ||
333 | |||
334 | int num_data_lanes; | ||
335 | |||
336 | unsigned scp_clk_refcount; | ||
337 | }; | ||
338 | |||
339 | struct dsi_packet_sent_handler_data { | ||
340 | struct platform_device *dsidev; | ||
341 | struct completion *completion; | ||
342 | }; | ||
343 | |||
344 | static struct platform_device *dsi_pdev_map[MAX_NUM_DSI]; | ||
279 | 345 | ||
280 | #ifdef DEBUG | 346 | #ifdef DEBUG |
281 | static unsigned int dsi_perf; | 347 | static unsigned int dsi_perf; |
282 | module_param_named(dsi_perf, dsi_perf, bool, 0644); | 348 | module_param_named(dsi_perf, dsi_perf, bool, 0644); |
283 | #endif | 349 | #endif |
284 | 350 | ||
285 | static inline void dsi_write_reg(const struct dsi_reg idx, u32 val) | 351 | static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dsidev) |
352 | { | ||
353 | return dev_get_drvdata(&dsidev->dev); | ||
354 | } | ||
355 | |||
356 | static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev) | ||
286 | { | 357 | { |
287 | __raw_writel(val, dsi.base + idx.idx); | 358 | return dsi_pdev_map[dssdev->phy.dsi.module]; |
288 | } | 359 | } |
289 | 360 | ||
290 | static inline u32 dsi_read_reg(const struct dsi_reg idx) | 361 | struct platform_device *dsi_get_dsidev_from_id(int module) |
291 | { | 362 | { |
292 | return __raw_readl(dsi.base + idx.idx); | 363 | return dsi_pdev_map[module]; |
364 | } | ||
365 | |||
366 | static int dsi_get_dsidev_id(struct platform_device *dsidev) | ||
367 | { | ||
368 | /* TEMP: Pass 0 as the dsi module index till the time the dsi platform | ||
369 | * device names aren't changed to the form "omapdss_dsi.0", | ||
370 | * "omapdss_dsi.1" and so on */ | ||
371 | BUG_ON(dsidev->id != -1); | ||
372 | |||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | static inline void dsi_write_reg(struct platform_device *dsidev, | ||
377 | const struct dsi_reg idx, u32 val) | ||
378 | { | ||
379 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
380 | |||
381 | __raw_writel(val, dsi->base + idx.idx); | ||
382 | } | ||
383 | |||
384 | static inline u32 dsi_read_reg(struct platform_device *dsidev, | ||
385 | const struct dsi_reg idx) | ||
386 | { | ||
387 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
388 | |||
389 | return __raw_readl(dsi->base + idx.idx); | ||
293 | } | 390 | } |
294 | 391 | ||
295 | 392 | ||
@@ -301,29 +398,42 @@ void dsi_restore_context(void) | |||
301 | { | 398 | { |
302 | } | 399 | } |
303 | 400 | ||
304 | void dsi_bus_lock(void) | 401 | void dsi_bus_lock(struct omap_dss_device *dssdev) |
305 | { | 402 | { |
306 | down(&dsi.bus_lock); | 403 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
404 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
405 | |||
406 | down(&dsi->bus_lock); | ||
307 | } | 407 | } |
308 | EXPORT_SYMBOL(dsi_bus_lock); | 408 | EXPORT_SYMBOL(dsi_bus_lock); |
309 | 409 | ||
310 | void dsi_bus_unlock(void) | 410 | void dsi_bus_unlock(struct omap_dss_device *dssdev) |
311 | { | 411 | { |
312 | up(&dsi.bus_lock); | 412 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
413 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
414 | |||
415 | up(&dsi->bus_lock); | ||
313 | } | 416 | } |
314 | EXPORT_SYMBOL(dsi_bus_unlock); | 417 | EXPORT_SYMBOL(dsi_bus_unlock); |
315 | 418 | ||
316 | static bool dsi_bus_is_locked(void) | 419 | static bool dsi_bus_is_locked(struct platform_device *dsidev) |
317 | { | 420 | { |
318 | return dsi.bus_lock.count == 0; | 421 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
422 | |||
423 | return dsi->bus_lock.count == 0; | ||
319 | } | 424 | } |
320 | 425 | ||
321 | static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum, | 426 | static void dsi_completion_handler(void *data, u32 mask) |
322 | int value) | 427 | { |
428 | complete((struct completion *)data); | ||
429 | } | ||
430 | |||
431 | static inline int wait_for_bit_change(struct platform_device *dsidev, | ||
432 | const struct dsi_reg idx, int bitnum, int value) | ||
323 | { | 433 | { |
324 | int t = 100000; | 434 | int t = 100000; |
325 | 435 | ||
326 | while (REG_GET(idx, bitnum, bitnum) != value) { | 436 | while (REG_GET(dsidev, idx, bitnum, bitnum) != value) { |
327 | if (--t == 0) | 437 | if (--t == 0) |
328 | return !value; | 438 | return !value; |
329 | } | 439 | } |
@@ -332,18 +442,21 @@ static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum, | |||
332 | } | 442 | } |
333 | 443 | ||
334 | #ifdef DEBUG | 444 | #ifdef DEBUG |
335 | static void dsi_perf_mark_setup(void) | 445 | static void dsi_perf_mark_setup(struct platform_device *dsidev) |
336 | { | 446 | { |
337 | dsi.perf_setup_time = ktime_get(); | 447 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
448 | dsi->perf_setup_time = ktime_get(); | ||
338 | } | 449 | } |
339 | 450 | ||
340 | static void dsi_perf_mark_start(void) | 451 | static void dsi_perf_mark_start(struct platform_device *dsidev) |
341 | { | 452 | { |
342 | dsi.perf_start_time = ktime_get(); | 453 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
454 | dsi->perf_start_time = ktime_get(); | ||
343 | } | 455 | } |
344 | 456 | ||
345 | static void dsi_perf_show(const char *name) | 457 | static void dsi_perf_show(struct platform_device *dsidev, const char *name) |
346 | { | 458 | { |
459 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
347 | ktime_t t, setup_time, trans_time; | 460 | ktime_t t, setup_time, trans_time; |
348 | u32 total_bytes; | 461 | u32 total_bytes; |
349 | u32 setup_us, trans_us, total_us; | 462 | u32 setup_us, trans_us, total_us; |
@@ -353,21 +466,21 @@ static void dsi_perf_show(const char *name) | |||
353 | 466 | ||
354 | t = ktime_get(); | 467 | t = ktime_get(); |
355 | 468 | ||
356 | setup_time = ktime_sub(dsi.perf_start_time, dsi.perf_setup_time); | 469 | setup_time = ktime_sub(dsi->perf_start_time, dsi->perf_setup_time); |
357 | setup_us = (u32)ktime_to_us(setup_time); | 470 | setup_us = (u32)ktime_to_us(setup_time); |
358 | if (setup_us == 0) | 471 | if (setup_us == 0) |
359 | setup_us = 1; | 472 | setup_us = 1; |
360 | 473 | ||
361 | trans_time = ktime_sub(t, dsi.perf_start_time); | 474 | trans_time = ktime_sub(t, dsi->perf_start_time); |
362 | trans_us = (u32)ktime_to_us(trans_time); | 475 | trans_us = (u32)ktime_to_us(trans_time); |
363 | if (trans_us == 0) | 476 | if (trans_us == 0) |
364 | trans_us = 1; | 477 | trans_us = 1; |
365 | 478 | ||
366 | total_us = setup_us + trans_us; | 479 | total_us = setup_us + trans_us; |
367 | 480 | ||
368 | total_bytes = dsi.update_region.w * | 481 | total_bytes = dsi->update_region.w * |
369 | dsi.update_region.h * | 482 | dsi->update_region.h * |
370 | dsi.update_region.device->ctrl.pixel_size / 8; | 483 | dsi->update_region.device->ctrl.pixel_size / 8; |
371 | 484 | ||
372 | printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), " | 485 | printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), " |
373 | "%u bytes, %u kbytes/sec\n", | 486 | "%u bytes, %u kbytes/sec\n", |
@@ -380,13 +493,16 @@ static void dsi_perf_show(const char *name) | |||
380 | total_bytes * 1000 / total_us); | 493 | total_bytes * 1000 / total_us); |
381 | } | 494 | } |
382 | #else | 495 | #else |
383 | #define dsi_perf_mark_setup() | 496 | #define dsi_perf_mark_setup(x) |
384 | #define dsi_perf_mark_start() | 497 | #define dsi_perf_mark_start(x) |
385 | #define dsi_perf_show(x) | 498 | #define dsi_perf_show(x, y) |
386 | #endif | 499 | #endif |
387 | 500 | ||
388 | static void print_irq_status(u32 status) | 501 | static void print_irq_status(u32 status) |
389 | { | 502 | { |
503 | if (status == 0) | ||
504 | return; | ||
505 | |||
390 | #ifndef VERBOSE_IRQ | 506 | #ifndef VERBOSE_IRQ |
391 | if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0) | 507 | if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0) |
392 | return; | 508 | return; |
@@ -422,6 +538,9 @@ static void print_irq_status(u32 status) | |||
422 | 538 | ||
423 | static void print_irq_status_vc(int channel, u32 status) | 539 | static void print_irq_status_vc(int channel, u32 status) |
424 | { | 540 | { |
541 | if (status == 0) | ||
542 | return; | ||
543 | |||
425 | #ifndef VERBOSE_IRQ | 544 | #ifndef VERBOSE_IRQ |
426 | if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0) | 545 | if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0) |
427 | return; | 546 | return; |
@@ -448,6 +567,9 @@ static void print_irq_status_vc(int channel, u32 status) | |||
448 | 567 | ||
449 | static void print_irq_status_cio(u32 status) | 568 | static void print_irq_status_cio(u32 status) |
450 | { | 569 | { |
570 | if (status == 0) | ||
571 | return; | ||
572 | |||
451 | printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status); | 573 | printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status); |
452 | 574 | ||
453 | #define PIS(x) \ | 575 | #define PIS(x) \ |
@@ -478,192 +600,476 @@ static void print_irq_status_cio(u32 status) | |||
478 | printk("\n"); | 600 | printk("\n"); |
479 | } | 601 | } |
480 | 602 | ||
481 | static int debug_irq; | 603 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS |
482 | 604 | static void dsi_collect_irq_stats(struct platform_device *dsidev, u32 irqstatus, | |
483 | /* called from dss */ | 605 | u32 *vcstatus, u32 ciostatus) |
484 | void dsi_irq_handler(void) | ||
485 | { | 606 | { |
486 | u32 irqstatus, vcstatus, ciostatus; | 607 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
487 | int i; | 608 | int i; |
488 | 609 | ||
489 | irqstatus = dsi_read_reg(DSI_IRQSTATUS); | 610 | spin_lock(&dsi->irq_stats_lock); |
490 | 611 | ||
491 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 612 | dsi->irq_stats.irq_count++; |
492 | spin_lock(&dsi.irq_stats_lock); | 613 | dss_collect_irq_stats(irqstatus, dsi->irq_stats.dsi_irqs); |
493 | dsi.irq_stats.irq_count++; | 614 | |
494 | dss_collect_irq_stats(irqstatus, dsi.irq_stats.dsi_irqs); | 615 | for (i = 0; i < 4; ++i) |
616 | dss_collect_irq_stats(vcstatus[i], dsi->irq_stats.vc_irqs[i]); | ||
617 | |||
618 | dss_collect_irq_stats(ciostatus, dsi->irq_stats.cio_irqs); | ||
619 | |||
620 | spin_unlock(&dsi->irq_stats_lock); | ||
621 | } | ||
622 | #else | ||
623 | #define dsi_collect_irq_stats(dsidev, irqstatus, vcstatus, ciostatus) | ||
495 | #endif | 624 | #endif |
496 | 625 | ||
626 | static int debug_irq; | ||
627 | |||
628 | static void dsi_handle_irq_errors(struct platform_device *dsidev, u32 irqstatus, | ||
629 | u32 *vcstatus, u32 ciostatus) | ||
630 | { | ||
631 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
632 | int i; | ||
633 | |||
497 | if (irqstatus & DSI_IRQ_ERROR_MASK) { | 634 | if (irqstatus & DSI_IRQ_ERROR_MASK) { |
498 | DSSERR("DSI error, irqstatus %x\n", irqstatus); | 635 | DSSERR("DSI error, irqstatus %x\n", irqstatus); |
499 | print_irq_status(irqstatus); | 636 | print_irq_status(irqstatus); |
500 | spin_lock(&dsi.errors_lock); | 637 | spin_lock(&dsi->errors_lock); |
501 | dsi.errors |= irqstatus & DSI_IRQ_ERROR_MASK; | 638 | dsi->errors |= irqstatus & DSI_IRQ_ERROR_MASK; |
502 | spin_unlock(&dsi.errors_lock); | 639 | spin_unlock(&dsi->errors_lock); |
503 | } else if (debug_irq) { | 640 | } else if (debug_irq) { |
504 | print_irq_status(irqstatus); | 641 | print_irq_status(irqstatus); |
505 | } | 642 | } |
506 | 643 | ||
507 | #ifdef DSI_CATCH_MISSING_TE | 644 | for (i = 0; i < 4; ++i) { |
508 | if (irqstatus & DSI_IRQ_TE_TRIGGER) | 645 | if (vcstatus[i] & DSI_VC_IRQ_ERROR_MASK) { |
509 | del_timer(&dsi.te_timer); | 646 | DSSERR("DSI VC(%d) error, vc irqstatus %x\n", |
510 | #endif | 647 | i, vcstatus[i]); |
648 | print_irq_status_vc(i, vcstatus[i]); | ||
649 | } else if (debug_irq) { | ||
650 | print_irq_status_vc(i, vcstatus[i]); | ||
651 | } | ||
652 | } | ||
653 | |||
654 | if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) { | ||
655 | DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus); | ||
656 | print_irq_status_cio(ciostatus); | ||
657 | } else if (debug_irq) { | ||
658 | print_irq_status_cio(ciostatus); | ||
659 | } | ||
660 | } | ||
661 | |||
662 | static void dsi_call_isrs(struct dsi_isr_data *isr_array, | ||
663 | unsigned isr_array_size, u32 irqstatus) | ||
664 | { | ||
665 | struct dsi_isr_data *isr_data; | ||
666 | int i; | ||
667 | |||
668 | for (i = 0; i < isr_array_size; i++) { | ||
669 | isr_data = &isr_array[i]; | ||
670 | if (isr_data->isr && isr_data->mask & irqstatus) | ||
671 | isr_data->isr(isr_data->arg, irqstatus); | ||
672 | } | ||
673 | } | ||
674 | |||
675 | static void dsi_handle_isrs(struct dsi_isr_tables *isr_tables, | ||
676 | u32 irqstatus, u32 *vcstatus, u32 ciostatus) | ||
677 | { | ||
678 | int i; | ||
679 | |||
680 | dsi_call_isrs(isr_tables->isr_table, | ||
681 | ARRAY_SIZE(isr_tables->isr_table), | ||
682 | irqstatus); | ||
511 | 683 | ||
512 | for (i = 0; i < 4; ++i) { | 684 | for (i = 0; i < 4; ++i) { |
513 | if ((irqstatus & (1<<i)) == 0) | 685 | if (vcstatus[i] == 0) |
514 | continue; | 686 | continue; |
687 | dsi_call_isrs(isr_tables->isr_table_vc[i], | ||
688 | ARRAY_SIZE(isr_tables->isr_table_vc[i]), | ||
689 | vcstatus[i]); | ||
690 | } | ||
515 | 691 | ||
516 | vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i)); | 692 | if (ciostatus != 0) |
693 | dsi_call_isrs(isr_tables->isr_table_cio, | ||
694 | ARRAY_SIZE(isr_tables->isr_table_cio), | ||
695 | ciostatus); | ||
696 | } | ||
517 | 697 | ||
518 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 698 | static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) |
519 | dss_collect_irq_stats(vcstatus, dsi.irq_stats.vc_irqs[i]); | 699 | { |
520 | #endif | 700 | struct platform_device *dsidev; |
701 | struct dsi_data *dsi; | ||
702 | u32 irqstatus, vcstatus[4], ciostatus; | ||
703 | int i; | ||
521 | 704 | ||
522 | if (vcstatus & DSI_VC_IRQ_BTA) { | 705 | dsidev = (struct platform_device *) arg; |
523 | complete(&dsi.bta_completion); | 706 | dsi = dsi_get_dsidrv_data(dsidev); |
524 | 707 | ||
525 | if (dsi.bta_callback) | 708 | spin_lock(&dsi->irq_lock); |
526 | dsi.bta_callback(); | ||
527 | } | ||
528 | 709 | ||
529 | if (vcstatus & DSI_VC_IRQ_ERROR_MASK) { | 710 | irqstatus = dsi_read_reg(dsidev, DSI_IRQSTATUS); |
530 | DSSERR("DSI VC(%d) error, vc irqstatus %x\n", | 711 | |
531 | i, vcstatus); | 712 | /* IRQ is not for us */ |
532 | print_irq_status_vc(i, vcstatus); | 713 | if (!irqstatus) { |
533 | } else if (debug_irq) { | 714 | spin_unlock(&dsi->irq_lock); |
534 | print_irq_status_vc(i, vcstatus); | 715 | return IRQ_NONE; |
716 | } | ||
717 | |||
718 | dsi_write_reg(dsidev, DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); | ||
719 | /* flush posted write */ | ||
720 | dsi_read_reg(dsidev, DSI_IRQSTATUS); | ||
721 | |||
722 | for (i = 0; i < 4; ++i) { | ||
723 | if ((irqstatus & (1 << i)) == 0) { | ||
724 | vcstatus[i] = 0; | ||
725 | continue; | ||
535 | } | 726 | } |
536 | 727 | ||
537 | dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus); | 728 | vcstatus[i] = dsi_read_reg(dsidev, DSI_VC_IRQSTATUS(i)); |
729 | |||
730 | dsi_write_reg(dsidev, DSI_VC_IRQSTATUS(i), vcstatus[i]); | ||
538 | /* flush posted write */ | 731 | /* flush posted write */ |
539 | dsi_read_reg(DSI_VC_IRQSTATUS(i)); | 732 | dsi_read_reg(dsidev, DSI_VC_IRQSTATUS(i)); |
540 | } | 733 | } |
541 | 734 | ||
542 | if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) { | 735 | if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) { |
543 | ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); | 736 | ciostatus = dsi_read_reg(dsidev, DSI_COMPLEXIO_IRQ_STATUS); |
544 | 737 | ||
545 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 738 | dsi_write_reg(dsidev, DSI_COMPLEXIO_IRQ_STATUS, ciostatus); |
546 | dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs); | 739 | /* flush posted write */ |
740 | dsi_read_reg(dsidev, DSI_COMPLEXIO_IRQ_STATUS); | ||
741 | } else { | ||
742 | ciostatus = 0; | ||
743 | } | ||
744 | |||
745 | #ifdef DSI_CATCH_MISSING_TE | ||
746 | if (irqstatus & DSI_IRQ_TE_TRIGGER) | ||
747 | del_timer(&dsi->te_timer); | ||
547 | #endif | 748 | #endif |
548 | 749 | ||
549 | dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus); | 750 | /* make a copy and unlock, so that isrs can unregister |
550 | /* flush posted write */ | 751 | * themselves */ |
551 | dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); | 752 | memcpy(&dsi->isr_tables_copy, &dsi->isr_tables, |
753 | sizeof(dsi->isr_tables)); | ||
552 | 754 | ||
553 | if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) { | 755 | spin_unlock(&dsi->irq_lock); |
554 | DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus); | 756 | |
555 | print_irq_status_cio(ciostatus); | 757 | dsi_handle_isrs(&dsi->isr_tables_copy, irqstatus, vcstatus, ciostatus); |
556 | } else if (debug_irq) { | 758 | |
557 | print_irq_status_cio(ciostatus); | 759 | dsi_handle_irq_errors(dsidev, irqstatus, vcstatus, ciostatus); |
558 | } | 760 | |
761 | dsi_collect_irq_stats(dsidev, irqstatus, vcstatus, ciostatus); | ||
762 | |||
763 | return IRQ_HANDLED; | ||
764 | } | ||
765 | |||
766 | /* dsi->irq_lock has to be locked by the caller */ | ||
767 | static void _omap_dsi_configure_irqs(struct platform_device *dsidev, | ||
768 | struct dsi_isr_data *isr_array, | ||
769 | unsigned isr_array_size, u32 default_mask, | ||
770 | const struct dsi_reg enable_reg, | ||
771 | const struct dsi_reg status_reg) | ||
772 | { | ||
773 | struct dsi_isr_data *isr_data; | ||
774 | u32 mask; | ||
775 | u32 old_mask; | ||
776 | int i; | ||
777 | |||
778 | mask = default_mask; | ||
779 | |||
780 | for (i = 0; i < isr_array_size; i++) { | ||
781 | isr_data = &isr_array[i]; | ||
782 | |||
783 | if (isr_data->isr == NULL) | ||
784 | continue; | ||
785 | |||
786 | mask |= isr_data->mask; | ||
559 | } | 787 | } |
560 | 788 | ||
561 | dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); | 789 | old_mask = dsi_read_reg(dsidev, enable_reg); |
562 | /* flush posted write */ | 790 | /* clear the irqstatus for newly enabled irqs */ |
563 | dsi_read_reg(DSI_IRQSTATUS); | 791 | dsi_write_reg(dsidev, status_reg, (mask ^ old_mask) & mask); |
792 | dsi_write_reg(dsidev, enable_reg, mask); | ||
564 | 793 | ||
565 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 794 | /* flush posted writes */ |
566 | spin_unlock(&dsi.irq_stats_lock); | 795 | dsi_read_reg(dsidev, enable_reg); |
796 | dsi_read_reg(dsidev, status_reg); | ||
797 | } | ||
798 | |||
799 | /* dsi->irq_lock has to be locked by the caller */ | ||
800 | static void _omap_dsi_set_irqs(struct platform_device *dsidev) | ||
801 | { | ||
802 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
803 | u32 mask = DSI_IRQ_ERROR_MASK; | ||
804 | #ifdef DSI_CATCH_MISSING_TE | ||
805 | mask |= DSI_IRQ_TE_TRIGGER; | ||
567 | #endif | 806 | #endif |
807 | _omap_dsi_configure_irqs(dsidev, dsi->isr_tables.isr_table, | ||
808 | ARRAY_SIZE(dsi->isr_tables.isr_table), mask, | ||
809 | DSI_IRQENABLE, DSI_IRQSTATUS); | ||
810 | } | ||
811 | |||
812 | /* dsi->irq_lock has to be locked by the caller */ | ||
813 | static void _omap_dsi_set_irqs_vc(struct platform_device *dsidev, int vc) | ||
814 | { | ||
815 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
816 | |||
817 | _omap_dsi_configure_irqs(dsidev, dsi->isr_tables.isr_table_vc[vc], | ||
818 | ARRAY_SIZE(dsi->isr_tables.isr_table_vc[vc]), | ||
819 | DSI_VC_IRQ_ERROR_MASK, | ||
820 | DSI_VC_IRQENABLE(vc), DSI_VC_IRQSTATUS(vc)); | ||
568 | } | 821 | } |
569 | 822 | ||
823 | /* dsi->irq_lock has to be locked by the caller */ | ||
824 | static void _omap_dsi_set_irqs_cio(struct platform_device *dsidev) | ||
825 | { | ||
826 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
827 | |||
828 | _omap_dsi_configure_irqs(dsidev, dsi->isr_tables.isr_table_cio, | ||
829 | ARRAY_SIZE(dsi->isr_tables.isr_table_cio), | ||
830 | DSI_CIO_IRQ_ERROR_MASK, | ||
831 | DSI_COMPLEXIO_IRQ_ENABLE, DSI_COMPLEXIO_IRQ_STATUS); | ||
832 | } | ||
570 | 833 | ||
571 | static void _dsi_initialize_irq(void) | 834 | static void _dsi_initialize_irq(struct platform_device *dsidev) |
572 | { | 835 | { |
573 | u32 l; | 836 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
837 | unsigned long flags; | ||
838 | int vc; | ||
839 | |||
840 | spin_lock_irqsave(&dsi->irq_lock, flags); | ||
841 | |||
842 | memset(&dsi->isr_tables, 0, sizeof(dsi->isr_tables)); | ||
843 | |||
844 | _omap_dsi_set_irqs(dsidev); | ||
845 | for (vc = 0; vc < 4; ++vc) | ||
846 | _omap_dsi_set_irqs_vc(dsidev, vc); | ||
847 | _omap_dsi_set_irqs_cio(dsidev); | ||
848 | |||
849 | spin_unlock_irqrestore(&dsi->irq_lock, flags); | ||
850 | } | ||
851 | |||
852 | static int _dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask, | ||
853 | struct dsi_isr_data *isr_array, unsigned isr_array_size) | ||
854 | { | ||
855 | struct dsi_isr_data *isr_data; | ||
856 | int free_idx; | ||
574 | int i; | 857 | int i; |
575 | 858 | ||
576 | /* disable all interrupts */ | 859 | BUG_ON(isr == NULL); |
577 | dsi_write_reg(DSI_IRQENABLE, 0); | ||
578 | for (i = 0; i < 4; ++i) | ||
579 | dsi_write_reg(DSI_VC_IRQENABLE(i), 0); | ||
580 | dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0); | ||
581 | 860 | ||
582 | /* clear interrupt status */ | 861 | /* check for duplicate entry and find a free slot */ |
583 | l = dsi_read_reg(DSI_IRQSTATUS); | 862 | free_idx = -1; |
584 | dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK); | 863 | for (i = 0; i < isr_array_size; i++) { |
864 | isr_data = &isr_array[i]; | ||
585 | 865 | ||
586 | for (i = 0; i < 4; ++i) { | 866 | if (isr_data->isr == isr && isr_data->arg == arg && |
587 | l = dsi_read_reg(DSI_VC_IRQSTATUS(i)); | 867 | isr_data->mask == mask) { |
588 | dsi_write_reg(DSI_VC_IRQSTATUS(i), l); | 868 | return -EINVAL; |
869 | } | ||
870 | |||
871 | if (isr_data->isr == NULL && free_idx == -1) | ||
872 | free_idx = i; | ||
589 | } | 873 | } |
590 | 874 | ||
591 | l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); | 875 | if (free_idx == -1) |
592 | dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l); | 876 | return -EBUSY; |
593 | 877 | ||
594 | /* enable error irqs */ | 878 | isr_data = &isr_array[free_idx]; |
595 | l = DSI_IRQ_ERROR_MASK; | 879 | isr_data->isr = isr; |
596 | #ifdef DSI_CATCH_MISSING_TE | 880 | isr_data->arg = arg; |
597 | l |= DSI_IRQ_TE_TRIGGER; | 881 | isr_data->mask = mask; |
598 | #endif | ||
599 | dsi_write_reg(DSI_IRQENABLE, l); | ||
600 | 882 | ||
601 | l = DSI_VC_IRQ_ERROR_MASK; | 883 | return 0; |
602 | for (i = 0; i < 4; ++i) | 884 | } |
603 | dsi_write_reg(DSI_VC_IRQENABLE(i), l); | 885 | |
886 | static int _dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask, | ||
887 | struct dsi_isr_data *isr_array, unsigned isr_array_size) | ||
888 | { | ||
889 | struct dsi_isr_data *isr_data; | ||
890 | int i; | ||
891 | |||
892 | for (i = 0; i < isr_array_size; i++) { | ||
893 | isr_data = &isr_array[i]; | ||
894 | if (isr_data->isr != isr || isr_data->arg != arg || | ||
895 | isr_data->mask != mask) | ||
896 | continue; | ||
897 | |||
898 | isr_data->isr = NULL; | ||
899 | isr_data->arg = NULL; | ||
900 | isr_data->mask = 0; | ||
604 | 901 | ||
605 | l = DSI_CIO_IRQ_ERROR_MASK; | 902 | return 0; |
606 | dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, l); | 903 | } |
904 | |||
905 | return -EINVAL; | ||
607 | } | 906 | } |
608 | 907 | ||
609 | static u32 dsi_get_errors(void) | 908 | static int dsi_register_isr(struct platform_device *dsidev, omap_dsi_isr_t isr, |
909 | void *arg, u32 mask) | ||
610 | { | 910 | { |
911 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
611 | unsigned long flags; | 912 | unsigned long flags; |
612 | u32 e; | 913 | int r; |
613 | spin_lock_irqsave(&dsi.errors_lock, flags); | 914 | |
614 | e = dsi.errors; | 915 | spin_lock_irqsave(&dsi->irq_lock, flags); |
615 | dsi.errors = 0; | 916 | |
616 | spin_unlock_irqrestore(&dsi.errors_lock, flags); | 917 | r = _dsi_register_isr(isr, arg, mask, dsi->isr_tables.isr_table, |
617 | return e; | 918 | ARRAY_SIZE(dsi->isr_tables.isr_table)); |
919 | |||
920 | if (r == 0) | ||
921 | _omap_dsi_set_irqs(dsidev); | ||
922 | |||
923 | spin_unlock_irqrestore(&dsi->irq_lock, flags); | ||
924 | |||
925 | return r; | ||
618 | } | 926 | } |
619 | 927 | ||
620 | static void dsi_vc_enable_bta_irq(int channel) | 928 | static int dsi_unregister_isr(struct platform_device *dsidev, |
929 | omap_dsi_isr_t isr, void *arg, u32 mask) | ||
621 | { | 930 | { |
622 | u32 l; | 931 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
932 | unsigned long flags; | ||
933 | int r; | ||
623 | 934 | ||
624 | dsi_write_reg(DSI_VC_IRQSTATUS(channel), DSI_VC_IRQ_BTA); | 935 | spin_lock_irqsave(&dsi->irq_lock, flags); |
625 | 936 | ||
626 | l = dsi_read_reg(DSI_VC_IRQENABLE(channel)); | 937 | r = _dsi_unregister_isr(isr, arg, mask, dsi->isr_tables.isr_table, |
627 | l |= DSI_VC_IRQ_BTA; | 938 | ARRAY_SIZE(dsi->isr_tables.isr_table)); |
628 | dsi_write_reg(DSI_VC_IRQENABLE(channel), l); | 939 | |
940 | if (r == 0) | ||
941 | _omap_dsi_set_irqs(dsidev); | ||
942 | |||
943 | spin_unlock_irqrestore(&dsi->irq_lock, flags); | ||
944 | |||
945 | return r; | ||
629 | } | 946 | } |
630 | 947 | ||
631 | static void dsi_vc_disable_bta_irq(int channel) | 948 | static int dsi_register_isr_vc(struct platform_device *dsidev, int channel, |
949 | omap_dsi_isr_t isr, void *arg, u32 mask) | ||
632 | { | 950 | { |
633 | u32 l; | 951 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
952 | unsigned long flags; | ||
953 | int r; | ||
954 | |||
955 | spin_lock_irqsave(&dsi->irq_lock, flags); | ||
956 | |||
957 | r = _dsi_register_isr(isr, arg, mask, | ||
958 | dsi->isr_tables.isr_table_vc[channel], | ||
959 | ARRAY_SIZE(dsi->isr_tables.isr_table_vc[channel])); | ||
960 | |||
961 | if (r == 0) | ||
962 | _omap_dsi_set_irqs_vc(dsidev, channel); | ||
963 | |||
964 | spin_unlock_irqrestore(&dsi->irq_lock, flags); | ||
965 | |||
966 | return r; | ||
967 | } | ||
968 | |||
969 | static int dsi_unregister_isr_vc(struct platform_device *dsidev, int channel, | ||
970 | omap_dsi_isr_t isr, void *arg, u32 mask) | ||
971 | { | ||
972 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
973 | unsigned long flags; | ||
974 | int r; | ||
975 | |||
976 | spin_lock_irqsave(&dsi->irq_lock, flags); | ||
977 | |||
978 | r = _dsi_unregister_isr(isr, arg, mask, | ||
979 | dsi->isr_tables.isr_table_vc[channel], | ||
980 | ARRAY_SIZE(dsi->isr_tables.isr_table_vc[channel])); | ||
981 | |||
982 | if (r == 0) | ||
983 | _omap_dsi_set_irqs_vc(dsidev, channel); | ||
984 | |||
985 | spin_unlock_irqrestore(&dsi->irq_lock, flags); | ||
986 | |||
987 | return r; | ||
988 | } | ||
634 | 989 | ||
635 | l = dsi_read_reg(DSI_VC_IRQENABLE(channel)); | 990 | static int dsi_register_isr_cio(struct platform_device *dsidev, |
636 | l &= ~DSI_VC_IRQ_BTA; | 991 | omap_dsi_isr_t isr, void *arg, u32 mask) |
637 | dsi_write_reg(DSI_VC_IRQENABLE(channel), l); | 992 | { |
993 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
994 | unsigned long flags; | ||
995 | int r; | ||
996 | |||
997 | spin_lock_irqsave(&dsi->irq_lock, flags); | ||
998 | |||
999 | r = _dsi_register_isr(isr, arg, mask, dsi->isr_tables.isr_table_cio, | ||
1000 | ARRAY_SIZE(dsi->isr_tables.isr_table_cio)); | ||
1001 | |||
1002 | if (r == 0) | ||
1003 | _omap_dsi_set_irqs_cio(dsidev); | ||
1004 | |||
1005 | spin_unlock_irqrestore(&dsi->irq_lock, flags); | ||
1006 | |||
1007 | return r; | ||
1008 | } | ||
1009 | |||
1010 | static int dsi_unregister_isr_cio(struct platform_device *dsidev, | ||
1011 | omap_dsi_isr_t isr, void *arg, u32 mask) | ||
1012 | { | ||
1013 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1014 | unsigned long flags; | ||
1015 | int r; | ||
1016 | |||
1017 | spin_lock_irqsave(&dsi->irq_lock, flags); | ||
1018 | |||
1019 | r = _dsi_unregister_isr(isr, arg, mask, dsi->isr_tables.isr_table_cio, | ||
1020 | ARRAY_SIZE(dsi->isr_tables.isr_table_cio)); | ||
1021 | |||
1022 | if (r == 0) | ||
1023 | _omap_dsi_set_irqs_cio(dsidev); | ||
1024 | |||
1025 | spin_unlock_irqrestore(&dsi->irq_lock, flags); | ||
1026 | |||
1027 | return r; | ||
638 | } | 1028 | } |
639 | 1029 | ||
640 | /* DSI func clock. this could also be DSI2_PLL_FCLK */ | 1030 | static u32 dsi_get_errors(struct platform_device *dsidev) |
1031 | { | ||
1032 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1033 | unsigned long flags; | ||
1034 | u32 e; | ||
1035 | spin_lock_irqsave(&dsi->errors_lock, flags); | ||
1036 | e = dsi->errors; | ||
1037 | dsi->errors = 0; | ||
1038 | spin_unlock_irqrestore(&dsi->errors_lock, flags); | ||
1039 | return e; | ||
1040 | } | ||
1041 | |||
1042 | /* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */ | ||
641 | static inline void enable_clocks(bool enable) | 1043 | static inline void enable_clocks(bool enable) |
642 | { | 1044 | { |
643 | if (enable) | 1045 | if (enable) |
644 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 1046 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
645 | else | 1047 | else |
646 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 1048 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
647 | } | 1049 | } |
648 | 1050 | ||
649 | /* source clock for DSI PLL. this could also be PCLKFREE */ | 1051 | /* source clock for DSI PLL. this could also be PCLKFREE */ |
650 | static inline void dsi_enable_pll_clock(bool enable) | 1052 | static inline void dsi_enable_pll_clock(struct platform_device *dsidev, |
1053 | bool enable) | ||
651 | { | 1054 | { |
1055 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1056 | |||
652 | if (enable) | 1057 | if (enable) |
653 | dss_clk_enable(DSS_CLK_FCK2); | 1058 | dss_clk_enable(DSS_CLK_SYSCK); |
654 | else | 1059 | else |
655 | dss_clk_disable(DSS_CLK_FCK2); | 1060 | dss_clk_disable(DSS_CLK_SYSCK); |
656 | 1061 | ||
657 | if (enable && dsi.pll_locked) { | 1062 | if (enable && dsi->pll_locked) { |
658 | if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) | 1063 | if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1) |
659 | DSSERR("cannot lock PLL when enabling clocks\n"); | 1064 | DSSERR("cannot lock PLL when enabling clocks\n"); |
660 | } | 1065 | } |
661 | } | 1066 | } |
662 | 1067 | ||
663 | #ifdef DEBUG | 1068 | #ifdef DEBUG |
664 | static void _dsi_print_reset_status(void) | 1069 | static void _dsi_print_reset_status(struct platform_device *dsidev) |
665 | { | 1070 | { |
666 | u32 l; | 1071 | u32 l; |
1072 | int b0, b1, b2; | ||
667 | 1073 | ||
668 | if (!dss_debug) | 1074 | if (!dss_debug) |
669 | return; | 1075 | return; |
@@ -671,35 +1077,47 @@ static void _dsi_print_reset_status(void) | |||
671 | /* A dummy read using the SCP interface to any DSIPHY register is | 1077 | /* A dummy read using the SCP interface to any DSIPHY register is |
672 | * required after DSIPHY reset to complete the reset of the DSI complex | 1078 | * required after DSIPHY reset to complete the reset of the DSI complex |
673 | * I/O. */ | 1079 | * I/O. */ |
674 | l = dsi_read_reg(DSI_DSIPHY_CFG5); | 1080 | l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5); |
675 | 1081 | ||
676 | printk(KERN_DEBUG "DSI resets: "); | 1082 | printk(KERN_DEBUG "DSI resets: "); |
677 | 1083 | ||
678 | l = dsi_read_reg(DSI_PLL_STATUS); | 1084 | l = dsi_read_reg(dsidev, DSI_PLL_STATUS); |
679 | printk("PLL (%d) ", FLD_GET(l, 0, 0)); | 1085 | printk("PLL (%d) ", FLD_GET(l, 0, 0)); |
680 | 1086 | ||
681 | l = dsi_read_reg(DSI_COMPLEXIO_CFG1); | 1087 | l = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1); |
682 | printk("CIO (%d) ", FLD_GET(l, 29, 29)); | 1088 | printk("CIO (%d) ", FLD_GET(l, 29, 29)); |
683 | 1089 | ||
684 | l = dsi_read_reg(DSI_DSIPHY_CFG5); | 1090 | if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) { |
685 | printk("PHY (%x, %d, %d, %d)\n", | 1091 | b0 = 28; |
686 | FLD_GET(l, 28, 26), | 1092 | b1 = 27; |
1093 | b2 = 26; | ||
1094 | } else { | ||
1095 | b0 = 24; | ||
1096 | b1 = 25; | ||
1097 | b2 = 26; | ||
1098 | } | ||
1099 | |||
1100 | l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5); | ||
1101 | printk("PHY (%x%x%x, %d, %d, %d)\n", | ||
1102 | FLD_GET(l, b0, b0), | ||
1103 | FLD_GET(l, b1, b1), | ||
1104 | FLD_GET(l, b2, b2), | ||
687 | FLD_GET(l, 29, 29), | 1105 | FLD_GET(l, 29, 29), |
688 | FLD_GET(l, 30, 30), | 1106 | FLD_GET(l, 30, 30), |
689 | FLD_GET(l, 31, 31)); | 1107 | FLD_GET(l, 31, 31)); |
690 | } | 1108 | } |
691 | #else | 1109 | #else |
692 | #define _dsi_print_reset_status() | 1110 | #define _dsi_print_reset_status(x) |
693 | #endif | 1111 | #endif |
694 | 1112 | ||
695 | static inline int dsi_if_enable(bool enable) | 1113 | static inline int dsi_if_enable(struct platform_device *dsidev, bool enable) |
696 | { | 1114 | { |
697 | DSSDBG("dsi_if_enable(%d)\n", enable); | 1115 | DSSDBG("dsi_if_enable(%d)\n", enable); |
698 | 1116 | ||
699 | enable = enable ? 1 : 0; | 1117 | enable = enable ? 1 : 0; |
700 | REG_FLD_MOD(DSI_CTRL, enable, 0, 0); /* IF_EN */ | 1118 | REG_FLD_MOD(dsidev, DSI_CTRL, enable, 0, 0); /* IF_EN */ |
701 | 1119 | ||
702 | if (wait_for_bit_change(DSI_CTRL, 0, enable) != enable) { | 1120 | if (wait_for_bit_change(dsidev, DSI_CTRL, 0, enable) != enable) { |
703 | DSSERR("Failed to set dsi_if_enable to %d\n", enable); | 1121 | DSSERR("Failed to set dsi_if_enable to %d\n", enable); |
704 | return -EIO; | 1122 | return -EIO; |
705 | } | 1123 | } |
@@ -707,31 +1125,38 @@ static inline int dsi_if_enable(bool enable) | |||
707 | return 0; | 1125 | return 0; |
708 | } | 1126 | } |
709 | 1127 | ||
710 | unsigned long dsi_get_dsi1_pll_rate(void) | 1128 | unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev) |
711 | { | 1129 | { |
712 | return dsi.current_cinfo.dsi1_pll_fclk; | 1130 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
1131 | |||
1132 | return dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk; | ||
713 | } | 1133 | } |
714 | 1134 | ||
715 | static unsigned long dsi_get_dsi2_pll_rate(void) | 1135 | static unsigned long dsi_get_pll_hsdiv_dsi_rate(struct platform_device *dsidev) |
716 | { | 1136 | { |
717 | return dsi.current_cinfo.dsi2_pll_fclk; | 1137 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
1138 | |||
1139 | return dsi->current_cinfo.dsi_pll_hsdiv_dsi_clk; | ||
718 | } | 1140 | } |
719 | 1141 | ||
720 | static unsigned long dsi_get_txbyteclkhs(void) | 1142 | static unsigned long dsi_get_txbyteclkhs(struct platform_device *dsidev) |
721 | { | 1143 | { |
722 | return dsi.current_cinfo.clkin4ddr / 16; | 1144 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
1145 | |||
1146 | return dsi->current_cinfo.clkin4ddr / 16; | ||
723 | } | 1147 | } |
724 | 1148 | ||
725 | static unsigned long dsi_fclk_rate(void) | 1149 | static unsigned long dsi_fclk_rate(struct platform_device *dsidev) |
726 | { | 1150 | { |
727 | unsigned long r; | 1151 | unsigned long r; |
1152 | int dsi_module = dsi_get_dsidev_id(dsidev); | ||
728 | 1153 | ||
729 | if (dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK) { | 1154 | if (dss_get_dsi_clk_source(dsi_module) == OMAP_DSS_CLK_SRC_FCK) { |
730 | /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */ | 1155 | /* DSI FCLK source is DSS_CLK_FCK */ |
731 | r = dss_clk_get_rate(DSS_CLK_FCK1); | 1156 | r = dss_clk_get_rate(DSS_CLK_FCK); |
732 | } else { | 1157 | } else { |
733 | /* DSI FCLK source is DSI2_PLL_FCLK */ | 1158 | /* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */ |
734 | r = dsi_get_dsi2_pll_rate(); | 1159 | r = dsi_get_pll_hsdiv_dsi_rate(dsidev); |
735 | } | 1160 | } |
736 | 1161 | ||
737 | return r; | 1162 | return r; |
@@ -739,31 +1164,50 @@ static unsigned long dsi_fclk_rate(void) | |||
739 | 1164 | ||
740 | static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev) | 1165 | static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev) |
741 | { | 1166 | { |
1167 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
1168 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
742 | unsigned long dsi_fclk; | 1169 | unsigned long dsi_fclk; |
743 | unsigned lp_clk_div; | 1170 | unsigned lp_clk_div; |
744 | unsigned long lp_clk; | 1171 | unsigned long lp_clk; |
745 | 1172 | ||
746 | lp_clk_div = dssdev->phy.dsi.div.lp_clk_div; | 1173 | lp_clk_div = dssdev->clocks.dsi.lp_clk_div; |
747 | 1174 | ||
748 | if (lp_clk_div == 0 || lp_clk_div > LP_DIV_MAX) | 1175 | if (lp_clk_div == 0 || lp_clk_div > dsi->lpdiv_max) |
749 | return -EINVAL; | 1176 | return -EINVAL; |
750 | 1177 | ||
751 | dsi_fclk = dsi_fclk_rate(); | 1178 | dsi_fclk = dsi_fclk_rate(dsidev); |
752 | 1179 | ||
753 | lp_clk = dsi_fclk / 2 / lp_clk_div; | 1180 | lp_clk = dsi_fclk / 2 / lp_clk_div; |
754 | 1181 | ||
755 | DSSDBG("LP_CLK_DIV %u, LP_CLK %lu\n", lp_clk_div, lp_clk); | 1182 | DSSDBG("LP_CLK_DIV %u, LP_CLK %lu\n", lp_clk_div, lp_clk); |
756 | dsi.current_cinfo.lp_clk = lp_clk; | 1183 | dsi->current_cinfo.lp_clk = lp_clk; |
757 | dsi.current_cinfo.lp_clk_div = lp_clk_div; | 1184 | dsi->current_cinfo.lp_clk_div = lp_clk_div; |
758 | 1185 | ||
759 | REG_FLD_MOD(DSI_CLK_CTRL, lp_clk_div, 12, 0); /* LP_CLK_DIVISOR */ | 1186 | /* LP_CLK_DIVISOR */ |
1187 | REG_FLD_MOD(dsidev, DSI_CLK_CTRL, lp_clk_div, 12, 0); | ||
760 | 1188 | ||
761 | REG_FLD_MOD(DSI_CLK_CTRL, dsi_fclk > 30000000 ? 1 : 0, | 1189 | /* LP_RX_SYNCHRO_ENABLE */ |
762 | 21, 21); /* LP_RX_SYNCHRO_ENABLE */ | 1190 | REG_FLD_MOD(dsidev, DSI_CLK_CTRL, dsi_fclk > 30000000 ? 1 : 0, 21, 21); |
763 | 1191 | ||
764 | return 0; | 1192 | return 0; |
765 | } | 1193 | } |
766 | 1194 | ||
1195 | static void dsi_enable_scp_clk(struct platform_device *dsidev) | ||
1196 | { | ||
1197 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1198 | |||
1199 | if (dsi->scp_clk_refcount++ == 0) | ||
1200 | REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 14, 14); /* CIO_CLK_ICG */ | ||
1201 | } | ||
1202 | |||
1203 | static void dsi_disable_scp_clk(struct platform_device *dsidev) | ||
1204 | { | ||
1205 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1206 | |||
1207 | WARN_ON(dsi->scp_clk_refcount == 0); | ||
1208 | if (--dsi->scp_clk_refcount == 0) | ||
1209 | REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 14, 14); /* CIO_CLK_ICG */ | ||
1210 | } | ||
767 | 1211 | ||
768 | enum dsi_pll_power_state { | 1212 | enum dsi_pll_power_state { |
769 | DSI_PLL_POWER_OFF = 0x0, | 1213 | DSI_PLL_POWER_OFF = 0x0, |
@@ -772,14 +1216,21 @@ enum dsi_pll_power_state { | |||
772 | DSI_PLL_POWER_ON_DIV = 0x3, | 1216 | DSI_PLL_POWER_ON_DIV = 0x3, |
773 | }; | 1217 | }; |
774 | 1218 | ||
775 | static int dsi_pll_power(enum dsi_pll_power_state state) | 1219 | static int dsi_pll_power(struct platform_device *dsidev, |
1220 | enum dsi_pll_power_state state) | ||
776 | { | 1221 | { |
777 | int t = 0; | 1222 | int t = 0; |
778 | 1223 | ||
779 | REG_FLD_MOD(DSI_CLK_CTRL, state, 31, 30); /* PLL_PWR_CMD */ | 1224 | /* DSI-PLL power command 0x3 is not working */ |
1225 | if (dss_has_feature(FEAT_DSI_PLL_PWR_BUG) && | ||
1226 | state == DSI_PLL_POWER_ON_DIV) | ||
1227 | state = DSI_PLL_POWER_ON_ALL; | ||
1228 | |||
1229 | /* PLL_PWR_CMD */ | ||
1230 | REG_FLD_MOD(dsidev, DSI_CLK_CTRL, state, 31, 30); | ||
780 | 1231 | ||
781 | /* PLL_PWR_STATUS */ | 1232 | /* PLL_PWR_STATUS */ |
782 | while (FLD_GET(dsi_read_reg(DSI_CLK_CTRL), 29, 28) != state) { | 1233 | while (FLD_GET(dsi_read_reg(dsidev, DSI_CLK_CTRL), 29, 28) != state) { |
783 | if (++t > 1000) { | 1234 | if (++t > 1000) { |
784 | DSSERR("Failed to set DSI PLL power mode to %d\n", | 1235 | DSSERR("Failed to set DSI PLL power mode to %d\n", |
785 | state); | 1236 | state); |
@@ -792,27 +1243,31 @@ static int dsi_pll_power(enum dsi_pll_power_state state) | |||
792 | } | 1243 | } |
793 | 1244 | ||
794 | /* calculate clock rates using dividers in cinfo */ | 1245 | /* calculate clock rates using dividers in cinfo */ |
795 | static int dsi_calc_clock_rates(struct dsi_clock_info *cinfo) | 1246 | static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, |
1247 | struct dsi_clock_info *cinfo) | ||
796 | { | 1248 | { |
797 | if (cinfo->regn == 0 || cinfo->regn > REGN_MAX) | 1249 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
1250 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1251 | |||
1252 | if (cinfo->regn == 0 || cinfo->regn > dsi->regn_max) | ||
798 | return -EINVAL; | 1253 | return -EINVAL; |
799 | 1254 | ||
800 | if (cinfo->regm == 0 || cinfo->regm > REGM_MAX) | 1255 | if (cinfo->regm == 0 || cinfo->regm > dsi->regm_max) |
801 | return -EINVAL; | 1256 | return -EINVAL; |
802 | 1257 | ||
803 | if (cinfo->regm3 > REGM3_MAX) | 1258 | if (cinfo->regm_dispc > dsi->regm_dispc_max) |
804 | return -EINVAL; | 1259 | return -EINVAL; |
805 | 1260 | ||
806 | if (cinfo->regm4 > REGM4_MAX) | 1261 | if (cinfo->regm_dsi > dsi->regm_dsi_max) |
807 | return -EINVAL; | 1262 | return -EINVAL; |
808 | 1263 | ||
809 | if (cinfo->use_dss2_fck) { | 1264 | if (cinfo->use_sys_clk) { |
810 | cinfo->clkin = dss_clk_get_rate(DSS_CLK_FCK2); | 1265 | cinfo->clkin = dss_clk_get_rate(DSS_CLK_SYSCK); |
811 | /* XXX it is unclear if highfreq should be used | 1266 | /* XXX it is unclear if highfreq should be used |
812 | * with DSS2_FCK source also */ | 1267 | * with DSS_SYS_CLK source also */ |
813 | cinfo->highfreq = 0; | 1268 | cinfo->highfreq = 0; |
814 | } else { | 1269 | } else { |
815 | cinfo->clkin = dispc_pclk_rate(); | 1270 | cinfo->clkin = dispc_pclk_rate(dssdev->manager->id); |
816 | 1271 | ||
817 | if (cinfo->clkin < 32000000) | 1272 | if (cinfo->clkin < 32000000) |
818 | cinfo->highfreq = 0; | 1273 | cinfo->highfreq = 0; |
@@ -822,7 +1277,7 @@ static int dsi_calc_clock_rates(struct dsi_clock_info *cinfo) | |||
822 | 1277 | ||
823 | cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1)); | 1278 | cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1)); |
824 | 1279 | ||
825 | if (cinfo->fint > FINT_MAX || cinfo->fint < FINT_MIN) | 1280 | if (cinfo->fint > dsi->fint_max || cinfo->fint < dsi->fint_min) |
826 | return -EINVAL; | 1281 | return -EINVAL; |
827 | 1282 | ||
828 | cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint; | 1283 | cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint; |
@@ -830,44 +1285,49 @@ static int dsi_calc_clock_rates(struct dsi_clock_info *cinfo) | |||
830 | if (cinfo->clkin4ddr > 1800 * 1000 * 1000) | 1285 | if (cinfo->clkin4ddr > 1800 * 1000 * 1000) |
831 | return -EINVAL; | 1286 | return -EINVAL; |
832 | 1287 | ||
833 | if (cinfo->regm3 > 0) | 1288 | if (cinfo->regm_dispc > 0) |
834 | cinfo->dsi1_pll_fclk = cinfo->clkin4ddr / cinfo->regm3; | 1289 | cinfo->dsi_pll_hsdiv_dispc_clk = |
1290 | cinfo->clkin4ddr / cinfo->regm_dispc; | ||
835 | else | 1291 | else |
836 | cinfo->dsi1_pll_fclk = 0; | 1292 | cinfo->dsi_pll_hsdiv_dispc_clk = 0; |
837 | 1293 | ||
838 | if (cinfo->regm4 > 0) | 1294 | if (cinfo->regm_dsi > 0) |
839 | cinfo->dsi2_pll_fclk = cinfo->clkin4ddr / cinfo->regm4; | 1295 | cinfo->dsi_pll_hsdiv_dsi_clk = |
1296 | cinfo->clkin4ddr / cinfo->regm_dsi; | ||
840 | else | 1297 | else |
841 | cinfo->dsi2_pll_fclk = 0; | 1298 | cinfo->dsi_pll_hsdiv_dsi_clk = 0; |
842 | 1299 | ||
843 | return 0; | 1300 | return 0; |
844 | } | 1301 | } |
845 | 1302 | ||
846 | int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, | 1303 | int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft, |
847 | struct dsi_clock_info *dsi_cinfo, | 1304 | unsigned long req_pck, struct dsi_clock_info *dsi_cinfo, |
848 | struct dispc_clock_info *dispc_cinfo) | 1305 | struct dispc_clock_info *dispc_cinfo) |
849 | { | 1306 | { |
1307 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
850 | struct dsi_clock_info cur, best; | 1308 | struct dsi_clock_info cur, best; |
851 | struct dispc_clock_info best_dispc; | 1309 | struct dispc_clock_info best_dispc; |
852 | int min_fck_per_pck; | 1310 | int min_fck_per_pck; |
853 | int match = 0; | 1311 | int match = 0; |
854 | unsigned long dss_clk_fck2; | 1312 | unsigned long dss_sys_clk, max_dss_fck; |
1313 | |||
1314 | dss_sys_clk = dss_clk_get_rate(DSS_CLK_SYSCK); | ||
855 | 1315 | ||
856 | dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2); | 1316 | max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); |
857 | 1317 | ||
858 | if (req_pck == dsi.cache_req_pck && | 1318 | if (req_pck == dsi->cache_req_pck && |
859 | dsi.cache_cinfo.clkin == dss_clk_fck2) { | 1319 | dsi->cache_cinfo.clkin == dss_sys_clk) { |
860 | DSSDBG("DSI clock info found from cache\n"); | 1320 | DSSDBG("DSI clock info found from cache\n"); |
861 | *dsi_cinfo = dsi.cache_cinfo; | 1321 | *dsi_cinfo = dsi->cache_cinfo; |
862 | dispc_find_clk_divs(is_tft, req_pck, dsi_cinfo->dsi1_pll_fclk, | 1322 | dispc_find_clk_divs(is_tft, req_pck, |
863 | dispc_cinfo); | 1323 | dsi_cinfo->dsi_pll_hsdiv_dispc_clk, dispc_cinfo); |
864 | return 0; | 1324 | return 0; |
865 | } | 1325 | } |
866 | 1326 | ||
867 | min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; | 1327 | min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; |
868 | 1328 | ||
869 | if (min_fck_per_pck && | 1329 | if (min_fck_per_pck && |
870 | req_pck * min_fck_per_pck > DISPC_MAX_FCK) { | 1330 | req_pck * min_fck_per_pck > max_dss_fck) { |
871 | DSSERR("Requested pixel clock not possible with the current " | 1331 | DSSERR("Requested pixel clock not possible with the current " |
872 | "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " | 1332 | "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " |
873 | "the constraint off.\n"); | 1333 | "the constraint off.\n"); |
@@ -881,24 +1341,24 @@ retry: | |||
881 | memset(&best_dispc, 0, sizeof(best_dispc)); | 1341 | memset(&best_dispc, 0, sizeof(best_dispc)); |
882 | 1342 | ||
883 | memset(&cur, 0, sizeof(cur)); | 1343 | memset(&cur, 0, sizeof(cur)); |
884 | cur.clkin = dss_clk_fck2; | 1344 | cur.clkin = dss_sys_clk; |
885 | cur.use_dss2_fck = 1; | 1345 | cur.use_sys_clk = 1; |
886 | cur.highfreq = 0; | 1346 | cur.highfreq = 0; |
887 | 1347 | ||
888 | /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ | 1348 | /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ |
889 | /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ | 1349 | /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ |
890 | /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ | 1350 | /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ |
891 | for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) { | 1351 | for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) { |
892 | if (cur.highfreq == 0) | 1352 | if (cur.highfreq == 0) |
893 | cur.fint = cur.clkin / cur.regn; | 1353 | cur.fint = cur.clkin / cur.regn; |
894 | else | 1354 | else |
895 | cur.fint = cur.clkin / (2 * cur.regn); | 1355 | cur.fint = cur.clkin / (2 * cur.regn); |
896 | 1356 | ||
897 | if (cur.fint > FINT_MAX || cur.fint < FINT_MIN) | 1357 | if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min) |
898 | continue; | 1358 | continue; |
899 | 1359 | ||
900 | /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ | 1360 | /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ |
901 | for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) { | 1361 | for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) { |
902 | unsigned long a, b; | 1362 | unsigned long a, b; |
903 | 1363 | ||
904 | a = 2 * cur.regm * (cur.clkin/1000); | 1364 | a = 2 * cur.regm * (cur.clkin/1000); |
@@ -908,30 +1368,32 @@ retry: | |||
908 | if (cur.clkin4ddr > 1800 * 1000 * 1000) | 1368 | if (cur.clkin4ddr > 1800 * 1000 * 1000) |
909 | break; | 1369 | break; |
910 | 1370 | ||
911 | /* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3 < 173MHz */ | 1371 | /* dsi_pll_hsdiv_dispc_clk(MHz) = |
912 | for (cur.regm3 = 1; cur.regm3 < REGM3_MAX; | 1372 | * DSIPHY(MHz) / regm_dispc < 173MHz/186Mhz */ |
913 | ++cur.regm3) { | 1373 | for (cur.regm_dispc = 1; cur.regm_dispc < |
1374 | dsi->regm_dispc_max; ++cur.regm_dispc) { | ||
914 | struct dispc_clock_info cur_dispc; | 1375 | struct dispc_clock_info cur_dispc; |
915 | cur.dsi1_pll_fclk = cur.clkin4ddr / cur.regm3; | 1376 | cur.dsi_pll_hsdiv_dispc_clk = |
1377 | cur.clkin4ddr / cur.regm_dispc; | ||
916 | 1378 | ||
917 | /* this will narrow down the search a bit, | 1379 | /* this will narrow down the search a bit, |
918 | * but still give pixclocks below what was | 1380 | * but still give pixclocks below what was |
919 | * requested */ | 1381 | * requested */ |
920 | if (cur.dsi1_pll_fclk < req_pck) | 1382 | if (cur.dsi_pll_hsdiv_dispc_clk < req_pck) |
921 | break; | 1383 | break; |
922 | 1384 | ||
923 | if (cur.dsi1_pll_fclk > DISPC_MAX_FCK) | 1385 | if (cur.dsi_pll_hsdiv_dispc_clk > max_dss_fck) |
924 | continue; | 1386 | continue; |
925 | 1387 | ||
926 | if (min_fck_per_pck && | 1388 | if (min_fck_per_pck && |
927 | cur.dsi1_pll_fclk < | 1389 | cur.dsi_pll_hsdiv_dispc_clk < |
928 | req_pck * min_fck_per_pck) | 1390 | req_pck * min_fck_per_pck) |
929 | continue; | 1391 | continue; |
930 | 1392 | ||
931 | match = 1; | 1393 | match = 1; |
932 | 1394 | ||
933 | dispc_find_clk_divs(is_tft, req_pck, | 1395 | dispc_find_clk_divs(is_tft, req_pck, |
934 | cur.dsi1_pll_fclk, | 1396 | cur.dsi_pll_hsdiv_dispc_clk, |
935 | &cur_dispc); | 1397 | &cur_dispc); |
936 | 1398 | ||
937 | if (abs(cur_dispc.pck - req_pck) < | 1399 | if (abs(cur_dispc.pck - req_pck) < |
@@ -960,44 +1422,53 @@ found: | |||
960 | return -EINVAL; | 1422 | return -EINVAL; |
961 | } | 1423 | } |
962 | 1424 | ||
963 | /* DSI2_PLL_FCLK (regm4) is not used */ | 1425 | /* dsi_pll_hsdiv_dsi_clk (regm_dsi) is not used */ |
964 | best.regm4 = 0; | 1426 | best.regm_dsi = 0; |
965 | best.dsi2_pll_fclk = 0; | 1427 | best.dsi_pll_hsdiv_dsi_clk = 0; |
966 | 1428 | ||
967 | if (dsi_cinfo) | 1429 | if (dsi_cinfo) |
968 | *dsi_cinfo = best; | 1430 | *dsi_cinfo = best; |
969 | if (dispc_cinfo) | 1431 | if (dispc_cinfo) |
970 | *dispc_cinfo = best_dispc; | 1432 | *dispc_cinfo = best_dispc; |
971 | 1433 | ||
972 | dsi.cache_req_pck = req_pck; | 1434 | dsi->cache_req_pck = req_pck; |
973 | dsi.cache_clk_freq = 0; | 1435 | dsi->cache_clk_freq = 0; |
974 | dsi.cache_cinfo = best; | 1436 | dsi->cache_cinfo = best; |
975 | 1437 | ||
976 | return 0; | 1438 | return 0; |
977 | } | 1439 | } |
978 | 1440 | ||
979 | int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) | 1441 | int dsi_pll_set_clock_div(struct platform_device *dsidev, |
1442 | struct dsi_clock_info *cinfo) | ||
980 | { | 1443 | { |
1444 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
981 | int r = 0; | 1445 | int r = 0; |
982 | u32 l; | 1446 | u32 l; |
983 | int f; | 1447 | int f = 0; |
1448 | u8 regn_start, regn_end, regm_start, regm_end; | ||
1449 | u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end; | ||
984 | 1450 | ||
985 | DSSDBGF(); | 1451 | DSSDBGF(); |
986 | 1452 | ||
987 | dsi.current_cinfo.fint = cinfo->fint; | 1453 | dsi->current_cinfo.use_sys_clk = cinfo->use_sys_clk; |
988 | dsi.current_cinfo.clkin4ddr = cinfo->clkin4ddr; | 1454 | dsi->current_cinfo.highfreq = cinfo->highfreq; |
989 | dsi.current_cinfo.dsi1_pll_fclk = cinfo->dsi1_pll_fclk; | ||
990 | dsi.current_cinfo.dsi2_pll_fclk = cinfo->dsi2_pll_fclk; | ||
991 | 1455 | ||
992 | dsi.current_cinfo.regn = cinfo->regn; | 1456 | dsi->current_cinfo.fint = cinfo->fint; |
993 | dsi.current_cinfo.regm = cinfo->regm; | 1457 | dsi->current_cinfo.clkin4ddr = cinfo->clkin4ddr; |
994 | dsi.current_cinfo.regm3 = cinfo->regm3; | 1458 | dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk = |
995 | dsi.current_cinfo.regm4 = cinfo->regm4; | 1459 | cinfo->dsi_pll_hsdiv_dispc_clk; |
1460 | dsi->current_cinfo.dsi_pll_hsdiv_dsi_clk = | ||
1461 | cinfo->dsi_pll_hsdiv_dsi_clk; | ||
1462 | |||
1463 | dsi->current_cinfo.regn = cinfo->regn; | ||
1464 | dsi->current_cinfo.regm = cinfo->regm; | ||
1465 | dsi->current_cinfo.regm_dispc = cinfo->regm_dispc; | ||
1466 | dsi->current_cinfo.regm_dsi = cinfo->regm_dsi; | ||
996 | 1467 | ||
997 | DSSDBG("DSI Fint %ld\n", cinfo->fint); | 1468 | DSSDBG("DSI Fint %ld\n", cinfo->fint); |
998 | 1469 | ||
999 | DSSDBG("clkin (%s) rate %ld, highfreq %d\n", | 1470 | DSSDBG("clkin (%s) rate %ld, highfreq %d\n", |
1000 | cinfo->use_dss2_fck ? "dss2_fck" : "pclkfree", | 1471 | cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree", |
1001 | cinfo->clkin, | 1472 | cinfo->clkin, |
1002 | cinfo->highfreq); | 1473 | cinfo->highfreq); |
1003 | 1474 | ||
@@ -1014,63 +1485,79 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) | |||
1014 | 1485 | ||
1015 | DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4); | 1486 | DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4); |
1016 | 1487 | ||
1017 | DSSDBG("regm3 = %d, dsi1_pll_fclk = %lu\n", | 1488 | DSSDBG("regm_dispc = %d, %s (%s) = %lu\n", cinfo->regm_dispc, |
1018 | cinfo->regm3, cinfo->dsi1_pll_fclk); | 1489 | dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), |
1019 | DSSDBG("regm4 = %d, dsi2_pll_fclk = %lu\n", | 1490 | dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), |
1020 | cinfo->regm4, cinfo->dsi2_pll_fclk); | 1491 | cinfo->dsi_pll_hsdiv_dispc_clk); |
1021 | 1492 | DSSDBG("regm_dsi = %d, %s (%s) = %lu\n", cinfo->regm_dsi, | |
1022 | REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */ | 1493 | dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), |
1023 | 1494 | dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), | |
1024 | l = dsi_read_reg(DSI_PLL_CONFIGURATION1); | 1495 | cinfo->dsi_pll_hsdiv_dsi_clk); |
1496 | |||
1497 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGN, ®n_start, ®n_end); | ||
1498 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM, ®m_start, ®m_end); | ||
1499 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DISPC, ®m_dispc_start, | ||
1500 | ®m_dispc_end); | ||
1501 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DSI, ®m_dsi_start, | ||
1502 | ®m_dsi_end); | ||
1503 | |||
1504 | /* DSI_PLL_AUTOMODE = manual */ | ||
1505 | REG_FLD_MOD(dsidev, DSI_PLL_CONTROL, 0, 0, 0); | ||
1506 | |||
1507 | l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION1); | ||
1025 | l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */ | 1508 | l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */ |
1026 | l = FLD_MOD(l, cinfo->regn - 1, 7, 1); /* DSI_PLL_REGN */ | 1509 | /* DSI_PLL_REGN */ |
1027 | l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */ | 1510 | l = FLD_MOD(l, cinfo->regn - 1, regn_start, regn_end); |
1028 | l = FLD_MOD(l, cinfo->regm3 > 0 ? cinfo->regm3 - 1 : 0, | 1511 | /* DSI_PLL_REGM */ |
1029 | 22, 19); /* DSI_CLOCK_DIV */ | 1512 | l = FLD_MOD(l, cinfo->regm, regm_start, regm_end); |
1030 | l = FLD_MOD(l, cinfo->regm4 > 0 ? cinfo->regm4 - 1 : 0, | 1513 | /* DSI_CLOCK_DIV */ |
1031 | 26, 23); /* DSIPROTO_CLOCK_DIV */ | 1514 | l = FLD_MOD(l, cinfo->regm_dispc > 0 ? cinfo->regm_dispc - 1 : 0, |
1032 | dsi_write_reg(DSI_PLL_CONFIGURATION1, l); | 1515 | regm_dispc_start, regm_dispc_end); |
1033 | 1516 | /* DSIPROTO_CLOCK_DIV */ | |
1034 | BUG_ON(cinfo->fint < 750000 || cinfo->fint > 2100000); | 1517 | l = FLD_MOD(l, cinfo->regm_dsi > 0 ? cinfo->regm_dsi - 1 : 0, |
1035 | if (cinfo->fint < 1000000) | 1518 | regm_dsi_start, regm_dsi_end); |
1036 | f = 0x3; | 1519 | dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION1, l); |
1037 | else if (cinfo->fint < 1250000) | 1520 | |
1038 | f = 0x4; | 1521 | BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max); |
1039 | else if (cinfo->fint < 1500000) | 1522 | |
1040 | f = 0x5; | 1523 | if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) { |
1041 | else if (cinfo->fint < 1750000) | 1524 | f = cinfo->fint < 1000000 ? 0x3 : |
1042 | f = 0x6; | 1525 | cinfo->fint < 1250000 ? 0x4 : |
1043 | else | 1526 | cinfo->fint < 1500000 ? 0x5 : |
1044 | f = 0x7; | 1527 | cinfo->fint < 1750000 ? 0x6 : |
1528 | 0x7; | ||
1529 | } | ||
1045 | 1530 | ||
1046 | l = dsi_read_reg(DSI_PLL_CONFIGURATION2); | 1531 | l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2); |
1047 | l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ | 1532 | |
1048 | l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1, | 1533 | if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) |
1534 | l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ | ||
1535 | l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1, | ||
1049 | 11, 11); /* DSI_PLL_CLKSEL */ | 1536 | 11, 11); /* DSI_PLL_CLKSEL */ |
1050 | l = FLD_MOD(l, cinfo->highfreq, | 1537 | l = FLD_MOD(l, cinfo->highfreq, |
1051 | 12, 12); /* DSI_PLL_HIGHFREQ */ | 1538 | 12, 12); /* DSI_PLL_HIGHFREQ */ |
1052 | l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ | 1539 | l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ |
1053 | l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ | 1540 | l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ |
1054 | l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ | 1541 | l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ |
1055 | dsi_write_reg(DSI_PLL_CONFIGURATION2, l); | 1542 | dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l); |
1056 | 1543 | ||
1057 | REG_FLD_MOD(DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */ | 1544 | REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */ |
1058 | 1545 | ||
1059 | if (wait_for_bit_change(DSI_PLL_GO, 0, 0) != 0) { | 1546 | if (wait_for_bit_change(dsidev, DSI_PLL_GO, 0, 0) != 0) { |
1060 | DSSERR("dsi pll go bit not going down.\n"); | 1547 | DSSERR("dsi pll go bit not going down.\n"); |
1061 | r = -EIO; | 1548 | r = -EIO; |
1062 | goto err; | 1549 | goto err; |
1063 | } | 1550 | } |
1064 | 1551 | ||
1065 | if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) { | 1552 | if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1) { |
1066 | DSSERR("cannot lock PLL\n"); | 1553 | DSSERR("cannot lock PLL\n"); |
1067 | r = -EIO; | 1554 | r = -EIO; |
1068 | goto err; | 1555 | goto err; |
1069 | } | 1556 | } |
1070 | 1557 | ||
1071 | dsi.pll_locked = 1; | 1558 | dsi->pll_locked = 1; |
1072 | 1559 | ||
1073 | l = dsi_read_reg(DSI_PLL_CONFIGURATION2); | 1560 | l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2); |
1074 | l = FLD_MOD(l, 0, 0, 0); /* DSI_PLL_IDLE */ | 1561 | l = FLD_MOD(l, 0, 0, 0); /* DSI_PLL_IDLE */ |
1075 | l = FLD_MOD(l, 0, 5, 5); /* DSI_PLL_PLLLPMODE */ | 1562 | l = FLD_MOD(l, 0, 5, 5); /* DSI_PLL_PLLLPMODE */ |
1076 | l = FLD_MOD(l, 0, 6, 6); /* DSI_PLL_LOWCURRSTBY */ | 1563 | l = FLD_MOD(l, 0, 6, 6); /* DSI_PLL_LOWCURRSTBY */ |
@@ -1085,32 +1572,53 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) | |||
1085 | l = FLD_MOD(l, 1, 18, 18); /* DSI_PROTO_CLOCK_EN */ | 1572 | l = FLD_MOD(l, 1, 18, 18); /* DSI_PROTO_CLOCK_EN */ |
1086 | l = FLD_MOD(l, 0, 19, 19); /* DSI_PROTO_CLOCK_PWDN */ | 1573 | l = FLD_MOD(l, 0, 19, 19); /* DSI_PROTO_CLOCK_PWDN */ |
1087 | l = FLD_MOD(l, 0, 20, 20); /* DSI_HSDIVBYPASS */ | 1574 | l = FLD_MOD(l, 0, 20, 20); /* DSI_HSDIVBYPASS */ |
1088 | dsi_write_reg(DSI_PLL_CONFIGURATION2, l); | 1575 | dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l); |
1089 | 1576 | ||
1090 | DSSDBG("PLL config done\n"); | 1577 | DSSDBG("PLL config done\n"); |
1091 | err: | 1578 | err: |
1092 | return r; | 1579 | return r; |
1093 | } | 1580 | } |
1094 | 1581 | ||
1095 | int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, | 1582 | int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk, |
1096 | bool enable_hsdiv) | 1583 | bool enable_hsdiv) |
1097 | { | 1584 | { |
1585 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1098 | int r = 0; | 1586 | int r = 0; |
1099 | enum dsi_pll_power_state pwstate; | 1587 | enum dsi_pll_power_state pwstate; |
1100 | 1588 | ||
1101 | DSSDBG("PLL init\n"); | 1589 | DSSDBG("PLL init\n"); |
1102 | 1590 | ||
1591 | if (dsi->vdds_dsi_reg == NULL) { | ||
1592 | struct regulator *vdds_dsi; | ||
1593 | |||
1594 | vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi"); | ||
1595 | |||
1596 | if (IS_ERR(vdds_dsi)) { | ||
1597 | DSSERR("can't get VDDS_DSI regulator\n"); | ||
1598 | return PTR_ERR(vdds_dsi); | ||
1599 | } | ||
1600 | |||
1601 | dsi->vdds_dsi_reg = vdds_dsi; | ||
1602 | } | ||
1603 | |||
1103 | enable_clocks(1); | 1604 | enable_clocks(1); |
1104 | dsi_enable_pll_clock(1); | 1605 | dsi_enable_pll_clock(dsidev, 1); |
1606 | /* | ||
1607 | * Note: SCP CLK is not required on OMAP3, but it is required on OMAP4. | ||
1608 | */ | ||
1609 | dsi_enable_scp_clk(dsidev); | ||
1105 | 1610 | ||
1106 | r = regulator_enable(dsi.vdds_dsi_reg); | 1611 | if (!dsi->vdds_dsi_enabled) { |
1107 | if (r) | 1612 | r = regulator_enable(dsi->vdds_dsi_reg); |
1108 | goto err0; | 1613 | if (r) |
1614 | goto err0; | ||
1615 | dsi->vdds_dsi_enabled = true; | ||
1616 | } | ||
1109 | 1617 | ||
1110 | /* XXX PLL does not come out of reset without this... */ | 1618 | /* XXX PLL does not come out of reset without this... */ |
1111 | dispc_pck_free_enable(1); | 1619 | dispc_pck_free_enable(1); |
1112 | 1620 | ||
1113 | if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) { | 1621 | if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 0, 1) != 1) { |
1114 | DSSERR("PLL not coming out of reset.\n"); | 1622 | DSSERR("PLL not coming out of reset.\n"); |
1115 | r = -ENODEV; | 1623 | r = -ENODEV; |
1116 | dispc_pck_free_enable(0); | 1624 | dispc_pck_free_enable(0); |
@@ -1130,7 +1638,7 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, | |||
1130 | else | 1638 | else |
1131 | pwstate = DSI_PLL_POWER_OFF; | 1639 | pwstate = DSI_PLL_POWER_OFF; |
1132 | 1640 | ||
1133 | r = dsi_pll_power(pwstate); | 1641 | r = dsi_pll_power(dsidev, pwstate); |
1134 | 1642 | ||
1135 | if (r) | 1643 | if (r) |
1136 | goto err1; | 1644 | goto err1; |
@@ -1139,92 +1647,121 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, | |||
1139 | 1647 | ||
1140 | return 0; | 1648 | return 0; |
1141 | err1: | 1649 | err1: |
1142 | regulator_disable(dsi.vdds_dsi_reg); | 1650 | if (dsi->vdds_dsi_enabled) { |
1651 | regulator_disable(dsi->vdds_dsi_reg); | ||
1652 | dsi->vdds_dsi_enabled = false; | ||
1653 | } | ||
1143 | err0: | 1654 | err0: |
1655 | dsi_disable_scp_clk(dsidev); | ||
1144 | enable_clocks(0); | 1656 | enable_clocks(0); |
1145 | dsi_enable_pll_clock(0); | 1657 | dsi_enable_pll_clock(dsidev, 0); |
1146 | return r; | 1658 | return r; |
1147 | } | 1659 | } |
1148 | 1660 | ||
1149 | void dsi_pll_uninit(void) | 1661 | void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes) |
1150 | { | 1662 | { |
1663 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1664 | |||
1665 | dsi->pll_locked = 0; | ||
1666 | dsi_pll_power(dsidev, DSI_PLL_POWER_OFF); | ||
1667 | if (disconnect_lanes) { | ||
1668 | WARN_ON(!dsi->vdds_dsi_enabled); | ||
1669 | regulator_disable(dsi->vdds_dsi_reg); | ||
1670 | dsi->vdds_dsi_enabled = false; | ||
1671 | } | ||
1672 | |||
1673 | dsi_disable_scp_clk(dsidev); | ||
1151 | enable_clocks(0); | 1674 | enable_clocks(0); |
1152 | dsi_enable_pll_clock(0); | 1675 | dsi_enable_pll_clock(dsidev, 0); |
1153 | 1676 | ||
1154 | dsi.pll_locked = 0; | ||
1155 | dsi_pll_power(DSI_PLL_POWER_OFF); | ||
1156 | regulator_disable(dsi.vdds_dsi_reg); | ||
1157 | DSSDBG("PLL uninit done\n"); | 1677 | DSSDBG("PLL uninit done\n"); |
1158 | } | 1678 | } |
1159 | 1679 | ||
1160 | void dsi_dump_clocks(struct seq_file *s) | 1680 | static void dsi_dump_dsidev_clocks(struct platform_device *dsidev, |
1681 | struct seq_file *s) | ||
1161 | { | 1682 | { |
1162 | int clksel; | 1683 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
1163 | struct dsi_clock_info *cinfo = &dsi.current_cinfo; | 1684 | struct dsi_clock_info *cinfo = &dsi->current_cinfo; |
1685 | enum omap_dss_clk_source dispc_clk_src, dsi_clk_src; | ||
1686 | int dsi_module = dsi_get_dsidev_id(dsidev); | ||
1164 | 1687 | ||
1165 | enable_clocks(1); | 1688 | dispc_clk_src = dss_get_dispc_clk_source(); |
1689 | dsi_clk_src = dss_get_dsi_clk_source(dsi_module); | ||
1166 | 1690 | ||
1167 | clksel = REG_GET(DSI_PLL_CONFIGURATION2, 11, 11); | 1691 | enable_clocks(1); |
1168 | 1692 | ||
1169 | seq_printf(s, "- DSI PLL -\n"); | 1693 | seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1); |
1170 | 1694 | ||
1171 | seq_printf(s, "dsi pll source = %s\n", | 1695 | seq_printf(s, "dsi pll source = %s\n", |
1172 | clksel == 0 ? | 1696 | cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree"); |
1173 | "dss2_alwon_fclk" : "pclkfree"); | ||
1174 | 1697 | ||
1175 | seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); | 1698 | seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); |
1176 | 1699 | ||
1177 | seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n", | 1700 | seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n", |
1178 | cinfo->clkin4ddr, cinfo->regm); | 1701 | cinfo->clkin4ddr, cinfo->regm); |
1179 | 1702 | ||
1180 | seq_printf(s, "dsi1_pll_fck\t%-16luregm3 %u\t(%s)\n", | 1703 | seq_printf(s, "%s (%s)\t%-16luregm_dispc %u\t(%s)\n", |
1181 | cinfo->dsi1_pll_fclk, | 1704 | dss_get_generic_clk_source_name(dispc_clk_src), |
1182 | cinfo->regm3, | 1705 | dss_feat_get_clk_source_name(dispc_clk_src), |
1183 | dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? | 1706 | cinfo->dsi_pll_hsdiv_dispc_clk, |
1707 | cinfo->regm_dispc, | ||
1708 | dispc_clk_src == OMAP_DSS_CLK_SRC_FCK ? | ||
1184 | "off" : "on"); | 1709 | "off" : "on"); |
1185 | 1710 | ||
1186 | seq_printf(s, "dsi2_pll_fck\t%-16luregm4 %u\t(%s)\n", | 1711 | seq_printf(s, "%s (%s)\t%-16luregm_dsi %u\t(%s)\n", |
1187 | cinfo->dsi2_pll_fclk, | 1712 | dss_get_generic_clk_source_name(dsi_clk_src), |
1188 | cinfo->regm4, | 1713 | dss_feat_get_clk_source_name(dsi_clk_src), |
1189 | dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? | 1714 | cinfo->dsi_pll_hsdiv_dsi_clk, |
1715 | cinfo->regm_dsi, | ||
1716 | dsi_clk_src == OMAP_DSS_CLK_SRC_FCK ? | ||
1190 | "off" : "on"); | 1717 | "off" : "on"); |
1191 | 1718 | ||
1192 | seq_printf(s, "- DSI -\n"); | 1719 | seq_printf(s, "- DSI%d -\n", dsi_module + 1); |
1193 | 1720 | ||
1194 | seq_printf(s, "dsi fclk source = %s\n", | 1721 | seq_printf(s, "dsi fclk source = %s (%s)\n", |
1195 | dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? | 1722 | dss_get_generic_clk_source_name(dsi_clk_src), |
1196 | "dss1_alwon_fclk" : "dsi2_pll_fclk"); | 1723 | dss_feat_get_clk_source_name(dsi_clk_src)); |
1197 | 1724 | ||
1198 | seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate()); | 1725 | seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate(dsidev)); |
1199 | 1726 | ||
1200 | seq_printf(s, "DDR_CLK\t\t%lu\n", | 1727 | seq_printf(s, "DDR_CLK\t\t%lu\n", |
1201 | cinfo->clkin4ddr / 4); | 1728 | cinfo->clkin4ddr / 4); |
1202 | 1729 | ||
1203 | seq_printf(s, "TxByteClkHS\t%lu\n", dsi_get_txbyteclkhs()); | 1730 | seq_printf(s, "TxByteClkHS\t%lu\n", dsi_get_txbyteclkhs(dsidev)); |
1204 | 1731 | ||
1205 | seq_printf(s, "LP_CLK\t\t%lu\n", cinfo->lp_clk); | 1732 | seq_printf(s, "LP_CLK\t\t%lu\n", cinfo->lp_clk); |
1206 | 1733 | ||
1207 | seq_printf(s, "VP_CLK\t\t%lu\n" | ||
1208 | "VP_PCLK\t\t%lu\n", | ||
1209 | dispc_lclk_rate(), | ||
1210 | dispc_pclk_rate()); | ||
1211 | |||
1212 | enable_clocks(0); | 1734 | enable_clocks(0); |
1213 | } | 1735 | } |
1214 | 1736 | ||
1737 | void dsi_dump_clocks(struct seq_file *s) | ||
1738 | { | ||
1739 | struct platform_device *dsidev; | ||
1740 | int i; | ||
1741 | |||
1742 | for (i = 0; i < MAX_NUM_DSI; i++) { | ||
1743 | dsidev = dsi_get_dsidev_from_id(i); | ||
1744 | if (dsidev) | ||
1745 | dsi_dump_dsidev_clocks(dsidev, s); | ||
1746 | } | ||
1747 | } | ||
1748 | |||
1215 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 1749 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS |
1216 | void dsi_dump_irqs(struct seq_file *s) | 1750 | static void dsi_dump_dsidev_irqs(struct platform_device *dsidev, |
1751 | struct seq_file *s) | ||
1217 | { | 1752 | { |
1753 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1218 | unsigned long flags; | 1754 | unsigned long flags; |
1219 | struct dsi_irq_stats stats; | 1755 | struct dsi_irq_stats stats; |
1756 | int dsi_module = dsi_get_dsidev_id(dsidev); | ||
1220 | 1757 | ||
1221 | spin_lock_irqsave(&dsi.irq_stats_lock, flags); | 1758 | spin_lock_irqsave(&dsi->irq_stats_lock, flags); |
1222 | 1759 | ||
1223 | stats = dsi.irq_stats; | 1760 | stats = dsi->irq_stats; |
1224 | memset(&dsi.irq_stats, 0, sizeof(dsi.irq_stats)); | 1761 | memset(&dsi->irq_stats, 0, sizeof(dsi->irq_stats)); |
1225 | dsi.irq_stats.last_reset = jiffies; | 1762 | dsi->irq_stats.last_reset = jiffies; |
1226 | 1763 | ||
1227 | spin_unlock_irqrestore(&dsi.irq_stats_lock, flags); | 1764 | spin_unlock_irqrestore(&dsi->irq_stats_lock, flags); |
1228 | 1765 | ||
1229 | seq_printf(s, "period %u ms\n", | 1766 | seq_printf(s, "period %u ms\n", |
1230 | jiffies_to_msecs(jiffies - stats.last_reset)); | 1767 | jiffies_to_msecs(jiffies - stats.last_reset)); |
@@ -1233,7 +1770,7 @@ void dsi_dump_irqs(struct seq_file *s) | |||
1233 | #define PIS(x) \ | 1770 | #define PIS(x) \ |
1234 | seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]); | 1771 | seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]); |
1235 | 1772 | ||
1236 | seq_printf(s, "-- DSI interrupts --\n"); | 1773 | seq_printf(s, "-- DSI%d interrupts --\n", dsi_module + 1); |
1237 | PIS(VC0); | 1774 | PIS(VC0); |
1238 | PIS(VC1); | 1775 | PIS(VC1); |
1239 | PIS(VC2); | 1776 | PIS(VC2); |
@@ -1299,13 +1836,45 @@ void dsi_dump_irqs(struct seq_file *s) | |||
1299 | PIS(ULPSACTIVENOT_ALL1); | 1836 | PIS(ULPSACTIVENOT_ALL1); |
1300 | #undef PIS | 1837 | #undef PIS |
1301 | } | 1838 | } |
1839 | |||
1840 | static void dsi1_dump_irqs(struct seq_file *s) | ||
1841 | { | ||
1842 | struct platform_device *dsidev = dsi_get_dsidev_from_id(0); | ||
1843 | |||
1844 | dsi_dump_dsidev_irqs(dsidev, s); | ||
1845 | } | ||
1846 | |||
1847 | static void dsi2_dump_irqs(struct seq_file *s) | ||
1848 | { | ||
1849 | struct platform_device *dsidev = dsi_get_dsidev_from_id(1); | ||
1850 | |||
1851 | dsi_dump_dsidev_irqs(dsidev, s); | ||
1852 | } | ||
1853 | |||
1854 | void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir, | ||
1855 | const struct file_operations *debug_fops) | ||
1856 | { | ||
1857 | struct platform_device *dsidev; | ||
1858 | |||
1859 | dsidev = dsi_get_dsidev_from_id(0); | ||
1860 | if (dsidev) | ||
1861 | debugfs_create_file("dsi1_irqs", S_IRUGO, debugfs_dir, | ||
1862 | &dsi1_dump_irqs, debug_fops); | ||
1863 | |||
1864 | dsidev = dsi_get_dsidev_from_id(1); | ||
1865 | if (dsidev) | ||
1866 | debugfs_create_file("dsi2_irqs", S_IRUGO, debugfs_dir, | ||
1867 | &dsi2_dump_irqs, debug_fops); | ||
1868 | } | ||
1302 | #endif | 1869 | #endif |
1303 | 1870 | ||
1304 | void dsi_dump_regs(struct seq_file *s) | 1871 | static void dsi_dump_dsidev_regs(struct platform_device *dsidev, |
1872 | struct seq_file *s) | ||
1305 | { | 1873 | { |
1306 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r)) | 1874 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsidev, r)) |
1307 | 1875 | ||
1308 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 1876 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
1877 | dsi_enable_scp_clk(dsidev); | ||
1309 | 1878 | ||
1310 | DUMPREG(DSI_REVISION); | 1879 | DUMPREG(DSI_REVISION); |
1311 | DUMPREG(DSI_SYSCONFIG); | 1880 | DUMPREG(DSI_SYSCONFIG); |
@@ -1377,25 +1946,57 @@ void dsi_dump_regs(struct seq_file *s) | |||
1377 | DUMPREG(DSI_PLL_CONFIGURATION1); | 1946 | DUMPREG(DSI_PLL_CONFIGURATION1); |
1378 | DUMPREG(DSI_PLL_CONFIGURATION2); | 1947 | DUMPREG(DSI_PLL_CONFIGURATION2); |
1379 | 1948 | ||
1380 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 1949 | dsi_disable_scp_clk(dsidev); |
1950 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); | ||
1381 | #undef DUMPREG | 1951 | #undef DUMPREG |
1382 | } | 1952 | } |
1383 | 1953 | ||
1384 | enum dsi_complexio_power_state { | 1954 | static void dsi1_dump_regs(struct seq_file *s) |
1955 | { | ||
1956 | struct platform_device *dsidev = dsi_get_dsidev_from_id(0); | ||
1957 | |||
1958 | dsi_dump_dsidev_regs(dsidev, s); | ||
1959 | } | ||
1960 | |||
1961 | static void dsi2_dump_regs(struct seq_file *s) | ||
1962 | { | ||
1963 | struct platform_device *dsidev = dsi_get_dsidev_from_id(1); | ||
1964 | |||
1965 | dsi_dump_dsidev_regs(dsidev, s); | ||
1966 | } | ||
1967 | |||
1968 | void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir, | ||
1969 | const struct file_operations *debug_fops) | ||
1970 | { | ||
1971 | struct platform_device *dsidev; | ||
1972 | |||
1973 | dsidev = dsi_get_dsidev_from_id(0); | ||
1974 | if (dsidev) | ||
1975 | debugfs_create_file("dsi1_regs", S_IRUGO, debugfs_dir, | ||
1976 | &dsi1_dump_regs, debug_fops); | ||
1977 | |||
1978 | dsidev = dsi_get_dsidev_from_id(1); | ||
1979 | if (dsidev) | ||
1980 | debugfs_create_file("dsi2_regs", S_IRUGO, debugfs_dir, | ||
1981 | &dsi2_dump_regs, debug_fops); | ||
1982 | } | ||
1983 | enum dsi_cio_power_state { | ||
1385 | DSI_COMPLEXIO_POWER_OFF = 0x0, | 1984 | DSI_COMPLEXIO_POWER_OFF = 0x0, |
1386 | DSI_COMPLEXIO_POWER_ON = 0x1, | 1985 | DSI_COMPLEXIO_POWER_ON = 0x1, |
1387 | DSI_COMPLEXIO_POWER_ULPS = 0x2, | 1986 | DSI_COMPLEXIO_POWER_ULPS = 0x2, |
1388 | }; | 1987 | }; |
1389 | 1988 | ||
1390 | static int dsi_complexio_power(enum dsi_complexio_power_state state) | 1989 | static int dsi_cio_power(struct platform_device *dsidev, |
1990 | enum dsi_cio_power_state state) | ||
1391 | { | 1991 | { |
1392 | int t = 0; | 1992 | int t = 0; |
1393 | 1993 | ||
1394 | /* PWR_CMD */ | 1994 | /* PWR_CMD */ |
1395 | REG_FLD_MOD(DSI_COMPLEXIO_CFG1, state, 28, 27); | 1995 | REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG1, state, 28, 27); |
1396 | 1996 | ||
1397 | /* PWR_STATUS */ | 1997 | /* PWR_STATUS */ |
1398 | while (FLD_GET(dsi_read_reg(DSI_COMPLEXIO_CFG1), 26, 25) != state) { | 1998 | while (FLD_GET(dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1), |
1999 | 26, 25) != state) { | ||
1399 | if (++t > 1000) { | 2000 | if (++t > 1000) { |
1400 | DSSERR("failed to set complexio power state to " | 2001 | DSSERR("failed to set complexio power state to " |
1401 | "%d\n", state); | 2002 | "%d\n", state); |
@@ -1407,9 +2008,70 @@ static int dsi_complexio_power(enum dsi_complexio_power_state state) | |||
1407 | return 0; | 2008 | return 0; |
1408 | } | 2009 | } |
1409 | 2010 | ||
1410 | static void dsi_complexio_config(struct omap_dss_device *dssdev) | 2011 | /* Number of data lanes present on DSI interface */ |
2012 | static inline int dsi_get_num_data_lanes(struct platform_device *dsidev) | ||
1411 | { | 2013 | { |
2014 | /* DSI on OMAP3 doesn't have register DSI_GNQ, set number | ||
2015 | * of data lanes as 2 by default */ | ||
2016 | if (dss_has_feature(FEAT_DSI_GNQ)) | ||
2017 | return REG_GET(dsidev, DSI_GNQ, 11, 9); /* NB_DATA_LANES */ | ||
2018 | else | ||
2019 | return 2; | ||
2020 | } | ||
2021 | |||
2022 | /* Number of data lanes used by the dss device */ | ||
2023 | static inline int dsi_get_num_data_lanes_dssdev(struct omap_dss_device *dssdev) | ||
2024 | { | ||
2025 | int num_data_lanes = 0; | ||
2026 | |||
2027 | if (dssdev->phy.dsi.data1_lane != 0) | ||
2028 | num_data_lanes++; | ||
2029 | if (dssdev->phy.dsi.data2_lane != 0) | ||
2030 | num_data_lanes++; | ||
2031 | if (dssdev->phy.dsi.data3_lane != 0) | ||
2032 | num_data_lanes++; | ||
2033 | if (dssdev->phy.dsi.data4_lane != 0) | ||
2034 | num_data_lanes++; | ||
2035 | |||
2036 | return num_data_lanes; | ||
2037 | } | ||
2038 | |||
2039 | static unsigned dsi_get_line_buf_size(struct platform_device *dsidev) | ||
2040 | { | ||
2041 | int val; | ||
2042 | |||
2043 | /* line buffer on OMAP3 is 1024 x 24bits */ | ||
2044 | /* XXX: for some reason using full buffer size causes | ||
2045 | * considerable TX slowdown with update sizes that fill the | ||
2046 | * whole buffer */ | ||
2047 | if (!dss_has_feature(FEAT_DSI_GNQ)) | ||
2048 | return 1023 * 3; | ||
2049 | |||
2050 | val = REG_GET(dsidev, DSI_GNQ, 14, 12); /* VP1_LINE_BUFFER_SIZE */ | ||
2051 | |||
2052 | switch (val) { | ||
2053 | case 1: | ||
2054 | return 512 * 3; /* 512x24 bits */ | ||
2055 | case 2: | ||
2056 | return 682 * 3; /* 682x24 bits */ | ||
2057 | case 3: | ||
2058 | return 853 * 3; /* 853x24 bits */ | ||
2059 | case 4: | ||
2060 | return 1024 * 3; /* 1024x24 bits */ | ||
2061 | case 5: | ||
2062 | return 1194 * 3; /* 1194x24 bits */ | ||
2063 | case 6: | ||
2064 | return 1365 * 3; /* 1365x24 bits */ | ||
2065 | default: | ||
2066 | BUG(); | ||
2067 | } | ||
2068 | } | ||
2069 | |||
2070 | static void dsi_set_lane_config(struct omap_dss_device *dssdev) | ||
2071 | { | ||
2072 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
1412 | u32 r; | 2073 | u32 r; |
2074 | int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev); | ||
1413 | 2075 | ||
1414 | int clk_lane = dssdev->phy.dsi.clk_lane; | 2076 | int clk_lane = dssdev->phy.dsi.clk_lane; |
1415 | int data1_lane = dssdev->phy.dsi.data1_lane; | 2077 | int data1_lane = dssdev->phy.dsi.data1_lane; |
@@ -1418,14 +2080,28 @@ static void dsi_complexio_config(struct omap_dss_device *dssdev) | |||
1418 | int data1_pol = dssdev->phy.dsi.data1_pol; | 2080 | int data1_pol = dssdev->phy.dsi.data1_pol; |
1419 | int data2_pol = dssdev->phy.dsi.data2_pol; | 2081 | int data2_pol = dssdev->phy.dsi.data2_pol; |
1420 | 2082 | ||
1421 | r = dsi_read_reg(DSI_COMPLEXIO_CFG1); | 2083 | r = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1); |
1422 | r = FLD_MOD(r, clk_lane, 2, 0); | 2084 | r = FLD_MOD(r, clk_lane, 2, 0); |
1423 | r = FLD_MOD(r, clk_pol, 3, 3); | 2085 | r = FLD_MOD(r, clk_pol, 3, 3); |
1424 | r = FLD_MOD(r, data1_lane, 6, 4); | 2086 | r = FLD_MOD(r, data1_lane, 6, 4); |
1425 | r = FLD_MOD(r, data1_pol, 7, 7); | 2087 | r = FLD_MOD(r, data1_pol, 7, 7); |
1426 | r = FLD_MOD(r, data2_lane, 10, 8); | 2088 | r = FLD_MOD(r, data2_lane, 10, 8); |
1427 | r = FLD_MOD(r, data2_pol, 11, 11); | 2089 | r = FLD_MOD(r, data2_pol, 11, 11); |
1428 | dsi_write_reg(DSI_COMPLEXIO_CFG1, r); | 2090 | if (num_data_lanes_dssdev > 2) { |
2091 | int data3_lane = dssdev->phy.dsi.data3_lane; | ||
2092 | int data3_pol = dssdev->phy.dsi.data3_pol; | ||
2093 | |||
2094 | r = FLD_MOD(r, data3_lane, 14, 12); | ||
2095 | r = FLD_MOD(r, data3_pol, 15, 15); | ||
2096 | } | ||
2097 | if (num_data_lanes_dssdev > 3) { | ||
2098 | int data4_lane = dssdev->phy.dsi.data4_lane; | ||
2099 | int data4_pol = dssdev->phy.dsi.data4_pol; | ||
2100 | |||
2101 | r = FLD_MOD(r, data4_lane, 18, 16); | ||
2102 | r = FLD_MOD(r, data4_pol, 19, 19); | ||
2103 | } | ||
2104 | dsi_write_reg(dsidev, DSI_COMPLEXIO_CFG1, r); | ||
1429 | 2105 | ||
1430 | /* The configuration of the DSI complex I/O (number of data lanes, | 2106 | /* The configuration of the DSI complex I/O (number of data lanes, |
1431 | position, differential order) should not be changed while | 2107 | position, differential order) should not be changed while |
@@ -1439,27 +2115,31 @@ static void dsi_complexio_config(struct omap_dss_device *dssdev) | |||
1439 | DSI complex I/O configuration is unknown. */ | 2115 | DSI complex I/O configuration is unknown. */ |
1440 | 2116 | ||
1441 | /* | 2117 | /* |
1442 | REG_FLD_MOD(DSI_CTRL, 1, 0, 0); | 2118 | REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0); |
1443 | REG_FLD_MOD(DSI_CTRL, 0, 0, 0); | 2119 | REG_FLD_MOD(dsidev, DSI_CTRL, 0, 0, 0); |
1444 | REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); | 2120 | REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); |
1445 | REG_FLD_MOD(DSI_CTRL, 1, 0, 0); | 2121 | REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0); |
1446 | */ | 2122 | */ |
1447 | } | 2123 | } |
1448 | 2124 | ||
1449 | static inline unsigned ns2ddr(unsigned ns) | 2125 | static inline unsigned ns2ddr(struct platform_device *dsidev, unsigned ns) |
1450 | { | 2126 | { |
2127 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2128 | |||
1451 | /* convert time in ns to ddr ticks, rounding up */ | 2129 | /* convert time in ns to ddr ticks, rounding up */ |
1452 | unsigned long ddr_clk = dsi.current_cinfo.clkin4ddr / 4; | 2130 | unsigned long ddr_clk = dsi->current_cinfo.clkin4ddr / 4; |
1453 | return (ns * (ddr_clk / 1000 / 1000) + 999) / 1000; | 2131 | return (ns * (ddr_clk / 1000 / 1000) + 999) / 1000; |
1454 | } | 2132 | } |
1455 | 2133 | ||
1456 | static inline unsigned ddr2ns(unsigned ddr) | 2134 | static inline unsigned ddr2ns(struct platform_device *dsidev, unsigned ddr) |
1457 | { | 2135 | { |
1458 | unsigned long ddr_clk = dsi.current_cinfo.clkin4ddr / 4; | 2136 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
2137 | |||
2138 | unsigned long ddr_clk = dsi->current_cinfo.clkin4ddr / 4; | ||
1459 | return ddr * 1000 * 1000 / (ddr_clk / 1000); | 2139 | return ddr * 1000 * 1000 / (ddr_clk / 1000); |
1460 | } | 2140 | } |
1461 | 2141 | ||
1462 | static void dsi_complexio_timings(void) | 2142 | static void dsi_cio_timings(struct platform_device *dsidev) |
1463 | { | 2143 | { |
1464 | u32 r; | 2144 | u32 r; |
1465 | u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit; | 2145 | u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit; |
@@ -1471,139 +2151,323 @@ static void dsi_complexio_timings(void) | |||
1471 | /* 1 * DDR_CLK = 2 * UI */ | 2151 | /* 1 * DDR_CLK = 2 * UI */ |
1472 | 2152 | ||
1473 | /* min 40ns + 4*UI max 85ns + 6*UI */ | 2153 | /* min 40ns + 4*UI max 85ns + 6*UI */ |
1474 | ths_prepare = ns2ddr(70) + 2; | 2154 | ths_prepare = ns2ddr(dsidev, 70) + 2; |
1475 | 2155 | ||
1476 | /* min 145ns + 10*UI */ | 2156 | /* min 145ns + 10*UI */ |
1477 | ths_prepare_ths_zero = ns2ddr(175) + 2; | 2157 | ths_prepare_ths_zero = ns2ddr(dsidev, 175) + 2; |
1478 | 2158 | ||
1479 | /* min max(8*UI, 60ns+4*UI) */ | 2159 | /* min max(8*UI, 60ns+4*UI) */ |
1480 | ths_trail = ns2ddr(60) + 5; | 2160 | ths_trail = ns2ddr(dsidev, 60) + 5; |
1481 | 2161 | ||
1482 | /* min 100ns */ | 2162 | /* min 100ns */ |
1483 | ths_exit = ns2ddr(145); | 2163 | ths_exit = ns2ddr(dsidev, 145); |
1484 | 2164 | ||
1485 | /* tlpx min 50n */ | 2165 | /* tlpx min 50n */ |
1486 | tlpx_half = ns2ddr(25); | 2166 | tlpx_half = ns2ddr(dsidev, 25); |
1487 | 2167 | ||
1488 | /* min 60ns */ | 2168 | /* min 60ns */ |
1489 | tclk_trail = ns2ddr(60) + 2; | 2169 | tclk_trail = ns2ddr(dsidev, 60) + 2; |
1490 | 2170 | ||
1491 | /* min 38ns, max 95ns */ | 2171 | /* min 38ns, max 95ns */ |
1492 | tclk_prepare = ns2ddr(65); | 2172 | tclk_prepare = ns2ddr(dsidev, 65); |
1493 | 2173 | ||
1494 | /* min tclk-prepare + tclk-zero = 300ns */ | 2174 | /* min tclk-prepare + tclk-zero = 300ns */ |
1495 | tclk_zero = ns2ddr(260); | 2175 | tclk_zero = ns2ddr(dsidev, 260); |
1496 | 2176 | ||
1497 | DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n", | 2177 | DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n", |
1498 | ths_prepare, ddr2ns(ths_prepare), | 2178 | ths_prepare, ddr2ns(dsidev, ths_prepare), |
1499 | ths_prepare_ths_zero, ddr2ns(ths_prepare_ths_zero)); | 2179 | ths_prepare_ths_zero, ddr2ns(dsidev, ths_prepare_ths_zero)); |
1500 | DSSDBG("ths_trail %u (%uns), ths_exit %u (%uns)\n", | 2180 | DSSDBG("ths_trail %u (%uns), ths_exit %u (%uns)\n", |
1501 | ths_trail, ddr2ns(ths_trail), | 2181 | ths_trail, ddr2ns(dsidev, ths_trail), |
1502 | ths_exit, ddr2ns(ths_exit)); | 2182 | ths_exit, ddr2ns(dsidev, ths_exit)); |
1503 | 2183 | ||
1504 | DSSDBG("tlpx_half %u (%uns), tclk_trail %u (%uns), " | 2184 | DSSDBG("tlpx_half %u (%uns), tclk_trail %u (%uns), " |
1505 | "tclk_zero %u (%uns)\n", | 2185 | "tclk_zero %u (%uns)\n", |
1506 | tlpx_half, ddr2ns(tlpx_half), | 2186 | tlpx_half, ddr2ns(dsidev, tlpx_half), |
1507 | tclk_trail, ddr2ns(tclk_trail), | 2187 | tclk_trail, ddr2ns(dsidev, tclk_trail), |
1508 | tclk_zero, ddr2ns(tclk_zero)); | 2188 | tclk_zero, ddr2ns(dsidev, tclk_zero)); |
1509 | DSSDBG("tclk_prepare %u (%uns)\n", | 2189 | DSSDBG("tclk_prepare %u (%uns)\n", |
1510 | tclk_prepare, ddr2ns(tclk_prepare)); | 2190 | tclk_prepare, ddr2ns(dsidev, tclk_prepare)); |
1511 | 2191 | ||
1512 | /* program timings */ | 2192 | /* program timings */ |
1513 | 2193 | ||
1514 | r = dsi_read_reg(DSI_DSIPHY_CFG0); | 2194 | r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0); |
1515 | r = FLD_MOD(r, ths_prepare, 31, 24); | 2195 | r = FLD_MOD(r, ths_prepare, 31, 24); |
1516 | r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16); | 2196 | r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16); |
1517 | r = FLD_MOD(r, ths_trail, 15, 8); | 2197 | r = FLD_MOD(r, ths_trail, 15, 8); |
1518 | r = FLD_MOD(r, ths_exit, 7, 0); | 2198 | r = FLD_MOD(r, ths_exit, 7, 0); |
1519 | dsi_write_reg(DSI_DSIPHY_CFG0, r); | 2199 | dsi_write_reg(dsidev, DSI_DSIPHY_CFG0, r); |
1520 | 2200 | ||
1521 | r = dsi_read_reg(DSI_DSIPHY_CFG1); | 2201 | r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1); |
1522 | r = FLD_MOD(r, tlpx_half, 22, 16); | 2202 | r = FLD_MOD(r, tlpx_half, 22, 16); |
1523 | r = FLD_MOD(r, tclk_trail, 15, 8); | 2203 | r = FLD_MOD(r, tclk_trail, 15, 8); |
1524 | r = FLD_MOD(r, tclk_zero, 7, 0); | 2204 | r = FLD_MOD(r, tclk_zero, 7, 0); |
1525 | dsi_write_reg(DSI_DSIPHY_CFG1, r); | 2205 | dsi_write_reg(dsidev, DSI_DSIPHY_CFG1, r); |
1526 | 2206 | ||
1527 | r = dsi_read_reg(DSI_DSIPHY_CFG2); | 2207 | r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2); |
1528 | r = FLD_MOD(r, tclk_prepare, 7, 0); | 2208 | r = FLD_MOD(r, tclk_prepare, 7, 0); |
1529 | dsi_write_reg(DSI_DSIPHY_CFG2, r); | 2209 | dsi_write_reg(dsidev, DSI_DSIPHY_CFG2, r); |
2210 | } | ||
2211 | |||
2212 | static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev, | ||
2213 | enum dsi_lane lanes) | ||
2214 | { | ||
2215 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2216 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2217 | int clk_lane = dssdev->phy.dsi.clk_lane; | ||
2218 | int data1_lane = dssdev->phy.dsi.data1_lane; | ||
2219 | int data2_lane = dssdev->phy.dsi.data2_lane; | ||
2220 | int data3_lane = dssdev->phy.dsi.data3_lane; | ||
2221 | int data4_lane = dssdev->phy.dsi.data4_lane; | ||
2222 | int clk_pol = dssdev->phy.dsi.clk_pol; | ||
2223 | int data1_pol = dssdev->phy.dsi.data1_pol; | ||
2224 | int data2_pol = dssdev->phy.dsi.data2_pol; | ||
2225 | int data3_pol = dssdev->phy.dsi.data3_pol; | ||
2226 | int data4_pol = dssdev->phy.dsi.data4_pol; | ||
2227 | |||
2228 | u32 l = 0; | ||
2229 | u8 lptxscp_start = dsi->num_data_lanes == 2 ? 22 : 26; | ||
2230 | |||
2231 | if (lanes & DSI_CLK_P) | ||
2232 | l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 0 : 1)); | ||
2233 | if (lanes & DSI_CLK_N) | ||
2234 | l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 1 : 0)); | ||
2235 | |||
2236 | if (lanes & DSI_DATA1_P) | ||
2237 | l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 0 : 1)); | ||
2238 | if (lanes & DSI_DATA1_N) | ||
2239 | l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 1 : 0)); | ||
2240 | |||
2241 | if (lanes & DSI_DATA2_P) | ||
2242 | l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 0 : 1)); | ||
2243 | if (lanes & DSI_DATA2_N) | ||
2244 | l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 1 : 0)); | ||
2245 | |||
2246 | if (lanes & DSI_DATA3_P) | ||
2247 | l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 0 : 1)); | ||
2248 | if (lanes & DSI_DATA3_N) | ||
2249 | l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 1 : 0)); | ||
2250 | |||
2251 | if (lanes & DSI_DATA4_P) | ||
2252 | l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 0 : 1)); | ||
2253 | if (lanes & DSI_DATA4_N) | ||
2254 | l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 1 : 0)); | ||
2255 | /* | ||
2256 | * Bits in REGLPTXSCPDAT4TO0DXDY: | ||
2257 | * 17: DY0 18: DX0 | ||
2258 | * 19: DY1 20: DX1 | ||
2259 | * 21: DY2 22: DX2 | ||
2260 | * 23: DY3 24: DX3 | ||
2261 | * 25: DY4 26: DX4 | ||
2262 | */ | ||
2263 | |||
2264 | /* Set the lane override configuration */ | ||
2265 | |||
2266 | /* REGLPTXSCPDAT4TO0DXDY */ | ||
2267 | REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, l, lptxscp_start, 17); | ||
2268 | |||
2269 | /* Enable lane override */ | ||
2270 | |||
2271 | /* ENLPTXSCPDAT */ | ||
2272 | REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 1, 27, 27); | ||
1530 | } | 2273 | } |
1531 | 2274 | ||
2275 | static void dsi_cio_disable_lane_override(struct platform_device *dsidev) | ||
2276 | { | ||
2277 | /* Disable lane override */ | ||
2278 | REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 27, 27); /* ENLPTXSCPDAT */ | ||
2279 | /* Reset the lane override configuration */ | ||
2280 | /* REGLPTXSCPDAT4TO0DXDY */ | ||
2281 | REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 22, 17); | ||
2282 | } | ||
1532 | 2283 | ||
1533 | static int dsi_complexio_init(struct omap_dss_device *dssdev) | 2284 | static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev) |
1534 | { | 2285 | { |
1535 | int r = 0; | 2286 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
2287 | int t; | ||
2288 | int bits[3]; | ||
2289 | bool in_use[3]; | ||
2290 | |||
2291 | if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) { | ||
2292 | bits[0] = 28; | ||
2293 | bits[1] = 27; | ||
2294 | bits[2] = 26; | ||
2295 | } else { | ||
2296 | bits[0] = 24; | ||
2297 | bits[1] = 25; | ||
2298 | bits[2] = 26; | ||
2299 | } | ||
2300 | |||
2301 | in_use[0] = false; | ||
2302 | in_use[1] = false; | ||
2303 | in_use[2] = false; | ||
2304 | |||
2305 | if (dssdev->phy.dsi.clk_lane != 0) | ||
2306 | in_use[dssdev->phy.dsi.clk_lane - 1] = true; | ||
2307 | if (dssdev->phy.dsi.data1_lane != 0) | ||
2308 | in_use[dssdev->phy.dsi.data1_lane - 1] = true; | ||
2309 | if (dssdev->phy.dsi.data2_lane != 0) | ||
2310 | in_use[dssdev->phy.dsi.data2_lane - 1] = true; | ||
2311 | |||
2312 | t = 100000; | ||
2313 | while (true) { | ||
2314 | u32 l; | ||
2315 | int i; | ||
2316 | int ok; | ||
2317 | |||
2318 | l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5); | ||
2319 | |||
2320 | ok = 0; | ||
2321 | for (i = 0; i < 3; ++i) { | ||
2322 | if (!in_use[i] || (l & (1 << bits[i]))) | ||
2323 | ok++; | ||
2324 | } | ||
2325 | |||
2326 | if (ok == 3) | ||
2327 | break; | ||
2328 | |||
2329 | if (--t == 0) { | ||
2330 | for (i = 0; i < 3; ++i) { | ||
2331 | if (!in_use[i] || (l & (1 << bits[i]))) | ||
2332 | continue; | ||
2333 | |||
2334 | DSSERR("CIO TXCLKESC%d domain not coming " \ | ||
2335 | "out of reset\n", i); | ||
2336 | } | ||
2337 | return -EIO; | ||
2338 | } | ||
2339 | } | ||
2340 | |||
2341 | return 0; | ||
2342 | } | ||
2343 | |||
2344 | static int dsi_cio_init(struct omap_dss_device *dssdev) | ||
2345 | { | ||
2346 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2347 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2348 | int r; | ||
2349 | int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev); | ||
2350 | u32 l; | ||
2351 | |||
2352 | DSSDBGF(); | ||
1536 | 2353 | ||
1537 | DSSDBG("dsi_complexio_init\n"); | 2354 | if (dsi->dsi_mux_pads) |
2355 | dsi->dsi_mux_pads(true); | ||
1538 | 2356 | ||
1539 | /* CIO_CLK_ICG, enable L3 clk to CIO */ | 2357 | dsi_enable_scp_clk(dsidev); |
1540 | REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14); | ||
1541 | 2358 | ||
1542 | /* A dummy read using the SCP interface to any DSIPHY register is | 2359 | /* A dummy read using the SCP interface to any DSIPHY register is |
1543 | * required after DSIPHY reset to complete the reset of the DSI complex | 2360 | * required after DSIPHY reset to complete the reset of the DSI complex |
1544 | * I/O. */ | 2361 | * I/O. */ |
1545 | dsi_read_reg(DSI_DSIPHY_CFG5); | 2362 | dsi_read_reg(dsidev, DSI_DSIPHY_CFG5); |
1546 | 2363 | ||
1547 | if (wait_for_bit_change(DSI_DSIPHY_CFG5, 30, 1) != 1) { | 2364 | if (wait_for_bit_change(dsidev, DSI_DSIPHY_CFG5, 30, 1) != 1) { |
1548 | DSSERR("ComplexIO PHY not coming out of reset.\n"); | 2365 | DSSERR("CIO SCP Clock domain not coming out of reset.\n"); |
1549 | r = -ENODEV; | 2366 | r = -EIO; |
1550 | goto err; | 2367 | goto err_scp_clk_dom; |
1551 | } | 2368 | } |
1552 | 2369 | ||
1553 | dsi_complexio_config(dssdev); | 2370 | dsi_set_lane_config(dssdev); |
2371 | |||
2372 | /* set TX STOP MODE timer to maximum for this operation */ | ||
2373 | l = dsi_read_reg(dsidev, DSI_TIMING1); | ||
2374 | l = FLD_MOD(l, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ | ||
2375 | l = FLD_MOD(l, 1, 14, 14); /* STOP_STATE_X16_IO */ | ||
2376 | l = FLD_MOD(l, 1, 13, 13); /* STOP_STATE_X4_IO */ | ||
2377 | l = FLD_MOD(l, 0x1fff, 12, 0); /* STOP_STATE_COUNTER_IO */ | ||
2378 | dsi_write_reg(dsidev, DSI_TIMING1, l); | ||
2379 | |||
2380 | if (dsi->ulps_enabled) { | ||
2381 | u32 lane_mask = DSI_CLK_P | DSI_DATA1_P | DSI_DATA2_P; | ||
2382 | |||
2383 | DSSDBG("manual ulps exit\n"); | ||
2384 | |||
2385 | /* ULPS is exited by Mark-1 state for 1ms, followed by | ||
2386 | * stop state. DSS HW cannot do this via the normal | ||
2387 | * ULPS exit sequence, as after reset the DSS HW thinks | ||
2388 | * that we are not in ULPS mode, and refuses to send the | ||
2389 | * sequence. So we need to send the ULPS exit sequence | ||
2390 | * manually. | ||
2391 | */ | ||
2392 | |||
2393 | if (num_data_lanes_dssdev > 2) | ||
2394 | lane_mask |= DSI_DATA3_P; | ||
2395 | |||
2396 | if (num_data_lanes_dssdev > 3) | ||
2397 | lane_mask |= DSI_DATA4_P; | ||
1554 | 2398 | ||
1555 | r = dsi_complexio_power(DSI_COMPLEXIO_POWER_ON); | 2399 | dsi_cio_enable_lane_override(dssdev, lane_mask); |
2400 | } | ||
1556 | 2401 | ||
2402 | r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON); | ||
1557 | if (r) | 2403 | if (r) |
1558 | goto err; | 2404 | goto err_cio_pwr; |
1559 | 2405 | ||
1560 | if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 29, 1) != 1) { | 2406 | if (wait_for_bit_change(dsidev, DSI_COMPLEXIO_CFG1, 29, 1) != 1) { |
1561 | DSSERR("ComplexIO not coming out of reset.\n"); | 2407 | DSSERR("CIO PWR clock domain not coming out of reset.\n"); |
1562 | r = -ENODEV; | 2408 | r = -ENODEV; |
1563 | goto err; | 2409 | goto err_cio_pwr_dom; |
1564 | } | 2410 | } |
1565 | 2411 | ||
1566 | if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) { | 2412 | dsi_if_enable(dsidev, true); |
1567 | DSSERR("ComplexIO LDO power down.\n"); | 2413 | dsi_if_enable(dsidev, false); |
1568 | r = -ENODEV; | 2414 | REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */ |
1569 | goto err; | 2415 | |
2416 | r = dsi_cio_wait_tx_clk_esc_reset(dssdev); | ||
2417 | if (r) | ||
2418 | goto err_tx_clk_esc_rst; | ||
2419 | |||
2420 | if (dsi->ulps_enabled) { | ||
2421 | /* Keep Mark-1 state for 1ms (as per DSI spec) */ | ||
2422 | ktime_t wait = ns_to_ktime(1000 * 1000); | ||
2423 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
2424 | schedule_hrtimeout(&wait, HRTIMER_MODE_REL); | ||
2425 | |||
2426 | /* Disable the override. The lanes should be set to Mark-11 | ||
2427 | * state by the HW */ | ||
2428 | dsi_cio_disable_lane_override(dsidev); | ||
1570 | } | 2429 | } |
1571 | 2430 | ||
1572 | dsi_complexio_timings(); | 2431 | /* FORCE_TX_STOP_MODE_IO */ |
2432 | REG_FLD_MOD(dsidev, DSI_TIMING1, 0, 15, 15); | ||
1573 | 2433 | ||
1574 | /* | 2434 | dsi_cio_timings(dsidev); |
1575 | The configuration of the DSI complex I/O (number of data lanes, | 2435 | |
1576 | position, differential order) should not be changed while | 2436 | dsi->ulps_enabled = false; |
1577 | DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. For the | ||
1578 | hardware to recognize a new configuration of the complex I/O (done | ||
1579 | in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to follow | ||
1580 | this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, next | ||
1581 | reset the DSS.DSI_CTRL[0] IF_EN to 0, then set DSS.DSI_CLK_CTRL[20] | ||
1582 | LP_CLK_ENABLE to 1, and finally, set again the DSS.DSI_CTRL[0] IF_EN | ||
1583 | bit to 1. If the sequence is not followed, the DSi complex I/O | ||
1584 | configuration is undetermined. | ||
1585 | */ | ||
1586 | dsi_if_enable(1); | ||
1587 | dsi_if_enable(0); | ||
1588 | REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */ | ||
1589 | dsi_if_enable(1); | ||
1590 | dsi_if_enable(0); | ||
1591 | 2437 | ||
1592 | DSSDBG("CIO init done\n"); | 2438 | DSSDBG("CIO init done\n"); |
1593 | err: | 2439 | |
2440 | return 0; | ||
2441 | |||
2442 | err_tx_clk_esc_rst: | ||
2443 | REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 20, 20); /* LP_CLK_ENABLE */ | ||
2444 | err_cio_pwr_dom: | ||
2445 | dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); | ||
2446 | err_cio_pwr: | ||
2447 | if (dsi->ulps_enabled) | ||
2448 | dsi_cio_disable_lane_override(dsidev); | ||
2449 | err_scp_clk_dom: | ||
2450 | dsi_disable_scp_clk(dsidev); | ||
2451 | if (dsi->dsi_mux_pads) | ||
2452 | dsi->dsi_mux_pads(false); | ||
1594 | return r; | 2453 | return r; |
1595 | } | 2454 | } |
1596 | 2455 | ||
1597 | static void dsi_complexio_uninit(void) | 2456 | static void dsi_cio_uninit(struct platform_device *dsidev) |
1598 | { | 2457 | { |
1599 | dsi_complexio_power(DSI_COMPLEXIO_POWER_OFF); | 2458 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
2459 | |||
2460 | dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); | ||
2461 | dsi_disable_scp_clk(dsidev); | ||
2462 | if (dsi->dsi_mux_pads) | ||
2463 | dsi->dsi_mux_pads(false); | ||
1600 | } | 2464 | } |
1601 | 2465 | ||
1602 | static int _dsi_wait_reset(void) | 2466 | static int _dsi_wait_reset(struct platform_device *dsidev) |
1603 | { | 2467 | { |
1604 | int t = 0; | 2468 | int t = 0; |
1605 | 2469 | ||
1606 | while (REG_GET(DSI_SYSSTATUS, 0, 0) == 0) { | 2470 | while (REG_GET(dsidev, DSI_SYSSTATUS, 0, 0) == 0) { |
1607 | if (++t > 5) { | 2471 | if (++t > 5) { |
1608 | DSSERR("soft reset failed\n"); | 2472 | DSSERR("soft reset failed\n"); |
1609 | return -ENODEV; | 2473 | return -ENODEV; |
@@ -1614,42 +2478,30 @@ static int _dsi_wait_reset(void) | |||
1614 | return 0; | 2478 | return 0; |
1615 | } | 2479 | } |
1616 | 2480 | ||
1617 | static int _dsi_reset(void) | 2481 | static int _dsi_reset(struct platform_device *dsidev) |
1618 | { | 2482 | { |
1619 | /* Soft reset */ | 2483 | /* Soft reset */ |
1620 | REG_FLD_MOD(DSI_SYSCONFIG, 1, 1, 1); | 2484 | REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 1, 1); |
1621 | return _dsi_wait_reset(); | 2485 | return _dsi_wait_reset(dsidev); |
1622 | } | ||
1623 | |||
1624 | static void dsi_reset_tx_fifo(int channel) | ||
1625 | { | ||
1626 | u32 mask; | ||
1627 | u32 l; | ||
1628 | |||
1629 | /* set fifosize of the channel to 0, then return the old size */ | ||
1630 | l = dsi_read_reg(DSI_TX_FIFO_VC_SIZE); | ||
1631 | |||
1632 | mask = FLD_MASK((8 * channel) + 7, (8 * channel) + 4); | ||
1633 | dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l & ~mask); | ||
1634 | |||
1635 | dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l); | ||
1636 | } | 2486 | } |
1637 | 2487 | ||
1638 | static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2, | 2488 | static void dsi_config_tx_fifo(struct platform_device *dsidev, |
2489 | enum fifo_size size1, enum fifo_size size2, | ||
1639 | enum fifo_size size3, enum fifo_size size4) | 2490 | enum fifo_size size3, enum fifo_size size4) |
1640 | { | 2491 | { |
2492 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1641 | u32 r = 0; | 2493 | u32 r = 0; |
1642 | int add = 0; | 2494 | int add = 0; |
1643 | int i; | 2495 | int i; |
1644 | 2496 | ||
1645 | dsi.vc[0].fifo_size = size1; | 2497 | dsi->vc[0].fifo_size = size1; |
1646 | dsi.vc[1].fifo_size = size2; | 2498 | dsi->vc[1].fifo_size = size2; |
1647 | dsi.vc[2].fifo_size = size3; | 2499 | dsi->vc[2].fifo_size = size3; |
1648 | dsi.vc[3].fifo_size = size4; | 2500 | dsi->vc[3].fifo_size = size4; |
1649 | 2501 | ||
1650 | for (i = 0; i < 4; i++) { | 2502 | for (i = 0; i < 4; i++) { |
1651 | u8 v; | 2503 | u8 v; |
1652 | int size = dsi.vc[i].fifo_size; | 2504 | int size = dsi->vc[i].fifo_size; |
1653 | 2505 | ||
1654 | if (add + size > 4) { | 2506 | if (add + size > 4) { |
1655 | DSSERR("Illegal FIFO configuration\n"); | 2507 | DSSERR("Illegal FIFO configuration\n"); |
@@ -1662,24 +2514,26 @@ static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2, | |||
1662 | add += size; | 2514 | add += size; |
1663 | } | 2515 | } |
1664 | 2516 | ||
1665 | dsi_write_reg(DSI_TX_FIFO_VC_SIZE, r); | 2517 | dsi_write_reg(dsidev, DSI_TX_FIFO_VC_SIZE, r); |
1666 | } | 2518 | } |
1667 | 2519 | ||
1668 | static void dsi_config_rx_fifo(enum fifo_size size1, enum fifo_size size2, | 2520 | static void dsi_config_rx_fifo(struct platform_device *dsidev, |
2521 | enum fifo_size size1, enum fifo_size size2, | ||
1669 | enum fifo_size size3, enum fifo_size size4) | 2522 | enum fifo_size size3, enum fifo_size size4) |
1670 | { | 2523 | { |
2524 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1671 | u32 r = 0; | 2525 | u32 r = 0; |
1672 | int add = 0; | 2526 | int add = 0; |
1673 | int i; | 2527 | int i; |
1674 | 2528 | ||
1675 | dsi.vc[0].fifo_size = size1; | 2529 | dsi->vc[0].fifo_size = size1; |
1676 | dsi.vc[1].fifo_size = size2; | 2530 | dsi->vc[1].fifo_size = size2; |
1677 | dsi.vc[2].fifo_size = size3; | 2531 | dsi->vc[2].fifo_size = size3; |
1678 | dsi.vc[3].fifo_size = size4; | 2532 | dsi->vc[3].fifo_size = size4; |
1679 | 2533 | ||
1680 | for (i = 0; i < 4; i++) { | 2534 | for (i = 0; i < 4; i++) { |
1681 | u8 v; | 2535 | u8 v; |
1682 | int size = dsi.vc[i].fifo_size; | 2536 | int size = dsi->vc[i].fifo_size; |
1683 | 2537 | ||
1684 | if (add + size > 4) { | 2538 | if (add + size > 4) { |
1685 | DSSERR("Illegal FIFO configuration\n"); | 2539 | DSSERR("Illegal FIFO configuration\n"); |
@@ -1692,18 +2546,18 @@ static void dsi_config_rx_fifo(enum fifo_size size1, enum fifo_size size2, | |||
1692 | add += size; | 2546 | add += size; |
1693 | } | 2547 | } |
1694 | 2548 | ||
1695 | dsi_write_reg(DSI_RX_FIFO_VC_SIZE, r); | 2549 | dsi_write_reg(dsidev, DSI_RX_FIFO_VC_SIZE, r); |
1696 | } | 2550 | } |
1697 | 2551 | ||
1698 | static int dsi_force_tx_stop_mode_io(void) | 2552 | static int dsi_force_tx_stop_mode_io(struct platform_device *dsidev) |
1699 | { | 2553 | { |
1700 | u32 r; | 2554 | u32 r; |
1701 | 2555 | ||
1702 | r = dsi_read_reg(DSI_TIMING1); | 2556 | r = dsi_read_reg(dsidev, DSI_TIMING1); |
1703 | r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ | 2557 | r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ |
1704 | dsi_write_reg(DSI_TIMING1, r); | 2558 | dsi_write_reg(dsidev, DSI_TIMING1, r); |
1705 | 2559 | ||
1706 | if (wait_for_bit_change(DSI_TIMING1, 15, 0) != 0) { | 2560 | if (wait_for_bit_change(dsidev, DSI_TIMING1, 15, 0) != 0) { |
1707 | DSSERR("TX_STOP bit not going down\n"); | 2561 | DSSERR("TX_STOP bit not going down\n"); |
1708 | return -EIO; | 2562 | return -EIO; |
1709 | } | 2563 | } |
@@ -1711,16 +2565,135 @@ static int dsi_force_tx_stop_mode_io(void) | |||
1711 | return 0; | 2565 | return 0; |
1712 | } | 2566 | } |
1713 | 2567 | ||
1714 | static int dsi_vc_enable(int channel, bool enable) | 2568 | static bool dsi_vc_is_enabled(struct platform_device *dsidev, int channel) |
2569 | { | ||
2570 | return REG_GET(dsidev, DSI_VC_CTRL(channel), 0, 0); | ||
2571 | } | ||
2572 | |||
2573 | static void dsi_packet_sent_handler_vp(void *data, u32 mask) | ||
2574 | { | ||
2575 | struct dsi_packet_sent_handler_data *vp_data = | ||
2576 | (struct dsi_packet_sent_handler_data *) data; | ||
2577 | struct dsi_data *dsi = dsi_get_dsidrv_data(vp_data->dsidev); | ||
2578 | const int channel = dsi->update_channel; | ||
2579 | u8 bit = dsi->te_enabled ? 30 : 31; | ||
2580 | |||
2581 | if (REG_GET(vp_data->dsidev, DSI_VC_TE(channel), bit, bit) == 0) | ||
2582 | complete(vp_data->completion); | ||
2583 | } | ||
2584 | |||
2585 | static int dsi_sync_vc_vp(struct platform_device *dsidev, int channel) | ||
2586 | { | ||
2587 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2588 | DECLARE_COMPLETION_ONSTACK(completion); | ||
2589 | struct dsi_packet_sent_handler_data vp_data = { dsidev, &completion }; | ||
2590 | int r = 0; | ||
2591 | u8 bit; | ||
2592 | |||
2593 | bit = dsi->te_enabled ? 30 : 31; | ||
2594 | |||
2595 | r = dsi_register_isr_vc(dsidev, channel, dsi_packet_sent_handler_vp, | ||
2596 | &vp_data, DSI_VC_IRQ_PACKET_SENT); | ||
2597 | if (r) | ||
2598 | goto err0; | ||
2599 | |||
2600 | /* Wait for completion only if TE_EN/TE_START is still set */ | ||
2601 | if (REG_GET(dsidev, DSI_VC_TE(channel), bit, bit)) { | ||
2602 | if (wait_for_completion_timeout(&completion, | ||
2603 | msecs_to_jiffies(10)) == 0) { | ||
2604 | DSSERR("Failed to complete previous frame transfer\n"); | ||
2605 | r = -EIO; | ||
2606 | goto err1; | ||
2607 | } | ||
2608 | } | ||
2609 | |||
2610 | dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_vp, | ||
2611 | &vp_data, DSI_VC_IRQ_PACKET_SENT); | ||
2612 | |||
2613 | return 0; | ||
2614 | err1: | ||
2615 | dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_vp, | ||
2616 | &vp_data, DSI_VC_IRQ_PACKET_SENT); | ||
2617 | err0: | ||
2618 | return r; | ||
2619 | } | ||
2620 | |||
2621 | static void dsi_packet_sent_handler_l4(void *data, u32 mask) | ||
2622 | { | ||
2623 | struct dsi_packet_sent_handler_data *l4_data = | ||
2624 | (struct dsi_packet_sent_handler_data *) data; | ||
2625 | struct dsi_data *dsi = dsi_get_dsidrv_data(l4_data->dsidev); | ||
2626 | const int channel = dsi->update_channel; | ||
2627 | |||
2628 | if (REG_GET(l4_data->dsidev, DSI_VC_CTRL(channel), 5, 5) == 0) | ||
2629 | complete(l4_data->completion); | ||
2630 | } | ||
2631 | |||
2632 | static int dsi_sync_vc_l4(struct platform_device *dsidev, int channel) | ||
2633 | { | ||
2634 | DECLARE_COMPLETION_ONSTACK(completion); | ||
2635 | struct dsi_packet_sent_handler_data l4_data = { dsidev, &completion }; | ||
2636 | int r = 0; | ||
2637 | |||
2638 | r = dsi_register_isr_vc(dsidev, channel, dsi_packet_sent_handler_l4, | ||
2639 | &l4_data, DSI_VC_IRQ_PACKET_SENT); | ||
2640 | if (r) | ||
2641 | goto err0; | ||
2642 | |||
2643 | /* Wait for completion only if TX_FIFO_NOT_EMPTY is still set */ | ||
2644 | if (REG_GET(dsidev, DSI_VC_CTRL(channel), 5, 5)) { | ||
2645 | if (wait_for_completion_timeout(&completion, | ||
2646 | msecs_to_jiffies(10)) == 0) { | ||
2647 | DSSERR("Failed to complete previous l4 transfer\n"); | ||
2648 | r = -EIO; | ||
2649 | goto err1; | ||
2650 | } | ||
2651 | } | ||
2652 | |||
2653 | dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_l4, | ||
2654 | &l4_data, DSI_VC_IRQ_PACKET_SENT); | ||
2655 | |||
2656 | return 0; | ||
2657 | err1: | ||
2658 | dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_l4, | ||
2659 | &l4_data, DSI_VC_IRQ_PACKET_SENT); | ||
2660 | err0: | ||
2661 | return r; | ||
2662 | } | ||
2663 | |||
2664 | static int dsi_sync_vc(struct platform_device *dsidev, int channel) | ||
2665 | { | ||
2666 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2667 | |||
2668 | WARN_ON(!dsi_bus_is_locked(dsidev)); | ||
2669 | |||
2670 | WARN_ON(in_interrupt()); | ||
2671 | |||
2672 | if (!dsi_vc_is_enabled(dsidev, channel)) | ||
2673 | return 0; | ||
2674 | |||
2675 | switch (dsi->vc[channel].mode) { | ||
2676 | case DSI_VC_MODE_VP: | ||
2677 | return dsi_sync_vc_vp(dsidev, channel); | ||
2678 | case DSI_VC_MODE_L4: | ||
2679 | return dsi_sync_vc_l4(dsidev, channel); | ||
2680 | default: | ||
2681 | BUG(); | ||
2682 | } | ||
2683 | } | ||
2684 | |||
2685 | static int dsi_vc_enable(struct platform_device *dsidev, int channel, | ||
2686 | bool enable) | ||
1715 | { | 2687 | { |
1716 | DSSDBG("dsi_vc_enable channel %d, enable %d\n", | 2688 | DSSDBG("dsi_vc_enable channel %d, enable %d\n", |
1717 | channel, enable); | 2689 | channel, enable); |
1718 | 2690 | ||
1719 | enable = enable ? 1 : 0; | 2691 | enable = enable ? 1 : 0; |
1720 | 2692 | ||
1721 | REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 0, 0); | 2693 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 0, 0); |
1722 | 2694 | ||
1723 | if (wait_for_bit_change(DSI_VC_CTRL(channel), 0, enable) != enable) { | 2695 | if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel), |
2696 | 0, enable) != enable) { | ||
1724 | DSSERR("Failed to set dsi_vc_enable to %d\n", enable); | 2697 | DSSERR("Failed to set dsi_vc_enable to %d\n", enable); |
1725 | return -EIO; | 2698 | return -EIO; |
1726 | } | 2699 | } |
@@ -1728,13 +2701,13 @@ static int dsi_vc_enable(int channel, bool enable) | |||
1728 | return 0; | 2701 | return 0; |
1729 | } | 2702 | } |
1730 | 2703 | ||
1731 | static void dsi_vc_initial_config(int channel) | 2704 | static void dsi_vc_initial_config(struct platform_device *dsidev, int channel) |
1732 | { | 2705 | { |
1733 | u32 r; | 2706 | u32 r; |
1734 | 2707 | ||
1735 | DSSDBGF("%d", channel); | 2708 | DSSDBGF("%d", channel); |
1736 | 2709 | ||
1737 | r = dsi_read_reg(DSI_VC_CTRL(channel)); | 2710 | r = dsi_read_reg(dsidev, DSI_VC_CTRL(channel)); |
1738 | 2711 | ||
1739 | if (FLD_GET(r, 15, 15)) /* VC_BUSY */ | 2712 | if (FLD_GET(r, 15, 15)) /* VC_BUSY */ |
1740 | DSSERR("VC(%d) busy when trying to configure it!\n", | 2713 | DSSERR("VC(%d) busy when trying to configure it!\n", |
@@ -1747,87 +2720,107 @@ static void dsi_vc_initial_config(int channel) | |||
1747 | r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */ | 2720 | r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */ |
1748 | r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */ | 2721 | r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */ |
1749 | r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */ | 2722 | r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */ |
2723 | if (dss_has_feature(FEAT_DSI_VC_OCP_WIDTH)) | ||
2724 | r = FLD_MOD(r, 3, 11, 10); /* OCP_WIDTH = 32 bit */ | ||
1750 | 2725 | ||
1751 | r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */ | 2726 | r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */ |
1752 | r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ | 2727 | r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ |
1753 | 2728 | ||
1754 | dsi_write_reg(DSI_VC_CTRL(channel), r); | 2729 | dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r); |
1755 | |||
1756 | dsi.vc[channel].mode = DSI_VC_MODE_L4; | ||
1757 | } | 2730 | } |
1758 | 2731 | ||
1759 | static int dsi_vc_config_l4(int channel) | 2732 | static int dsi_vc_config_l4(struct platform_device *dsidev, int channel) |
1760 | { | 2733 | { |
1761 | if (dsi.vc[channel].mode == DSI_VC_MODE_L4) | 2734 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
2735 | |||
2736 | if (dsi->vc[channel].mode == DSI_VC_MODE_L4) | ||
1762 | return 0; | 2737 | return 0; |
1763 | 2738 | ||
1764 | DSSDBGF("%d", channel); | 2739 | DSSDBGF("%d", channel); |
1765 | 2740 | ||
1766 | dsi_vc_enable(channel, 0); | 2741 | dsi_sync_vc(dsidev, channel); |
2742 | |||
2743 | dsi_vc_enable(dsidev, channel, 0); | ||
1767 | 2744 | ||
1768 | /* VC_BUSY */ | 2745 | /* VC_BUSY */ |
1769 | if (wait_for_bit_change(DSI_VC_CTRL(channel), 15, 0) != 0) { | 2746 | if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel), 15, 0) != 0) { |
1770 | DSSERR("vc(%d) busy when trying to config for L4\n", channel); | 2747 | DSSERR("vc(%d) busy when trying to config for L4\n", channel); |
1771 | return -EIO; | 2748 | return -EIO; |
1772 | } | 2749 | } |
1773 | 2750 | ||
1774 | REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */ | 2751 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */ |
2752 | |||
2753 | /* DCS_CMD_ENABLE */ | ||
2754 | if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) | ||
2755 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 30, 30); | ||
1775 | 2756 | ||
1776 | dsi_vc_enable(channel, 1); | 2757 | dsi_vc_enable(dsidev, channel, 1); |
1777 | 2758 | ||
1778 | dsi.vc[channel].mode = DSI_VC_MODE_L4; | 2759 | dsi->vc[channel].mode = DSI_VC_MODE_L4; |
1779 | 2760 | ||
1780 | return 0; | 2761 | return 0; |
1781 | } | 2762 | } |
1782 | 2763 | ||
1783 | static int dsi_vc_config_vp(int channel) | 2764 | static int dsi_vc_config_vp(struct platform_device *dsidev, int channel) |
1784 | { | 2765 | { |
1785 | if (dsi.vc[channel].mode == DSI_VC_MODE_VP) | 2766 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
2767 | |||
2768 | if (dsi->vc[channel].mode == DSI_VC_MODE_VP) | ||
1786 | return 0; | 2769 | return 0; |
1787 | 2770 | ||
1788 | DSSDBGF("%d", channel); | 2771 | DSSDBGF("%d", channel); |
1789 | 2772 | ||
1790 | dsi_vc_enable(channel, 0); | 2773 | dsi_sync_vc(dsidev, channel); |
2774 | |||
2775 | dsi_vc_enable(dsidev, channel, 0); | ||
1791 | 2776 | ||
1792 | /* VC_BUSY */ | 2777 | /* VC_BUSY */ |
1793 | if (wait_for_bit_change(DSI_VC_CTRL(channel), 15, 0) != 0) { | 2778 | if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel), 15, 0) != 0) { |
1794 | DSSERR("vc(%d) busy when trying to config for VP\n", channel); | 2779 | DSSERR("vc(%d) busy when trying to config for VP\n", channel); |
1795 | return -EIO; | 2780 | return -EIO; |
1796 | } | 2781 | } |
1797 | 2782 | ||
1798 | REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */ | 2783 | /* SOURCE, 1 = video port */ |
2784 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 1, 1); | ||
2785 | |||
2786 | /* DCS_CMD_ENABLE */ | ||
2787 | if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) | ||
2788 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 30, 30); | ||
1799 | 2789 | ||
1800 | dsi_vc_enable(channel, 1); | 2790 | dsi_vc_enable(dsidev, channel, 1); |
1801 | 2791 | ||
1802 | dsi.vc[channel].mode = DSI_VC_MODE_VP; | 2792 | dsi->vc[channel].mode = DSI_VC_MODE_VP; |
1803 | 2793 | ||
1804 | return 0; | 2794 | return 0; |
1805 | } | 2795 | } |
1806 | 2796 | ||
1807 | 2797 | ||
1808 | void omapdss_dsi_vc_enable_hs(int channel, bool enable) | 2798 | void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel, |
2799 | bool enable) | ||
1809 | { | 2800 | { |
2801 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2802 | |||
1810 | DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable); | 2803 | DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable); |
1811 | 2804 | ||
1812 | WARN_ON(!dsi_bus_is_locked()); | 2805 | WARN_ON(!dsi_bus_is_locked(dsidev)); |
1813 | 2806 | ||
1814 | dsi_vc_enable(channel, 0); | 2807 | dsi_vc_enable(dsidev, channel, 0); |
1815 | dsi_if_enable(0); | 2808 | dsi_if_enable(dsidev, 0); |
1816 | 2809 | ||
1817 | REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 9, 9); | 2810 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 9, 9); |
1818 | 2811 | ||
1819 | dsi_vc_enable(channel, 1); | 2812 | dsi_vc_enable(dsidev, channel, 1); |
1820 | dsi_if_enable(1); | 2813 | dsi_if_enable(dsidev, 1); |
1821 | 2814 | ||
1822 | dsi_force_tx_stop_mode_io(); | 2815 | dsi_force_tx_stop_mode_io(dsidev); |
1823 | } | 2816 | } |
1824 | EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs); | 2817 | EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs); |
1825 | 2818 | ||
1826 | static void dsi_vc_flush_long_data(int channel) | 2819 | static void dsi_vc_flush_long_data(struct platform_device *dsidev, int channel) |
1827 | { | 2820 | { |
1828 | while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { | 2821 | while (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) { |
1829 | u32 val; | 2822 | u32 val; |
1830 | val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); | 2823 | val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel)); |
1831 | DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n", | 2824 | DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n", |
1832 | (val >> 0) & 0xff, | 2825 | (val >> 0) & 0xff, |
1833 | (val >> 8) & 0xff, | 2826 | (val >> 8) & 0xff, |
@@ -1873,13 +2866,14 @@ static void dsi_show_rx_ack_with_err(u16 err) | |||
1873 | DSSERR("\t\tDSI Protocol Violation\n"); | 2866 | DSSERR("\t\tDSI Protocol Violation\n"); |
1874 | } | 2867 | } |
1875 | 2868 | ||
1876 | static u16 dsi_vc_flush_receive_data(int channel) | 2869 | static u16 dsi_vc_flush_receive_data(struct platform_device *dsidev, |
2870 | int channel) | ||
1877 | { | 2871 | { |
1878 | /* RX_FIFO_NOT_EMPTY */ | 2872 | /* RX_FIFO_NOT_EMPTY */ |
1879 | while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { | 2873 | while (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) { |
1880 | u32 val; | 2874 | u32 val; |
1881 | u8 dt; | 2875 | u8 dt; |
1882 | val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); | 2876 | val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel)); |
1883 | DSSERR("\trawval %#08x\n", val); | 2877 | DSSERR("\trawval %#08x\n", val); |
1884 | dt = FLD_GET(val, 5, 0); | 2878 | dt = FLD_GET(val, 5, 0); |
1885 | if (dt == DSI_DT_RX_ACK_WITH_ERR) { | 2879 | if (dt == DSI_DT_RX_ACK_WITH_ERR) { |
@@ -1894,7 +2888,7 @@ static u16 dsi_vc_flush_receive_data(int channel) | |||
1894 | } else if (dt == DSI_DT_RX_DCS_LONG_READ) { | 2888 | } else if (dt == DSI_DT_RX_DCS_LONG_READ) { |
1895 | DSSERR("\tDCS long response, len %d\n", | 2889 | DSSERR("\tDCS long response, len %d\n", |
1896 | FLD_GET(val, 23, 8)); | 2890 | FLD_GET(val, 23, 8)); |
1897 | dsi_vc_flush_long_data(channel); | 2891 | dsi_vc_flush_long_data(dsidev, channel); |
1898 | } else { | 2892 | } else { |
1899 | DSSERR("\tunknown datatype 0x%02x\n", dt); | 2893 | DSSERR("\tunknown datatype 0x%02x\n", dt); |
1900 | } | 2894 | } |
@@ -1902,74 +2896,90 @@ static u16 dsi_vc_flush_receive_data(int channel) | |||
1902 | return 0; | 2896 | return 0; |
1903 | } | 2897 | } |
1904 | 2898 | ||
1905 | static int dsi_vc_send_bta(int channel) | 2899 | static int dsi_vc_send_bta(struct platform_device *dsidev, int channel) |
1906 | { | 2900 | { |
1907 | if (dsi.debug_write || dsi.debug_read) | 2901 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
2902 | |||
2903 | if (dsi->debug_write || dsi->debug_read) | ||
1908 | DSSDBG("dsi_vc_send_bta %d\n", channel); | 2904 | DSSDBG("dsi_vc_send_bta %d\n", channel); |
1909 | 2905 | ||
1910 | WARN_ON(!dsi_bus_is_locked()); | 2906 | WARN_ON(!dsi_bus_is_locked(dsidev)); |
1911 | 2907 | ||
1912 | if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */ | 2908 | /* RX_FIFO_NOT_EMPTY */ |
2909 | if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) { | ||
1913 | DSSERR("rx fifo not empty when sending BTA, dumping data:\n"); | 2910 | DSSERR("rx fifo not empty when sending BTA, dumping data:\n"); |
1914 | dsi_vc_flush_receive_data(channel); | 2911 | dsi_vc_flush_receive_data(dsidev, channel); |
1915 | } | 2912 | } |
1916 | 2913 | ||
1917 | REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */ | 2914 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */ |
1918 | 2915 | ||
1919 | return 0; | 2916 | return 0; |
1920 | } | 2917 | } |
1921 | 2918 | ||
1922 | int dsi_vc_send_bta_sync(int channel) | 2919 | int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel) |
1923 | { | 2920 | { |
2921 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2922 | DECLARE_COMPLETION_ONSTACK(completion); | ||
1924 | int r = 0; | 2923 | int r = 0; |
1925 | u32 err; | 2924 | u32 err; |
1926 | 2925 | ||
1927 | INIT_COMPLETION(dsi.bta_completion); | 2926 | r = dsi_register_isr_vc(dsidev, channel, dsi_completion_handler, |
2927 | &completion, DSI_VC_IRQ_BTA); | ||
2928 | if (r) | ||
2929 | goto err0; | ||
1928 | 2930 | ||
1929 | dsi_vc_enable_bta_irq(channel); | 2931 | r = dsi_register_isr(dsidev, dsi_completion_handler, &completion, |
2932 | DSI_IRQ_ERROR_MASK); | ||
2933 | if (r) | ||
2934 | goto err1; | ||
1930 | 2935 | ||
1931 | r = dsi_vc_send_bta(channel); | 2936 | r = dsi_vc_send_bta(dsidev, channel); |
1932 | if (r) | 2937 | if (r) |
1933 | goto err; | 2938 | goto err2; |
1934 | 2939 | ||
1935 | if (wait_for_completion_timeout(&dsi.bta_completion, | 2940 | if (wait_for_completion_timeout(&completion, |
1936 | msecs_to_jiffies(500)) == 0) { | 2941 | msecs_to_jiffies(500)) == 0) { |
1937 | DSSERR("Failed to receive BTA\n"); | 2942 | DSSERR("Failed to receive BTA\n"); |
1938 | r = -EIO; | 2943 | r = -EIO; |
1939 | goto err; | 2944 | goto err2; |
1940 | } | 2945 | } |
1941 | 2946 | ||
1942 | err = dsi_get_errors(); | 2947 | err = dsi_get_errors(dsidev); |
1943 | if (err) { | 2948 | if (err) { |
1944 | DSSERR("Error while sending BTA: %x\n", err); | 2949 | DSSERR("Error while sending BTA: %x\n", err); |
1945 | r = -EIO; | 2950 | r = -EIO; |
1946 | goto err; | 2951 | goto err2; |
1947 | } | 2952 | } |
1948 | err: | 2953 | err2: |
1949 | dsi_vc_disable_bta_irq(channel); | 2954 | dsi_unregister_isr(dsidev, dsi_completion_handler, &completion, |
1950 | 2955 | DSI_IRQ_ERROR_MASK); | |
2956 | err1: | ||
2957 | dsi_unregister_isr_vc(dsidev, channel, dsi_completion_handler, | ||
2958 | &completion, DSI_VC_IRQ_BTA); | ||
2959 | err0: | ||
1951 | return r; | 2960 | return r; |
1952 | } | 2961 | } |
1953 | EXPORT_SYMBOL(dsi_vc_send_bta_sync); | 2962 | EXPORT_SYMBOL(dsi_vc_send_bta_sync); |
1954 | 2963 | ||
1955 | static inline void dsi_vc_write_long_header(int channel, u8 data_type, | 2964 | static inline void dsi_vc_write_long_header(struct platform_device *dsidev, |
1956 | u16 len, u8 ecc) | 2965 | int channel, u8 data_type, u16 len, u8 ecc) |
1957 | { | 2966 | { |
2967 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1958 | u32 val; | 2968 | u32 val; |
1959 | u8 data_id; | 2969 | u8 data_id; |
1960 | 2970 | ||
1961 | WARN_ON(!dsi_bus_is_locked()); | 2971 | WARN_ON(!dsi_bus_is_locked(dsidev)); |
1962 | 2972 | ||
1963 | data_id = data_type | channel << 6; | 2973 | data_id = data_type | dsi->vc[channel].vc_id << 6; |
1964 | 2974 | ||
1965 | val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) | | 2975 | val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) | |
1966 | FLD_VAL(ecc, 31, 24); | 2976 | FLD_VAL(ecc, 31, 24); |
1967 | 2977 | ||
1968 | dsi_write_reg(DSI_VC_LONG_PACKET_HEADER(channel), val); | 2978 | dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_HEADER(channel), val); |
1969 | } | 2979 | } |
1970 | 2980 | ||
1971 | static inline void dsi_vc_write_long_payload(int channel, | 2981 | static inline void dsi_vc_write_long_payload(struct platform_device *dsidev, |
1972 | u8 b1, u8 b2, u8 b3, u8 b4) | 2982 | int channel, u8 b1, u8 b2, u8 b3, u8 b4) |
1973 | { | 2983 | { |
1974 | u32 val; | 2984 | u32 val; |
1975 | 2985 | ||
@@ -1978,34 +2988,35 @@ static inline void dsi_vc_write_long_payload(int channel, | |||
1978 | /* DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n", | 2988 | /* DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n", |
1979 | b1, b2, b3, b4, val); */ | 2989 | b1, b2, b3, b4, val); */ |
1980 | 2990 | ||
1981 | dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(channel), val); | 2991 | dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_PAYLOAD(channel), val); |
1982 | } | 2992 | } |
1983 | 2993 | ||
1984 | static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len, | 2994 | static int dsi_vc_send_long(struct platform_device *dsidev, int channel, |
1985 | u8 ecc) | 2995 | u8 data_type, u8 *data, u16 len, u8 ecc) |
1986 | { | 2996 | { |
1987 | /*u32 val; */ | 2997 | /*u32 val; */ |
2998 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1988 | int i; | 2999 | int i; |
1989 | u8 *p; | 3000 | u8 *p; |
1990 | int r = 0; | 3001 | int r = 0; |
1991 | u8 b1, b2, b3, b4; | 3002 | u8 b1, b2, b3, b4; |
1992 | 3003 | ||
1993 | if (dsi.debug_write) | 3004 | if (dsi->debug_write) |
1994 | DSSDBG("dsi_vc_send_long, %d bytes\n", len); | 3005 | DSSDBG("dsi_vc_send_long, %d bytes\n", len); |
1995 | 3006 | ||
1996 | /* len + header */ | 3007 | /* len + header */ |
1997 | if (dsi.vc[channel].fifo_size * 32 * 4 < len + 4) { | 3008 | if (dsi->vc[channel].fifo_size * 32 * 4 < len + 4) { |
1998 | DSSERR("unable to send long packet: packet too long.\n"); | 3009 | DSSERR("unable to send long packet: packet too long.\n"); |
1999 | return -EINVAL; | 3010 | return -EINVAL; |
2000 | } | 3011 | } |
2001 | 3012 | ||
2002 | dsi_vc_config_l4(channel); | 3013 | dsi_vc_config_l4(dsidev, channel); |
2003 | 3014 | ||
2004 | dsi_vc_write_long_header(channel, data_type, len, ecc); | 3015 | dsi_vc_write_long_header(dsidev, channel, data_type, len, ecc); |
2005 | 3016 | ||
2006 | p = data; | 3017 | p = data; |
2007 | for (i = 0; i < len >> 2; i++) { | 3018 | for (i = 0; i < len >> 2; i++) { |
2008 | if (dsi.debug_write) | 3019 | if (dsi->debug_write) |
2009 | DSSDBG("\tsending full packet %d\n", i); | 3020 | DSSDBG("\tsending full packet %d\n", i); |
2010 | 3021 | ||
2011 | b1 = *p++; | 3022 | b1 = *p++; |
@@ -2013,14 +3024,14 @@ static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len, | |||
2013 | b3 = *p++; | 3024 | b3 = *p++; |
2014 | b4 = *p++; | 3025 | b4 = *p++; |
2015 | 3026 | ||
2016 | dsi_vc_write_long_payload(channel, b1, b2, b3, b4); | 3027 | dsi_vc_write_long_payload(dsidev, channel, b1, b2, b3, b4); |
2017 | } | 3028 | } |
2018 | 3029 | ||
2019 | i = len % 4; | 3030 | i = len % 4; |
2020 | if (i) { | 3031 | if (i) { |
2021 | b1 = 0; b2 = 0; b3 = 0; | 3032 | b1 = 0; b2 = 0; b3 = 0; |
2022 | 3033 | ||
2023 | if (dsi.debug_write) | 3034 | if (dsi->debug_write) |
2024 | DSSDBG("\tsending remainder bytes %d\n", i); | 3035 | DSSDBG("\tsending remainder bytes %d\n", i); |
2025 | 3036 | ||
2026 | switch (i) { | 3037 | switch (i) { |
@@ -2038,62 +3049,69 @@ static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len, | |||
2038 | break; | 3049 | break; |
2039 | } | 3050 | } |
2040 | 3051 | ||
2041 | dsi_vc_write_long_payload(channel, b1, b2, b3, 0); | 3052 | dsi_vc_write_long_payload(dsidev, channel, b1, b2, b3, 0); |
2042 | } | 3053 | } |
2043 | 3054 | ||
2044 | return r; | 3055 | return r; |
2045 | } | 3056 | } |
2046 | 3057 | ||
2047 | static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc) | 3058 | static int dsi_vc_send_short(struct platform_device *dsidev, int channel, |
3059 | u8 data_type, u16 data, u8 ecc) | ||
2048 | { | 3060 | { |
3061 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2049 | u32 r; | 3062 | u32 r; |
2050 | u8 data_id; | 3063 | u8 data_id; |
2051 | 3064 | ||
2052 | WARN_ON(!dsi_bus_is_locked()); | 3065 | WARN_ON(!dsi_bus_is_locked(dsidev)); |
2053 | 3066 | ||
2054 | if (dsi.debug_write) | 3067 | if (dsi->debug_write) |
2055 | DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n", | 3068 | DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n", |
2056 | channel, | 3069 | channel, |
2057 | data_type, data & 0xff, (data >> 8) & 0xff); | 3070 | data_type, data & 0xff, (data >> 8) & 0xff); |
2058 | 3071 | ||
2059 | dsi_vc_config_l4(channel); | 3072 | dsi_vc_config_l4(dsidev, channel); |
2060 | 3073 | ||
2061 | if (FLD_GET(dsi_read_reg(DSI_VC_CTRL(channel)), 16, 16)) { | 3074 | if (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(channel)), 16, 16)) { |
2062 | DSSERR("ERROR FIFO FULL, aborting transfer\n"); | 3075 | DSSERR("ERROR FIFO FULL, aborting transfer\n"); |
2063 | return -EINVAL; | 3076 | return -EINVAL; |
2064 | } | 3077 | } |
2065 | 3078 | ||
2066 | data_id = data_type | channel << 6; | 3079 | data_id = data_type | dsi->vc[channel].vc_id << 6; |
2067 | 3080 | ||
2068 | r = (data_id << 0) | (data << 8) | (ecc << 24); | 3081 | r = (data_id << 0) | (data << 8) | (ecc << 24); |
2069 | 3082 | ||
2070 | dsi_write_reg(DSI_VC_SHORT_PACKET_HEADER(channel), r); | 3083 | dsi_write_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel), r); |
2071 | 3084 | ||
2072 | return 0; | 3085 | return 0; |
2073 | } | 3086 | } |
2074 | 3087 | ||
2075 | int dsi_vc_send_null(int channel) | 3088 | int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel) |
2076 | { | 3089 | { |
3090 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2077 | u8 nullpkg[] = {0, 0, 0, 0}; | 3091 | u8 nullpkg[] = {0, 0, 0, 0}; |
2078 | return dsi_vc_send_long(channel, DSI_DT_NULL_PACKET, nullpkg, 4, 0); | 3092 | |
3093 | return dsi_vc_send_long(dsidev, channel, DSI_DT_NULL_PACKET, nullpkg, | ||
3094 | 4, 0); | ||
2079 | } | 3095 | } |
2080 | EXPORT_SYMBOL(dsi_vc_send_null); | 3096 | EXPORT_SYMBOL(dsi_vc_send_null); |
2081 | 3097 | ||
2082 | int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len) | 3098 | int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel, |
3099 | u8 *data, int len) | ||
2083 | { | 3100 | { |
3101 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2084 | int r; | 3102 | int r; |
2085 | 3103 | ||
2086 | BUG_ON(len == 0); | 3104 | BUG_ON(len == 0); |
2087 | 3105 | ||
2088 | if (len == 1) { | 3106 | if (len == 1) { |
2089 | r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_0, | 3107 | r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_0, |
2090 | data[0], 0); | 3108 | data[0], 0); |
2091 | } else if (len == 2) { | 3109 | } else if (len == 2) { |
2092 | r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_1, | 3110 | r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_1, |
2093 | data[0] | (data[1] << 8), 0); | 3111 | data[0] | (data[1] << 8), 0); |
2094 | } else { | 3112 | } else { |
2095 | /* 0x39 = DCS Long Write */ | 3113 | /* 0x39 = DCS Long Write */ |
2096 | r = dsi_vc_send_long(channel, DSI_DT_DCS_LONG_WRITE, | 3114 | r = dsi_vc_send_long(dsidev, channel, DSI_DT_DCS_LONG_WRITE, |
2097 | data, len, 0); | 3115 | data, len, 0); |
2098 | } | 3116 | } |
2099 | 3117 | ||
@@ -2101,21 +3119,24 @@ int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len) | |||
2101 | } | 3119 | } |
2102 | EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); | 3120 | EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); |
2103 | 3121 | ||
2104 | int dsi_vc_dcs_write(int channel, u8 *data, int len) | 3122 | int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data, |
3123 | int len) | ||
2105 | { | 3124 | { |
3125 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2106 | int r; | 3126 | int r; |
2107 | 3127 | ||
2108 | r = dsi_vc_dcs_write_nosync(channel, data, len); | 3128 | r = dsi_vc_dcs_write_nosync(dssdev, channel, data, len); |
2109 | if (r) | 3129 | if (r) |
2110 | goto err; | 3130 | goto err; |
2111 | 3131 | ||
2112 | r = dsi_vc_send_bta_sync(channel); | 3132 | r = dsi_vc_send_bta_sync(dssdev, channel); |
2113 | if (r) | 3133 | if (r) |
2114 | goto err; | 3134 | goto err; |
2115 | 3135 | ||
2116 | if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */ | 3136 | /* RX_FIFO_NOT_EMPTY */ |
3137 | if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) { | ||
2117 | DSSERR("rx fifo not empty after write, dumping data:\n"); | 3138 | DSSERR("rx fifo not empty after write, dumping data:\n"); |
2118 | dsi_vc_flush_receive_data(channel); | 3139 | dsi_vc_flush_receive_data(dsidev, channel); |
2119 | r = -EIO; | 3140 | r = -EIO; |
2120 | goto err; | 3141 | goto err; |
2121 | } | 3142 | } |
@@ -2128,47 +3149,51 @@ err: | |||
2128 | } | 3149 | } |
2129 | EXPORT_SYMBOL(dsi_vc_dcs_write); | 3150 | EXPORT_SYMBOL(dsi_vc_dcs_write); |
2130 | 3151 | ||
2131 | int dsi_vc_dcs_write_0(int channel, u8 dcs_cmd) | 3152 | int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd) |
2132 | { | 3153 | { |
2133 | return dsi_vc_dcs_write(channel, &dcs_cmd, 1); | 3154 | return dsi_vc_dcs_write(dssdev, channel, &dcs_cmd, 1); |
2134 | } | 3155 | } |
2135 | EXPORT_SYMBOL(dsi_vc_dcs_write_0); | 3156 | EXPORT_SYMBOL(dsi_vc_dcs_write_0); |
2136 | 3157 | ||
2137 | int dsi_vc_dcs_write_1(int channel, u8 dcs_cmd, u8 param) | 3158 | int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, |
3159 | u8 param) | ||
2138 | { | 3160 | { |
2139 | u8 buf[2]; | 3161 | u8 buf[2]; |
2140 | buf[0] = dcs_cmd; | 3162 | buf[0] = dcs_cmd; |
2141 | buf[1] = param; | 3163 | buf[1] = param; |
2142 | return dsi_vc_dcs_write(channel, buf, 2); | 3164 | return dsi_vc_dcs_write(dssdev, channel, buf, 2); |
2143 | } | 3165 | } |
2144 | EXPORT_SYMBOL(dsi_vc_dcs_write_1); | 3166 | EXPORT_SYMBOL(dsi_vc_dcs_write_1); |
2145 | 3167 | ||
2146 | int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen) | 3168 | int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, |
3169 | u8 *buf, int buflen) | ||
2147 | { | 3170 | { |
3171 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
3172 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2148 | u32 val; | 3173 | u32 val; |
2149 | u8 dt; | 3174 | u8 dt; |
2150 | int r; | 3175 | int r; |
2151 | 3176 | ||
2152 | if (dsi.debug_read) | 3177 | if (dsi->debug_read) |
2153 | DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %x)\n", channel, dcs_cmd); | 3178 | DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %x)\n", channel, dcs_cmd); |
2154 | 3179 | ||
2155 | r = dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0); | 3180 | r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_READ, dcs_cmd, 0); |
2156 | if (r) | 3181 | if (r) |
2157 | goto err; | 3182 | goto err; |
2158 | 3183 | ||
2159 | r = dsi_vc_send_bta_sync(channel); | 3184 | r = dsi_vc_send_bta_sync(dssdev, channel); |
2160 | if (r) | 3185 | if (r) |
2161 | goto err; | 3186 | goto err; |
2162 | 3187 | ||
2163 | /* RX_FIFO_NOT_EMPTY */ | 3188 | /* RX_FIFO_NOT_EMPTY */ |
2164 | if (REG_GET(DSI_VC_CTRL(channel), 20, 20) == 0) { | 3189 | if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20) == 0) { |
2165 | DSSERR("RX fifo empty when trying to read.\n"); | 3190 | DSSERR("RX fifo empty when trying to read.\n"); |
2166 | r = -EIO; | 3191 | r = -EIO; |
2167 | goto err; | 3192 | goto err; |
2168 | } | 3193 | } |
2169 | 3194 | ||
2170 | val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); | 3195 | val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel)); |
2171 | if (dsi.debug_read) | 3196 | if (dsi->debug_read) |
2172 | DSSDBG("\theader: %08x\n", val); | 3197 | DSSDBG("\theader: %08x\n", val); |
2173 | dt = FLD_GET(val, 5, 0); | 3198 | dt = FLD_GET(val, 5, 0); |
2174 | if (dt == DSI_DT_RX_ACK_WITH_ERR) { | 3199 | if (dt == DSI_DT_RX_ACK_WITH_ERR) { |
@@ -2179,7 +3204,7 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen) | |||
2179 | 3204 | ||
2180 | } else if (dt == DSI_DT_RX_SHORT_READ_1) { | 3205 | } else if (dt == DSI_DT_RX_SHORT_READ_1) { |
2181 | u8 data = FLD_GET(val, 15, 8); | 3206 | u8 data = FLD_GET(val, 15, 8); |
2182 | if (dsi.debug_read) | 3207 | if (dsi->debug_read) |
2183 | DSSDBG("\tDCS short response, 1 byte: %02x\n", data); | 3208 | DSSDBG("\tDCS short response, 1 byte: %02x\n", data); |
2184 | 3209 | ||
2185 | if (buflen < 1) { | 3210 | if (buflen < 1) { |
@@ -2192,7 +3217,7 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen) | |||
2192 | return 1; | 3217 | return 1; |
2193 | } else if (dt == DSI_DT_RX_SHORT_READ_2) { | 3218 | } else if (dt == DSI_DT_RX_SHORT_READ_2) { |
2194 | u16 data = FLD_GET(val, 23, 8); | 3219 | u16 data = FLD_GET(val, 23, 8); |
2195 | if (dsi.debug_read) | 3220 | if (dsi->debug_read) |
2196 | DSSDBG("\tDCS short response, 2 byte: %04x\n", data); | 3221 | DSSDBG("\tDCS short response, 2 byte: %04x\n", data); |
2197 | 3222 | ||
2198 | if (buflen < 2) { | 3223 | if (buflen < 2) { |
@@ -2207,7 +3232,7 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen) | |||
2207 | } else if (dt == DSI_DT_RX_DCS_LONG_READ) { | 3232 | } else if (dt == DSI_DT_RX_DCS_LONG_READ) { |
2208 | int w; | 3233 | int w; |
2209 | int len = FLD_GET(val, 23, 8); | 3234 | int len = FLD_GET(val, 23, 8); |
2210 | if (dsi.debug_read) | 3235 | if (dsi->debug_read) |
2211 | DSSDBG("\tDCS long response, len %d\n", len); | 3236 | DSSDBG("\tDCS long response, len %d\n", len); |
2212 | 3237 | ||
2213 | if (len > buflen) { | 3238 | if (len > buflen) { |
@@ -2218,8 +3243,9 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen) | |||
2218 | /* two byte checksum ends the packet, not included in len */ | 3243 | /* two byte checksum ends the packet, not included in len */ |
2219 | for (w = 0; w < len + 2;) { | 3244 | for (w = 0; w < len + 2;) { |
2220 | int b; | 3245 | int b; |
2221 | val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); | 3246 | val = dsi_read_reg(dsidev, |
2222 | if (dsi.debug_read) | 3247 | DSI_VC_SHORT_PACKET_HEADER(channel)); |
3248 | if (dsi->debug_read) | ||
2223 | DSSDBG("\t\t%02x %02x %02x %02x\n", | 3249 | DSSDBG("\t\t%02x %02x %02x %02x\n", |
2224 | (val >> 0) & 0xff, | 3250 | (val >> 0) & 0xff, |
2225 | (val >> 8) & 0xff, | 3251 | (val >> 8) & 0xff, |
@@ -2250,11 +3276,12 @@ err: | |||
2250 | } | 3276 | } |
2251 | EXPORT_SYMBOL(dsi_vc_dcs_read); | 3277 | EXPORT_SYMBOL(dsi_vc_dcs_read); |
2252 | 3278 | ||
2253 | int dsi_vc_dcs_read_1(int channel, u8 dcs_cmd, u8 *data) | 3279 | int dsi_vc_dcs_read_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, |
3280 | u8 *data) | ||
2254 | { | 3281 | { |
2255 | int r; | 3282 | int r; |
2256 | 3283 | ||
2257 | r = dsi_vc_dcs_read(channel, dcs_cmd, data, 1); | 3284 | r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, data, 1); |
2258 | 3285 | ||
2259 | if (r < 0) | 3286 | if (r < 0) |
2260 | return r; | 3287 | return r; |
@@ -2266,12 +3293,13 @@ int dsi_vc_dcs_read_1(int channel, u8 dcs_cmd, u8 *data) | |||
2266 | } | 3293 | } |
2267 | EXPORT_SYMBOL(dsi_vc_dcs_read_1); | 3294 | EXPORT_SYMBOL(dsi_vc_dcs_read_1); |
2268 | 3295 | ||
2269 | int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u8 *data1, u8 *data2) | 3296 | int dsi_vc_dcs_read_2(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, |
3297 | u8 *data1, u8 *data2) | ||
2270 | { | 3298 | { |
2271 | u8 buf[2]; | 3299 | u8 buf[2]; |
2272 | int r; | 3300 | int r; |
2273 | 3301 | ||
2274 | r = dsi_vc_dcs_read(channel, dcs_cmd, buf, 2); | 3302 | r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, buf, 2); |
2275 | 3303 | ||
2276 | if (r < 0) | 3304 | if (r < 0) |
2277 | return r; | 3305 | return r; |
@@ -2286,14 +3314,94 @@ int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u8 *data1, u8 *data2) | |||
2286 | } | 3314 | } |
2287 | EXPORT_SYMBOL(dsi_vc_dcs_read_2); | 3315 | EXPORT_SYMBOL(dsi_vc_dcs_read_2); |
2288 | 3316 | ||
2289 | int dsi_vc_set_max_rx_packet_size(int channel, u16 len) | 3317 | int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel, |
3318 | u16 len) | ||
2290 | { | 3319 | { |
2291 | return dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE, | 3320 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
3321 | |||
3322 | return dsi_vc_send_short(dsidev, channel, DSI_DT_SET_MAX_RET_PKG_SIZE, | ||
2292 | len, 0); | 3323 | len, 0); |
2293 | } | 3324 | } |
2294 | EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size); | 3325 | EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size); |
2295 | 3326 | ||
2296 | static void dsi_set_lp_rx_timeout(unsigned ticks, bool x4, bool x16) | 3327 | static int dsi_enter_ulps(struct platform_device *dsidev) |
3328 | { | ||
3329 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
3330 | DECLARE_COMPLETION_ONSTACK(completion); | ||
3331 | int r; | ||
3332 | |||
3333 | DSSDBGF(); | ||
3334 | |||
3335 | WARN_ON(!dsi_bus_is_locked(dsidev)); | ||
3336 | |||
3337 | WARN_ON(dsi->ulps_enabled); | ||
3338 | |||
3339 | if (dsi->ulps_enabled) | ||
3340 | return 0; | ||
3341 | |||
3342 | if (REG_GET(dsidev, DSI_CLK_CTRL, 13, 13)) { | ||
3343 | DSSERR("DDR_CLK_ALWAYS_ON enabled when entering ULPS\n"); | ||
3344 | return -EIO; | ||
3345 | } | ||
3346 | |||
3347 | dsi_sync_vc(dsidev, 0); | ||
3348 | dsi_sync_vc(dsidev, 1); | ||
3349 | dsi_sync_vc(dsidev, 2); | ||
3350 | dsi_sync_vc(dsidev, 3); | ||
3351 | |||
3352 | dsi_force_tx_stop_mode_io(dsidev); | ||
3353 | |||
3354 | dsi_vc_enable(dsidev, 0, false); | ||
3355 | dsi_vc_enable(dsidev, 1, false); | ||
3356 | dsi_vc_enable(dsidev, 2, false); | ||
3357 | dsi_vc_enable(dsidev, 3, false); | ||
3358 | |||
3359 | if (REG_GET(dsidev, DSI_COMPLEXIO_CFG2, 16, 16)) { /* HS_BUSY */ | ||
3360 | DSSERR("HS busy when enabling ULPS\n"); | ||
3361 | return -EIO; | ||
3362 | } | ||
3363 | |||
3364 | if (REG_GET(dsidev, DSI_COMPLEXIO_CFG2, 17, 17)) { /* LP_BUSY */ | ||
3365 | DSSERR("LP busy when enabling ULPS\n"); | ||
3366 | return -EIO; | ||
3367 | } | ||
3368 | |||
3369 | r = dsi_register_isr_cio(dsidev, dsi_completion_handler, &completion, | ||
3370 | DSI_CIO_IRQ_ULPSACTIVENOT_ALL0); | ||
3371 | if (r) | ||
3372 | return r; | ||
3373 | |||
3374 | /* Assert TxRequestEsc for data lanes and TxUlpsClk for clk lane */ | ||
3375 | /* LANEx_ULPS_SIG2 */ | ||
3376 | REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (1 << 0) | (1 << 1) | (1 << 2), | ||
3377 | 7, 5); | ||
3378 | |||
3379 | if (wait_for_completion_timeout(&completion, | ||
3380 | msecs_to_jiffies(1000)) == 0) { | ||
3381 | DSSERR("ULPS enable timeout\n"); | ||
3382 | r = -EIO; | ||
3383 | goto err; | ||
3384 | } | ||
3385 | |||
3386 | dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion, | ||
3387 | DSI_CIO_IRQ_ULPSACTIVENOT_ALL0); | ||
3388 | |||
3389 | dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS); | ||
3390 | |||
3391 | dsi_if_enable(dsidev, false); | ||
3392 | |||
3393 | dsi->ulps_enabled = true; | ||
3394 | |||
3395 | return 0; | ||
3396 | |||
3397 | err: | ||
3398 | dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion, | ||
3399 | DSI_CIO_IRQ_ULPSACTIVENOT_ALL0); | ||
3400 | return r; | ||
3401 | } | ||
3402 | |||
3403 | static void dsi_set_lp_rx_timeout(struct platform_device *dsidev, | ||
3404 | unsigned ticks, bool x4, bool x16) | ||
2297 | { | 3405 | { |
2298 | unsigned long fck; | 3406 | unsigned long fck; |
2299 | unsigned long total_ticks; | 3407 | unsigned long total_ticks; |
@@ -2302,14 +3410,14 @@ static void dsi_set_lp_rx_timeout(unsigned ticks, bool x4, bool x16) | |||
2302 | BUG_ON(ticks > 0x1fff); | 3410 | BUG_ON(ticks > 0x1fff); |
2303 | 3411 | ||
2304 | /* ticks in DSI_FCK */ | 3412 | /* ticks in DSI_FCK */ |
2305 | fck = dsi_fclk_rate(); | 3413 | fck = dsi_fclk_rate(dsidev); |
2306 | 3414 | ||
2307 | r = dsi_read_reg(DSI_TIMING2); | 3415 | r = dsi_read_reg(dsidev, DSI_TIMING2); |
2308 | r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */ | 3416 | r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */ |
2309 | r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* LP_RX_TO_X16 */ | 3417 | r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* LP_RX_TO_X16 */ |
2310 | r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* LP_RX_TO_X4 */ | 3418 | r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* LP_RX_TO_X4 */ |
2311 | r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */ | 3419 | r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */ |
2312 | dsi_write_reg(DSI_TIMING2, r); | 3420 | dsi_write_reg(dsidev, DSI_TIMING2, r); |
2313 | 3421 | ||
2314 | total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1); | 3422 | total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1); |
2315 | 3423 | ||
@@ -2319,7 +3427,8 @@ static void dsi_set_lp_rx_timeout(unsigned ticks, bool x4, bool x16) | |||
2319 | (total_ticks * 1000) / (fck / 1000 / 1000)); | 3427 | (total_ticks * 1000) / (fck / 1000 / 1000)); |
2320 | } | 3428 | } |
2321 | 3429 | ||
2322 | static void dsi_set_ta_timeout(unsigned ticks, bool x8, bool x16) | 3430 | static void dsi_set_ta_timeout(struct platform_device *dsidev, unsigned ticks, |
3431 | bool x8, bool x16) | ||
2323 | { | 3432 | { |
2324 | unsigned long fck; | 3433 | unsigned long fck; |
2325 | unsigned long total_ticks; | 3434 | unsigned long total_ticks; |
@@ -2328,14 +3437,14 @@ static void dsi_set_ta_timeout(unsigned ticks, bool x8, bool x16) | |||
2328 | BUG_ON(ticks > 0x1fff); | 3437 | BUG_ON(ticks > 0x1fff); |
2329 | 3438 | ||
2330 | /* ticks in DSI_FCK */ | 3439 | /* ticks in DSI_FCK */ |
2331 | fck = dsi_fclk_rate(); | 3440 | fck = dsi_fclk_rate(dsidev); |
2332 | 3441 | ||
2333 | r = dsi_read_reg(DSI_TIMING1); | 3442 | r = dsi_read_reg(dsidev, DSI_TIMING1); |
2334 | r = FLD_MOD(r, 1, 31, 31); /* TA_TO */ | 3443 | r = FLD_MOD(r, 1, 31, 31); /* TA_TO */ |
2335 | r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* TA_TO_X16 */ | 3444 | r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* TA_TO_X16 */ |
2336 | r = FLD_MOD(r, x8 ? 1 : 0, 29, 29); /* TA_TO_X8 */ | 3445 | r = FLD_MOD(r, x8 ? 1 : 0, 29, 29); /* TA_TO_X8 */ |
2337 | r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */ | 3446 | r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */ |
2338 | dsi_write_reg(DSI_TIMING1, r); | 3447 | dsi_write_reg(dsidev, DSI_TIMING1, r); |
2339 | 3448 | ||
2340 | total_ticks = ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1); | 3449 | total_ticks = ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1); |
2341 | 3450 | ||
@@ -2345,7 +3454,8 @@ static void dsi_set_ta_timeout(unsigned ticks, bool x8, bool x16) | |||
2345 | (total_ticks * 1000) / (fck / 1000 / 1000)); | 3454 | (total_ticks * 1000) / (fck / 1000 / 1000)); |
2346 | } | 3455 | } |
2347 | 3456 | ||
2348 | static void dsi_set_stop_state_counter(unsigned ticks, bool x4, bool x16) | 3457 | static void dsi_set_stop_state_counter(struct platform_device *dsidev, |
3458 | unsigned ticks, bool x4, bool x16) | ||
2349 | { | 3459 | { |
2350 | unsigned long fck; | 3460 | unsigned long fck; |
2351 | unsigned long total_ticks; | 3461 | unsigned long total_ticks; |
@@ -2354,14 +3464,14 @@ static void dsi_set_stop_state_counter(unsigned ticks, bool x4, bool x16) | |||
2354 | BUG_ON(ticks > 0x1fff); | 3464 | BUG_ON(ticks > 0x1fff); |
2355 | 3465 | ||
2356 | /* ticks in DSI_FCK */ | 3466 | /* ticks in DSI_FCK */ |
2357 | fck = dsi_fclk_rate(); | 3467 | fck = dsi_fclk_rate(dsidev); |
2358 | 3468 | ||
2359 | r = dsi_read_reg(DSI_TIMING1); | 3469 | r = dsi_read_reg(dsidev, DSI_TIMING1); |
2360 | r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ | 3470 | r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ |
2361 | r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* STOP_STATE_X16_IO */ | 3471 | r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* STOP_STATE_X16_IO */ |
2362 | r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* STOP_STATE_X4_IO */ | 3472 | r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* STOP_STATE_X4_IO */ |
2363 | r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */ | 3473 | r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */ |
2364 | dsi_write_reg(DSI_TIMING1, r); | 3474 | dsi_write_reg(dsidev, DSI_TIMING1, r); |
2365 | 3475 | ||
2366 | total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1); | 3476 | total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1); |
2367 | 3477 | ||
@@ -2371,7 +3481,8 @@ static void dsi_set_stop_state_counter(unsigned ticks, bool x4, bool x16) | |||
2371 | (total_ticks * 1000) / (fck / 1000 / 1000)); | 3481 | (total_ticks * 1000) / (fck / 1000 / 1000)); |
2372 | } | 3482 | } |
2373 | 3483 | ||
2374 | static void dsi_set_hs_tx_timeout(unsigned ticks, bool x4, bool x16) | 3484 | static void dsi_set_hs_tx_timeout(struct platform_device *dsidev, |
3485 | unsigned ticks, bool x4, bool x16) | ||
2375 | { | 3486 | { |
2376 | unsigned long fck; | 3487 | unsigned long fck; |
2377 | unsigned long total_ticks; | 3488 | unsigned long total_ticks; |
@@ -2380,14 +3491,14 @@ static void dsi_set_hs_tx_timeout(unsigned ticks, bool x4, bool x16) | |||
2380 | BUG_ON(ticks > 0x1fff); | 3491 | BUG_ON(ticks > 0x1fff); |
2381 | 3492 | ||
2382 | /* ticks in TxByteClkHS */ | 3493 | /* ticks in TxByteClkHS */ |
2383 | fck = dsi_get_txbyteclkhs(); | 3494 | fck = dsi_get_txbyteclkhs(dsidev); |
2384 | 3495 | ||
2385 | r = dsi_read_reg(DSI_TIMING2); | 3496 | r = dsi_read_reg(dsidev, DSI_TIMING2); |
2386 | r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */ | 3497 | r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */ |
2387 | r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* HS_TX_TO_X16 */ | 3498 | r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* HS_TX_TO_X16 */ |
2388 | r = FLD_MOD(r, x4 ? 1 : 0, 29, 29); /* HS_TX_TO_X8 (4 really) */ | 3499 | r = FLD_MOD(r, x4 ? 1 : 0, 29, 29); /* HS_TX_TO_X8 (4 really) */ |
2389 | r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */ | 3500 | r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */ |
2390 | dsi_write_reg(DSI_TIMING2, r); | 3501 | dsi_write_reg(dsidev, DSI_TIMING2, r); |
2391 | 3502 | ||
2392 | total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1); | 3503 | total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1); |
2393 | 3504 | ||
@@ -2398,24 +3509,25 @@ static void dsi_set_hs_tx_timeout(unsigned ticks, bool x4, bool x16) | |||
2398 | } | 3509 | } |
2399 | static int dsi_proto_config(struct omap_dss_device *dssdev) | 3510 | static int dsi_proto_config(struct omap_dss_device *dssdev) |
2400 | { | 3511 | { |
3512 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2401 | u32 r; | 3513 | u32 r; |
2402 | int buswidth = 0; | 3514 | int buswidth = 0; |
2403 | 3515 | ||
2404 | dsi_config_tx_fifo(DSI_FIFO_SIZE_32, | 3516 | dsi_config_tx_fifo(dsidev, DSI_FIFO_SIZE_32, |
2405 | DSI_FIFO_SIZE_32, | 3517 | DSI_FIFO_SIZE_32, |
2406 | DSI_FIFO_SIZE_32, | 3518 | DSI_FIFO_SIZE_32, |
2407 | DSI_FIFO_SIZE_32); | 3519 | DSI_FIFO_SIZE_32); |
2408 | 3520 | ||
2409 | dsi_config_rx_fifo(DSI_FIFO_SIZE_32, | 3521 | dsi_config_rx_fifo(dsidev, DSI_FIFO_SIZE_32, |
2410 | DSI_FIFO_SIZE_32, | 3522 | DSI_FIFO_SIZE_32, |
2411 | DSI_FIFO_SIZE_32, | 3523 | DSI_FIFO_SIZE_32, |
2412 | DSI_FIFO_SIZE_32); | 3524 | DSI_FIFO_SIZE_32); |
2413 | 3525 | ||
2414 | /* XXX what values for the timeouts? */ | 3526 | /* XXX what values for the timeouts? */ |
2415 | dsi_set_stop_state_counter(0x1000, false, false); | 3527 | dsi_set_stop_state_counter(dsidev, 0x1000, false, false); |
2416 | dsi_set_ta_timeout(0x1fff, true, true); | 3528 | dsi_set_ta_timeout(dsidev, 0x1fff, true, true); |
2417 | dsi_set_lp_rx_timeout(0x1fff, true, true); | 3529 | dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true); |
2418 | dsi_set_hs_tx_timeout(0x1fff, true, true); | 3530 | dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true); |
2419 | 3531 | ||
2420 | switch (dssdev->ctrl.pixel_size) { | 3532 | switch (dssdev->ctrl.pixel_size) { |
2421 | case 16: | 3533 | case 16: |
@@ -2431,7 +3543,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) | |||
2431 | BUG(); | 3543 | BUG(); |
2432 | } | 3544 | } |
2433 | 3545 | ||
2434 | r = dsi_read_reg(DSI_CTRL); | 3546 | r = dsi_read_reg(dsidev, DSI_CTRL); |
2435 | r = FLD_MOD(r, 1, 1, 1); /* CS_RX_EN */ | 3547 | r = FLD_MOD(r, 1, 1, 1); /* CS_RX_EN */ |
2436 | r = FLD_MOD(r, 1, 2, 2); /* ECC_RX_EN */ | 3548 | r = FLD_MOD(r, 1, 2, 2); /* ECC_RX_EN */ |
2437 | r = FLD_MOD(r, 1, 3, 3); /* TX_FIFO_ARBITRATION */ | 3549 | r = FLD_MOD(r, 1, 3, 3); /* TX_FIFO_ARBITRATION */ |
@@ -2441,21 +3553,25 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) | |||
2441 | r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */ | 3553 | r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */ |
2442 | r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */ | 3554 | r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */ |
2443 | r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */ | 3555 | r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */ |
2444 | r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */ | 3556 | if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) { |
2445 | r = FLD_MOD(r, 0, 25, 25); /* DCS_CMD_CODE, 1=start, 0=continue */ | 3557 | r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */ |
3558 | /* DCS_CMD_CODE, 1=start, 0=continue */ | ||
3559 | r = FLD_MOD(r, 0, 25, 25); | ||
3560 | } | ||
2446 | 3561 | ||
2447 | dsi_write_reg(DSI_CTRL, r); | 3562 | dsi_write_reg(dsidev, DSI_CTRL, r); |
2448 | 3563 | ||
2449 | dsi_vc_initial_config(0); | 3564 | dsi_vc_initial_config(dsidev, 0); |
2450 | dsi_vc_initial_config(1); | 3565 | dsi_vc_initial_config(dsidev, 1); |
2451 | dsi_vc_initial_config(2); | 3566 | dsi_vc_initial_config(dsidev, 2); |
2452 | dsi_vc_initial_config(3); | 3567 | dsi_vc_initial_config(dsidev, 3); |
2453 | 3568 | ||
2454 | return 0; | 3569 | return 0; |
2455 | } | 3570 | } |
2456 | 3571 | ||
2457 | static void dsi_proto_timings(struct omap_dss_device *dssdev) | 3572 | static void dsi_proto_timings(struct omap_dss_device *dssdev) |
2458 | { | 3573 | { |
3574 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2459 | unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail; | 3575 | unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail; |
2460 | unsigned tclk_pre, tclk_post; | 3576 | unsigned tclk_pre, tclk_post; |
2461 | unsigned ths_prepare, ths_prepare_ths_zero, ths_zero; | 3577 | unsigned ths_prepare, ths_prepare_ths_zero, ths_zero; |
@@ -2465,32 +3581,27 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) | |||
2465 | unsigned ths_eot; | 3581 | unsigned ths_eot; |
2466 | u32 r; | 3582 | u32 r; |
2467 | 3583 | ||
2468 | r = dsi_read_reg(DSI_DSIPHY_CFG0); | 3584 | r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0); |
2469 | ths_prepare = FLD_GET(r, 31, 24); | 3585 | ths_prepare = FLD_GET(r, 31, 24); |
2470 | ths_prepare_ths_zero = FLD_GET(r, 23, 16); | 3586 | ths_prepare_ths_zero = FLD_GET(r, 23, 16); |
2471 | ths_zero = ths_prepare_ths_zero - ths_prepare; | 3587 | ths_zero = ths_prepare_ths_zero - ths_prepare; |
2472 | ths_trail = FLD_GET(r, 15, 8); | 3588 | ths_trail = FLD_GET(r, 15, 8); |
2473 | ths_exit = FLD_GET(r, 7, 0); | 3589 | ths_exit = FLD_GET(r, 7, 0); |
2474 | 3590 | ||
2475 | r = dsi_read_reg(DSI_DSIPHY_CFG1); | 3591 | r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1); |
2476 | tlpx = FLD_GET(r, 22, 16) * 2; | 3592 | tlpx = FLD_GET(r, 22, 16) * 2; |
2477 | tclk_trail = FLD_GET(r, 15, 8); | 3593 | tclk_trail = FLD_GET(r, 15, 8); |
2478 | tclk_zero = FLD_GET(r, 7, 0); | 3594 | tclk_zero = FLD_GET(r, 7, 0); |
2479 | 3595 | ||
2480 | r = dsi_read_reg(DSI_DSIPHY_CFG2); | 3596 | r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2); |
2481 | tclk_prepare = FLD_GET(r, 7, 0); | 3597 | tclk_prepare = FLD_GET(r, 7, 0); |
2482 | 3598 | ||
2483 | /* min 8*UI */ | 3599 | /* min 8*UI */ |
2484 | tclk_pre = 20; | 3600 | tclk_pre = 20; |
2485 | /* min 60ns + 52*UI */ | 3601 | /* min 60ns + 52*UI */ |
2486 | tclk_post = ns2ddr(60) + 26; | 3602 | tclk_post = ns2ddr(dsidev, 60) + 26; |
2487 | 3603 | ||
2488 | /* ths_eot is 2 for 2 datalanes and 4 for 1 datalane */ | 3604 | ths_eot = DIV_ROUND_UP(4, dsi_get_num_data_lanes_dssdev(dssdev)); |
2489 | if (dssdev->phy.dsi.data1_lane != 0 && | ||
2490 | dssdev->phy.dsi.data2_lane != 0) | ||
2491 | ths_eot = 2; | ||
2492 | else | ||
2493 | ths_eot = 4; | ||
2494 | 3605 | ||
2495 | ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare, | 3606 | ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare, |
2496 | 4); | 3607 | 4); |
@@ -2499,10 +3610,10 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) | |||
2499 | BUG_ON(ddr_clk_pre == 0 || ddr_clk_pre > 255); | 3610 | BUG_ON(ddr_clk_pre == 0 || ddr_clk_pre > 255); |
2500 | BUG_ON(ddr_clk_post == 0 || ddr_clk_post > 255); | 3611 | BUG_ON(ddr_clk_post == 0 || ddr_clk_post > 255); |
2501 | 3612 | ||
2502 | r = dsi_read_reg(DSI_CLK_TIMING); | 3613 | r = dsi_read_reg(dsidev, DSI_CLK_TIMING); |
2503 | r = FLD_MOD(r, ddr_clk_pre, 15, 8); | 3614 | r = FLD_MOD(r, ddr_clk_pre, 15, 8); |
2504 | r = FLD_MOD(r, ddr_clk_post, 7, 0); | 3615 | r = FLD_MOD(r, ddr_clk_post, 7, 0); |
2505 | dsi_write_reg(DSI_CLK_TIMING, r); | 3616 | dsi_write_reg(dsidev, DSI_CLK_TIMING, r); |
2506 | 3617 | ||
2507 | DSSDBG("ddr_clk_pre %u, ddr_clk_post %u\n", | 3618 | DSSDBG("ddr_clk_pre %u, ddr_clk_post %u\n", |
2508 | ddr_clk_pre, | 3619 | ddr_clk_pre, |
@@ -2516,7 +3627,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) | |||
2516 | 3627 | ||
2517 | r = FLD_VAL(enter_hs_mode_lat, 31, 16) | | 3628 | r = FLD_VAL(enter_hs_mode_lat, 31, 16) | |
2518 | FLD_VAL(exit_hs_mode_lat, 15, 0); | 3629 | FLD_VAL(exit_hs_mode_lat, 15, 0); |
2519 | dsi_write_reg(DSI_VM_TIMING7, r); | 3630 | dsi_write_reg(dsidev, DSI_VM_TIMING7, r); |
2520 | 3631 | ||
2521 | DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n", | 3632 | DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n", |
2522 | enter_hs_mode_lat, exit_hs_mode_lat); | 3633 | enter_hs_mode_lat, exit_hs_mode_lat); |
@@ -2526,25 +3637,27 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) | |||
2526 | #define DSI_DECL_VARS \ | 3637 | #define DSI_DECL_VARS \ |
2527 | int __dsi_cb = 0; u32 __dsi_cv = 0; | 3638 | int __dsi_cb = 0; u32 __dsi_cv = 0; |
2528 | 3639 | ||
2529 | #define DSI_FLUSH(ch) \ | 3640 | #define DSI_FLUSH(dsidev, ch) \ |
2530 | if (__dsi_cb > 0) { \ | 3641 | if (__dsi_cb > 0) { \ |
2531 | /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \ | 3642 | /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \ |
2532 | dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \ | 3643 | dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \ |
2533 | __dsi_cb = __dsi_cv = 0; \ | 3644 | __dsi_cb = __dsi_cv = 0; \ |
2534 | } | 3645 | } |
2535 | 3646 | ||
2536 | #define DSI_PUSH(ch, data) \ | 3647 | #define DSI_PUSH(dsidev, ch, data) \ |
2537 | do { \ | 3648 | do { \ |
2538 | __dsi_cv |= (data) << (__dsi_cb * 8); \ | 3649 | __dsi_cv |= (data) << (__dsi_cb * 8); \ |
2539 | /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \ | 3650 | /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \ |
2540 | if (++__dsi_cb > 3) \ | 3651 | if (++__dsi_cb > 3) \ |
2541 | DSI_FLUSH(ch); \ | 3652 | DSI_FLUSH(dsidev, ch); \ |
2542 | } while (0) | 3653 | } while (0) |
2543 | 3654 | ||
2544 | static int dsi_update_screen_l4(struct omap_dss_device *dssdev, | 3655 | static int dsi_update_screen_l4(struct omap_dss_device *dssdev, |
2545 | int x, int y, int w, int h) | 3656 | int x, int y, int w, int h) |
2546 | { | 3657 | { |
2547 | /* Note: supports only 24bit colors in 32bit container */ | 3658 | /* Note: supports only 24bit colors in 32bit container */ |
3659 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
3660 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2548 | int first = 1; | 3661 | int first = 1; |
2549 | int fifo_stalls = 0; | 3662 | int fifo_stalls = 0; |
2550 | int max_dsi_packet_size; | 3663 | int max_dsi_packet_size; |
@@ -2583,7 +3696,7 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev, | |||
2583 | * in fifo */ | 3696 | * in fifo */ |
2584 | 3697 | ||
2585 | /* When using CPU, max long packet size is TX buffer size */ | 3698 | /* When using CPU, max long packet size is TX buffer size */ |
2586 | max_dsi_packet_size = dsi.vc[0].fifo_size * 32 * 4; | 3699 | max_dsi_packet_size = dsi->vc[0].fifo_size * 32 * 4; |
2587 | 3700 | ||
2588 | /* we seem to get better perf if we divide the tx fifo to half, | 3701 | /* we seem to get better perf if we divide the tx fifo to half, |
2589 | and while the other half is being sent, we fill the other half | 3702 | and while the other half is being sent, we fill the other half |
@@ -2612,35 +3725,36 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev, | |||
2612 | #if 1 | 3725 | #if 1 |
2613 | /* using fifo not empty */ | 3726 | /* using fifo not empty */ |
2614 | /* TX_FIFO_NOT_EMPTY */ | 3727 | /* TX_FIFO_NOT_EMPTY */ |
2615 | while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) { | 3728 | while (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(0)), 5, 5)) { |
2616 | fifo_stalls++; | 3729 | fifo_stalls++; |
2617 | if (fifo_stalls > 0xfffff) { | 3730 | if (fifo_stalls > 0xfffff) { |
2618 | DSSERR("fifo stalls overflow, pixels left %d\n", | 3731 | DSSERR("fifo stalls overflow, pixels left %d\n", |
2619 | pixels_left); | 3732 | pixels_left); |
2620 | dsi_if_enable(0); | 3733 | dsi_if_enable(dsidev, 0); |
2621 | return -EIO; | 3734 | return -EIO; |
2622 | } | 3735 | } |
2623 | udelay(1); | 3736 | udelay(1); |
2624 | } | 3737 | } |
2625 | #elif 1 | 3738 | #elif 1 |
2626 | /* using fifo emptiness */ | 3739 | /* using fifo emptiness */ |
2627 | while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 < | 3740 | while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 < |
2628 | max_dsi_packet_size) { | 3741 | max_dsi_packet_size) { |
2629 | fifo_stalls++; | 3742 | fifo_stalls++; |
2630 | if (fifo_stalls > 0xfffff) { | 3743 | if (fifo_stalls > 0xfffff) { |
2631 | DSSERR("fifo stalls overflow, pixels left %d\n", | 3744 | DSSERR("fifo stalls overflow, pixels left %d\n", |
2632 | pixels_left); | 3745 | pixels_left); |
2633 | dsi_if_enable(0); | 3746 | dsi_if_enable(dsidev, 0); |
2634 | return -EIO; | 3747 | return -EIO; |
2635 | } | 3748 | } |
2636 | } | 3749 | } |
2637 | #else | 3750 | #else |
2638 | while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 == 0) { | 3751 | while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS, |
3752 | 7, 0) + 1) * 4 == 0) { | ||
2639 | fifo_stalls++; | 3753 | fifo_stalls++; |
2640 | if (fifo_stalls > 0xfffff) { | 3754 | if (fifo_stalls > 0xfffff) { |
2641 | DSSERR("fifo stalls overflow, pixels left %d\n", | 3755 | DSSERR("fifo stalls overflow, pixels left %d\n", |
2642 | pixels_left); | 3756 | pixels_left); |
2643 | dsi_if_enable(0); | 3757 | dsi_if_enable(dsidev, 0); |
2644 | return -EIO; | 3758 | return -EIO; |
2645 | } | 3759 | } |
2646 | } | 3760 | } |
@@ -2649,17 +3763,17 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev, | |||
2649 | 3763 | ||
2650 | pixels_left -= pixels; | 3764 | pixels_left -= pixels; |
2651 | 3765 | ||
2652 | dsi_vc_write_long_header(0, DSI_DT_DCS_LONG_WRITE, | 3766 | dsi_vc_write_long_header(dsidev, 0, DSI_DT_DCS_LONG_WRITE, |
2653 | 1 + pixels * bytespp, 0); | 3767 | 1 + pixels * bytespp, 0); |
2654 | 3768 | ||
2655 | DSI_PUSH(0, dcs_cmd); | 3769 | DSI_PUSH(dsidev, 0, dcs_cmd); |
2656 | 3770 | ||
2657 | while (pixels-- > 0) { | 3771 | while (pixels-- > 0) { |
2658 | u32 pix = __raw_readl(data++); | 3772 | u32 pix = __raw_readl(data++); |
2659 | 3773 | ||
2660 | DSI_PUSH(0, (pix >> 16) & 0xff); | 3774 | DSI_PUSH(dsidev, 0, (pix >> 16) & 0xff); |
2661 | DSI_PUSH(0, (pix >> 8) & 0xff); | 3775 | DSI_PUSH(dsidev, 0, (pix >> 8) & 0xff); |
2662 | DSI_PUSH(0, (pix >> 0) & 0xff); | 3776 | DSI_PUSH(dsidev, 0, (pix >> 0) & 0xff); |
2663 | 3777 | ||
2664 | current_x++; | 3778 | current_x++; |
2665 | if (current_x == x+w) { | 3779 | if (current_x == x+w) { |
@@ -2668,7 +3782,7 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev, | |||
2668 | } | 3782 | } |
2669 | } | 3783 | } |
2670 | 3784 | ||
2671 | DSI_FLUSH(0); | 3785 | DSI_FLUSH(dsidev, 0); |
2672 | } | 3786 | } |
2673 | 3787 | ||
2674 | return 0; | 3788 | return 0; |
@@ -2677,6 +3791,8 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev, | |||
2677 | static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, | 3791 | static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, |
2678 | u16 x, u16 y, u16 w, u16 h) | 3792 | u16 x, u16 y, u16 w, u16 h) |
2679 | { | 3793 | { |
3794 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
3795 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2680 | unsigned bytespp; | 3796 | unsigned bytespp; |
2681 | unsigned bytespl; | 3797 | unsigned bytespl; |
2682 | unsigned bytespf; | 3798 | unsigned bytespf; |
@@ -2685,16 +3801,13 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, | |||
2685 | unsigned packet_len; | 3801 | unsigned packet_len; |
2686 | u32 l; | 3802 | u32 l; |
2687 | int r; | 3803 | int r; |
2688 | const unsigned channel = dsi.update_channel; | 3804 | const unsigned channel = dsi->update_channel; |
2689 | /* line buffer is 1024 x 24bits */ | 3805 | const unsigned line_buf_size = dsi_get_line_buf_size(dsidev); |
2690 | /* XXX: for some reason using full buffer size causes considerable TX | ||
2691 | * slowdown with update sizes that fill the whole buffer */ | ||
2692 | const unsigned line_buf_size = 1023 * 3; | ||
2693 | 3806 | ||
2694 | DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n", | 3807 | DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n", |
2695 | x, y, w, h); | 3808 | x, y, w, h); |
2696 | 3809 | ||
2697 | dsi_vc_config_vp(channel); | 3810 | dsi_vc_config_vp(dsidev, channel); |
2698 | 3811 | ||
2699 | bytespp = dssdev->ctrl.pixel_size / 8; | 3812 | bytespp = dssdev->ctrl.pixel_size / 8; |
2700 | bytespl = w * bytespp; | 3813 | bytespl = w * bytespp; |
@@ -2715,15 +3828,16 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, | |||
2715 | total_len += (bytespf % packet_payload) + 1; | 3828 | total_len += (bytespf % packet_payload) + 1; |
2716 | 3829 | ||
2717 | l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */ | 3830 | l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */ |
2718 | dsi_write_reg(DSI_VC_TE(channel), l); | 3831 | dsi_write_reg(dsidev, DSI_VC_TE(channel), l); |
2719 | 3832 | ||
2720 | dsi_vc_write_long_header(channel, DSI_DT_DCS_LONG_WRITE, packet_len, 0); | 3833 | dsi_vc_write_long_header(dsidev, channel, DSI_DT_DCS_LONG_WRITE, |
3834 | packet_len, 0); | ||
2721 | 3835 | ||
2722 | if (dsi.te_enabled) | 3836 | if (dsi->te_enabled) |
2723 | l = FLD_MOD(l, 1, 30, 30); /* TE_EN */ | 3837 | l = FLD_MOD(l, 1, 30, 30); /* TE_EN */ |
2724 | else | 3838 | else |
2725 | l = FLD_MOD(l, 1, 31, 31); /* TE_START */ | 3839 | l = FLD_MOD(l, 1, 31, 31); /* TE_START */ |
2726 | dsi_write_reg(DSI_VC_TE(channel), l); | 3840 | dsi_write_reg(dsidev, DSI_VC_TE(channel), l); |
2727 | 3841 | ||
2728 | /* We put SIDLEMODE to no-idle for the duration of the transfer, | 3842 | /* We put SIDLEMODE to no-idle for the duration of the transfer, |
2729 | * because DSS interrupts are not capable of waking up the CPU and the | 3843 | * because DSS interrupts are not capable of waking up the CPU and the |
@@ -2733,23 +3847,23 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, | |||
2733 | */ | 3847 | */ |
2734 | dispc_disable_sidle(); | 3848 | dispc_disable_sidle(); |
2735 | 3849 | ||
2736 | dsi_perf_mark_start(); | 3850 | dsi_perf_mark_start(dsidev); |
2737 | 3851 | ||
2738 | r = queue_delayed_work(dsi.workqueue, &dsi.framedone_timeout_work, | 3852 | r = schedule_delayed_work(&dsi->framedone_timeout_work, |
2739 | msecs_to_jiffies(250)); | 3853 | msecs_to_jiffies(250)); |
2740 | BUG_ON(r == 0); | 3854 | BUG_ON(r == 0); |
2741 | 3855 | ||
2742 | dss_start_update(dssdev); | 3856 | dss_start_update(dssdev); |
2743 | 3857 | ||
2744 | if (dsi.te_enabled) { | 3858 | if (dsi->te_enabled) { |
2745 | /* disable LP_RX_TO, so that we can receive TE. Time to wait | 3859 | /* disable LP_RX_TO, so that we can receive TE. Time to wait |
2746 | * for TE is longer than the timer allows */ | 3860 | * for TE is longer than the timer allows */ |
2747 | REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */ | 3861 | REG_FLD_MOD(dsidev, DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */ |
2748 | 3862 | ||
2749 | dsi_vc_send_bta(channel); | 3863 | dsi_vc_send_bta(dsidev, channel); |
2750 | 3864 | ||
2751 | #ifdef DSI_CATCH_MISSING_TE | 3865 | #ifdef DSI_CATCH_MISSING_TE |
2752 | mod_timer(&dsi.te_timer, jiffies + msecs_to_jiffies(250)); | 3866 | mod_timer(&dsi->te_timer, jiffies + msecs_to_jiffies(250)); |
2753 | #endif | 3867 | #endif |
2754 | } | 3868 | } |
2755 | } | 3869 | } |
@@ -2761,40 +3875,28 @@ static void dsi_te_timeout(unsigned long arg) | |||
2761 | } | 3875 | } |
2762 | #endif | 3876 | #endif |
2763 | 3877 | ||
2764 | static void dsi_handle_framedone(int error) | 3878 | static void dsi_handle_framedone(struct platform_device *dsidev, int error) |
2765 | { | 3879 | { |
2766 | const int channel = dsi.update_channel; | 3880 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
2767 | |||
2768 | cancel_delayed_work(&dsi.framedone_timeout_work); | ||
2769 | |||
2770 | dsi_vc_disable_bta_irq(channel); | ||
2771 | 3881 | ||
2772 | /* SIDLEMODE back to smart-idle */ | 3882 | /* SIDLEMODE back to smart-idle */ |
2773 | dispc_enable_sidle(); | 3883 | dispc_enable_sidle(); |
2774 | 3884 | ||
2775 | dsi.bta_callback = NULL; | 3885 | if (dsi->te_enabled) { |
2776 | |||
2777 | if (dsi.te_enabled) { | ||
2778 | /* enable LP_RX_TO again after the TE */ | 3886 | /* enable LP_RX_TO again after the TE */ |
2779 | REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ | 3887 | REG_FLD_MOD(dsidev, DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ |
2780 | } | ||
2781 | |||
2782 | /* RX_FIFO_NOT_EMPTY */ | ||
2783 | if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { | ||
2784 | DSSERR("Received error during frame transfer:\n"); | ||
2785 | dsi_vc_flush_receive_data(channel); | ||
2786 | if (!error) | ||
2787 | error = -EIO; | ||
2788 | } | 3888 | } |
2789 | 3889 | ||
2790 | dsi.framedone_callback(error, dsi.framedone_data); | 3890 | dsi->framedone_callback(error, dsi->framedone_data); |
2791 | 3891 | ||
2792 | if (!error) | 3892 | if (!error) |
2793 | dsi_perf_show("DISPC"); | 3893 | dsi_perf_show(dsidev, "DISPC"); |
2794 | } | 3894 | } |
2795 | 3895 | ||
2796 | static void dsi_framedone_timeout_work_callback(struct work_struct *work) | 3896 | static void dsi_framedone_timeout_work_callback(struct work_struct *work) |
2797 | { | 3897 | { |
3898 | struct dsi_data *dsi = container_of(work, struct dsi_data, | ||
3899 | framedone_timeout_work.work); | ||
2798 | /* XXX While extremely unlikely, we could get FRAMEDONE interrupt after | 3900 | /* XXX While extremely unlikely, we could get FRAMEDONE interrupt after |
2799 | * 250ms which would conflict with this timeout work. What should be | 3901 | * 250ms which would conflict with this timeout work. What should be |
2800 | * done is first cancel the transfer on the HW, and then cancel the | 3902 | * done is first cancel the transfer on the HW, and then cancel the |
@@ -2804,66 +3906,34 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work) | |||
2804 | 3906 | ||
2805 | DSSERR("Framedone not received for 250ms!\n"); | 3907 | DSSERR("Framedone not received for 250ms!\n"); |
2806 | 3908 | ||
2807 | dsi_handle_framedone(-ETIMEDOUT); | 3909 | dsi_handle_framedone(dsi->pdev, -ETIMEDOUT); |
2808 | } | ||
2809 | |||
2810 | static void dsi_framedone_bta_callback(void) | ||
2811 | { | ||
2812 | dsi_handle_framedone(0); | ||
2813 | |||
2814 | #ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC | ||
2815 | dispc_fake_vsync_irq(); | ||
2816 | #endif | ||
2817 | } | 3910 | } |
2818 | 3911 | ||
2819 | static void dsi_framedone_irq_callback(void *data, u32 mask) | 3912 | static void dsi_framedone_irq_callback(void *data, u32 mask) |
2820 | { | 3913 | { |
2821 | const int channel = dsi.update_channel; | 3914 | struct omap_dss_device *dssdev = (struct omap_dss_device *) data; |
2822 | int r; | 3915 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
3916 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2823 | 3917 | ||
2824 | /* Note: We get FRAMEDONE when DISPC has finished sending pixels and | 3918 | /* Note: We get FRAMEDONE when DISPC has finished sending pixels and |
2825 | * turns itself off. However, DSI still has the pixels in its buffers, | 3919 | * turns itself off. However, DSI still has the pixels in its buffers, |
2826 | * and is sending the data. | 3920 | * and is sending the data. |
2827 | */ | 3921 | */ |
2828 | 3922 | ||
2829 | if (dsi.te_enabled) { | 3923 | __cancel_delayed_work(&dsi->framedone_timeout_work); |
2830 | /* enable LP_RX_TO again after the TE */ | ||
2831 | REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ | ||
2832 | } | ||
2833 | |||
2834 | /* Send BTA after the frame. We need this for the TE to work, as TE | ||
2835 | * trigger is only sent for BTAs without preceding packet. Thus we need | ||
2836 | * to BTA after the pixel packets so that next BTA will cause TE | ||
2837 | * trigger. | ||
2838 | * | ||
2839 | * This is not needed when TE is not in use, but we do it anyway to | ||
2840 | * make sure that the transfer has been completed. It would be more | ||
2841 | * optimal, but more complex, to wait only just before starting next | ||
2842 | * transfer. | ||
2843 | * | ||
2844 | * Also, as there's no interrupt telling when the transfer has been | ||
2845 | * done and the channel could be reconfigured, the only way is to | ||
2846 | * busyloop until TE_SIZE is zero. With BTA we can do this | ||
2847 | * asynchronously. | ||
2848 | * */ | ||
2849 | |||
2850 | dsi.bta_callback = dsi_framedone_bta_callback; | ||
2851 | |||
2852 | barrier(); | ||
2853 | 3924 | ||
2854 | dsi_vc_enable_bta_irq(channel); | 3925 | dsi_handle_framedone(dsidev, 0); |
2855 | 3926 | ||
2856 | r = dsi_vc_send_bta(channel); | 3927 | #ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC |
2857 | if (r) { | 3928 | dispc_fake_vsync_irq(); |
2858 | DSSERR("BTA after framedone failed\n"); | 3929 | #endif |
2859 | dsi_handle_framedone(-EIO); | ||
2860 | } | ||
2861 | } | 3930 | } |
2862 | 3931 | ||
2863 | int omap_dsi_prepare_update(struct omap_dss_device *dssdev, | 3932 | int omap_dsi_prepare_update(struct omap_dss_device *dssdev, |
2864 | u16 *x, u16 *y, u16 *w, u16 *h, | 3933 | u16 *x, u16 *y, u16 *w, u16 *h, |
2865 | bool enlarge_update_area) | 3934 | bool enlarge_update_area) |
2866 | { | 3935 | { |
3936 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2867 | u16 dw, dh; | 3937 | u16 dw, dh; |
2868 | 3938 | ||
2869 | dssdev->driver->get_resolution(dssdev, &dw, &dh); | 3939 | dssdev->driver->get_resolution(dssdev, &dw, &dh); |
@@ -2883,12 +3953,12 @@ int omap_dsi_prepare_update(struct omap_dss_device *dssdev, | |||
2883 | if (*w == 0 || *h == 0) | 3953 | if (*w == 0 || *h == 0) |
2884 | return -EINVAL; | 3954 | return -EINVAL; |
2885 | 3955 | ||
2886 | dsi_perf_mark_setup(); | 3956 | dsi_perf_mark_setup(dsidev); |
2887 | 3957 | ||
2888 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 3958 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { |
2889 | dss_setup_partial_planes(dssdev, x, y, w, h, | 3959 | dss_setup_partial_planes(dssdev, x, y, w, h, |
2890 | enlarge_update_area); | 3960 | enlarge_update_area); |
2891 | dispc_set_lcd_size(*w, *h); | 3961 | dispc_set_lcd_size(dssdev->manager->id, *w, *h); |
2892 | } | 3962 | } |
2893 | 3963 | ||
2894 | return 0; | 3964 | return 0; |
@@ -2900,7 +3970,10 @@ int omap_dsi_update(struct omap_dss_device *dssdev, | |||
2900 | u16 x, u16 y, u16 w, u16 h, | 3970 | u16 x, u16 y, u16 w, u16 h, |
2901 | void (*callback)(int, void *), void *data) | 3971 | void (*callback)(int, void *), void *data) |
2902 | { | 3972 | { |
2903 | dsi.update_channel = channel; | 3973 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
3974 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
3975 | |||
3976 | dsi->update_channel = channel; | ||
2904 | 3977 | ||
2905 | /* OMAP DSS cannot send updates of odd widths. | 3978 | /* OMAP DSS cannot send updates of odd widths. |
2906 | * omap_dsi_prepare_update() makes the widths even, but add a BUG_ON | 3979 | * omap_dsi_prepare_update() makes the widths even, but add a BUG_ON |
@@ -2909,14 +3982,14 @@ int omap_dsi_update(struct omap_dss_device *dssdev, | |||
2909 | BUG_ON(x % 2 == 1); | 3982 | BUG_ON(x % 2 == 1); |
2910 | 3983 | ||
2911 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 3984 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { |
2912 | dsi.framedone_callback = callback; | 3985 | dsi->framedone_callback = callback; |
2913 | dsi.framedone_data = data; | 3986 | dsi->framedone_data = data; |
2914 | 3987 | ||
2915 | dsi.update_region.x = x; | 3988 | dsi->update_region.x = x; |
2916 | dsi.update_region.y = y; | 3989 | dsi->update_region.y = y; |
2917 | dsi.update_region.w = w; | 3990 | dsi->update_region.w = w; |
2918 | dsi.update_region.h = h; | 3991 | dsi->update_region.h = h; |
2919 | dsi.update_region.device = dssdev; | 3992 | dsi->update_region.device = dssdev; |
2920 | 3993 | ||
2921 | dsi_update_screen_dispc(dssdev, x, y, w, h); | 3994 | dsi_update_screen_dispc(dssdev, x, y, w, h); |
2922 | } else { | 3995 | } else { |
@@ -2926,7 +3999,7 @@ int omap_dsi_update(struct omap_dss_device *dssdev, | |||
2926 | if (r) | 3999 | if (r) |
2927 | return r; | 4000 | return r; |
2928 | 4001 | ||
2929 | dsi_perf_show("L4"); | 4002 | dsi_perf_show(dsidev, "L4"); |
2930 | callback(0, data); | 4003 | callback(0, data); |
2931 | } | 4004 | } |
2932 | 4005 | ||
@@ -2939,20 +4012,26 @@ EXPORT_SYMBOL(omap_dsi_update); | |||
2939 | static int dsi_display_init_dispc(struct omap_dss_device *dssdev) | 4012 | static int dsi_display_init_dispc(struct omap_dss_device *dssdev) |
2940 | { | 4013 | { |
2941 | int r; | 4014 | int r; |
4015 | u32 irq; | ||
4016 | |||
4017 | irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? | ||
4018 | DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; | ||
2942 | 4019 | ||
2943 | r = omap_dispc_register_isr(dsi_framedone_irq_callback, NULL, | 4020 | r = omap_dispc_register_isr(dsi_framedone_irq_callback, (void *) dssdev, |
2944 | DISPC_IRQ_FRAMEDONE); | 4021 | irq); |
2945 | if (r) { | 4022 | if (r) { |
2946 | DSSERR("can't get FRAMEDONE irq\n"); | 4023 | DSSERR("can't get FRAMEDONE irq\n"); |
2947 | return r; | 4024 | return r; |
2948 | } | 4025 | } |
2949 | 4026 | ||
2950 | dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT); | 4027 | dispc_set_lcd_display_type(dssdev->manager->id, |
4028 | OMAP_DSS_LCD_DISPLAY_TFT); | ||
2951 | 4029 | ||
2952 | dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_DSI); | 4030 | dispc_set_parallel_interface_mode(dssdev->manager->id, |
2953 | dispc_enable_fifohandcheck(1); | 4031 | OMAP_DSS_PARALLELMODE_DSI); |
4032 | dispc_enable_fifohandcheck(dssdev->manager->id, 1); | ||
2954 | 4033 | ||
2955 | dispc_set_tft_data_lines(dssdev->ctrl.pixel_size); | 4034 | dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size); |
2956 | 4035 | ||
2957 | { | 4036 | { |
2958 | struct omap_video_timings timings = { | 4037 | struct omap_video_timings timings = { |
@@ -2964,7 +4043,7 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev) | |||
2964 | .vbp = 0, | 4043 | .vbp = 0, |
2965 | }; | 4044 | }; |
2966 | 4045 | ||
2967 | dispc_set_lcd_timings(&timings); | 4046 | dispc_set_lcd_timings(dssdev->manager->id, &timings); |
2968 | } | 4047 | } |
2969 | 4048 | ||
2970 | return 0; | 4049 | return 0; |
@@ -2972,28 +4051,34 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev) | |||
2972 | 4051 | ||
2973 | static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) | 4052 | static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) |
2974 | { | 4053 | { |
2975 | omap_dispc_unregister_isr(dsi_framedone_irq_callback, NULL, | 4054 | u32 irq; |
2976 | DISPC_IRQ_FRAMEDONE); | 4055 | |
4056 | irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? | ||
4057 | DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; | ||
4058 | |||
4059 | omap_dispc_unregister_isr(dsi_framedone_irq_callback, (void *) dssdev, | ||
4060 | irq); | ||
2977 | } | 4061 | } |
2978 | 4062 | ||
2979 | static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) | 4063 | static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) |
2980 | { | 4064 | { |
4065 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2981 | struct dsi_clock_info cinfo; | 4066 | struct dsi_clock_info cinfo; |
2982 | int r; | 4067 | int r; |
2983 | 4068 | ||
2984 | /* we always use DSS2_FCK as input clock */ | 4069 | /* we always use DSS_CLK_SYSCK as input clock */ |
2985 | cinfo.use_dss2_fck = true; | 4070 | cinfo.use_sys_clk = true; |
2986 | cinfo.regn = dssdev->phy.dsi.div.regn; | 4071 | cinfo.regn = dssdev->clocks.dsi.regn; |
2987 | cinfo.regm = dssdev->phy.dsi.div.regm; | 4072 | cinfo.regm = dssdev->clocks.dsi.regm; |
2988 | cinfo.regm3 = dssdev->phy.dsi.div.regm3; | 4073 | cinfo.regm_dispc = dssdev->clocks.dsi.regm_dispc; |
2989 | cinfo.regm4 = dssdev->phy.dsi.div.regm4; | 4074 | cinfo.regm_dsi = dssdev->clocks.dsi.regm_dsi; |
2990 | r = dsi_calc_clock_rates(&cinfo); | 4075 | r = dsi_calc_clock_rates(dssdev, &cinfo); |
2991 | if (r) { | 4076 | if (r) { |
2992 | DSSERR("Failed to calc dsi clocks\n"); | 4077 | DSSERR("Failed to calc dsi clocks\n"); |
2993 | return r; | 4078 | return r; |
2994 | } | 4079 | } |
2995 | 4080 | ||
2996 | r = dsi_pll_set_clock_div(&cinfo); | 4081 | r = dsi_pll_set_clock_div(dsidev, &cinfo); |
2997 | if (r) { | 4082 | if (r) { |
2998 | DSSERR("Failed to set dsi clocks\n"); | 4083 | DSSERR("Failed to set dsi clocks\n"); |
2999 | return r; | 4084 | return r; |
@@ -3004,14 +4089,15 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) | |||
3004 | 4089 | ||
3005 | static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) | 4090 | static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) |
3006 | { | 4091 | { |
4092 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
3007 | struct dispc_clock_info dispc_cinfo; | 4093 | struct dispc_clock_info dispc_cinfo; |
3008 | int r; | 4094 | int r; |
3009 | unsigned long long fck; | 4095 | unsigned long long fck; |
3010 | 4096 | ||
3011 | fck = dsi_get_dsi1_pll_rate(); | 4097 | fck = dsi_get_pll_hsdiv_dispc_rate(dsidev); |
3012 | 4098 | ||
3013 | dispc_cinfo.lck_div = dssdev->phy.dsi.div.lck_div; | 4099 | dispc_cinfo.lck_div = dssdev->clocks.dispc.channel.lck_div; |
3014 | dispc_cinfo.pck_div = dssdev->phy.dsi.div.pck_div; | 4100 | dispc_cinfo.pck_div = dssdev->clocks.dispc.channel.pck_div; |
3015 | 4101 | ||
3016 | r = dispc_calc_clock_rates(fck, &dispc_cinfo); | 4102 | r = dispc_calc_clock_rates(fck, &dispc_cinfo); |
3017 | if (r) { | 4103 | if (r) { |
@@ -3019,7 +4105,7 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) | |||
3019 | return r; | 4105 | return r; |
3020 | } | 4106 | } |
3021 | 4107 | ||
3022 | r = dispc_set_clock_div(&dispc_cinfo); | 4108 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); |
3023 | if (r) { | 4109 | if (r) { |
3024 | DSSERR("Failed to set dispc clocks\n"); | 4110 | DSSERR("Failed to set dispc clocks\n"); |
3025 | return r; | 4111 | return r; |
@@ -3030,11 +4116,11 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) | |||
3030 | 4116 | ||
3031 | static int dsi_display_init_dsi(struct omap_dss_device *dssdev) | 4117 | static int dsi_display_init_dsi(struct omap_dss_device *dssdev) |
3032 | { | 4118 | { |
4119 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4120 | int dsi_module = dsi_get_dsidev_id(dsidev); | ||
3033 | int r; | 4121 | int r; |
3034 | 4122 | ||
3035 | _dsi_print_reset_status(); | 4123 | r = dsi_pll_init(dsidev, true, true); |
3036 | |||
3037 | r = dsi_pll_init(dssdev, true, true); | ||
3038 | if (r) | 4124 | if (r) |
3039 | goto err0; | 4125 | goto err0; |
3040 | 4126 | ||
@@ -3042,8 +4128,10 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) | |||
3042 | if (r) | 4128 | if (r) |
3043 | goto err1; | 4129 | goto err1; |
3044 | 4130 | ||
3045 | dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK); | 4131 | dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); |
3046 | dss_select_dsi_clk_source(DSS_SRC_DSI2_PLL_FCLK); | 4132 | dss_select_dsi_clk_source(dsi_module, dssdev->clocks.dsi.dsi_fclk_src); |
4133 | dss_select_lcd_clk_source(dssdev->manager->id, | ||
4134 | dssdev->clocks.dispc.channel.lcd_clk_src); | ||
3047 | 4135 | ||
3048 | DSSDBG("PLL OK\n"); | 4136 | DSSDBG("PLL OK\n"); |
3049 | 4137 | ||
@@ -3051,82 +4139,92 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) | |||
3051 | if (r) | 4139 | if (r) |
3052 | goto err2; | 4140 | goto err2; |
3053 | 4141 | ||
3054 | r = dsi_complexio_init(dssdev); | 4142 | r = dsi_cio_init(dssdev); |
3055 | if (r) | 4143 | if (r) |
3056 | goto err2; | 4144 | goto err2; |
3057 | 4145 | ||
3058 | _dsi_print_reset_status(); | 4146 | _dsi_print_reset_status(dsidev); |
3059 | 4147 | ||
3060 | dsi_proto_timings(dssdev); | 4148 | dsi_proto_timings(dssdev); |
3061 | dsi_set_lp_clk_divisor(dssdev); | 4149 | dsi_set_lp_clk_divisor(dssdev); |
3062 | 4150 | ||
3063 | if (1) | 4151 | if (1) |
3064 | _dsi_print_reset_status(); | 4152 | _dsi_print_reset_status(dsidev); |
3065 | 4153 | ||
3066 | r = dsi_proto_config(dssdev); | 4154 | r = dsi_proto_config(dssdev); |
3067 | if (r) | 4155 | if (r) |
3068 | goto err3; | 4156 | goto err3; |
3069 | 4157 | ||
3070 | /* enable interface */ | 4158 | /* enable interface */ |
3071 | dsi_vc_enable(0, 1); | 4159 | dsi_vc_enable(dsidev, 0, 1); |
3072 | dsi_vc_enable(1, 1); | 4160 | dsi_vc_enable(dsidev, 1, 1); |
3073 | dsi_vc_enable(2, 1); | 4161 | dsi_vc_enable(dsidev, 2, 1); |
3074 | dsi_vc_enable(3, 1); | 4162 | dsi_vc_enable(dsidev, 3, 1); |
3075 | dsi_if_enable(1); | 4163 | dsi_if_enable(dsidev, 1); |
3076 | dsi_force_tx_stop_mode_io(); | 4164 | dsi_force_tx_stop_mode_io(dsidev); |
3077 | 4165 | ||
3078 | return 0; | 4166 | return 0; |
3079 | err3: | 4167 | err3: |
3080 | dsi_complexio_uninit(); | 4168 | dsi_cio_uninit(dsidev); |
3081 | err2: | 4169 | err2: |
3082 | dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 4170 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); |
3083 | dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 4171 | dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); |
3084 | err1: | 4172 | err1: |
3085 | dsi_pll_uninit(); | 4173 | dsi_pll_uninit(dsidev, true); |
3086 | err0: | 4174 | err0: |
3087 | return r; | 4175 | return r; |
3088 | } | 4176 | } |
3089 | 4177 | ||
3090 | static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev) | 4178 | static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev, |
4179 | bool disconnect_lanes, bool enter_ulps) | ||
3091 | { | 4180 | { |
3092 | /* disable interface */ | 4181 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
3093 | dsi_if_enable(0); | 4182 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
3094 | dsi_vc_enable(0, 0); | 4183 | int dsi_module = dsi_get_dsidev_id(dsidev); |
3095 | dsi_vc_enable(1, 0); | 4184 | |
3096 | dsi_vc_enable(2, 0); | 4185 | if (enter_ulps && !dsi->ulps_enabled) |
3097 | dsi_vc_enable(3, 0); | 4186 | dsi_enter_ulps(dsidev); |
3098 | 4187 | ||
3099 | dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 4188 | /* disable interface */ |
3100 | dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 4189 | dsi_if_enable(dsidev, 0); |
3101 | dsi_complexio_uninit(); | 4190 | dsi_vc_enable(dsidev, 0, 0); |
3102 | dsi_pll_uninit(); | 4191 | dsi_vc_enable(dsidev, 1, 0); |
4192 | dsi_vc_enable(dsidev, 2, 0); | ||
4193 | dsi_vc_enable(dsidev, 3, 0); | ||
4194 | |||
4195 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); | ||
4196 | dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); | ||
4197 | dsi_cio_uninit(dsidev); | ||
4198 | dsi_pll_uninit(dsidev, disconnect_lanes); | ||
3103 | } | 4199 | } |
3104 | 4200 | ||
3105 | static int dsi_core_init(void) | 4201 | static int dsi_core_init(struct platform_device *dsidev) |
3106 | { | 4202 | { |
3107 | /* Autoidle */ | 4203 | /* Autoidle */ |
3108 | REG_FLD_MOD(DSI_SYSCONFIG, 1, 0, 0); | 4204 | REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 0, 0); |
3109 | 4205 | ||
3110 | /* ENWAKEUP */ | 4206 | /* ENWAKEUP */ |
3111 | REG_FLD_MOD(DSI_SYSCONFIG, 1, 2, 2); | 4207 | REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 2, 2); |
3112 | 4208 | ||
3113 | /* SIDLEMODE smart-idle */ | 4209 | /* SIDLEMODE smart-idle */ |
3114 | REG_FLD_MOD(DSI_SYSCONFIG, 2, 4, 3); | 4210 | REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 2, 4, 3); |
3115 | 4211 | ||
3116 | _dsi_initialize_irq(); | 4212 | _dsi_initialize_irq(dsidev); |
3117 | 4213 | ||
3118 | return 0; | 4214 | return 0; |
3119 | } | 4215 | } |
3120 | 4216 | ||
3121 | int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) | 4217 | int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) |
3122 | { | 4218 | { |
4219 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4220 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
3123 | int r = 0; | 4221 | int r = 0; |
3124 | 4222 | ||
3125 | DSSDBG("dsi_display_enable\n"); | 4223 | DSSDBG("dsi_display_enable\n"); |
3126 | 4224 | ||
3127 | WARN_ON(!dsi_bus_is_locked()); | 4225 | WARN_ON(!dsi_bus_is_locked(dsidev)); |
3128 | 4226 | ||
3129 | mutex_lock(&dsi.lock); | 4227 | mutex_lock(&dsi->lock); |
3130 | 4228 | ||
3131 | r = omap_dss_start_device(dssdev); | 4229 | r = omap_dss_start_device(dssdev); |
3132 | if (r) { | 4230 | if (r) { |
@@ -3135,13 +4233,13 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) | |||
3135 | } | 4233 | } |
3136 | 4234 | ||
3137 | enable_clocks(1); | 4235 | enable_clocks(1); |
3138 | dsi_enable_pll_clock(1); | 4236 | dsi_enable_pll_clock(dsidev, 1); |
3139 | 4237 | ||
3140 | r = _dsi_reset(); | 4238 | r = _dsi_reset(dsidev); |
3141 | if (r) | 4239 | if (r) |
3142 | goto err1; | 4240 | goto err1; |
3143 | 4241 | ||
3144 | dsi_core_init(); | 4242 | dsi_core_init(dsidev); |
3145 | 4243 | ||
3146 | r = dsi_display_init_dispc(dssdev); | 4244 | r = dsi_display_init_dispc(dssdev); |
3147 | if (r) | 4245 | if (r) |
@@ -3151,7 +4249,7 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) | |||
3151 | if (r) | 4249 | if (r) |
3152 | goto err2; | 4250 | goto err2; |
3153 | 4251 | ||
3154 | mutex_unlock(&dsi.lock); | 4252 | mutex_unlock(&dsi->lock); |
3155 | 4253 | ||
3156 | return 0; | 4254 | return 0; |
3157 | 4255 | ||
@@ -3159,39 +4257,46 @@ err2: | |||
3159 | dsi_display_uninit_dispc(dssdev); | 4257 | dsi_display_uninit_dispc(dssdev); |
3160 | err1: | 4258 | err1: |
3161 | enable_clocks(0); | 4259 | enable_clocks(0); |
3162 | dsi_enable_pll_clock(0); | 4260 | dsi_enable_pll_clock(dsidev, 0); |
3163 | omap_dss_stop_device(dssdev); | 4261 | omap_dss_stop_device(dssdev); |
3164 | err0: | 4262 | err0: |
3165 | mutex_unlock(&dsi.lock); | 4263 | mutex_unlock(&dsi->lock); |
3166 | DSSDBG("dsi_display_enable FAILED\n"); | 4264 | DSSDBG("dsi_display_enable FAILED\n"); |
3167 | return r; | 4265 | return r; |
3168 | } | 4266 | } |
3169 | EXPORT_SYMBOL(omapdss_dsi_display_enable); | 4267 | EXPORT_SYMBOL(omapdss_dsi_display_enable); |
3170 | 4268 | ||
3171 | void omapdss_dsi_display_disable(struct omap_dss_device *dssdev) | 4269 | void omapdss_dsi_display_disable(struct omap_dss_device *dssdev, |
4270 | bool disconnect_lanes, bool enter_ulps) | ||
3172 | { | 4271 | { |
4272 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4273 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
4274 | |||
3173 | DSSDBG("dsi_display_disable\n"); | 4275 | DSSDBG("dsi_display_disable\n"); |
3174 | 4276 | ||
3175 | WARN_ON(!dsi_bus_is_locked()); | 4277 | WARN_ON(!dsi_bus_is_locked(dsidev)); |
3176 | 4278 | ||
3177 | mutex_lock(&dsi.lock); | 4279 | mutex_lock(&dsi->lock); |
3178 | 4280 | ||
3179 | dsi_display_uninit_dispc(dssdev); | 4281 | dsi_display_uninit_dispc(dssdev); |
3180 | 4282 | ||
3181 | dsi_display_uninit_dsi(dssdev); | 4283 | dsi_display_uninit_dsi(dssdev, disconnect_lanes, enter_ulps); |
3182 | 4284 | ||
3183 | enable_clocks(0); | 4285 | enable_clocks(0); |
3184 | dsi_enable_pll_clock(0); | 4286 | dsi_enable_pll_clock(dsidev, 0); |
3185 | 4287 | ||
3186 | omap_dss_stop_device(dssdev); | 4288 | omap_dss_stop_device(dssdev); |
3187 | 4289 | ||
3188 | mutex_unlock(&dsi.lock); | 4290 | mutex_unlock(&dsi->lock); |
3189 | } | 4291 | } |
3190 | EXPORT_SYMBOL(omapdss_dsi_display_disable); | 4292 | EXPORT_SYMBOL(omapdss_dsi_display_disable); |
3191 | 4293 | ||
3192 | int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable) | 4294 | int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable) |
3193 | { | 4295 | { |
3194 | dsi.te_enabled = enable; | 4296 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
4297 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
4298 | |||
4299 | dsi->te_enabled = enable; | ||
3195 | return 0; | 4300 | return 0; |
3196 | } | 4301 | } |
3197 | EXPORT_SYMBOL(omapdss_dsi_enable_te); | 4302 | EXPORT_SYMBOL(omapdss_dsi_enable_te); |
@@ -3211,97 +4316,284 @@ void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, | |||
3211 | 4316 | ||
3212 | int dsi_init_display(struct omap_dss_device *dssdev) | 4317 | int dsi_init_display(struct omap_dss_device *dssdev) |
3213 | { | 4318 | { |
4319 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4320 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
4321 | int dsi_module = dsi_get_dsidev_id(dsidev); | ||
4322 | |||
3214 | DSSDBG("DSI init\n"); | 4323 | DSSDBG("DSI init\n"); |
3215 | 4324 | ||
3216 | /* XXX these should be figured out dynamically */ | 4325 | /* XXX these should be figured out dynamically */ |
3217 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | | 4326 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | |
3218 | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; | 4327 | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; |
3219 | 4328 | ||
3220 | dsi.vc[0].dssdev = dssdev; | 4329 | if (dsi->vdds_dsi_reg == NULL) { |
3221 | dsi.vc[1].dssdev = dssdev; | 4330 | struct regulator *vdds_dsi; |
4331 | |||
4332 | vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi"); | ||
4333 | |||
4334 | if (IS_ERR(vdds_dsi)) { | ||
4335 | DSSERR("can't get VDDS_DSI regulator\n"); | ||
4336 | return PTR_ERR(vdds_dsi); | ||
4337 | } | ||
4338 | |||
4339 | dsi->vdds_dsi_reg = vdds_dsi; | ||
4340 | } | ||
4341 | |||
4342 | if (dsi_get_num_data_lanes_dssdev(dssdev) > dsi->num_data_lanes) { | ||
4343 | DSSERR("DSI%d can't support more than %d data lanes\n", | ||
4344 | dsi_module + 1, dsi->num_data_lanes); | ||
4345 | return -EINVAL; | ||
4346 | } | ||
4347 | |||
4348 | return 0; | ||
4349 | } | ||
4350 | |||
4351 | int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel) | ||
4352 | { | ||
4353 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4354 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
4355 | int i; | ||
4356 | |||
4357 | for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) { | ||
4358 | if (!dsi->vc[i].dssdev) { | ||
4359 | dsi->vc[i].dssdev = dssdev; | ||
4360 | *channel = i; | ||
4361 | return 0; | ||
4362 | } | ||
4363 | } | ||
4364 | |||
4365 | DSSERR("cannot get VC for display %s", dssdev->name); | ||
4366 | return -ENOSPC; | ||
4367 | } | ||
4368 | EXPORT_SYMBOL(omap_dsi_request_vc); | ||
4369 | |||
4370 | int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id) | ||
4371 | { | ||
4372 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4373 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
4374 | |||
4375 | if (vc_id < 0 || vc_id > 3) { | ||
4376 | DSSERR("VC ID out of range\n"); | ||
4377 | return -EINVAL; | ||
4378 | } | ||
4379 | |||
4380 | if (channel < 0 || channel > 3) { | ||
4381 | DSSERR("Virtual Channel out of range\n"); | ||
4382 | return -EINVAL; | ||
4383 | } | ||
4384 | |||
4385 | if (dsi->vc[channel].dssdev != dssdev) { | ||
4386 | DSSERR("Virtual Channel not allocated to display %s\n", | ||
4387 | dssdev->name); | ||
4388 | return -EINVAL; | ||
4389 | } | ||
4390 | |||
4391 | dsi->vc[channel].vc_id = vc_id; | ||
3222 | 4392 | ||
3223 | return 0; | 4393 | return 0; |
3224 | } | 4394 | } |
4395 | EXPORT_SYMBOL(omap_dsi_set_vc_id); | ||
4396 | |||
4397 | void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel) | ||
4398 | { | ||
4399 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4400 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
4401 | |||
4402 | if ((channel >= 0 && channel <= 3) && | ||
4403 | dsi->vc[channel].dssdev == dssdev) { | ||
4404 | dsi->vc[channel].dssdev = NULL; | ||
4405 | dsi->vc[channel].vc_id = 0; | ||
4406 | } | ||
4407 | } | ||
4408 | EXPORT_SYMBOL(omap_dsi_release_vc); | ||
4409 | |||
4410 | void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev) | ||
4411 | { | ||
4412 | if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 7, 1) != 1) | ||
4413 | DSSERR("%s (%s) not active\n", | ||
4414 | dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), | ||
4415 | dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC)); | ||
4416 | } | ||
3225 | 4417 | ||
3226 | void dsi_wait_dsi1_pll_active(void) | 4418 | void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev) |
3227 | { | 4419 | { |
3228 | if (wait_for_bit_change(DSI_PLL_STATUS, 7, 1) != 1) | 4420 | if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 8, 1) != 1) |
3229 | DSSERR("DSI1 PLL clock not active\n"); | 4421 | DSSERR("%s (%s) not active\n", |
4422 | dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), | ||
4423 | dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI)); | ||
3230 | } | 4424 | } |
3231 | 4425 | ||
3232 | void dsi_wait_dsi2_pll_active(void) | 4426 | static void dsi_calc_clock_param_ranges(struct platform_device *dsidev) |
3233 | { | 4427 | { |
3234 | if (wait_for_bit_change(DSI_PLL_STATUS, 8, 1) != 1) | 4428 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
3235 | DSSERR("DSI2 PLL clock not active\n"); | 4429 | |
4430 | dsi->regn_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGN); | ||
4431 | dsi->regm_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM); | ||
4432 | dsi->regm_dispc_max = | ||
4433 | dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DISPC); | ||
4434 | dsi->regm_dsi_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DSI); | ||
4435 | dsi->fint_min = dss_feat_get_param_min(FEAT_PARAM_DSIPLL_FINT); | ||
4436 | dsi->fint_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_FINT); | ||
4437 | dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV); | ||
3236 | } | 4438 | } |
3237 | 4439 | ||
3238 | int dsi_init(struct platform_device *pdev) | 4440 | static int dsi_init(struct platform_device *dsidev) |
3239 | { | 4441 | { |
4442 | struct omap_display_platform_data *dss_plat_data; | ||
4443 | struct omap_dss_board_info *board_info; | ||
3240 | u32 rev; | 4444 | u32 rev; |
3241 | int r; | 4445 | int r, i, dsi_module = dsi_get_dsidev_id(dsidev); |
4446 | struct resource *dsi_mem; | ||
4447 | struct dsi_data *dsi; | ||
3242 | 4448 | ||
3243 | spin_lock_init(&dsi.errors_lock); | 4449 | dsi = kzalloc(sizeof(*dsi), GFP_KERNEL); |
3244 | dsi.errors = 0; | 4450 | if (!dsi) { |
4451 | r = -ENOMEM; | ||
4452 | goto err0; | ||
4453 | } | ||
3245 | 4454 | ||
3246 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 4455 | dsi->pdev = dsidev; |
3247 | spin_lock_init(&dsi.irq_stats_lock); | 4456 | dsi_pdev_map[dsi_module] = dsidev; |
3248 | dsi.irq_stats.last_reset = jiffies; | 4457 | dev_set_drvdata(&dsidev->dev, dsi); |
3249 | #endif | ||
3250 | 4458 | ||
3251 | init_completion(&dsi.bta_completion); | 4459 | dss_plat_data = dsidev->dev.platform_data; |
4460 | board_info = dss_plat_data->board_data; | ||
4461 | dsi->dsi_mux_pads = board_info->dsi_mux_pads; | ||
3252 | 4462 | ||
3253 | mutex_init(&dsi.lock); | 4463 | spin_lock_init(&dsi->irq_lock); |
3254 | sema_init(&dsi.bus_lock, 1); | 4464 | spin_lock_init(&dsi->errors_lock); |
4465 | dsi->errors = 0; | ||
3255 | 4466 | ||
3256 | dsi.workqueue = create_singlethread_workqueue("dsi"); | 4467 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS |
3257 | if (dsi.workqueue == NULL) | 4468 | spin_lock_init(&dsi->irq_stats_lock); |
3258 | return -ENOMEM; | 4469 | dsi->irq_stats.last_reset = jiffies; |
4470 | #endif | ||
3259 | 4471 | ||
3260 | INIT_DELAYED_WORK_DEFERRABLE(&dsi.framedone_timeout_work, | 4472 | mutex_init(&dsi->lock); |
4473 | sema_init(&dsi->bus_lock, 1); | ||
4474 | |||
4475 | INIT_DELAYED_WORK_DEFERRABLE(&dsi->framedone_timeout_work, | ||
3261 | dsi_framedone_timeout_work_callback); | 4476 | dsi_framedone_timeout_work_callback); |
3262 | 4477 | ||
3263 | #ifdef DSI_CATCH_MISSING_TE | 4478 | #ifdef DSI_CATCH_MISSING_TE |
3264 | init_timer(&dsi.te_timer); | 4479 | init_timer(&dsi->te_timer); |
3265 | dsi.te_timer.function = dsi_te_timeout; | 4480 | dsi->te_timer.function = dsi_te_timeout; |
3266 | dsi.te_timer.data = 0; | 4481 | dsi->te_timer.data = 0; |
3267 | #endif | 4482 | #endif |
3268 | dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS); | 4483 | dsi_mem = platform_get_resource(dsi->pdev, IORESOURCE_MEM, 0); |
3269 | if (!dsi.base) { | 4484 | if (!dsi_mem) { |
4485 | DSSERR("can't get IORESOURCE_MEM DSI\n"); | ||
4486 | r = -EINVAL; | ||
4487 | goto err1; | ||
4488 | } | ||
4489 | dsi->base = ioremap(dsi_mem->start, resource_size(dsi_mem)); | ||
4490 | if (!dsi->base) { | ||
3270 | DSSERR("can't ioremap DSI\n"); | 4491 | DSSERR("can't ioremap DSI\n"); |
3271 | r = -ENOMEM; | 4492 | r = -ENOMEM; |
3272 | goto err1; | 4493 | goto err1; |
3273 | } | 4494 | } |
4495 | dsi->irq = platform_get_irq(dsi->pdev, 0); | ||
4496 | if (dsi->irq < 0) { | ||
4497 | DSSERR("platform_get_irq failed\n"); | ||
4498 | r = -ENODEV; | ||
4499 | goto err2; | ||
4500 | } | ||
3274 | 4501 | ||
3275 | dsi.vdds_dsi_reg = dss_get_vdds_dsi(); | 4502 | r = request_irq(dsi->irq, omap_dsi_irq_handler, IRQF_SHARED, |
3276 | if (IS_ERR(dsi.vdds_dsi_reg)) { | 4503 | dev_name(&dsidev->dev), dsi->pdev); |
3277 | iounmap(dsi.base); | 4504 | if (r < 0) { |
3278 | DSSERR("can't get VDDS_DSI regulator\n"); | 4505 | DSSERR("request_irq failed\n"); |
3279 | r = PTR_ERR(dsi.vdds_dsi_reg); | ||
3280 | goto err2; | 4506 | goto err2; |
3281 | } | 4507 | } |
3282 | 4508 | ||
4509 | /* DSI VCs initialization */ | ||
4510 | for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) { | ||
4511 | dsi->vc[i].mode = DSI_VC_MODE_L4; | ||
4512 | dsi->vc[i].dssdev = NULL; | ||
4513 | dsi->vc[i].vc_id = 0; | ||
4514 | } | ||
4515 | |||
4516 | dsi_calc_clock_param_ranges(dsidev); | ||
4517 | |||
3283 | enable_clocks(1); | 4518 | enable_clocks(1); |
3284 | 4519 | ||
3285 | rev = dsi_read_reg(DSI_REVISION); | 4520 | rev = dsi_read_reg(dsidev, DSI_REVISION); |
3286 | printk(KERN_INFO "OMAP DSI rev %d.%d\n", | 4521 | dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n", |
3287 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | 4522 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); |
3288 | 4523 | ||
4524 | dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev); | ||
4525 | |||
3289 | enable_clocks(0); | 4526 | enable_clocks(0); |
3290 | 4527 | ||
3291 | return 0; | 4528 | return 0; |
3292 | err2: | 4529 | err2: |
3293 | iounmap(dsi.base); | 4530 | iounmap(dsi->base); |
3294 | err1: | 4531 | err1: |
3295 | destroy_workqueue(dsi.workqueue); | 4532 | kfree(dsi); |
4533 | err0: | ||
3296 | return r; | 4534 | return r; |
3297 | } | 4535 | } |
3298 | 4536 | ||
3299 | void dsi_exit(void) | 4537 | static void dsi_exit(struct platform_device *dsidev) |
3300 | { | 4538 | { |
3301 | iounmap(dsi.base); | 4539 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
4540 | |||
4541 | if (dsi->vdds_dsi_reg != NULL) { | ||
4542 | if (dsi->vdds_dsi_enabled) { | ||
4543 | regulator_disable(dsi->vdds_dsi_reg); | ||
4544 | dsi->vdds_dsi_enabled = false; | ||
4545 | } | ||
4546 | |||
4547 | regulator_put(dsi->vdds_dsi_reg); | ||
4548 | dsi->vdds_dsi_reg = NULL; | ||
4549 | } | ||
3302 | 4550 | ||
3303 | destroy_workqueue(dsi.workqueue); | 4551 | free_irq(dsi->irq, dsi->pdev); |
4552 | iounmap(dsi->base); | ||
4553 | |||
4554 | kfree(dsi); | ||
3304 | 4555 | ||
3305 | DSSDBG("omap_dsi_exit\n"); | 4556 | DSSDBG("omap_dsi_exit\n"); |
3306 | } | 4557 | } |
3307 | 4558 | ||
4559 | /* DSI1 HW IP initialisation */ | ||
4560 | static int omap_dsi1hw_probe(struct platform_device *dsidev) | ||
4561 | { | ||
4562 | int r; | ||
4563 | |||
4564 | r = dsi_init(dsidev); | ||
4565 | if (r) { | ||
4566 | DSSERR("Failed to initialize DSI\n"); | ||
4567 | goto err_dsi; | ||
4568 | } | ||
4569 | err_dsi: | ||
4570 | return r; | ||
4571 | } | ||
4572 | |||
4573 | static int omap_dsi1hw_remove(struct platform_device *dsidev) | ||
4574 | { | ||
4575 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
4576 | |||
4577 | dsi_exit(dsidev); | ||
4578 | WARN_ON(dsi->scp_clk_refcount > 0); | ||
4579 | return 0; | ||
4580 | } | ||
4581 | |||
4582 | static struct platform_driver omap_dsi1hw_driver = { | ||
4583 | .probe = omap_dsi1hw_probe, | ||
4584 | .remove = omap_dsi1hw_remove, | ||
4585 | .driver = { | ||
4586 | .name = "omapdss_dsi1", | ||
4587 | .owner = THIS_MODULE, | ||
4588 | }, | ||
4589 | }; | ||
4590 | |||
4591 | int dsi_init_platform_driver(void) | ||
4592 | { | ||
4593 | return platform_driver_register(&omap_dsi1hw_driver); | ||
4594 | } | ||
4595 | |||
4596 | void dsi_uninit_platform_driver(void) | ||
4597 | { | ||
4598 | return platform_driver_unregister(&omap_dsi1hw_driver); | ||
4599 | } | ||
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 77c3621c9171..d9489d5c4f08 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c | |||
@@ -26,14 +26,13 @@ | |||
26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/err.h> | 27 | #include <linux/err.h> |
28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/seq_file.h> | 29 | #include <linux/seq_file.h> |
31 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
32 | 31 | ||
33 | #include <plat/display.h> | 32 | #include <video/omapdss.h> |
33 | #include <plat/clock.h> | ||
34 | #include "dss.h" | 34 | #include "dss.h" |
35 | 35 | #include "dss_features.h" | |
36 | #define DSS_BASE 0x48050000 | ||
37 | 36 | ||
38 | #define DSS_SZ_REGS SZ_512 | 37 | #define DSS_SZ_REGS SZ_512 |
39 | 38 | ||
@@ -46,7 +45,6 @@ struct dss_reg { | |||
46 | #define DSS_REVISION DSS_REG(0x0000) | 45 | #define DSS_REVISION DSS_REG(0x0000) |
47 | #define DSS_SYSCONFIG DSS_REG(0x0010) | 46 | #define DSS_SYSCONFIG DSS_REG(0x0010) |
48 | #define DSS_SYSSTATUS DSS_REG(0x0014) | 47 | #define DSS_SYSSTATUS DSS_REG(0x0014) |
49 | #define DSS_IRQSTATUS DSS_REG(0x0018) | ||
50 | #define DSS_CONTROL DSS_REG(0x0040) | 48 | #define DSS_CONTROL DSS_REG(0x0040) |
51 | #define DSS_SDI_CONTROL DSS_REG(0x0044) | 49 | #define DSS_SDI_CONTROL DSS_REG(0x0044) |
52 | #define DSS_PLL_CONTROL DSS_REG(0x0048) | 50 | #define DSS_PLL_CONTROL DSS_REG(0x0048) |
@@ -59,21 +57,41 @@ struct dss_reg { | |||
59 | dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end)) | 57 | dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end)) |
60 | 58 | ||
61 | static struct { | 59 | static struct { |
60 | struct platform_device *pdev; | ||
62 | void __iomem *base; | 61 | void __iomem *base; |
62 | int ctx_id; | ||
63 | 63 | ||
64 | struct clk *dpll4_m4_ck; | 64 | struct clk *dpll4_m4_ck; |
65 | struct clk *dss_ick; | ||
66 | struct clk *dss_fck; | ||
67 | struct clk *dss_sys_clk; | ||
68 | struct clk *dss_tv_fck; | ||
69 | struct clk *dss_video_fck; | ||
70 | unsigned num_clks_enabled; | ||
65 | 71 | ||
66 | unsigned long cache_req_pck; | 72 | unsigned long cache_req_pck; |
67 | unsigned long cache_prate; | 73 | unsigned long cache_prate; |
68 | struct dss_clock_info cache_dss_cinfo; | 74 | struct dss_clock_info cache_dss_cinfo; |
69 | struct dispc_clock_info cache_dispc_cinfo; | 75 | struct dispc_clock_info cache_dispc_cinfo; |
70 | 76 | ||
71 | enum dss_clk_source dsi_clk_source; | 77 | enum omap_dss_clk_source dsi_clk_source[MAX_NUM_DSI]; |
72 | enum dss_clk_source dispc_clk_source; | 78 | enum omap_dss_clk_source dispc_clk_source; |
79 | enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS]; | ||
73 | 80 | ||
74 | u32 ctx[DSS_SZ_REGS / sizeof(u32)]; | 81 | u32 ctx[DSS_SZ_REGS / sizeof(u32)]; |
75 | } dss; | 82 | } dss; |
76 | 83 | ||
84 | static const char * const dss_generic_clk_source_names[] = { | ||
85 | [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC", | ||
86 | [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI", | ||
87 | [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK", | ||
88 | }; | ||
89 | |||
90 | static void dss_clk_enable_all_no_ctx(void); | ||
91 | static void dss_clk_disable_all_no_ctx(void); | ||
92 | static void dss_clk_enable_no_ctx(enum dss_clock clks); | ||
93 | static void dss_clk_disable_no_ctx(enum dss_clock clks); | ||
94 | |||
77 | static int _omap_dss_wait_reset(void); | 95 | static int _omap_dss_wait_reset(void); |
78 | 96 | ||
79 | static inline void dss_write_reg(const struct dss_reg idx, u32 val) | 97 | static inline void dss_write_reg(const struct dss_reg idx, u32 val) |
@@ -99,10 +117,11 @@ void dss_save_context(void) | |||
99 | SR(SYSCONFIG); | 117 | SR(SYSCONFIG); |
100 | SR(CONTROL); | 118 | SR(CONTROL); |
101 | 119 | ||
102 | #ifdef CONFIG_OMAP2_DSS_SDI | 120 | if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & |
103 | SR(SDI_CONTROL); | 121 | OMAP_DISPLAY_TYPE_SDI) { |
104 | SR(PLL_CONTROL); | 122 | SR(SDI_CONTROL); |
105 | #endif | 123 | SR(PLL_CONTROL); |
124 | } | ||
106 | } | 125 | } |
107 | 126 | ||
108 | void dss_restore_context(void) | 127 | void dss_restore_context(void) |
@@ -113,10 +132,11 @@ void dss_restore_context(void) | |||
113 | RR(SYSCONFIG); | 132 | RR(SYSCONFIG); |
114 | RR(CONTROL); | 133 | RR(CONTROL); |
115 | 134 | ||
116 | #ifdef CONFIG_OMAP2_DSS_SDI | 135 | if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & |
117 | RR(SDI_CONTROL); | 136 | OMAP_DISPLAY_TYPE_SDI) { |
118 | RR(PLL_CONTROL); | 137 | RR(SDI_CONTROL); |
119 | #endif | 138 | RR(PLL_CONTROL); |
139 | } | ||
120 | } | 140 | } |
121 | 141 | ||
122 | #undef SR | 142 | #undef SR |
@@ -209,125 +229,235 @@ void dss_sdi_disable(void) | |||
209 | REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */ | 229 | REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */ |
210 | } | 230 | } |
211 | 231 | ||
232 | const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src) | ||
233 | { | ||
234 | return dss_generic_clk_source_names[clk_src]; | ||
235 | } | ||
236 | |||
212 | void dss_dump_clocks(struct seq_file *s) | 237 | void dss_dump_clocks(struct seq_file *s) |
213 | { | 238 | { |
214 | unsigned long dpll4_ck_rate; | 239 | unsigned long dpll4_ck_rate; |
215 | unsigned long dpll4_m4_ck_rate; | 240 | unsigned long dpll4_m4_ck_rate; |
241 | const char *fclk_name, *fclk_real_name; | ||
242 | unsigned long fclk_rate; | ||
216 | 243 | ||
217 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 244 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
218 | |||
219 | dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); | ||
220 | dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck); | ||
221 | 245 | ||
222 | seq_printf(s, "- DSS -\n"); | 246 | seq_printf(s, "- DSS -\n"); |
223 | 247 | ||
224 | seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); | 248 | fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK); |
249 | fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK); | ||
250 | fclk_rate = dss_clk_get_rate(DSS_CLK_FCK); | ||
225 | 251 | ||
226 | if (cpu_is_omap3630()) | 252 | if (dss.dpll4_m4_ck) { |
227 | seq_printf(s, "dss1_alwon_fclk = %lu / %lu = %lu\n", | 253 | dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); |
228 | dpll4_ck_rate, | 254 | dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck); |
229 | dpll4_ck_rate / dpll4_m4_ck_rate, | 255 | |
230 | dss_clk_get_rate(DSS_CLK_FCK1)); | 256 | seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); |
231 | else | ||
232 | seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n", | ||
233 | dpll4_ck_rate, | ||
234 | dpll4_ck_rate / dpll4_m4_ck_rate, | ||
235 | dss_clk_get_rate(DSS_CLK_FCK1)); | ||
236 | 257 | ||
237 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 258 | if (cpu_is_omap3630() || cpu_is_omap44xx()) |
259 | seq_printf(s, "%s (%s) = %lu / %lu = %lu\n", | ||
260 | fclk_name, fclk_real_name, | ||
261 | dpll4_ck_rate, | ||
262 | dpll4_ck_rate / dpll4_m4_ck_rate, | ||
263 | fclk_rate); | ||
264 | else | ||
265 | seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n", | ||
266 | fclk_name, fclk_real_name, | ||
267 | dpll4_ck_rate, | ||
268 | dpll4_ck_rate / dpll4_m4_ck_rate, | ||
269 | fclk_rate); | ||
270 | } else { | ||
271 | seq_printf(s, "%s (%s) = %lu\n", | ||
272 | fclk_name, fclk_real_name, | ||
273 | fclk_rate); | ||
274 | } | ||
275 | |||
276 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); | ||
238 | } | 277 | } |
239 | 278 | ||
240 | void dss_dump_regs(struct seq_file *s) | 279 | void dss_dump_regs(struct seq_file *s) |
241 | { | 280 | { |
242 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r)) | 281 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r)) |
243 | 282 | ||
244 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 283 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
245 | 284 | ||
246 | DUMPREG(DSS_REVISION); | 285 | DUMPREG(DSS_REVISION); |
247 | DUMPREG(DSS_SYSCONFIG); | 286 | DUMPREG(DSS_SYSCONFIG); |
248 | DUMPREG(DSS_SYSSTATUS); | 287 | DUMPREG(DSS_SYSSTATUS); |
249 | DUMPREG(DSS_IRQSTATUS); | ||
250 | DUMPREG(DSS_CONTROL); | 288 | DUMPREG(DSS_CONTROL); |
251 | DUMPREG(DSS_SDI_CONTROL); | ||
252 | DUMPREG(DSS_PLL_CONTROL); | ||
253 | DUMPREG(DSS_SDI_STATUS); | ||
254 | 289 | ||
255 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 290 | if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & |
291 | OMAP_DISPLAY_TYPE_SDI) { | ||
292 | DUMPREG(DSS_SDI_CONTROL); | ||
293 | DUMPREG(DSS_PLL_CONTROL); | ||
294 | DUMPREG(DSS_SDI_STATUS); | ||
295 | } | ||
296 | |||
297 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); | ||
256 | #undef DUMPREG | 298 | #undef DUMPREG |
257 | } | 299 | } |
258 | 300 | ||
259 | void dss_select_dispc_clk_source(enum dss_clk_source clk_src) | 301 | void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src) |
260 | { | 302 | { |
303 | struct platform_device *dsidev; | ||
261 | int b; | 304 | int b; |
305 | u8 start, end; | ||
306 | |||
307 | switch (clk_src) { | ||
308 | case OMAP_DSS_CLK_SRC_FCK: | ||
309 | b = 0; | ||
310 | break; | ||
311 | case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: | ||
312 | b = 1; | ||
313 | dsidev = dsi_get_dsidev_from_id(0); | ||
314 | dsi_wait_pll_hsdiv_dispc_active(dsidev); | ||
315 | break; | ||
316 | case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: | ||
317 | b = 2; | ||
318 | dsidev = dsi_get_dsidev_from_id(1); | ||
319 | dsi_wait_pll_hsdiv_dispc_active(dsidev); | ||
320 | break; | ||
321 | default: | ||
322 | BUG(); | ||
323 | } | ||
262 | 324 | ||
263 | BUG_ON(clk_src != DSS_SRC_DSI1_PLL_FCLK && | 325 | dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end); |
264 | clk_src != DSS_SRC_DSS1_ALWON_FCLK); | ||
265 | |||
266 | b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1; | ||
267 | |||
268 | if (clk_src == DSS_SRC_DSI1_PLL_FCLK) | ||
269 | dsi_wait_dsi1_pll_active(); | ||
270 | 326 | ||
271 | REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */ | 327 | REG_FLD_MOD(DSS_CONTROL, b, start, end); /* DISPC_CLK_SWITCH */ |
272 | 328 | ||
273 | dss.dispc_clk_source = clk_src; | 329 | dss.dispc_clk_source = clk_src; |
274 | } | 330 | } |
275 | 331 | ||
276 | void dss_select_dsi_clk_source(enum dss_clk_source clk_src) | 332 | void dss_select_dsi_clk_source(int dsi_module, |
333 | enum omap_dss_clk_source clk_src) | ||
277 | { | 334 | { |
335 | struct platform_device *dsidev; | ||
278 | int b; | 336 | int b; |
279 | 337 | ||
280 | BUG_ON(clk_src != DSS_SRC_DSI2_PLL_FCLK && | 338 | switch (clk_src) { |
281 | clk_src != DSS_SRC_DSS1_ALWON_FCLK); | 339 | case OMAP_DSS_CLK_SRC_FCK: |
340 | b = 0; | ||
341 | break; | ||
342 | case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI: | ||
343 | BUG_ON(dsi_module != 0); | ||
344 | b = 1; | ||
345 | dsidev = dsi_get_dsidev_from_id(0); | ||
346 | dsi_wait_pll_hsdiv_dsi_active(dsidev); | ||
347 | break; | ||
348 | case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI: | ||
349 | BUG_ON(dsi_module != 1); | ||
350 | b = 1; | ||
351 | dsidev = dsi_get_dsidev_from_id(1); | ||
352 | dsi_wait_pll_hsdiv_dsi_active(dsidev); | ||
353 | break; | ||
354 | default: | ||
355 | BUG(); | ||
356 | } | ||
282 | 357 | ||
283 | b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1; | 358 | REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */ |
284 | 359 | ||
285 | if (clk_src == DSS_SRC_DSI2_PLL_FCLK) | 360 | dss.dsi_clk_source[dsi_module] = clk_src; |
286 | dsi_wait_dsi2_pll_active(); | 361 | } |
287 | 362 | ||
288 | REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */ | 363 | void dss_select_lcd_clk_source(enum omap_channel channel, |
364 | enum omap_dss_clk_source clk_src) | ||
365 | { | ||
366 | struct platform_device *dsidev; | ||
367 | int b, ix, pos; | ||
289 | 368 | ||
290 | dss.dsi_clk_source = clk_src; | 369 | if (!dss_has_feature(FEAT_LCD_CLK_SRC)) |
370 | return; | ||
371 | |||
372 | switch (clk_src) { | ||
373 | case OMAP_DSS_CLK_SRC_FCK: | ||
374 | b = 0; | ||
375 | break; | ||
376 | case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: | ||
377 | BUG_ON(channel != OMAP_DSS_CHANNEL_LCD); | ||
378 | b = 1; | ||
379 | dsidev = dsi_get_dsidev_from_id(0); | ||
380 | dsi_wait_pll_hsdiv_dispc_active(dsidev); | ||
381 | break; | ||
382 | case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: | ||
383 | BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2); | ||
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 | } | ||
391 | |||
392 | pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 12; | ||
393 | REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* LCDx_CLK_SWITCH */ | ||
394 | |||
395 | ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1; | ||
396 | dss.lcd_clk_source[ix] = clk_src; | ||
291 | } | 397 | } |
292 | 398 | ||
293 | enum dss_clk_source dss_get_dispc_clk_source(void) | 399 | enum omap_dss_clk_source dss_get_dispc_clk_source(void) |
294 | { | 400 | { |
295 | return dss.dispc_clk_source; | 401 | return dss.dispc_clk_source; |
296 | } | 402 | } |
297 | 403 | ||
298 | enum dss_clk_source dss_get_dsi_clk_source(void) | 404 | enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module) |
299 | { | 405 | { |
300 | return dss.dsi_clk_source; | 406 | return dss.dsi_clk_source[dsi_module]; |
407 | } | ||
408 | |||
409 | enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) | ||
410 | { | ||
411 | if (dss_has_feature(FEAT_LCD_CLK_SRC)) { | ||
412 | int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1; | ||
413 | return dss.lcd_clk_source[ix]; | ||
414 | } else { | ||
415 | /* LCD_CLK source is the same as DISPC_FCLK source for | ||
416 | * OMAP2 and OMAP3 */ | ||
417 | return dss.dispc_clk_source; | ||
418 | } | ||
301 | } | 419 | } |
302 | 420 | ||
303 | /* calculate clock rates using dividers in cinfo */ | 421 | /* calculate clock rates using dividers in cinfo */ |
304 | int dss_calc_clock_rates(struct dss_clock_info *cinfo) | 422 | int dss_calc_clock_rates(struct dss_clock_info *cinfo) |
305 | { | 423 | { |
306 | unsigned long prate; | 424 | if (dss.dpll4_m4_ck) { |
425 | unsigned long prate; | ||
426 | u16 fck_div_max = 16; | ||
307 | 427 | ||
308 | if (cinfo->fck_div > (cpu_is_omap3630() ? 32 : 16) || | 428 | if (cpu_is_omap3630() || cpu_is_omap44xx()) |
309 | cinfo->fck_div == 0) | 429 | fck_div_max = 32; |
310 | return -EINVAL; | 430 | |
431 | if (cinfo->fck_div > fck_div_max || cinfo->fck_div == 0) | ||
432 | return -EINVAL; | ||
311 | 433 | ||
312 | prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); | 434 | prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); |
313 | 435 | ||
314 | cinfo->fck = prate / cinfo->fck_div; | 436 | cinfo->fck = prate / cinfo->fck_div; |
437 | } else { | ||
438 | if (cinfo->fck_div != 0) | ||
439 | return -EINVAL; | ||
440 | cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK); | ||
441 | } | ||
315 | 442 | ||
316 | return 0; | 443 | return 0; |
317 | } | 444 | } |
318 | 445 | ||
319 | int dss_set_clock_div(struct dss_clock_info *cinfo) | 446 | int dss_set_clock_div(struct dss_clock_info *cinfo) |
320 | { | 447 | { |
321 | unsigned long prate; | 448 | if (dss.dpll4_m4_ck) { |
322 | int r; | 449 | unsigned long prate; |
450 | int r; | ||
323 | 451 | ||
324 | if (cpu_is_omap34xx()) { | ||
325 | prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); | 452 | prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); |
326 | DSSDBG("dpll4_m4 = %ld\n", prate); | 453 | DSSDBG("dpll4_m4 = %ld\n", prate); |
327 | 454 | ||
328 | r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div); | 455 | r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div); |
329 | if (r) | 456 | if (r) |
330 | return r; | 457 | return r; |
458 | } else { | ||
459 | if (cinfo->fck_div != 0) | ||
460 | return -EINVAL; | ||
331 | } | 461 | } |
332 | 462 | ||
333 | DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); | 463 | DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); |
@@ -337,12 +467,14 @@ int dss_set_clock_div(struct dss_clock_info *cinfo) | |||
337 | 467 | ||
338 | int dss_get_clock_div(struct dss_clock_info *cinfo) | 468 | int dss_get_clock_div(struct dss_clock_info *cinfo) |
339 | { | 469 | { |
340 | cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1); | 470 | cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK); |
341 | 471 | ||
342 | if (cpu_is_omap34xx()) { | 472 | if (dss.dpll4_m4_ck) { |
343 | unsigned long prate; | 473 | unsigned long prate; |
474 | |||
344 | prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); | 475 | prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); |
345 | if (cpu_is_omap3630()) | 476 | |
477 | if (cpu_is_omap3630() || cpu_is_omap44xx()) | ||
346 | cinfo->fck_div = prate / (cinfo->fck); | 478 | cinfo->fck_div = prate / (cinfo->fck); |
347 | else | 479 | else |
348 | cinfo->fck_div = prate / (cinfo->fck / 2); | 480 | cinfo->fck_div = prate / (cinfo->fck / 2); |
@@ -355,7 +487,7 @@ int dss_get_clock_div(struct dss_clock_info *cinfo) | |||
355 | 487 | ||
356 | unsigned long dss_get_dpll4_rate(void) | 488 | unsigned long dss_get_dpll4_rate(void) |
357 | { | 489 | { |
358 | if (cpu_is_omap34xx()) | 490 | if (dss.dpll4_m4_ck) |
359 | return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); | 491 | return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); |
360 | else | 492 | else |
361 | return 0; | 493 | return 0; |
@@ -369,16 +501,18 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck, | |||
369 | struct dss_clock_info best_dss; | 501 | struct dss_clock_info best_dss; |
370 | struct dispc_clock_info best_dispc; | 502 | struct dispc_clock_info best_dispc; |
371 | 503 | ||
372 | unsigned long fck; | 504 | unsigned long fck, max_dss_fck; |
373 | 505 | ||
374 | u16 fck_div; | 506 | u16 fck_div, fck_div_max = 16; |
375 | 507 | ||
376 | int match = 0; | 508 | int match = 0; |
377 | int min_fck_per_pck; | 509 | int min_fck_per_pck; |
378 | 510 | ||
379 | prate = dss_get_dpll4_rate(); | 511 | prate = dss_get_dpll4_rate(); |
380 | 512 | ||
381 | fck = dss_clk_get_rate(DSS_CLK_FCK1); | 513 | max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); |
514 | |||
515 | fck = dss_clk_get_rate(DSS_CLK_FCK); | ||
382 | if (req_pck == dss.cache_req_pck && | 516 | if (req_pck == dss.cache_req_pck && |
383 | ((cpu_is_omap34xx() && prate == dss.cache_prate) || | 517 | ((cpu_is_omap34xx() && prate == dss.cache_prate) || |
384 | dss.cache_dss_cinfo.fck == fck)) { | 518 | dss.cache_dss_cinfo.fck == fck)) { |
@@ -391,7 +525,7 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck, | |||
391 | min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; | 525 | min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; |
392 | 526 | ||
393 | if (min_fck_per_pck && | 527 | if (min_fck_per_pck && |
394 | req_pck * min_fck_per_pck > DISPC_MAX_FCK) { | 528 | req_pck * min_fck_per_pck > max_dss_fck) { |
395 | DSSERR("Requested pixel clock not possible with the current " | 529 | DSSERR("Requested pixel clock not possible with the current " |
396 | "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " | 530 | "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " |
397 | "the constraint off.\n"); | 531 | "the constraint off.\n"); |
@@ -402,10 +536,10 @@ retry: | |||
402 | memset(&best_dss, 0, sizeof(best_dss)); | 536 | memset(&best_dss, 0, sizeof(best_dss)); |
403 | memset(&best_dispc, 0, sizeof(best_dispc)); | 537 | memset(&best_dispc, 0, sizeof(best_dispc)); |
404 | 538 | ||
405 | if (cpu_is_omap24xx()) { | 539 | if (dss.dpll4_m4_ck == NULL) { |
406 | struct dispc_clock_info cur_dispc; | 540 | struct dispc_clock_info cur_dispc; |
407 | /* XXX can we change the clock on omap2? */ | 541 | /* XXX can we change the clock on omap2? */ |
408 | fck = dss_clk_get_rate(DSS_CLK_FCK1); | 542 | fck = dss_clk_get_rate(DSS_CLK_FCK); |
409 | fck_div = 1; | 543 | fck_div = 1; |
410 | 544 | ||
411 | dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc); | 545 | dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc); |
@@ -417,17 +551,19 @@ retry: | |||
417 | best_dispc = cur_dispc; | 551 | best_dispc = cur_dispc; |
418 | 552 | ||
419 | goto found; | 553 | goto found; |
420 | } else if (cpu_is_omap34xx()) { | 554 | } else { |
421 | for (fck_div = (cpu_is_omap3630() ? 32 : 16); | 555 | if (cpu_is_omap3630() || cpu_is_omap44xx()) |
422 | fck_div > 0; --fck_div) { | 556 | fck_div_max = 32; |
557 | |||
558 | for (fck_div = fck_div_max; fck_div > 0; --fck_div) { | ||
423 | struct dispc_clock_info cur_dispc; | 559 | struct dispc_clock_info cur_dispc; |
424 | 560 | ||
425 | if (cpu_is_omap3630()) | 561 | if (fck_div_max == 32) |
426 | fck = prate / fck_div; | 562 | fck = prate / fck_div; |
427 | else | 563 | else |
428 | fck = prate / fck_div * 2; | 564 | fck = prate / fck_div * 2; |
429 | 565 | ||
430 | if (fck > DISPC_MAX_FCK) | 566 | if (fck > max_dss_fck) |
431 | continue; | 567 | continue; |
432 | 568 | ||
433 | if (min_fck_per_pck && | 569 | if (min_fck_per_pck && |
@@ -450,8 +586,6 @@ retry: | |||
450 | goto found; | 586 | goto found; |
451 | } | 587 | } |
452 | } | 588 | } |
453 | } else { | ||
454 | BUG(); | ||
455 | } | 589 | } |
456 | 590 | ||
457 | found: | 591 | found: |
@@ -482,31 +616,6 @@ found: | |||
482 | return 0; | 616 | return 0; |
483 | } | 617 | } |
484 | 618 | ||
485 | |||
486 | |||
487 | static irqreturn_t dss_irq_handler_omap2(int irq, void *arg) | ||
488 | { | ||
489 | dispc_irq_handler(); | ||
490 | |||
491 | return IRQ_HANDLED; | ||
492 | } | ||
493 | |||
494 | static irqreturn_t dss_irq_handler_omap3(int irq, void *arg) | ||
495 | { | ||
496 | u32 irqstatus; | ||
497 | |||
498 | irqstatus = dss_read_reg(DSS_IRQSTATUS); | ||
499 | |||
500 | if (irqstatus & (1<<0)) /* DISPC_IRQ */ | ||
501 | dispc_irq_handler(); | ||
502 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
503 | if (irqstatus & (1<<1)) /* DSI_IRQ */ | ||
504 | dsi_irq_handler(); | ||
505 | #endif | ||
506 | |||
507 | return IRQ_HANDLED; | ||
508 | } | ||
509 | |||
510 | static int _omap_dss_wait_reset(void) | 619 | static int _omap_dss_wait_reset(void) |
511 | { | 620 | { |
512 | int t = 0; | 621 | int t = 0; |
@@ -549,34 +658,50 @@ void dss_set_dac_pwrdn_bgz(bool enable) | |||
549 | REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */ | 658 | REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */ |
550 | } | 659 | } |
551 | 660 | ||
552 | int dss_init(bool skip_init) | 661 | void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi) |
662 | { | ||
663 | REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */ | ||
664 | } | ||
665 | |||
666 | static int dss_init(void) | ||
553 | { | 667 | { |
554 | int r; | 668 | int r; |
555 | u32 rev; | 669 | u32 rev; |
670 | struct resource *dss_mem; | ||
671 | struct clk *dpll4_m4_ck; | ||
556 | 672 | ||
557 | dss.base = ioremap(DSS_BASE, DSS_SZ_REGS); | 673 | dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0); |
674 | if (!dss_mem) { | ||
675 | DSSERR("can't get IORESOURCE_MEM DSS\n"); | ||
676 | r = -EINVAL; | ||
677 | goto fail0; | ||
678 | } | ||
679 | dss.base = ioremap(dss_mem->start, resource_size(dss_mem)); | ||
558 | if (!dss.base) { | 680 | if (!dss.base) { |
559 | DSSERR("can't ioremap DSS\n"); | 681 | DSSERR("can't ioremap DSS\n"); |
560 | r = -ENOMEM; | 682 | r = -ENOMEM; |
561 | goto fail0; | 683 | goto fail0; |
562 | } | 684 | } |
563 | 685 | ||
564 | if (!skip_init) { | 686 | /* disable LCD and DIGIT output. This seems to fix the synclost |
565 | /* disable LCD and DIGIT output. This seems to fix the synclost | 687 | * problem that we get, if the bootloader starts the DSS and |
566 | * problem that we get, if the bootloader starts the DSS and | 688 | * the kernel resets it */ |
567 | * the kernel resets it */ | 689 | omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440); |
568 | omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440); | 690 | |
569 | 691 | #ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET | |
570 | /* We need to wait here a bit, otherwise we sometimes start to | 692 | /* We need to wait here a bit, otherwise we sometimes start to |
571 | * get synclost errors, and after that only power cycle will | 693 | * get synclost errors, and after that only power cycle will |
572 | * restore DSS functionality. I have no idea why this happens. | 694 | * restore DSS functionality. I have no idea why this happens. |
573 | * And we have to wait _before_ resetting the DSS, but after | 695 | * And we have to wait _before_ resetting the DSS, but after |
574 | * enabling clocks. | 696 | * enabling clocks. |
575 | */ | 697 | * |
576 | msleep(50); | 698 | * This bug was at least present on OMAP3430. It's unknown |
699 | * if it happens on OMAP2 or OMAP3630. | ||
700 | */ | ||
701 | msleep(50); | ||
702 | #endif | ||
577 | 703 | ||
578 | _omap_dss_reset(); | 704 | _omap_dss_reset(); |
579 | } | ||
580 | 705 | ||
581 | /* autoidle */ | 706 | /* autoidle */ |
582 | REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0); | 707 | REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0); |
@@ -589,29 +714,31 @@ int dss_init(bool skip_init) | |||
589 | REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ | 714 | REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ |
590 | REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ | 715 | REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ |
591 | #endif | 716 | #endif |
592 | |||
593 | r = request_irq(INT_24XX_DSS_IRQ, | ||
594 | cpu_is_omap24xx() | ||
595 | ? dss_irq_handler_omap2 | ||
596 | : dss_irq_handler_omap3, | ||
597 | 0, "OMAP DSS", NULL); | ||
598 | |||
599 | if (r < 0) { | ||
600 | DSSERR("omap2 dss: request_irq failed\n"); | ||
601 | goto fail1; | ||
602 | } | ||
603 | |||
604 | if (cpu_is_omap34xx()) { | 717 | if (cpu_is_omap34xx()) { |
605 | dss.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); | 718 | dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); |
606 | if (IS_ERR(dss.dpll4_m4_ck)) { | 719 | if (IS_ERR(dpll4_m4_ck)) { |
607 | DSSERR("Failed to get dpll4_m4_ck\n"); | 720 | DSSERR("Failed to get dpll4_m4_ck\n"); |
608 | r = PTR_ERR(dss.dpll4_m4_ck); | 721 | r = PTR_ERR(dpll4_m4_ck); |
609 | goto fail2; | 722 | goto fail1; |
610 | } | 723 | } |
724 | } else if (cpu_is_omap44xx()) { | ||
725 | dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck"); | ||
726 | if (IS_ERR(dpll4_m4_ck)) { | ||
727 | DSSERR("Failed to get dpll4_m4_ck\n"); | ||
728 | r = PTR_ERR(dpll4_m4_ck); | ||
729 | goto fail1; | ||
730 | } | ||
731 | } else { /* omap24xx */ | ||
732 | dpll4_m4_ck = NULL; | ||
611 | } | 733 | } |
612 | 734 | ||
613 | dss.dsi_clk_source = DSS_SRC_DSS1_ALWON_FCLK; | 735 | dss.dpll4_m4_ck = dpll4_m4_ck; |
614 | dss.dispc_clk_source = DSS_SRC_DSS1_ALWON_FCLK; | 736 | |
737 | dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; | ||
738 | dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; | ||
739 | dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK; | ||
740 | dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; | ||
741 | dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; | ||
615 | 742 | ||
616 | dss_save_context(); | 743 | dss_save_context(); |
617 | 744 | ||
@@ -621,21 +748,427 @@ int dss_init(bool skip_init) | |||
621 | 748 | ||
622 | return 0; | 749 | return 0; |
623 | 750 | ||
624 | fail2: | ||
625 | free_irq(INT_24XX_DSS_IRQ, NULL); | ||
626 | fail1: | 751 | fail1: |
627 | iounmap(dss.base); | 752 | iounmap(dss.base); |
628 | fail0: | 753 | fail0: |
629 | return r; | 754 | return r; |
630 | } | 755 | } |
631 | 756 | ||
632 | void dss_exit(void) | 757 | static void dss_exit(void) |
633 | { | 758 | { |
634 | if (cpu_is_omap34xx()) | 759 | if (dss.dpll4_m4_ck) |
635 | clk_put(dss.dpll4_m4_ck); | 760 | clk_put(dss.dpll4_m4_ck); |
636 | 761 | ||
637 | free_irq(INT_24XX_DSS_IRQ, NULL); | ||
638 | |||
639 | iounmap(dss.base); | 762 | iounmap(dss.base); |
640 | } | 763 | } |
641 | 764 | ||
765 | /* CONTEXT */ | ||
766 | static int dss_get_ctx_id(void) | ||
767 | { | ||
768 | struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data; | ||
769 | int r; | ||
770 | |||
771 | if (!pdata->board_data->get_last_off_on_transaction_id) | ||
772 | return 0; | ||
773 | r = pdata->board_data->get_last_off_on_transaction_id(&dss.pdev->dev); | ||
774 | if (r < 0) { | ||
775 | dev_err(&dss.pdev->dev, "getting transaction ID failed, " | ||
776 | "will force context restore\n"); | ||
777 | r = -1; | ||
778 | } | ||
779 | return r; | ||
780 | } | ||
781 | |||
782 | int dss_need_ctx_restore(void) | ||
783 | { | ||
784 | int id = dss_get_ctx_id(); | ||
785 | |||
786 | if (id < 0 || id != dss.ctx_id) { | ||
787 | DSSDBG("ctx id %d -> id %d\n", | ||
788 | dss.ctx_id, id); | ||
789 | dss.ctx_id = id; | ||
790 | return 1; | ||
791 | } else { | ||
792 | return 0; | ||
793 | } | ||
794 | } | ||
795 | |||
796 | static void save_all_ctx(void) | ||
797 | { | ||
798 | DSSDBG("save context\n"); | ||
799 | |||
800 | dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK); | ||
801 | |||
802 | dss_save_context(); | ||
803 | dispc_save_context(); | ||
804 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
805 | dsi_save_context(); | ||
806 | #endif | ||
807 | |||
808 | dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK); | ||
809 | } | ||
810 | |||
811 | static void restore_all_ctx(void) | ||
812 | { | ||
813 | DSSDBG("restore context\n"); | ||
814 | |||
815 | dss_clk_enable_all_no_ctx(); | ||
816 | |||
817 | dss_restore_context(); | ||
818 | dispc_restore_context(); | ||
819 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
820 | dsi_restore_context(); | ||
821 | #endif | ||
822 | |||
823 | dss_clk_disable_all_no_ctx(); | ||
824 | } | ||
825 | |||
826 | static int dss_get_clock(struct clk **clock, const char *clk_name) | ||
827 | { | ||
828 | struct clk *clk; | ||
829 | |||
830 | clk = clk_get(&dss.pdev->dev, clk_name); | ||
831 | |||
832 | if (IS_ERR(clk)) { | ||
833 | DSSERR("can't get clock %s", clk_name); | ||
834 | return PTR_ERR(clk); | ||
835 | } | ||
836 | |||
837 | *clock = clk; | ||
838 | |||
839 | DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk)); | ||
840 | |||
841 | return 0; | ||
842 | } | ||
843 | |||
844 | static int dss_get_clocks(void) | ||
845 | { | ||
846 | int r; | ||
847 | struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data; | ||
848 | |||
849 | dss.dss_ick = NULL; | ||
850 | dss.dss_fck = NULL; | ||
851 | dss.dss_sys_clk = NULL; | ||
852 | dss.dss_tv_fck = NULL; | ||
853 | dss.dss_video_fck = NULL; | ||
854 | |||
855 | r = dss_get_clock(&dss.dss_ick, "ick"); | ||
856 | if (r) | ||
857 | goto err; | ||
858 | |||
859 | r = dss_get_clock(&dss.dss_fck, "fck"); | ||
860 | if (r) | ||
861 | goto err; | ||
862 | |||
863 | if (!pdata->opt_clock_available) { | ||
864 | r = -ENODEV; | ||
865 | goto err; | ||
866 | } | ||
867 | |||
868 | if (pdata->opt_clock_available("sys_clk")) { | ||
869 | r = dss_get_clock(&dss.dss_sys_clk, "sys_clk"); | ||
870 | if (r) | ||
871 | goto err; | ||
872 | } | ||
873 | |||
874 | if (pdata->opt_clock_available("tv_clk")) { | ||
875 | r = dss_get_clock(&dss.dss_tv_fck, "tv_clk"); | ||
876 | if (r) | ||
877 | goto err; | ||
878 | } | ||
879 | |||
880 | if (pdata->opt_clock_available("video_clk")) { | ||
881 | r = dss_get_clock(&dss.dss_video_fck, "video_clk"); | ||
882 | if (r) | ||
883 | goto err; | ||
884 | } | ||
885 | |||
886 | return 0; | ||
887 | |||
888 | err: | ||
889 | if (dss.dss_ick) | ||
890 | clk_put(dss.dss_ick); | ||
891 | if (dss.dss_fck) | ||
892 | clk_put(dss.dss_fck); | ||
893 | if (dss.dss_sys_clk) | ||
894 | clk_put(dss.dss_sys_clk); | ||
895 | if (dss.dss_tv_fck) | ||
896 | clk_put(dss.dss_tv_fck); | ||
897 | if (dss.dss_video_fck) | ||
898 | clk_put(dss.dss_video_fck); | ||
899 | |||
900 | return r; | ||
901 | } | ||
902 | |||
903 | static void dss_put_clocks(void) | ||
904 | { | ||
905 | if (dss.dss_video_fck) | ||
906 | clk_put(dss.dss_video_fck); | ||
907 | if (dss.dss_tv_fck) | ||
908 | clk_put(dss.dss_tv_fck); | ||
909 | if (dss.dss_sys_clk) | ||
910 | clk_put(dss.dss_sys_clk); | ||
911 | clk_put(dss.dss_fck); | ||
912 | clk_put(dss.dss_ick); | ||
913 | } | ||
914 | |||
915 | unsigned long dss_clk_get_rate(enum dss_clock clk) | ||
916 | { | ||
917 | switch (clk) { | ||
918 | case DSS_CLK_ICK: | ||
919 | return clk_get_rate(dss.dss_ick); | ||
920 | case DSS_CLK_FCK: | ||
921 | return clk_get_rate(dss.dss_fck); | ||
922 | case DSS_CLK_SYSCK: | ||
923 | return clk_get_rate(dss.dss_sys_clk); | ||
924 | case DSS_CLK_TVFCK: | ||
925 | return clk_get_rate(dss.dss_tv_fck); | ||
926 | case DSS_CLK_VIDFCK: | ||
927 | return clk_get_rate(dss.dss_video_fck); | ||
928 | } | ||
929 | |||
930 | BUG(); | ||
931 | return 0; | ||
932 | } | ||
933 | |||
934 | static unsigned count_clk_bits(enum dss_clock clks) | ||
935 | { | ||
936 | unsigned num_clks = 0; | ||
937 | |||
938 | if (clks & DSS_CLK_ICK) | ||
939 | ++num_clks; | ||
940 | if (clks & DSS_CLK_FCK) | ||
941 | ++num_clks; | ||
942 | if (clks & DSS_CLK_SYSCK) | ||
943 | ++num_clks; | ||
944 | if (clks & DSS_CLK_TVFCK) | ||
945 | ++num_clks; | ||
946 | if (clks & DSS_CLK_VIDFCK) | ||
947 | ++num_clks; | ||
948 | |||
949 | return num_clks; | ||
950 | } | ||
951 | |||
952 | static void dss_clk_enable_no_ctx(enum dss_clock clks) | ||
953 | { | ||
954 | unsigned num_clks = count_clk_bits(clks); | ||
955 | |||
956 | if (clks & DSS_CLK_ICK) | ||
957 | clk_enable(dss.dss_ick); | ||
958 | if (clks & DSS_CLK_FCK) | ||
959 | clk_enable(dss.dss_fck); | ||
960 | if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk) | ||
961 | clk_enable(dss.dss_sys_clk); | ||
962 | if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck) | ||
963 | clk_enable(dss.dss_tv_fck); | ||
964 | if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck) | ||
965 | clk_enable(dss.dss_video_fck); | ||
966 | |||
967 | dss.num_clks_enabled += num_clks; | ||
968 | } | ||
969 | |||
970 | void dss_clk_enable(enum dss_clock clks) | ||
971 | { | ||
972 | bool check_ctx = dss.num_clks_enabled == 0; | ||
973 | |||
974 | dss_clk_enable_no_ctx(clks); | ||
975 | |||
976 | /* | ||
977 | * HACK: On omap4 the registers may not be accessible right after | ||
978 | * enabling the clocks. At some point this will be handled by | ||
979 | * pm_runtime, but for the time begin this should make things work. | ||
980 | */ | ||
981 | if (cpu_is_omap44xx() && check_ctx) | ||
982 | udelay(10); | ||
983 | |||
984 | if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore()) | ||
985 | restore_all_ctx(); | ||
986 | } | ||
987 | |||
988 | static void dss_clk_disable_no_ctx(enum dss_clock clks) | ||
989 | { | ||
990 | unsigned num_clks = count_clk_bits(clks); | ||
991 | |||
992 | if (clks & DSS_CLK_ICK) | ||
993 | clk_disable(dss.dss_ick); | ||
994 | if (clks & DSS_CLK_FCK) | ||
995 | clk_disable(dss.dss_fck); | ||
996 | if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk) | ||
997 | clk_disable(dss.dss_sys_clk); | ||
998 | if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck) | ||
999 | clk_disable(dss.dss_tv_fck); | ||
1000 | if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck) | ||
1001 | clk_disable(dss.dss_video_fck); | ||
1002 | |||
1003 | dss.num_clks_enabled -= num_clks; | ||
1004 | } | ||
1005 | |||
1006 | void dss_clk_disable(enum dss_clock clks) | ||
1007 | { | ||
1008 | if (cpu_is_omap34xx()) { | ||
1009 | unsigned num_clks = count_clk_bits(clks); | ||
1010 | |||
1011 | BUG_ON(dss.num_clks_enabled < num_clks); | ||
1012 | |||
1013 | if (dss.num_clks_enabled == num_clks) | ||
1014 | save_all_ctx(); | ||
1015 | } | ||
1016 | |||
1017 | dss_clk_disable_no_ctx(clks); | ||
1018 | } | ||
1019 | |||
1020 | static void dss_clk_enable_all_no_ctx(void) | ||
1021 | { | ||
1022 | enum dss_clock clks; | ||
1023 | |||
1024 | clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK; | ||
1025 | if (cpu_is_omap34xx()) | ||
1026 | clks |= DSS_CLK_VIDFCK; | ||
1027 | dss_clk_enable_no_ctx(clks); | ||
1028 | } | ||
1029 | |||
1030 | static void dss_clk_disable_all_no_ctx(void) | ||
1031 | { | ||
1032 | enum dss_clock clks; | ||
1033 | |||
1034 | clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK; | ||
1035 | if (cpu_is_omap34xx()) | ||
1036 | clks |= DSS_CLK_VIDFCK; | ||
1037 | dss_clk_disable_no_ctx(clks); | ||
1038 | } | ||
1039 | |||
1040 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | ||
1041 | /* CLOCKS */ | ||
1042 | static void core_dump_clocks(struct seq_file *s) | ||
1043 | { | ||
1044 | int i; | ||
1045 | struct clk *clocks[5] = { | ||
1046 | dss.dss_ick, | ||
1047 | dss.dss_fck, | ||
1048 | dss.dss_sys_clk, | ||
1049 | dss.dss_tv_fck, | ||
1050 | dss.dss_video_fck | ||
1051 | }; | ||
1052 | |||
1053 | const char *names[5] = { | ||
1054 | "ick", | ||
1055 | "fck", | ||
1056 | "sys_clk", | ||
1057 | "tv_fck", | ||
1058 | "video_fck" | ||
1059 | }; | ||
1060 | |||
1061 | seq_printf(s, "- CORE -\n"); | ||
1062 | |||
1063 | seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled); | ||
1064 | |||
1065 | for (i = 0; i < 5; i++) { | ||
1066 | if (!clocks[i]) | ||
1067 | continue; | ||
1068 | seq_printf(s, "%s (%s)%*s\t%lu\t%d\n", | ||
1069 | names[i], | ||
1070 | clocks[i]->name, | ||
1071 | 24 - strlen(names[i]) - strlen(clocks[i]->name), | ||
1072 | "", | ||
1073 | clk_get_rate(clocks[i]), | ||
1074 | clocks[i]->usecount); | ||
1075 | } | ||
1076 | } | ||
1077 | #endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */ | ||
1078 | |||
1079 | /* DEBUGFS */ | ||
1080 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | ||
1081 | void dss_debug_dump_clocks(struct seq_file *s) | ||
1082 | { | ||
1083 | core_dump_clocks(s); | ||
1084 | dss_dump_clocks(s); | ||
1085 | dispc_dump_clocks(s); | ||
1086 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
1087 | dsi_dump_clocks(s); | ||
1088 | #endif | ||
1089 | } | ||
1090 | #endif | ||
1091 | |||
1092 | |||
1093 | /* DSS HW IP initialisation */ | ||
1094 | static int omap_dsshw_probe(struct platform_device *pdev) | ||
1095 | { | ||
1096 | int r; | ||
1097 | |||
1098 | dss.pdev = pdev; | ||
1099 | |||
1100 | r = dss_get_clocks(); | ||
1101 | if (r) | ||
1102 | goto err_clocks; | ||
1103 | |||
1104 | dss_clk_enable_all_no_ctx(); | ||
1105 | |||
1106 | dss.ctx_id = dss_get_ctx_id(); | ||
1107 | DSSDBG("initial ctx id %u\n", dss.ctx_id); | ||
1108 | |||
1109 | r = dss_init(); | ||
1110 | if (r) { | ||
1111 | DSSERR("Failed to initialize DSS\n"); | ||
1112 | goto err_dss; | ||
1113 | } | ||
1114 | |||
1115 | r = dpi_init(); | ||
1116 | if (r) { | ||
1117 | DSSERR("Failed to initialize DPI\n"); | ||
1118 | goto err_dpi; | ||
1119 | } | ||
1120 | |||
1121 | r = sdi_init(); | ||
1122 | if (r) { | ||
1123 | DSSERR("Failed to initialize SDI\n"); | ||
1124 | goto err_sdi; | ||
1125 | } | ||
1126 | |||
1127 | dss_clk_disable_all_no_ctx(); | ||
1128 | return 0; | ||
1129 | err_sdi: | ||
1130 | dpi_exit(); | ||
1131 | err_dpi: | ||
1132 | dss_exit(); | ||
1133 | err_dss: | ||
1134 | dss_clk_disable_all_no_ctx(); | ||
1135 | dss_put_clocks(); | ||
1136 | err_clocks: | ||
1137 | return r; | ||
1138 | } | ||
1139 | |||
1140 | static int omap_dsshw_remove(struct platform_device *pdev) | ||
1141 | { | ||
1142 | |||
1143 | dss_exit(); | ||
1144 | |||
1145 | /* | ||
1146 | * As part of hwmod changes, DSS is not the only controller of dss | ||
1147 | * clocks; hwmod framework itself will also enable clocks during hwmod | ||
1148 | * init for dss, and autoidle is set in h/w for DSS. Hence, there's no | ||
1149 | * need to disable clocks if their usecounts > 1. | ||
1150 | */ | ||
1151 | WARN_ON(dss.num_clks_enabled > 0); | ||
1152 | |||
1153 | dss_put_clocks(); | ||
1154 | return 0; | ||
1155 | } | ||
1156 | |||
1157 | static struct platform_driver omap_dsshw_driver = { | ||
1158 | .probe = omap_dsshw_probe, | ||
1159 | .remove = omap_dsshw_remove, | ||
1160 | .driver = { | ||
1161 | .name = "omapdss_dss", | ||
1162 | .owner = THIS_MODULE, | ||
1163 | }, | ||
1164 | }; | ||
1165 | |||
1166 | int dss_init_platform_driver(void) | ||
1167 | { | ||
1168 | return platform_driver_register(&omap_dsshw_driver); | ||
1169 | } | ||
1170 | |||
1171 | void dss_uninit_platform_driver(void) | ||
1172 | { | ||
1173 | return platform_driver_unregister(&omap_dsshw_driver); | ||
1174 | } | ||
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 5c7940d5f282..8ab6d43329bb 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h | |||
@@ -97,8 +97,6 @@ extern unsigned int dss_debug; | |||
97 | #define FLD_MOD(orig, val, start, end) \ | 97 | #define FLD_MOD(orig, val, start, end) \ |
98 | (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) | 98 | (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) |
99 | 99 | ||
100 | #define DISPC_MAX_FCK 173000000 | ||
101 | |||
102 | enum omap_burst_size { | 100 | enum omap_burst_size { |
103 | OMAP_DSS_BURST_4x32 = 0, | 101 | OMAP_DSS_BURST_4x32 = 0, |
104 | OMAP_DSS_BURST_8x32 = 1, | 102 | OMAP_DSS_BURST_8x32 = 1, |
@@ -112,17 +110,16 @@ enum omap_parallel_interface_mode { | |||
112 | }; | 110 | }; |
113 | 111 | ||
114 | enum dss_clock { | 112 | enum dss_clock { |
115 | DSS_CLK_ICK = 1 << 0, | 113 | DSS_CLK_ICK = 1 << 0, /* DSS_L3_ICLK and DSS_L4_ICLK */ |
116 | DSS_CLK_FCK1 = 1 << 1, | 114 | DSS_CLK_FCK = 1 << 1, /* DSS1_ALWON_FCLK */ |
117 | DSS_CLK_FCK2 = 1 << 2, | 115 | DSS_CLK_SYSCK = 1 << 2, /* DSS2_ALWON_FCLK */ |
118 | DSS_CLK_54M = 1 << 3, | 116 | DSS_CLK_TVFCK = 1 << 3, /* DSS_TV_FCLK */ |
119 | DSS_CLK_96M = 1 << 4, | 117 | DSS_CLK_VIDFCK = 1 << 4, /* DSS_96M_FCLK*/ |
120 | }; | 118 | }; |
121 | 119 | ||
122 | enum dss_clk_source { | 120 | enum dss_hdmi_venc_clk_source_select { |
123 | DSS_SRC_DSI1_PLL_FCLK, | 121 | DSS_VENC_TV_CLK = 0, |
124 | DSS_SRC_DSI2_PLL_FCLK, | 122 | DSS_HDMI_M_PCLK = 1, |
125 | DSS_SRC_DSS1_ALWON_FCLK, | ||
126 | }; | 123 | }; |
127 | 124 | ||
128 | struct dss_clock_info { | 125 | struct dss_clock_info { |
@@ -148,36 +145,42 @@ struct dsi_clock_info { | |||
148 | unsigned long fint; | 145 | unsigned long fint; |
149 | unsigned long clkin4ddr; | 146 | unsigned long clkin4ddr; |
150 | unsigned long clkin; | 147 | unsigned long clkin; |
151 | unsigned long dsi1_pll_fclk; | 148 | unsigned long dsi_pll_hsdiv_dispc_clk; /* OMAP3: DSI1_PLL_CLK |
152 | unsigned long dsi2_pll_fclk; | 149 | * OMAP4: PLLx_CLK1 */ |
153 | 150 | unsigned long dsi_pll_hsdiv_dsi_clk; /* OMAP3: DSI2_PLL_CLK | |
151 | * OMAP4: PLLx_CLK2 */ | ||
154 | unsigned long lp_clk; | 152 | unsigned long lp_clk; |
155 | 153 | ||
156 | /* dividers */ | 154 | /* dividers */ |
157 | u16 regn; | 155 | u16 regn; |
158 | u16 regm; | 156 | u16 regm; |
159 | u16 regm3; | 157 | u16 regm_dispc; /* OMAP3: REGM3 |
160 | u16 regm4; | 158 | * OMAP4: REGM4 */ |
161 | 159 | u16 regm_dsi; /* OMAP3: REGM4 | |
160 | * OMAP4: REGM5 */ | ||
162 | u16 lp_clk_div; | 161 | u16 lp_clk_div; |
163 | 162 | ||
164 | u8 highfreq; | 163 | u8 highfreq; |
165 | bool use_dss2_fck; | 164 | bool use_sys_clk; |
165 | }; | ||
166 | |||
167 | /* HDMI PLL structure */ | ||
168 | struct hdmi_pll_info { | ||
169 | u16 regn; | ||
170 | u16 regm; | ||
171 | u32 regmf; | ||
172 | u16 regm2; | ||
173 | u16 regsd; | ||
174 | u16 dcofreq; | ||
166 | }; | 175 | }; |
167 | 176 | ||
168 | struct seq_file; | 177 | struct seq_file; |
169 | struct platform_device; | 178 | struct platform_device; |
170 | 179 | ||
171 | /* core */ | 180 | /* core */ |
172 | void dss_clk_enable(enum dss_clock clks); | ||
173 | void dss_clk_disable(enum dss_clock clks); | ||
174 | unsigned long dss_clk_get_rate(enum dss_clock clk); | ||
175 | int dss_need_ctx_restore(void); | ||
176 | void dss_dump_clocks(struct seq_file *s); | ||
177 | struct bus_type *dss_get_bus(void); | 181 | struct bus_type *dss_get_bus(void); |
178 | struct regulator *dss_get_vdds_dsi(void); | 182 | struct regulator *dss_get_vdds_dsi(void); |
179 | struct regulator *dss_get_vdds_sdi(void); | 183 | struct regulator *dss_get_vdds_sdi(void); |
180 | struct regulator *dss_get_vdda_dac(void); | ||
181 | 184 | ||
182 | /* display */ | 185 | /* display */ |
183 | int dss_suspend_all_devices(void); | 186 | int dss_suspend_all_devices(void); |
@@ -214,22 +217,36 @@ void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr); | |||
214 | void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); | 217 | void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); |
215 | 218 | ||
216 | /* DSS */ | 219 | /* DSS */ |
217 | int dss_init(bool skip_init); | 220 | int dss_init_platform_driver(void); |
218 | void dss_exit(void); | 221 | void dss_uninit_platform_driver(void); |
219 | 222 | ||
223 | void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); | ||
220 | void dss_save_context(void); | 224 | void dss_save_context(void); |
221 | void dss_restore_context(void); | 225 | void dss_restore_context(void); |
226 | void dss_clk_enable(enum dss_clock clks); | ||
227 | void dss_clk_disable(enum dss_clock clks); | ||
228 | unsigned long dss_clk_get_rate(enum dss_clock clk); | ||
229 | int dss_need_ctx_restore(void); | ||
230 | const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); | ||
231 | void dss_dump_clocks(struct seq_file *s); | ||
222 | 232 | ||
223 | void dss_dump_regs(struct seq_file *s); | 233 | void dss_dump_regs(struct seq_file *s); |
234 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | ||
235 | void dss_debug_dump_clocks(struct seq_file *s); | ||
236 | #endif | ||
224 | 237 | ||
225 | void dss_sdi_init(u8 datapairs); | 238 | void dss_sdi_init(u8 datapairs); |
226 | int dss_sdi_enable(void); | 239 | int dss_sdi_enable(void); |
227 | void dss_sdi_disable(void); | 240 | void dss_sdi_disable(void); |
228 | 241 | ||
229 | void dss_select_dispc_clk_source(enum dss_clk_source clk_src); | 242 | void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src); |
230 | void dss_select_dsi_clk_source(enum dss_clk_source clk_src); | 243 | void dss_select_dsi_clk_source(int dsi_module, |
231 | enum dss_clk_source dss_get_dispc_clk_source(void); | 244 | enum omap_dss_clk_source clk_src); |
232 | enum dss_clk_source dss_get_dsi_clk_source(void); | 245 | void dss_select_lcd_clk_source(enum omap_channel channel, |
246 | enum omap_dss_clk_source clk_src); | ||
247 | enum omap_dss_clk_source dss_get_dispc_clk_source(void); | ||
248 | enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module); | ||
249 | enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel); | ||
233 | 250 | ||
234 | void dss_set_venc_output(enum omap_dss_venc_type type); | 251 | void dss_set_venc_output(enum omap_dss_venc_type type); |
235 | void dss_set_dac_pwrdn_bgz(bool enable); | 252 | void dss_set_dac_pwrdn_bgz(bool enable); |
@@ -244,11 +261,11 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck, | |||
244 | 261 | ||
245 | /* SDI */ | 262 | /* SDI */ |
246 | #ifdef CONFIG_OMAP2_DSS_SDI | 263 | #ifdef CONFIG_OMAP2_DSS_SDI |
247 | int sdi_init(bool skip_init); | 264 | int sdi_init(void); |
248 | void sdi_exit(void); | 265 | void sdi_exit(void); |
249 | int sdi_init_display(struct omap_dss_device *display); | 266 | int sdi_init_display(struct omap_dss_device *display); |
250 | #else | 267 | #else |
251 | static inline int sdi_init(bool skip_init) | 268 | static inline int sdi_init(void) |
252 | { | 269 | { |
253 | return 0; | 270 | return 0; |
254 | } | 271 | } |
@@ -259,54 +276,97 @@ static inline void sdi_exit(void) | |||
259 | 276 | ||
260 | /* DSI */ | 277 | /* DSI */ |
261 | #ifdef CONFIG_OMAP2_DSS_DSI | 278 | #ifdef CONFIG_OMAP2_DSS_DSI |
262 | int dsi_init(struct platform_device *pdev); | 279 | |
263 | void dsi_exit(void); | 280 | struct dentry; |
281 | struct file_operations; | ||
282 | |||
283 | int dsi_init_platform_driver(void); | ||
284 | void dsi_uninit_platform_driver(void); | ||
264 | 285 | ||
265 | void dsi_dump_clocks(struct seq_file *s); | 286 | void dsi_dump_clocks(struct seq_file *s); |
266 | void dsi_dump_irqs(struct seq_file *s); | 287 | void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir, |
267 | void dsi_dump_regs(struct seq_file *s); | 288 | const struct file_operations *debug_fops); |
289 | void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir, | ||
290 | const struct file_operations *debug_fops); | ||
268 | 291 | ||
269 | void dsi_save_context(void); | 292 | void dsi_save_context(void); |
270 | void dsi_restore_context(void); | 293 | void dsi_restore_context(void); |
271 | 294 | ||
272 | int dsi_init_display(struct omap_dss_device *display); | 295 | int dsi_init_display(struct omap_dss_device *display); |
273 | void dsi_irq_handler(void); | 296 | void dsi_irq_handler(void); |
274 | unsigned long dsi_get_dsi1_pll_rate(void); | 297 | unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); |
275 | int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo); | 298 | int dsi_pll_set_clock_div(struct platform_device *dsidev, |
276 | int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, | 299 | struct dsi_clock_info *cinfo); |
277 | struct dsi_clock_info *cinfo, | 300 | int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft, |
301 | unsigned long req_pck, struct dsi_clock_info *cinfo, | ||
278 | struct dispc_clock_info *dispc_cinfo); | 302 | struct dispc_clock_info *dispc_cinfo); |
279 | int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, | 303 | int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk, |
280 | bool enable_hsdiv); | 304 | bool enable_hsdiv); |
281 | void dsi_pll_uninit(void); | 305 | void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes); |
282 | void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, | 306 | void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, |
283 | u32 fifo_size, enum omap_burst_size *burst_size, | 307 | u32 fifo_size, enum omap_burst_size *burst_size, |
284 | u32 *fifo_low, u32 *fifo_high); | 308 | u32 *fifo_low, u32 *fifo_high); |
285 | void dsi_wait_dsi1_pll_active(void); | 309 | void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev); |
286 | void dsi_wait_dsi2_pll_active(void); | 310 | void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev); |
311 | struct platform_device *dsi_get_dsidev_from_id(int module); | ||
287 | #else | 312 | #else |
288 | static inline int dsi_init(struct platform_device *pdev) | 313 | static inline int dsi_init_platform_driver(void) |
289 | { | 314 | { |
290 | return 0; | 315 | return 0; |
291 | } | 316 | } |
292 | static inline void dsi_exit(void) | 317 | static inline void dsi_uninit_platform_driver(void) |
318 | { | ||
319 | } | ||
320 | static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev) | ||
293 | { | 321 | { |
322 | WARN("%s: DSI not compiled in, returning rate as 0\n", __func__); | ||
323 | return 0; | ||
294 | } | 324 | } |
295 | static inline void dsi_wait_dsi1_pll_active(void) | 325 | static inline int dsi_pll_set_clock_div(struct platform_device *dsidev, |
326 | struct dsi_clock_info *cinfo) | ||
296 | { | 327 | { |
328 | WARN("%s: DSI not compiled in\n", __func__); | ||
329 | return -ENODEV; | ||
297 | } | 330 | } |
298 | static inline void dsi_wait_dsi2_pll_active(void) | 331 | static inline int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, |
332 | bool is_tft, unsigned long req_pck, | ||
333 | struct dsi_clock_info *dsi_cinfo, | ||
334 | struct dispc_clock_info *dispc_cinfo) | ||
299 | { | 335 | { |
336 | WARN("%s: DSI not compiled in\n", __func__); | ||
337 | return -ENODEV; | ||
338 | } | ||
339 | static inline int dsi_pll_init(struct platform_device *dsidev, | ||
340 | bool enable_hsclk, bool enable_hsdiv) | ||
341 | { | ||
342 | WARN("%s: DSI not compiled in\n", __func__); | ||
343 | return -ENODEV; | ||
344 | } | ||
345 | static inline void dsi_pll_uninit(struct platform_device *dsidev, | ||
346 | bool disconnect_lanes) | ||
347 | { | ||
348 | } | ||
349 | static inline void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev) | ||
350 | { | ||
351 | } | ||
352 | static inline void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev) | ||
353 | { | ||
354 | } | ||
355 | static inline struct platform_device *dsi_get_dsidev_from_id(int module) | ||
356 | { | ||
357 | WARN("%s: DSI not compiled in, returning platform device as NULL\n", | ||
358 | __func__); | ||
359 | return NULL; | ||
300 | } | 360 | } |
301 | #endif | 361 | #endif |
302 | 362 | ||
303 | /* DPI */ | 363 | /* DPI */ |
304 | #ifdef CONFIG_OMAP2_DSS_DPI | 364 | #ifdef CONFIG_OMAP2_DSS_DPI |
305 | int dpi_init(struct platform_device *pdev); | 365 | int dpi_init(void); |
306 | void dpi_exit(void); | 366 | void dpi_exit(void); |
307 | int dpi_init_display(struct omap_dss_device *dssdev); | 367 | int dpi_init_display(struct omap_dss_device *dssdev); |
308 | #else | 368 | #else |
309 | static inline int dpi_init(struct platform_device *pdev) | 369 | static inline int dpi_init(void) |
310 | { | 370 | { |
311 | return 0; | 371 | return 0; |
312 | } | 372 | } |
@@ -316,8 +376,8 @@ static inline void dpi_exit(void) | |||
316 | #endif | 376 | #endif |
317 | 377 | ||
318 | /* DISPC */ | 378 | /* DISPC */ |
319 | int dispc_init(void); | 379 | int dispc_init_platform_driver(void); |
320 | void dispc_exit(void); | 380 | void dispc_uninit_platform_driver(void); |
321 | void dispc_dump_clocks(struct seq_file *s); | 381 | void dispc_dump_clocks(struct seq_file *s); |
322 | void dispc_dump_irqs(struct seq_file *s); | 382 | void dispc_dump_irqs(struct seq_file *s); |
323 | void dispc_dump_regs(struct seq_file *s); | 383 | void dispc_dump_regs(struct seq_file *s); |
@@ -333,9 +393,9 @@ void dispc_disable_sidle(void); | |||
333 | void dispc_lcd_enable_signal_polarity(bool act_high); | 393 | void dispc_lcd_enable_signal_polarity(bool act_high); |
334 | void dispc_lcd_enable_signal(bool enable); | 394 | void dispc_lcd_enable_signal(bool enable); |
335 | void dispc_pck_free_enable(bool enable); | 395 | void dispc_pck_free_enable(bool enable); |
336 | void dispc_enable_fifohandcheck(bool enable); | 396 | void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable); |
337 | 397 | ||
338 | void dispc_set_lcd_size(u16 width, u16 height); | 398 | void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height); |
339 | void dispc_set_digit_size(u16 width, u16 height); | 399 | void dispc_set_digit_size(u16 width, u16 height); |
340 | u32 dispc_get_plane_fifo_size(enum omap_plane plane); | 400 | u32 dispc_get_plane_fifo_size(enum omap_plane plane); |
341 | void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high); | 401 | void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high); |
@@ -350,6 +410,7 @@ void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height); | |||
350 | void dispc_set_channel_out(enum omap_plane plane, | 410 | void dispc_set_channel_out(enum omap_plane plane, |
351 | enum omap_channel channel_out); | 411 | enum omap_channel channel_out); |
352 | 412 | ||
413 | void dispc_enable_gamma_table(bool enable); | ||
353 | int dispc_setup_plane(enum omap_plane plane, | 414 | int dispc_setup_plane(enum omap_plane plane, |
354 | u32 paddr, u16 screen_width, | 415 | u32 paddr, u16 screen_width, |
355 | u16 pos_x, u16 pos_y, | 416 | u16 pos_x, u16 pos_y, |
@@ -359,7 +420,9 @@ int dispc_setup_plane(enum omap_plane plane, | |||
359 | bool ilace, | 420 | bool ilace, |
360 | enum omap_dss_rotation_type rotation_type, | 421 | enum omap_dss_rotation_type rotation_type, |
361 | u8 rotation, bool mirror, | 422 | u8 rotation, bool mirror, |
362 | u8 global_alpha); | 423 | u8 global_alpha, u8 pre_mult_alpha, |
424 | enum omap_channel channel, | ||
425 | u32 puv_addr); | ||
363 | 426 | ||
364 | bool dispc_go_busy(enum omap_channel channel); | 427 | bool dispc_go_busy(enum omap_channel channel); |
365 | void dispc_go(enum omap_channel channel); | 428 | void dispc_go(enum omap_channel channel); |
@@ -368,9 +431,11 @@ bool dispc_is_channel_enabled(enum omap_channel channel); | |||
368 | int dispc_enable_plane(enum omap_plane plane, bool enable); | 431 | int dispc_enable_plane(enum omap_plane plane, bool enable); |
369 | void dispc_enable_replication(enum omap_plane plane, bool enable); | 432 | void dispc_enable_replication(enum omap_plane plane, bool enable); |
370 | 433 | ||
371 | void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode); | 434 | void dispc_set_parallel_interface_mode(enum omap_channel channel, |
372 | void dispc_set_tft_data_lines(u8 data_lines); | 435 | enum omap_parallel_interface_mode mode); |
373 | void dispc_set_lcd_display_type(enum omap_lcd_display_type type); | 436 | void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines); |
437 | void dispc_set_lcd_display_type(enum omap_channel channel, | ||
438 | enum omap_lcd_display_type type); | ||
374 | void dispc_set_loadmode(enum omap_dss_load_mode mode); | 439 | void dispc_set_loadmode(enum omap_dss_load_mode mode); |
375 | 440 | ||
376 | void dispc_set_default_color(enum omap_channel channel, u32 color); | 441 | void dispc_set_default_color(enum omap_channel channel, u32 color); |
@@ -387,54 +452,77 @@ bool dispc_trans_key_enabled(enum omap_channel ch); | |||
387 | bool dispc_alpha_blending_enabled(enum omap_channel ch); | 452 | bool dispc_alpha_blending_enabled(enum omap_channel ch); |
388 | 453 | ||
389 | bool dispc_lcd_timings_ok(struct omap_video_timings *timings); | 454 | bool dispc_lcd_timings_ok(struct omap_video_timings *timings); |
390 | void dispc_set_lcd_timings(struct omap_video_timings *timings); | 455 | void dispc_set_lcd_timings(enum omap_channel channel, |
456 | struct omap_video_timings *timings); | ||
391 | unsigned long dispc_fclk_rate(void); | 457 | unsigned long dispc_fclk_rate(void); |
392 | unsigned long dispc_lclk_rate(void); | 458 | unsigned long dispc_lclk_rate(enum omap_channel channel); |
393 | unsigned long dispc_pclk_rate(void); | 459 | unsigned long dispc_pclk_rate(enum omap_channel channel); |
394 | void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb); | 460 | void dispc_set_pol_freq(enum omap_channel channel, |
461 | enum omap_panel_config config, u8 acbi, u8 acb); | ||
395 | void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, | 462 | void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, |
396 | struct dispc_clock_info *cinfo); | 463 | struct dispc_clock_info *cinfo); |
397 | int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, | 464 | int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, |
398 | struct dispc_clock_info *cinfo); | 465 | struct dispc_clock_info *cinfo); |
399 | int dispc_set_clock_div(struct dispc_clock_info *cinfo); | 466 | int dispc_set_clock_div(enum omap_channel channel, |
400 | int dispc_get_clock_div(struct dispc_clock_info *cinfo); | 467 | struct dispc_clock_info *cinfo); |
468 | int dispc_get_clock_div(enum omap_channel channel, | ||
469 | struct dispc_clock_info *cinfo); | ||
401 | 470 | ||
402 | 471 | ||
403 | /* VENC */ | 472 | /* VENC */ |
404 | #ifdef CONFIG_OMAP2_DSS_VENC | 473 | #ifdef CONFIG_OMAP2_DSS_VENC |
405 | int venc_init(struct platform_device *pdev); | 474 | int venc_init_platform_driver(void); |
406 | void venc_exit(void); | 475 | void venc_uninit_platform_driver(void); |
407 | void venc_dump_regs(struct seq_file *s); | 476 | void venc_dump_regs(struct seq_file *s); |
408 | int venc_init_display(struct omap_dss_device *display); | 477 | int venc_init_display(struct omap_dss_device *display); |
409 | #else | 478 | #else |
410 | static inline int venc_init(struct platform_device *pdev) | 479 | static inline int venc_init_platform_driver(void) |
411 | { | 480 | { |
412 | return 0; | 481 | return 0; |
413 | } | 482 | } |
414 | static inline void venc_exit(void) | 483 | static inline void venc_uninit_platform_driver(void) |
415 | { | 484 | { |
416 | } | 485 | } |
417 | #endif | 486 | #endif |
418 | 487 | ||
488 | /* HDMI */ | ||
489 | #ifdef CONFIG_OMAP4_DSS_HDMI | ||
490 | int hdmi_init_platform_driver(void); | ||
491 | void hdmi_uninit_platform_driver(void); | ||
492 | int hdmi_init_display(struct omap_dss_device *dssdev); | ||
493 | #else | ||
494 | static inline int hdmi_init_display(struct omap_dss_device *dssdev) | ||
495 | { | ||
496 | return 0; | ||
497 | } | ||
498 | static inline int hdmi_init_platform_driver(void) | ||
499 | { | ||
500 | return 0; | ||
501 | } | ||
502 | static inline void hdmi_uninit_platform_driver(void) | ||
503 | { | ||
504 | } | ||
505 | #endif | ||
506 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev); | ||
507 | void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); | ||
508 | void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev); | ||
509 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, | ||
510 | struct omap_video_timings *timings); | ||
511 | int hdmi_panel_init(void); | ||
512 | void hdmi_panel_exit(void); | ||
513 | |||
419 | /* RFBI */ | 514 | /* RFBI */ |
420 | #ifdef CONFIG_OMAP2_DSS_RFBI | 515 | #ifdef CONFIG_OMAP2_DSS_RFBI |
421 | int rfbi_init(void); | 516 | int rfbi_init_platform_driver(void); |
422 | void rfbi_exit(void); | 517 | void rfbi_uninit_platform_driver(void); |
423 | void rfbi_dump_regs(struct seq_file *s); | 518 | void rfbi_dump_regs(struct seq_file *s); |
424 | |||
425 | int rfbi_configure(int rfbi_module, int bpp, int lines); | ||
426 | void rfbi_enable_rfbi(bool enable); | ||
427 | void rfbi_transfer_area(u16 width, u16 height, | ||
428 | void (callback)(void *data), void *data); | ||
429 | void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t); | ||
430 | unsigned long rfbi_get_max_tx_rate(void); | ||
431 | int rfbi_init_display(struct omap_dss_device *display); | 519 | int rfbi_init_display(struct omap_dss_device *display); |
432 | #else | 520 | #else |
433 | static inline int rfbi_init(void) | 521 | static inline int rfbi_init_platform_driver(void) |
434 | { | 522 | { |
435 | return 0; | 523 | return 0; |
436 | } | 524 | } |
437 | static inline void rfbi_exit(void) | 525 | static inline void rfbi_uninit_platform_driver(void) |
438 | { | 526 | { |
439 | } | 527 | } |
440 | #endif | 528 | #endif |
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c new file mode 100644 index 000000000000..1c18888e5df3 --- /dev/null +++ b/drivers/video/omap2/dss/dss_features.c | |||
@@ -0,0 +1,433 @@ | |||
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/types.h> | ||
22 | #include <linux/err.h> | ||
23 | #include <linux/slab.h> | ||
24 | |||
25 | #include <video/omapdss.h> | ||
26 | #include <plat/cpu.h> | ||
27 | |||
28 | #include "dss.h" | ||
29 | #include "dss_features.h" | ||
30 | |||
31 | /* Defines a generic omap register field */ | ||
32 | struct dss_reg_field { | ||
33 | u8 start, end; | ||
34 | }; | ||
35 | |||
36 | struct dss_param_range { | ||
37 | int min, max; | ||
38 | }; | ||
39 | |||
40 | struct omap_dss_features { | ||
41 | const struct dss_reg_field *reg_fields; | ||
42 | const int num_reg_fields; | ||
43 | |||
44 | const u32 has_feature; | ||
45 | |||
46 | const int num_mgrs; | ||
47 | const int num_ovls; | ||
48 | const enum omap_display_type *supported_displays; | ||
49 | const enum omap_color_mode *supported_color_modes; | ||
50 | const char * const *clksrc_names; | ||
51 | const struct dss_param_range *dss_params; | ||
52 | }; | ||
53 | |||
54 | /* This struct is assigned to one of the below during initialization */ | ||
55 | static const struct omap_dss_features *omap_current_dss_features; | ||
56 | |||
57 | static const struct dss_reg_field omap2_dss_reg_fields[] = { | ||
58 | [FEAT_REG_FIRHINC] = { 11, 0 }, | ||
59 | [FEAT_REG_FIRVINC] = { 27, 16 }, | ||
60 | [FEAT_REG_FIFOLOWTHRESHOLD] = { 8, 0 }, | ||
61 | [FEAT_REG_FIFOHIGHTHRESHOLD] = { 24, 16 }, | ||
62 | [FEAT_REG_FIFOSIZE] = { 8, 0 }, | ||
63 | [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, | ||
64 | [FEAT_REG_VERTICALACCU] = { 25, 16 }, | ||
65 | [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 }, | ||
66 | [FEAT_REG_DSIPLL_REGN] = { 0, 0 }, | ||
67 | [FEAT_REG_DSIPLL_REGM] = { 0, 0 }, | ||
68 | [FEAT_REG_DSIPLL_REGM_DISPC] = { 0, 0 }, | ||
69 | [FEAT_REG_DSIPLL_REGM_DSI] = { 0, 0 }, | ||
70 | }; | ||
71 | |||
72 | static const struct dss_reg_field omap3_dss_reg_fields[] = { | ||
73 | [FEAT_REG_FIRHINC] = { 12, 0 }, | ||
74 | [FEAT_REG_FIRVINC] = { 28, 16 }, | ||
75 | [FEAT_REG_FIFOLOWTHRESHOLD] = { 11, 0 }, | ||
76 | [FEAT_REG_FIFOHIGHTHRESHOLD] = { 27, 16 }, | ||
77 | [FEAT_REG_FIFOSIZE] = { 10, 0 }, | ||
78 | [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, | ||
79 | [FEAT_REG_VERTICALACCU] = { 25, 16 }, | ||
80 | [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 }, | ||
81 | [FEAT_REG_DSIPLL_REGN] = { 7, 1 }, | ||
82 | [FEAT_REG_DSIPLL_REGM] = { 18, 8 }, | ||
83 | [FEAT_REG_DSIPLL_REGM_DISPC] = { 22, 19 }, | ||
84 | [FEAT_REG_DSIPLL_REGM_DSI] = { 26, 23 }, | ||
85 | }; | ||
86 | |||
87 | static const struct dss_reg_field omap4_dss_reg_fields[] = { | ||
88 | [FEAT_REG_FIRHINC] = { 12, 0 }, | ||
89 | [FEAT_REG_FIRVINC] = { 28, 16 }, | ||
90 | [FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 }, | ||
91 | [FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 }, | ||
92 | [FEAT_REG_FIFOSIZE] = { 15, 0 }, | ||
93 | [FEAT_REG_HORIZONTALACCU] = { 10, 0 }, | ||
94 | [FEAT_REG_VERTICALACCU] = { 26, 16 }, | ||
95 | [FEAT_REG_DISPC_CLK_SWITCH] = { 9, 8 }, | ||
96 | [FEAT_REG_DSIPLL_REGN] = { 8, 1 }, | ||
97 | [FEAT_REG_DSIPLL_REGM] = { 20, 9 }, | ||
98 | [FEAT_REG_DSIPLL_REGM_DISPC] = { 25, 21 }, | ||
99 | [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 }, | ||
100 | }; | ||
101 | |||
102 | static const enum omap_display_type omap2_dss_supported_displays[] = { | ||
103 | /* OMAP_DSS_CHANNEL_LCD */ | ||
104 | OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI, | ||
105 | |||
106 | /* OMAP_DSS_CHANNEL_DIGIT */ | ||
107 | OMAP_DISPLAY_TYPE_VENC, | ||
108 | }; | ||
109 | |||
110 | static const enum omap_display_type omap3430_dss_supported_displays[] = { | ||
111 | /* OMAP_DSS_CHANNEL_LCD */ | ||
112 | OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | | ||
113 | OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI, | ||
114 | |||
115 | /* OMAP_DSS_CHANNEL_DIGIT */ | ||
116 | OMAP_DISPLAY_TYPE_VENC, | ||
117 | }; | ||
118 | |||
119 | static const enum omap_display_type omap3630_dss_supported_displays[] = { | ||
120 | /* OMAP_DSS_CHANNEL_LCD */ | ||
121 | OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | | ||
122 | OMAP_DISPLAY_TYPE_DSI, | ||
123 | |||
124 | /* OMAP_DSS_CHANNEL_DIGIT */ | ||
125 | OMAP_DISPLAY_TYPE_VENC, | ||
126 | }; | ||
127 | |||
128 | static const enum omap_display_type omap4_dss_supported_displays[] = { | ||
129 | /* OMAP_DSS_CHANNEL_LCD */ | ||
130 | OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI, | ||
131 | |||
132 | /* OMAP_DSS_CHANNEL_DIGIT */ | ||
133 | OMAP_DISPLAY_TYPE_VENC | OMAP_DISPLAY_TYPE_HDMI, | ||
134 | |||
135 | /* OMAP_DSS_CHANNEL_LCD2 */ | ||
136 | OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | | ||
137 | OMAP_DISPLAY_TYPE_DSI, | ||
138 | }; | ||
139 | |||
140 | static const enum omap_color_mode omap2_dss_supported_color_modes[] = { | ||
141 | /* OMAP_DSS_GFX */ | ||
142 | OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 | | ||
143 | OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 | | ||
144 | OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 | | ||
145 | OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P, | ||
146 | |||
147 | /* OMAP_DSS_VIDEO1 */ | ||
148 | OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U | | ||
149 | OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 | | ||
150 | OMAP_DSS_COLOR_UYVY, | ||
151 | |||
152 | /* OMAP_DSS_VIDEO2 */ | ||
153 | OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U | | ||
154 | OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 | | ||
155 | OMAP_DSS_COLOR_UYVY, | ||
156 | }; | ||
157 | |||
158 | static const enum omap_color_mode omap3_dss_supported_color_modes[] = { | ||
159 | /* OMAP_DSS_GFX */ | ||
160 | OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 | | ||
161 | OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 | | ||
162 | OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 | | ||
163 | OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U | | ||
164 | OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 | | ||
165 | OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32, | ||
166 | |||
167 | /* OMAP_DSS_VIDEO1 */ | ||
168 | OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P | | ||
169 | OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 | | ||
170 | OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY, | ||
171 | |||
172 | /* OMAP_DSS_VIDEO2 */ | ||
173 | OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 | | ||
174 | OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U | | ||
175 | OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 | | ||
176 | OMAP_DSS_COLOR_UYVY | OMAP_DSS_COLOR_ARGB32 | | ||
177 | OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32, | ||
178 | }; | ||
179 | |||
180 | static const enum omap_color_mode omap4_dss_supported_color_modes[] = { | ||
181 | /* OMAP_DSS_GFX */ | ||
182 | OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 | | ||
183 | OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 | | ||
184 | OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 | | ||
185 | OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U | | ||
186 | OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 | | ||
187 | OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 | | ||
188 | OMAP_DSS_COLOR_ARGB16_1555, | ||
189 | |||
190 | /* OMAP_DSS_VIDEO1 */ | ||
191 | OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U | | ||
192 | OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 | | ||
193 | OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 | | ||
194 | OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U | | ||
195 | OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY | | ||
196 | OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 | | ||
197 | OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 | | ||
198 | OMAP_DSS_COLOR_RGBX32, | ||
199 | |||
200 | /* OMAP_DSS_VIDEO2 */ | ||
201 | OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U | | ||
202 | OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 | | ||
203 | OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 | | ||
204 | OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U | | ||
205 | OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY | | ||
206 | OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 | | ||
207 | OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 | | ||
208 | OMAP_DSS_COLOR_RGBX32, | ||
209 | }; | ||
210 | |||
211 | static const char * const omap2_dss_clk_source_names[] = { | ||
212 | [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "N/A", | ||
213 | [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "N/A", | ||
214 | [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCLK1", | ||
215 | }; | ||
216 | |||
217 | static const char * const omap3_dss_clk_source_names[] = { | ||
218 | [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI1_PLL_FCLK", | ||
219 | [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI2_PLL_FCLK", | ||
220 | [OMAP_DSS_CLK_SRC_FCK] = "DSS1_ALWON_FCLK", | ||
221 | }; | ||
222 | |||
223 | static const char * const omap4_dss_clk_source_names[] = { | ||
224 | [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "PLL1_CLK1", | ||
225 | [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "PLL1_CLK2", | ||
226 | [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCLK", | ||
227 | [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "PLL2_CLK1", | ||
228 | [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "PLL2_CLK2", | ||
229 | }; | ||
230 | |||
231 | static const struct dss_param_range omap2_dss_param_range[] = { | ||
232 | [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, | ||
233 | [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 }, | ||
234 | [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 }, | ||
235 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, 0 }, | ||
236 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, 0 }, | ||
237 | [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 }, | ||
238 | [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 }, | ||
239 | }; | ||
240 | |||
241 | static const struct dss_param_range omap3_dss_param_range[] = { | ||
242 | [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, | ||
243 | [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 7) - 1 }, | ||
244 | [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 11) - 1 }, | ||
245 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 4) - 1 }, | ||
246 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 }, | ||
247 | [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 }, | ||
248 | [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, | ||
249 | }; | ||
250 | |||
251 | static const struct dss_param_range omap4_dss_param_range[] = { | ||
252 | [FEAT_PARAM_DSS_FCK] = { 0, 186000000 }, | ||
253 | [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 }, | ||
254 | [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 }, | ||
255 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 }, | ||
256 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 }, | ||
257 | [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, | ||
258 | [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, | ||
259 | }; | ||
260 | |||
261 | /* OMAP2 DSS Features */ | ||
262 | static const struct omap_dss_features omap2_dss_features = { | ||
263 | .reg_fields = omap2_dss_reg_fields, | ||
264 | .num_reg_fields = ARRAY_SIZE(omap2_dss_reg_fields), | ||
265 | |||
266 | .has_feature = | ||
267 | FEAT_LCDENABLEPOL | FEAT_LCDENABLESIGNAL | | ||
268 | FEAT_PCKFREEENABLE | FEAT_FUNCGATED | | ||
269 | FEAT_ROWREPEATENABLE | FEAT_RESIZECONF, | ||
270 | |||
271 | .num_mgrs = 2, | ||
272 | .num_ovls = 3, | ||
273 | .supported_displays = omap2_dss_supported_displays, | ||
274 | .supported_color_modes = omap2_dss_supported_color_modes, | ||
275 | .clksrc_names = omap2_dss_clk_source_names, | ||
276 | .dss_params = omap2_dss_param_range, | ||
277 | }; | ||
278 | |||
279 | /* OMAP3 DSS Features */ | ||
280 | static const struct omap_dss_features omap3430_dss_features = { | ||
281 | .reg_fields = omap3_dss_reg_fields, | ||
282 | .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), | ||
283 | |||
284 | .has_feature = | ||
285 | FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | | ||
286 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | | ||
287 | FEAT_FUNCGATED | FEAT_ROWREPEATENABLE | | ||
288 | FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | | ||
289 | FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC, | ||
290 | |||
291 | .num_mgrs = 2, | ||
292 | .num_ovls = 3, | ||
293 | .supported_displays = omap3430_dss_supported_displays, | ||
294 | .supported_color_modes = omap3_dss_supported_color_modes, | ||
295 | .clksrc_names = omap3_dss_clk_source_names, | ||
296 | .dss_params = omap3_dss_param_range, | ||
297 | }; | ||
298 | |||
299 | static const struct omap_dss_features omap3630_dss_features = { | ||
300 | .reg_fields = omap3_dss_reg_fields, | ||
301 | .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), | ||
302 | |||
303 | .has_feature = | ||
304 | FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | | ||
305 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | | ||
306 | FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED | | ||
307 | FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | | ||
308 | FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG | | ||
309 | FEAT_DSI_PLL_FREQSEL, | ||
310 | |||
311 | .num_mgrs = 2, | ||
312 | .num_ovls = 3, | ||
313 | .supported_displays = omap3630_dss_supported_displays, | ||
314 | .supported_color_modes = omap3_dss_supported_color_modes, | ||
315 | .clksrc_names = omap3_dss_clk_source_names, | ||
316 | .dss_params = omap3_dss_param_range, | ||
317 | }; | ||
318 | |||
319 | /* OMAP4 DSS Features */ | ||
320 | /* For OMAP4430 ES 1.0 revision */ | ||
321 | static const struct omap_dss_features omap4430_es1_0_dss_features = { | ||
322 | .reg_fields = omap4_dss_reg_fields, | ||
323 | .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), | ||
324 | |||
325 | .has_feature = | ||
326 | FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | | ||
327 | FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | | ||
328 | FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | | ||
329 | FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | | ||
330 | FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2, | ||
331 | |||
332 | .num_mgrs = 3, | ||
333 | .num_ovls = 3, | ||
334 | .supported_displays = omap4_dss_supported_displays, | ||
335 | .supported_color_modes = omap4_dss_supported_color_modes, | ||
336 | .clksrc_names = omap4_dss_clk_source_names, | ||
337 | .dss_params = omap4_dss_param_range, | ||
338 | }; | ||
339 | |||
340 | /* For all the other OMAP4 versions */ | ||
341 | static const struct omap_dss_features omap4_dss_features = { | ||
342 | .reg_fields = omap4_dss_reg_fields, | ||
343 | .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), | ||
344 | |||
345 | .has_feature = | ||
346 | FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | | ||
347 | FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | | ||
348 | FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | | ||
349 | FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | | ||
350 | FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE | | ||
351 | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2, | ||
352 | |||
353 | .num_mgrs = 3, | ||
354 | .num_ovls = 3, | ||
355 | .supported_displays = omap4_dss_supported_displays, | ||
356 | .supported_color_modes = omap4_dss_supported_color_modes, | ||
357 | .clksrc_names = omap4_dss_clk_source_names, | ||
358 | .dss_params = omap4_dss_param_range, | ||
359 | }; | ||
360 | |||
361 | /* Functions returning values related to a DSS feature */ | ||
362 | int dss_feat_get_num_mgrs(void) | ||
363 | { | ||
364 | return omap_current_dss_features->num_mgrs; | ||
365 | } | ||
366 | |||
367 | int dss_feat_get_num_ovls(void) | ||
368 | { | ||
369 | return omap_current_dss_features->num_ovls; | ||
370 | } | ||
371 | |||
372 | unsigned long dss_feat_get_param_min(enum dss_range_param param) | ||
373 | { | ||
374 | return omap_current_dss_features->dss_params[param].min; | ||
375 | } | ||
376 | |||
377 | unsigned long dss_feat_get_param_max(enum dss_range_param param) | ||
378 | { | ||
379 | return omap_current_dss_features->dss_params[param].max; | ||
380 | } | ||
381 | |||
382 | enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel) | ||
383 | { | ||
384 | return omap_current_dss_features->supported_displays[channel]; | ||
385 | } | ||
386 | |||
387 | enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane) | ||
388 | { | ||
389 | return omap_current_dss_features->supported_color_modes[plane]; | ||
390 | } | ||
391 | |||
392 | bool dss_feat_color_mode_supported(enum omap_plane plane, | ||
393 | enum omap_color_mode color_mode) | ||
394 | { | ||
395 | return omap_current_dss_features->supported_color_modes[plane] & | ||
396 | color_mode; | ||
397 | } | ||
398 | |||
399 | const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id) | ||
400 | { | ||
401 | return omap_current_dss_features->clksrc_names[id]; | ||
402 | } | ||
403 | |||
404 | /* DSS has_feature check */ | ||
405 | bool dss_has_feature(enum dss_feat_id id) | ||
406 | { | ||
407 | return omap_current_dss_features->has_feature & id; | ||
408 | } | ||
409 | |||
410 | void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end) | ||
411 | { | ||
412 | if (id >= omap_current_dss_features->num_reg_fields) | ||
413 | BUG(); | ||
414 | |||
415 | *start = omap_current_dss_features->reg_fields[id].start; | ||
416 | *end = omap_current_dss_features->reg_fields[id].end; | ||
417 | } | ||
418 | |||
419 | void dss_features_init(void) | ||
420 | { | ||
421 | if (cpu_is_omap24xx()) | ||
422 | omap_current_dss_features = &omap2_dss_features; | ||
423 | else if (cpu_is_omap3630()) | ||
424 | omap_current_dss_features = &omap3630_dss_features; | ||
425 | else if (cpu_is_omap34xx()) | ||
426 | omap_current_dss_features = &omap3430_dss_features; | ||
427 | else if (omap_rev() == OMAP4430_REV_ES1_0) | ||
428 | omap_current_dss_features = &omap4430_es1_0_dss_features; | ||
429 | else if (cpu_is_omap44xx()) | ||
430 | omap_current_dss_features = &omap4_dss_features; | ||
431 | else | ||
432 | DSSWARN("Unsupported OMAP version"); | ||
433 | } | ||
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h new file mode 100644 index 000000000000..07b346f7d916 --- /dev/null +++ b/drivers/video/omap2/dss/dss_features.h | |||
@@ -0,0 +1,96 @@ | |||
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 3 | ||
24 | #define MAX_DSS_OVERLAYS 3 | ||
25 | #define MAX_DSS_LCD_MANAGERS 2 | ||
26 | #define MAX_NUM_DSI 2 | ||
27 | |||
28 | /* DSS has feature id */ | ||
29 | enum dss_feat_id { | ||
30 | FEAT_GLOBAL_ALPHA = 1 << 0, | ||
31 | FEAT_GLOBAL_ALPHA_VID1 = 1 << 1, | ||
32 | FEAT_PRE_MULT_ALPHA = 1 << 2, | ||
33 | FEAT_LCDENABLEPOL = 1 << 3, | ||
34 | FEAT_LCDENABLESIGNAL = 1 << 4, | ||
35 | FEAT_PCKFREEENABLE = 1 << 5, | ||
36 | FEAT_FUNCGATED = 1 << 6, | ||
37 | FEAT_MGR_LCD2 = 1 << 7, | ||
38 | FEAT_LINEBUFFERSPLIT = 1 << 8, | ||
39 | FEAT_ROWREPEATENABLE = 1 << 9, | ||
40 | FEAT_RESIZECONF = 1 << 10, | ||
41 | /* Independent core clk divider */ | ||
42 | FEAT_CORE_CLK_DIV = 1 << 11, | ||
43 | FEAT_LCD_CLK_SRC = 1 << 12, | ||
44 | /* DSI-PLL power command 0x3 is not working */ | ||
45 | FEAT_DSI_PLL_PWR_BUG = 1 << 13, | ||
46 | FEAT_DSI_PLL_FREQSEL = 1 << 14, | ||
47 | FEAT_DSI_DCS_CMD_CONFIG_VC = 1 << 15, | ||
48 | FEAT_DSI_VC_OCP_WIDTH = 1 << 16, | ||
49 | FEAT_DSI_REVERSE_TXCLKESC = 1 << 17, | ||
50 | FEAT_DSI_GNQ = 1 << 18, | ||
51 | FEAT_HDMI_CTS_SWMODE = 1 << 19, | ||
52 | FEAT_HANDLE_UV_SEPARATE = 1 << 20, | ||
53 | FEAT_ATTR2 = 1 << 21, | ||
54 | }; | ||
55 | |||
56 | /* DSS register field id */ | ||
57 | enum dss_feat_reg_field { | ||
58 | FEAT_REG_FIRHINC, | ||
59 | FEAT_REG_FIRVINC, | ||
60 | FEAT_REG_FIFOHIGHTHRESHOLD, | ||
61 | FEAT_REG_FIFOLOWTHRESHOLD, | ||
62 | FEAT_REG_FIFOSIZE, | ||
63 | FEAT_REG_HORIZONTALACCU, | ||
64 | FEAT_REG_VERTICALACCU, | ||
65 | FEAT_REG_DISPC_CLK_SWITCH, | ||
66 | FEAT_REG_DSIPLL_REGN, | ||
67 | FEAT_REG_DSIPLL_REGM, | ||
68 | FEAT_REG_DSIPLL_REGM_DISPC, | ||
69 | FEAT_REG_DSIPLL_REGM_DSI, | ||
70 | }; | ||
71 | |||
72 | enum dss_range_param { | ||
73 | FEAT_PARAM_DSS_FCK, | ||
74 | FEAT_PARAM_DSIPLL_REGN, | ||
75 | FEAT_PARAM_DSIPLL_REGM, | ||
76 | FEAT_PARAM_DSIPLL_REGM_DISPC, | ||
77 | FEAT_PARAM_DSIPLL_REGM_DSI, | ||
78 | FEAT_PARAM_DSIPLL_FINT, | ||
79 | FEAT_PARAM_DSIPLL_LPDIV, | ||
80 | }; | ||
81 | |||
82 | /* DSS Feature Functions */ | ||
83 | int dss_feat_get_num_mgrs(void); | ||
84 | int dss_feat_get_num_ovls(void); | ||
85 | unsigned long dss_feat_get_param_min(enum dss_range_param param); | ||
86 | unsigned long dss_feat_get_param_max(enum dss_range_param param); | ||
87 | enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); | ||
88 | enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); | ||
89 | bool dss_feat_color_mode_supported(enum omap_plane plane, | ||
90 | enum omap_color_mode color_mode); | ||
91 | const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id); | ||
92 | |||
93 | bool dss_has_feature(enum dss_feat_id id); | ||
94 | void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); | ||
95 | void dss_features_init(void); | ||
96 | #endif | ||
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c new file mode 100644 index 000000000000..b0555f4f0a78 --- /dev/null +++ b/drivers/video/omap2/dss/hdmi.c | |||
@@ -0,0 +1,1763 @@ | |||
1 | /* | ||
2 | * hdmi.c | ||
3 | * | ||
4 | * HDMI interface DSS driver setting for TI's OMAP4 family of processor. | ||
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 "HDMI" | ||
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/string.h> | ||
32 | #include <video/omapdss.h> | ||
33 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
34 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
35 | #include <sound/soc.h> | ||
36 | #include <sound/pcm_params.h> | ||
37 | #endif | ||
38 | |||
39 | #include "dss.h" | ||
40 | #include "hdmi.h" | ||
41 | #include "dss_features.h" | ||
42 | |||
43 | static struct { | ||
44 | struct mutex lock; | ||
45 | struct omap_display_platform_data *pdata; | ||
46 | struct platform_device *pdev; | ||
47 | void __iomem *base_wp; /* HDMI wrapper */ | ||
48 | int code; | ||
49 | int mode; | ||
50 | u8 edid[HDMI_EDID_MAX_LENGTH]; | ||
51 | u8 edid_set; | ||
52 | bool custom_set; | ||
53 | struct hdmi_config cfg; | ||
54 | } hdmi; | ||
55 | |||
56 | /* | ||
57 | * Logic for the below structure : | ||
58 | * user enters the CEA or VESA timings by specifying the HDMI/DVI code. | ||
59 | * There is a correspondence between CEA/VESA timing and code, please | ||
60 | * refer to section 6.3 in HDMI 1.3 specification for timing code. | ||
61 | * | ||
62 | * In the below structure, cea_vesa_timings corresponds to all OMAP4 | ||
63 | * supported CEA and VESA timing values.code_cea corresponds to the CEA | ||
64 | * code, It is used to get the timing from cea_vesa_timing array.Similarly | ||
65 | * with code_vesa. Code_index is used for back mapping, that is once EDID | ||
66 | * is read from the TV, EDID is parsed to find the timing values and then | ||
67 | * map it to corresponding CEA or VESA index. | ||
68 | */ | ||
69 | |||
70 | static const struct hdmi_timings cea_vesa_timings[OMAP_HDMI_TIMINGS_NB] = { | ||
71 | { {640, 480, 25200, 96, 16, 48, 2, 10, 33} , 0 , 0}, | ||
72 | { {1280, 720, 74250, 40, 440, 220, 5, 5, 20}, 1, 1}, | ||
73 | { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1}, | ||
74 | { {720, 480, 27027, 62, 16, 60, 6, 9, 30}, 0, 0}, | ||
75 | { {2880, 576, 108000, 256, 48, 272, 5, 5, 39}, 0, 0}, | ||
76 | { {1440, 240, 27027, 124, 38, 114, 3, 4, 15}, 0, 0}, | ||
77 | { {1440, 288, 27000, 126, 24, 138, 3, 2, 19}, 0, 0}, | ||
78 | { {1920, 540, 74250, 44, 528, 148, 5, 2, 15}, 1, 1}, | ||
79 | { {1920, 540, 74250, 44, 88, 148, 5, 2, 15}, 1, 1}, | ||
80 | { {1920, 1080, 148500, 44, 88, 148, 5, 4, 36}, 1, 1}, | ||
81 | { {720, 576, 27000, 64, 12, 68, 5, 5, 39}, 0, 0}, | ||
82 | { {1440, 576, 54000, 128, 24, 136, 5, 5, 39}, 0, 0}, | ||
83 | { {1920, 1080, 148500, 44, 528, 148, 5, 4, 36}, 1, 1}, | ||
84 | { {2880, 480, 108108, 248, 64, 240, 6, 9, 30}, 0, 0}, | ||
85 | { {1920, 1080, 74250, 44, 638, 148, 5, 4, 36}, 1, 1}, | ||
86 | /* VESA From Here */ | ||
87 | { {640, 480, 25175, 96, 16, 48, 2 , 11, 31}, 0, 0}, | ||
88 | { {800, 600, 40000, 128, 40, 88, 4 , 1, 23}, 1, 1}, | ||
89 | { {848, 480, 33750, 112, 16, 112, 8 , 6, 23}, 1, 1}, | ||
90 | { {1280, 768, 79500, 128, 64, 192, 7 , 3, 20}, 1, 0}, | ||
91 | { {1280, 800, 83500, 128, 72, 200, 6 , 3, 22}, 1, 0}, | ||
92 | { {1360, 768, 85500, 112, 64, 256, 6 , 3, 18}, 1, 1}, | ||
93 | { {1280, 960, 108000, 112, 96, 312, 3 , 1, 36}, 1, 1}, | ||
94 | { {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38}, 1, 1}, | ||
95 | { {1024, 768, 65000, 136, 24, 160, 6, 3, 29}, 0, 0}, | ||
96 | { {1400, 1050, 121750, 144, 88, 232, 4, 3, 32}, 1, 0}, | ||
97 | { {1440, 900, 106500, 152, 80, 232, 6, 3, 25}, 1, 0}, | ||
98 | { {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30}, 1, 0}, | ||
99 | { {1366, 768, 85500, 143, 70, 213, 3, 3, 24}, 1, 1}, | ||
100 | { {1920, 1080, 148500, 44, 148, 80, 5, 4, 36}, 1, 1}, | ||
101 | { {1280, 768, 68250, 32, 48, 80, 7, 3, 12}, 0, 1}, | ||
102 | { {1400, 1050, 101000, 32, 48, 80, 4, 3, 23}, 0, 1}, | ||
103 | { {1680, 1050, 119000, 32, 48, 80, 6, 3, 21}, 0, 1}, | ||
104 | { {1280, 800, 79500, 32, 48, 80, 6, 3, 14}, 0, 1}, | ||
105 | { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1} | ||
106 | }; | ||
107 | |||
108 | /* | ||
109 | * This is a static mapping array which maps the timing values | ||
110 | * with corresponding CEA / VESA code | ||
111 | */ | ||
112 | static const int code_index[OMAP_HDMI_TIMINGS_NB] = { | ||
113 | 1, 19, 4, 2, 37, 6, 21, 20, 5, 16, 17, 29, 31, 35, 32, | ||
114 | /* <--15 CEA 17--> vesa*/ | ||
115 | 4, 9, 0xE, 0x17, 0x1C, 0x27, 0x20, 0x23, 0x10, 0x2A, | ||
116 | 0X2F, 0x3A, 0X51, 0X52, 0x16, 0x29, 0x39, 0x1B | ||
117 | }; | ||
118 | |||
119 | /* | ||
120 | * This is reverse static mapping which maps the CEA / VESA code | ||
121 | * to the corresponding timing values | ||
122 | */ | ||
123 | static const int code_cea[39] = { | ||
124 | -1, 0, 3, 3, 2, 8, 5, 5, -1, -1, | ||
125 | -1, -1, -1, -1, -1, -1, 9, 10, 10, 1, | ||
126 | 7, 6, 6, -1, -1, -1, -1, -1, -1, 11, | ||
127 | 11, 12, 14, -1, -1, 13, 13, 4, 4 | ||
128 | }; | ||
129 | |||
130 | static const int code_vesa[85] = { | ||
131 | -1, -1, -1, -1, 15, -1, -1, -1, -1, 16, | ||
132 | -1, -1, -1, -1, 17, -1, 23, -1, -1, -1, | ||
133 | -1, -1, 29, 18, -1, -1, -1, 32, 19, -1, | ||
134 | -1, -1, 21, -1, -1, 22, -1, -1, -1, 20, | ||
135 | -1, 30, 24, -1, -1, -1, -1, 25, -1, -1, | ||
136 | -1, -1, -1, -1, -1, -1, -1, 31, 26, -1, | ||
137 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
138 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
139 | -1, 27, 28, -1, 33}; | ||
140 | |||
141 | static const u8 edid_header[8] = {0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0}; | ||
142 | |||
143 | static inline void hdmi_write_reg(const struct hdmi_reg idx, u32 val) | ||
144 | { | ||
145 | __raw_writel(val, hdmi.base_wp + idx.idx); | ||
146 | } | ||
147 | |||
148 | static inline u32 hdmi_read_reg(const struct hdmi_reg idx) | ||
149 | { | ||
150 | return __raw_readl(hdmi.base_wp + idx.idx); | ||
151 | } | ||
152 | |||
153 | static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx, | ||
154 | int b2, int b1, u32 val) | ||
155 | { | ||
156 | u32 t = 0; | ||
157 | while (val != REG_GET(idx, b2, b1)) { | ||
158 | udelay(1); | ||
159 | if (t++ > 10000) | ||
160 | return !val; | ||
161 | } | ||
162 | return val; | ||
163 | } | ||
164 | |||
165 | int hdmi_init_display(struct omap_dss_device *dssdev) | ||
166 | { | ||
167 | DSSDBG("init_display\n"); | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static int hdmi_pll_init(enum hdmi_clk_refsel refsel, int dcofreq, | ||
173 | struct hdmi_pll_info *fmt, u16 sd) | ||
174 | { | ||
175 | u32 r; | ||
176 | |||
177 | /* PLL start always use manual mode */ | ||
178 | REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 0, 0); | ||
179 | |||
180 | r = hdmi_read_reg(PLLCTRL_CFG1); | ||
181 | r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */ | ||
182 | r = FLD_MOD(r, fmt->regn, 8, 1); /* CFG1_PLL_REGN */ | ||
183 | |||
184 | hdmi_write_reg(PLLCTRL_CFG1, r); | ||
185 | |||
186 | r = hdmi_read_reg(PLLCTRL_CFG2); | ||
187 | |||
188 | r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */ | ||
189 | r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */ | ||
190 | r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */ | ||
191 | |||
192 | if (dcofreq) { | ||
193 | /* divider programming for frequency beyond 1000Mhz */ | ||
194 | REG_FLD_MOD(PLLCTRL_CFG3, sd, 17, 10); | ||
195 | r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */ | ||
196 | } else { | ||
197 | r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */ | ||
198 | } | ||
199 | |||
200 | hdmi_write_reg(PLLCTRL_CFG2, r); | ||
201 | |||
202 | r = hdmi_read_reg(PLLCTRL_CFG4); | ||
203 | r = FLD_MOD(r, fmt->regm2, 24, 18); | ||
204 | r = FLD_MOD(r, fmt->regmf, 17, 0); | ||
205 | |||
206 | hdmi_write_reg(PLLCTRL_CFG4, r); | ||
207 | |||
208 | /* go now */ | ||
209 | REG_FLD_MOD(PLLCTRL_PLL_GO, 0x1, 0, 0); | ||
210 | |||
211 | /* wait for bit change */ | ||
212 | if (hdmi_wait_for_bit_change(PLLCTRL_PLL_GO, 0, 0, 1) != 1) { | ||
213 | DSSERR("PLL GO bit not set\n"); | ||
214 | return -ETIMEDOUT; | ||
215 | } | ||
216 | |||
217 | /* Wait till the lock bit is set in PLL status */ | ||
218 | if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) { | ||
219 | DSSWARN("cannot lock PLL\n"); | ||
220 | DSSWARN("CFG1 0x%x\n", | ||
221 | hdmi_read_reg(PLLCTRL_CFG1)); | ||
222 | DSSWARN("CFG2 0x%x\n", | ||
223 | hdmi_read_reg(PLLCTRL_CFG2)); | ||
224 | DSSWARN("CFG4 0x%x\n", | ||
225 | hdmi_read_reg(PLLCTRL_CFG4)); | ||
226 | return -ETIMEDOUT; | ||
227 | } | ||
228 | |||
229 | DSSDBG("PLL locked!\n"); | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | /* PHY_PWR_CMD */ | ||
235 | static int hdmi_set_phy_pwr(enum hdmi_phy_pwr val) | ||
236 | { | ||
237 | /* Command for power control of HDMI PHY */ | ||
238 | REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 7, 6); | ||
239 | |||
240 | /* Status of the power control of HDMI PHY */ | ||
241 | if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 5, 4, val) != val) { | ||
242 | DSSERR("Failed to set PHY power mode to %d\n", val); | ||
243 | return -ETIMEDOUT; | ||
244 | } | ||
245 | |||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | /* PLL_PWR_CMD */ | ||
250 | static int hdmi_set_pll_pwr(enum hdmi_pll_pwr val) | ||
251 | { | ||
252 | /* Command for power control of HDMI PLL */ | ||
253 | REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 3, 2); | ||
254 | |||
255 | /* wait till PHY_PWR_STATUS is set */ | ||
256 | if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 1, 0, val) != val) { | ||
257 | DSSERR("Failed to set PHY_PWR_STATUS\n"); | ||
258 | return -ETIMEDOUT; | ||
259 | } | ||
260 | |||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | static int hdmi_pll_reset(void) | ||
265 | { | ||
266 | /* SYSRESET controlled by power FSM */ | ||
267 | REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 3, 3); | ||
268 | |||
269 | /* READ 0x0 reset is in progress */ | ||
270 | if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) { | ||
271 | DSSERR("Failed to sysreset PLL\n"); | ||
272 | return -ETIMEDOUT; | ||
273 | } | ||
274 | |||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static int hdmi_phy_init(void) | ||
279 | { | ||
280 | u16 r = 0; | ||
281 | |||
282 | r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_LDOON); | ||
283 | if (r) | ||
284 | return r; | ||
285 | |||
286 | r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_TXON); | ||
287 | if (r) | ||
288 | return r; | ||
289 | |||
290 | /* | ||
291 | * Read address 0 in order to get the SCP reset done completed | ||
292 | * Dummy access performed to make sure reset is done | ||
293 | */ | ||
294 | hdmi_read_reg(HDMI_TXPHY_TX_CTRL); | ||
295 | |||
296 | /* | ||
297 | * Write to phy address 0 to configure the clock | ||
298 | * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field | ||
299 | */ | ||
300 | REG_FLD_MOD(HDMI_TXPHY_TX_CTRL, 0x1, 31, 30); | ||
301 | |||
302 | /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */ | ||
303 | hdmi_write_reg(HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000); | ||
304 | |||
305 | /* Setup max LDO voltage */ | ||
306 | REG_FLD_MOD(HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0); | ||
307 | |||
308 | /* Write to phy address 3 to change the polarity control */ | ||
309 | REG_FLD_MOD(HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); | ||
310 | |||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static int hdmi_wait_softreset(void) | ||
315 | { | ||
316 | /* reset W1 */ | ||
317 | REG_FLD_MOD(HDMI_WP_SYSCONFIG, 0x1, 0, 0); | ||
318 | |||
319 | /* wait till SOFTRESET == 0 */ | ||
320 | if (hdmi_wait_for_bit_change(HDMI_WP_SYSCONFIG, 0, 0, 0) != 0) { | ||
321 | DSSERR("sysconfig reset failed\n"); | ||
322 | return -ETIMEDOUT; | ||
323 | } | ||
324 | |||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | static int hdmi_pll_program(struct hdmi_pll_info *fmt) | ||
329 | { | ||
330 | u16 r = 0; | ||
331 | enum hdmi_clk_refsel refsel; | ||
332 | |||
333 | /* wait for wrapper reset */ | ||
334 | r = hdmi_wait_softreset(); | ||
335 | if (r) | ||
336 | return r; | ||
337 | |||
338 | r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); | ||
339 | if (r) | ||
340 | return r; | ||
341 | |||
342 | r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_BOTHON_ALLCLKS); | ||
343 | if (r) | ||
344 | return r; | ||
345 | |||
346 | r = hdmi_pll_reset(); | ||
347 | if (r) | ||
348 | return r; | ||
349 | |||
350 | refsel = HDMI_REFSEL_SYSCLK; | ||
351 | |||
352 | r = hdmi_pll_init(refsel, fmt->dcofreq, fmt, fmt->regsd); | ||
353 | if (r) | ||
354 | return r; | ||
355 | |||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | static void hdmi_phy_off(void) | ||
360 | { | ||
361 | hdmi_set_phy_pwr(HDMI_PHYPWRCMD_OFF); | ||
362 | } | ||
363 | |||
364 | static int hdmi_core_ddc_edid(u8 *pedid, int ext) | ||
365 | { | ||
366 | u32 i, j; | ||
367 | char checksum = 0; | ||
368 | u32 offset = 0; | ||
369 | |||
370 | /* Turn on CLK for DDC */ | ||
371 | REG_FLD_MOD(HDMI_CORE_AV_DPD, 0x7, 2, 0); | ||
372 | |||
373 | /* | ||
374 | * SW HACK : Without the Delay DDC(i2c bus) reads 0 values / | ||
375 | * right shifted values( The behavior is not consistent and seen only | ||
376 | * with some TV's) | ||
377 | */ | ||
378 | usleep_range(800, 1000); | ||
379 | |||
380 | if (!ext) { | ||
381 | /* Clk SCL Devices */ | ||
382 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xA, 3, 0); | ||
383 | |||
384 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ | ||
385 | if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, | ||
386 | 4, 4, 0) != 0) { | ||
387 | DSSERR("Failed to program DDC\n"); | ||
388 | return -ETIMEDOUT; | ||
389 | } | ||
390 | |||
391 | /* Clear FIFO */ | ||
392 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x9, 3, 0); | ||
393 | |||
394 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ | ||
395 | if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, | ||
396 | 4, 4, 0) != 0) { | ||
397 | DSSERR("Failed to program DDC\n"); | ||
398 | return -ETIMEDOUT; | ||
399 | } | ||
400 | |||
401 | } else { | ||
402 | if (ext % 2 != 0) | ||
403 | offset = 0x80; | ||
404 | } | ||
405 | |||
406 | /* Load Segment Address Register */ | ||
407 | REG_FLD_MOD(HDMI_CORE_DDC_SEGM, ext/2, 7, 0); | ||
408 | |||
409 | /* Load Slave Address Register */ | ||
410 | REG_FLD_MOD(HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1); | ||
411 | |||
412 | /* Load Offset Address Register */ | ||
413 | REG_FLD_MOD(HDMI_CORE_DDC_OFFSET, offset, 7, 0); | ||
414 | |||
415 | /* Load Byte Count */ | ||
416 | REG_FLD_MOD(HDMI_CORE_DDC_COUNT1, 0x80, 7, 0); | ||
417 | REG_FLD_MOD(HDMI_CORE_DDC_COUNT2, 0x0, 1, 0); | ||
418 | |||
419 | /* Set DDC_CMD */ | ||
420 | if (ext) | ||
421 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x4, 3, 0); | ||
422 | else | ||
423 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x2, 3, 0); | ||
424 | |||
425 | /* HDMI_CORE_DDC_STATUS_BUS_LOW */ | ||
426 | if (REG_GET(HDMI_CORE_DDC_STATUS, 6, 6) == 1) { | ||
427 | DSSWARN("I2C Bus Low?\n"); | ||
428 | return -EIO; | ||
429 | } | ||
430 | /* HDMI_CORE_DDC_STATUS_NO_ACK */ | ||
431 | if (REG_GET(HDMI_CORE_DDC_STATUS, 5, 5) == 1) { | ||
432 | DSSWARN("I2C No Ack\n"); | ||
433 | return -EIO; | ||
434 | } | ||
435 | |||
436 | i = ext * 128; | ||
437 | j = 0; | ||
438 | while (((REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) == 1) || | ||
439 | (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0)) && | ||
440 | j < 128) { | ||
441 | |||
442 | if (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0) { | ||
443 | /* FIFO not empty */ | ||
444 | pedid[i++] = REG_GET(HDMI_CORE_DDC_DATA, 7, 0); | ||
445 | j++; | ||
446 | } | ||
447 | } | ||
448 | |||
449 | for (j = 0; j < 128; j++) | ||
450 | checksum += pedid[j]; | ||
451 | |||
452 | if (checksum != 0) { | ||
453 | DSSERR("E-EDID checksum failed!!\n"); | ||
454 | return -EIO; | ||
455 | } | ||
456 | |||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | static int read_edid(u8 *pedid, u16 max_length) | ||
461 | { | ||
462 | int r = 0, n = 0, i = 0; | ||
463 | int max_ext_blocks = (max_length / 128) - 1; | ||
464 | |||
465 | r = hdmi_core_ddc_edid(pedid, 0); | ||
466 | if (r) { | ||
467 | return r; | ||
468 | } else { | ||
469 | n = pedid[0x7e]; | ||
470 | |||
471 | /* | ||
472 | * README: need to comply with max_length set by the caller. | ||
473 | * Better implementation should be to allocate necessary | ||
474 | * memory to store EDID according to nb_block field found | ||
475 | * in first block | ||
476 | */ | ||
477 | if (n > max_ext_blocks) | ||
478 | n = max_ext_blocks; | ||
479 | |||
480 | for (i = 1; i <= n; i++) { | ||
481 | r = hdmi_core_ddc_edid(pedid, i); | ||
482 | if (r) | ||
483 | return r; | ||
484 | } | ||
485 | } | ||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | static int get_timings_index(void) | ||
490 | { | ||
491 | int code; | ||
492 | |||
493 | if (hdmi.mode == 0) | ||
494 | code = code_vesa[hdmi.code]; | ||
495 | else | ||
496 | code = code_cea[hdmi.code]; | ||
497 | |||
498 | if (code == -1) { | ||
499 | /* HDMI code 4 corresponds to 640 * 480 VGA */ | ||
500 | hdmi.code = 4; | ||
501 | /* DVI mode 1 corresponds to HDMI 0 to DVI */ | ||
502 | hdmi.mode = HDMI_DVI; | ||
503 | |||
504 | code = code_vesa[hdmi.code]; | ||
505 | } | ||
506 | return code; | ||
507 | } | ||
508 | |||
509 | static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) | ||
510 | { | ||
511 | int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0; | ||
512 | int timing_vsync = 0, timing_hsync = 0; | ||
513 | struct omap_video_timings temp; | ||
514 | struct hdmi_cm cm = {-1}; | ||
515 | DSSDBG("hdmi_get_code\n"); | ||
516 | |||
517 | for (i = 0; i < OMAP_HDMI_TIMINGS_NB; i++) { | ||
518 | temp = cea_vesa_timings[i].timings; | ||
519 | if ((temp.pixel_clock == timing->pixel_clock) && | ||
520 | (temp.x_res == timing->x_res) && | ||
521 | (temp.y_res == timing->y_res)) { | ||
522 | |||
523 | temp_hsync = temp.hfp + temp.hsw + temp.hbp; | ||
524 | timing_hsync = timing->hfp + timing->hsw + timing->hbp; | ||
525 | temp_vsync = temp.vfp + temp.vsw + temp.vbp; | ||
526 | timing_vsync = timing->vfp + timing->vsw + timing->vbp; | ||
527 | |||
528 | DSSDBG("temp_hsync = %d , temp_vsync = %d" | ||
529 | "timing_hsync = %d, timing_vsync = %d\n", | ||
530 | temp_hsync, temp_hsync, | ||
531 | timing_hsync, timing_vsync); | ||
532 | |||
533 | if ((temp_hsync == timing_hsync) && | ||
534 | (temp_vsync == timing_vsync)) { | ||
535 | code = i; | ||
536 | cm.code = code_index[i]; | ||
537 | if (code < 14) | ||
538 | cm.mode = HDMI_HDMI; | ||
539 | else | ||
540 | cm.mode = HDMI_DVI; | ||
541 | DSSDBG("Hdmi_code = %d mode = %d\n", | ||
542 | cm.code, cm.mode); | ||
543 | break; | ||
544 | } | ||
545 | } | ||
546 | } | ||
547 | |||
548 | return cm; | ||
549 | } | ||
550 | |||
551 | static void get_horz_vert_timing_info(int current_descriptor_addrs, u8 *edid , | ||
552 | struct omap_video_timings *timings) | ||
553 | { | ||
554 | /* X and Y resolution */ | ||
555 | timings->x_res = (((edid[current_descriptor_addrs + 4] & 0xF0) << 4) | | ||
556 | edid[current_descriptor_addrs + 2]); | ||
557 | timings->y_res = (((edid[current_descriptor_addrs + 7] & 0xF0) << 4) | | ||
558 | edid[current_descriptor_addrs + 5]); | ||
559 | |||
560 | timings->pixel_clock = ((edid[current_descriptor_addrs + 1] << 8) | | ||
561 | edid[current_descriptor_addrs]); | ||
562 | |||
563 | timings->pixel_clock = 10 * timings->pixel_clock; | ||
564 | |||
565 | /* HORIZONTAL FRONT PORCH */ | ||
566 | timings->hfp = edid[current_descriptor_addrs + 8] | | ||
567 | ((edid[current_descriptor_addrs + 11] & 0xc0) << 2); | ||
568 | /* HORIZONTAL SYNC WIDTH */ | ||
569 | timings->hsw = edid[current_descriptor_addrs + 9] | | ||
570 | ((edid[current_descriptor_addrs + 11] & 0x30) << 4); | ||
571 | /* HORIZONTAL BACK PORCH */ | ||
572 | timings->hbp = (((edid[current_descriptor_addrs + 4] & 0x0F) << 8) | | ||
573 | edid[current_descriptor_addrs + 3]) - | ||
574 | (timings->hfp + timings->hsw); | ||
575 | /* VERTICAL FRONT PORCH */ | ||
576 | timings->vfp = ((edid[current_descriptor_addrs + 10] & 0xF0) >> 4) | | ||
577 | ((edid[current_descriptor_addrs + 11] & 0x0f) << 2); | ||
578 | /* VERTICAL SYNC WIDTH */ | ||
579 | timings->vsw = (edid[current_descriptor_addrs + 10] & 0x0F) | | ||
580 | ((edid[current_descriptor_addrs + 11] & 0x03) << 4); | ||
581 | /* VERTICAL BACK PORCH */ | ||
582 | timings->vbp = (((edid[current_descriptor_addrs + 7] & 0x0F) << 8) | | ||
583 | edid[current_descriptor_addrs + 6]) - | ||
584 | (timings->vfp + timings->vsw); | ||
585 | |||
586 | } | ||
587 | |||
588 | /* Description : This function gets the resolution information from EDID */ | ||
589 | static void get_edid_timing_data(u8 *edid) | ||
590 | { | ||
591 | u8 count; | ||
592 | u16 current_descriptor_addrs; | ||
593 | struct hdmi_cm cm; | ||
594 | struct omap_video_timings edid_timings; | ||
595 | |||
596 | /* search block 0, there are 4 DTDs arranged in priority order */ | ||
597 | for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) { | ||
598 | current_descriptor_addrs = | ||
599 | EDID_DESCRIPTOR_BLOCK0_ADDRESS + | ||
600 | count * EDID_TIMING_DESCRIPTOR_SIZE; | ||
601 | get_horz_vert_timing_info(current_descriptor_addrs, | ||
602 | edid, &edid_timings); | ||
603 | cm = hdmi_get_code(&edid_timings); | ||
604 | DSSDBG("Block0[%d] value matches code = %d , mode = %d\n", | ||
605 | count, cm.code, cm.mode); | ||
606 | if (cm.code == -1) { | ||
607 | continue; | ||
608 | } else { | ||
609 | hdmi.code = cm.code; | ||
610 | hdmi.mode = cm.mode; | ||
611 | DSSDBG("code = %d , mode = %d\n", | ||
612 | hdmi.code, hdmi.mode); | ||
613 | return; | ||
614 | } | ||
615 | } | ||
616 | if (edid[0x7e] != 0x00) { | ||
617 | for (count = 0; count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR; | ||
618 | count++) { | ||
619 | current_descriptor_addrs = | ||
620 | EDID_DESCRIPTOR_BLOCK1_ADDRESS + | ||
621 | count * EDID_TIMING_DESCRIPTOR_SIZE; | ||
622 | get_horz_vert_timing_info(current_descriptor_addrs, | ||
623 | edid, &edid_timings); | ||
624 | cm = hdmi_get_code(&edid_timings); | ||
625 | DSSDBG("Block1[%d] value matches code = %d, mode = %d", | ||
626 | count, cm.code, cm.mode); | ||
627 | if (cm.code == -1) { | ||
628 | continue; | ||
629 | } else { | ||
630 | hdmi.code = cm.code; | ||
631 | hdmi.mode = cm.mode; | ||
632 | DSSDBG("code = %d , mode = %d\n", | ||
633 | hdmi.code, hdmi.mode); | ||
634 | return; | ||
635 | } | ||
636 | } | ||
637 | } | ||
638 | |||
639 | DSSINFO("no valid timing found , falling back to VGA\n"); | ||
640 | hdmi.code = 4; /* setting default value of 640 480 VGA */ | ||
641 | hdmi.mode = HDMI_DVI; | ||
642 | } | ||
643 | |||
644 | static void hdmi_read_edid(struct omap_video_timings *dp) | ||
645 | { | ||
646 | int ret = 0, code; | ||
647 | |||
648 | memset(hdmi.edid, 0, HDMI_EDID_MAX_LENGTH); | ||
649 | |||
650 | if (!hdmi.edid_set) | ||
651 | ret = read_edid(hdmi.edid, HDMI_EDID_MAX_LENGTH); | ||
652 | |||
653 | if (!ret) { | ||
654 | if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) { | ||
655 | /* search for timings of default resolution */ | ||
656 | get_edid_timing_data(hdmi.edid); | ||
657 | hdmi.edid_set = true; | ||
658 | } | ||
659 | } else { | ||
660 | DSSWARN("failed to read E-EDID\n"); | ||
661 | } | ||
662 | |||
663 | if (!hdmi.edid_set) { | ||
664 | DSSINFO("fallback to VGA\n"); | ||
665 | hdmi.code = 4; /* setting default value of 640 480 VGA */ | ||
666 | hdmi.mode = HDMI_DVI; | ||
667 | } | ||
668 | |||
669 | code = get_timings_index(); | ||
670 | |||
671 | *dp = cea_vesa_timings[code].timings; | ||
672 | } | ||
673 | |||
674 | static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, | ||
675 | struct hdmi_core_infoframe_avi *avi_cfg, | ||
676 | struct hdmi_core_packet_enable_repeat *repeat_cfg) | ||
677 | { | ||
678 | DSSDBG("Enter hdmi_core_init\n"); | ||
679 | |||
680 | /* video core */ | ||
681 | video_cfg->ip_bus_width = HDMI_INPUT_8BIT; | ||
682 | video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT; | ||
683 | video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE; | ||
684 | video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE; | ||
685 | video_cfg->hdmi_dvi = HDMI_DVI; | ||
686 | video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK; | ||
687 | |||
688 | /* info frame */ | ||
689 | avi_cfg->db1_format = 0; | ||
690 | avi_cfg->db1_active_info = 0; | ||
691 | avi_cfg->db1_bar_info_dv = 0; | ||
692 | avi_cfg->db1_scan_info = 0; | ||
693 | avi_cfg->db2_colorimetry = 0; | ||
694 | avi_cfg->db2_aspect_ratio = 0; | ||
695 | avi_cfg->db2_active_fmt_ar = 0; | ||
696 | avi_cfg->db3_itc = 0; | ||
697 | avi_cfg->db3_ec = 0; | ||
698 | avi_cfg->db3_q_range = 0; | ||
699 | avi_cfg->db3_nup_scaling = 0; | ||
700 | avi_cfg->db4_videocode = 0; | ||
701 | avi_cfg->db5_pixel_repeat = 0; | ||
702 | avi_cfg->db6_7_line_eoftop = 0 ; | ||
703 | avi_cfg->db8_9_line_sofbottom = 0; | ||
704 | avi_cfg->db10_11_pixel_eofleft = 0; | ||
705 | avi_cfg->db12_13_pixel_sofright = 0; | ||
706 | |||
707 | /* packet enable and repeat */ | ||
708 | repeat_cfg->audio_pkt = 0; | ||
709 | repeat_cfg->audio_pkt_repeat = 0; | ||
710 | repeat_cfg->avi_infoframe = 0; | ||
711 | repeat_cfg->avi_infoframe_repeat = 0; | ||
712 | repeat_cfg->gen_cntrl_pkt = 0; | ||
713 | repeat_cfg->gen_cntrl_pkt_repeat = 0; | ||
714 | repeat_cfg->generic_pkt = 0; | ||
715 | repeat_cfg->generic_pkt_repeat = 0; | ||
716 | } | ||
717 | |||
718 | static void hdmi_core_powerdown_disable(void) | ||
719 | { | ||
720 | DSSDBG("Enter hdmi_core_powerdown_disable\n"); | ||
721 | REG_FLD_MOD(HDMI_CORE_CTRL1, 0x0, 0, 0); | ||
722 | } | ||
723 | |||
724 | static void hdmi_core_swreset_release(void) | ||
725 | { | ||
726 | DSSDBG("Enter hdmi_core_swreset_release\n"); | ||
727 | REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x0, 0, 0); | ||
728 | } | ||
729 | |||
730 | static void hdmi_core_swreset_assert(void) | ||
731 | { | ||
732 | DSSDBG("Enter hdmi_core_swreset_assert\n"); | ||
733 | REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x1, 0, 0); | ||
734 | } | ||
735 | |||
736 | /* DSS_HDMI_CORE_VIDEO_CONFIG */ | ||
737 | static void hdmi_core_video_config(struct hdmi_core_video_config *cfg) | ||
738 | { | ||
739 | u32 r = 0; | ||
740 | |||
741 | /* sys_ctrl1 default configuration not tunable */ | ||
742 | r = hdmi_read_reg(HDMI_CORE_CTRL1); | ||
743 | r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5); | ||
744 | r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4); | ||
745 | r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2); | ||
746 | r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1); | ||
747 | hdmi_write_reg(HDMI_CORE_CTRL1, r); | ||
748 | |||
749 | REG_FLD_MOD(HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6); | ||
750 | |||
751 | /* Vid_Mode */ | ||
752 | r = hdmi_read_reg(HDMI_CORE_SYS_VID_MODE); | ||
753 | |||
754 | /* dither truncation configuration */ | ||
755 | if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) { | ||
756 | r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6); | ||
757 | r = FLD_MOD(r, 1, 5, 5); | ||
758 | } else { | ||
759 | r = FLD_MOD(r, cfg->op_dither_truc, 7, 6); | ||
760 | r = FLD_MOD(r, 0, 5, 5); | ||
761 | } | ||
762 | hdmi_write_reg(HDMI_CORE_SYS_VID_MODE, r); | ||
763 | |||
764 | /* HDMI_Ctrl */ | ||
765 | r = hdmi_read_reg(HDMI_CORE_AV_HDMI_CTRL); | ||
766 | r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6); | ||
767 | r = FLD_MOD(r, cfg->pkt_mode, 5, 3); | ||
768 | r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0); | ||
769 | hdmi_write_reg(HDMI_CORE_AV_HDMI_CTRL, r); | ||
770 | |||
771 | /* TMDS_CTRL */ | ||
772 | REG_FLD_MOD(HDMI_CORE_SYS_TMDS_CTRL, | ||
773 | cfg->tclk_sel_clkmult, 6, 5); | ||
774 | } | ||
775 | |||
776 | static void hdmi_core_aux_infoframe_avi_config( | ||
777 | struct hdmi_core_infoframe_avi info_avi) | ||
778 | { | ||
779 | u32 val; | ||
780 | char sum = 0, checksum = 0; | ||
781 | |||
782 | sum += 0x82 + 0x002 + 0x00D; | ||
783 | hdmi_write_reg(HDMI_CORE_AV_AVI_TYPE, 0x082); | ||
784 | hdmi_write_reg(HDMI_CORE_AV_AVI_VERS, 0x002); | ||
785 | hdmi_write_reg(HDMI_CORE_AV_AVI_LEN, 0x00D); | ||
786 | |||
787 | val = (info_avi.db1_format << 5) | | ||
788 | (info_avi.db1_active_info << 4) | | ||
789 | (info_avi.db1_bar_info_dv << 2) | | ||
790 | (info_avi.db1_scan_info); | ||
791 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(0), val); | ||
792 | sum += val; | ||
793 | |||
794 | val = (info_avi.db2_colorimetry << 6) | | ||
795 | (info_avi.db2_aspect_ratio << 4) | | ||
796 | (info_avi.db2_active_fmt_ar); | ||
797 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(1), val); | ||
798 | sum += val; | ||
799 | |||
800 | val = (info_avi.db3_itc << 7) | | ||
801 | (info_avi.db3_ec << 4) | | ||
802 | (info_avi.db3_q_range << 2) | | ||
803 | (info_avi.db3_nup_scaling); | ||
804 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(2), val); | ||
805 | sum += val; | ||
806 | |||
807 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(3), info_avi.db4_videocode); | ||
808 | sum += info_avi.db4_videocode; | ||
809 | |||
810 | val = info_avi.db5_pixel_repeat; | ||
811 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(4), val); | ||
812 | sum += val; | ||
813 | |||
814 | val = info_avi.db6_7_line_eoftop & 0x00FF; | ||
815 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(5), val); | ||
816 | sum += val; | ||
817 | |||
818 | val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF); | ||
819 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(6), val); | ||
820 | sum += val; | ||
821 | |||
822 | val = info_avi.db8_9_line_sofbottom & 0x00FF; | ||
823 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(7), val); | ||
824 | sum += val; | ||
825 | |||
826 | val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF); | ||
827 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(8), val); | ||
828 | sum += val; | ||
829 | |||
830 | val = info_avi.db10_11_pixel_eofleft & 0x00FF; | ||
831 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(9), val); | ||
832 | sum += val; | ||
833 | |||
834 | val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF); | ||
835 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(10), val); | ||
836 | sum += val; | ||
837 | |||
838 | val = info_avi.db12_13_pixel_sofright & 0x00FF; | ||
839 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(11), val); | ||
840 | sum += val; | ||
841 | |||
842 | val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF); | ||
843 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(12), val); | ||
844 | sum += val; | ||
845 | |||
846 | checksum = 0x100 - sum; | ||
847 | hdmi_write_reg(HDMI_CORE_AV_AVI_CHSUM, checksum); | ||
848 | } | ||
849 | |||
850 | static void hdmi_core_av_packet_config( | ||
851 | struct hdmi_core_packet_enable_repeat repeat_cfg) | ||
852 | { | ||
853 | /* enable/repeat the infoframe */ | ||
854 | hdmi_write_reg(HDMI_CORE_AV_PB_CTRL1, | ||
855 | (repeat_cfg.audio_pkt << 5) | | ||
856 | (repeat_cfg.audio_pkt_repeat << 4) | | ||
857 | (repeat_cfg.avi_infoframe << 1) | | ||
858 | (repeat_cfg.avi_infoframe_repeat)); | ||
859 | |||
860 | /* enable/repeat the packet */ | ||
861 | hdmi_write_reg(HDMI_CORE_AV_PB_CTRL2, | ||
862 | (repeat_cfg.gen_cntrl_pkt << 3) | | ||
863 | (repeat_cfg.gen_cntrl_pkt_repeat << 2) | | ||
864 | (repeat_cfg.generic_pkt << 1) | | ||
865 | (repeat_cfg.generic_pkt_repeat)); | ||
866 | } | ||
867 | |||
868 | static void hdmi_wp_init(struct omap_video_timings *timings, | ||
869 | struct hdmi_video_format *video_fmt, | ||
870 | struct hdmi_video_interface *video_int) | ||
871 | { | ||
872 | DSSDBG("Enter hdmi_wp_init\n"); | ||
873 | |||
874 | timings->hbp = 0; | ||
875 | timings->hfp = 0; | ||
876 | timings->hsw = 0; | ||
877 | timings->vbp = 0; | ||
878 | timings->vfp = 0; | ||
879 | timings->vsw = 0; | ||
880 | |||
881 | video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444; | ||
882 | video_fmt->y_res = 0; | ||
883 | video_fmt->x_res = 0; | ||
884 | |||
885 | video_int->vsp = 0; | ||
886 | video_int->hsp = 0; | ||
887 | |||
888 | video_int->interlacing = 0; | ||
889 | video_int->tm = 0; /* HDMI_TIMING_SLAVE */ | ||
890 | |||
891 | } | ||
892 | |||
893 | static void hdmi_wp_video_start(bool start) | ||
894 | { | ||
895 | REG_FLD_MOD(HDMI_WP_VIDEO_CFG, start, 31, 31); | ||
896 | } | ||
897 | |||
898 | static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt, | ||
899 | struct omap_video_timings *timings, struct hdmi_config *param) | ||
900 | { | ||
901 | DSSDBG("Enter hdmi_wp_video_init_format\n"); | ||
902 | |||
903 | video_fmt->y_res = param->timings.timings.y_res; | ||
904 | video_fmt->x_res = param->timings.timings.x_res; | ||
905 | |||
906 | timings->hbp = param->timings.timings.hbp; | ||
907 | timings->hfp = param->timings.timings.hfp; | ||
908 | timings->hsw = param->timings.timings.hsw; | ||
909 | timings->vbp = param->timings.timings.vbp; | ||
910 | timings->vfp = param->timings.timings.vfp; | ||
911 | timings->vsw = param->timings.timings.vsw; | ||
912 | } | ||
913 | |||
914 | static void hdmi_wp_video_config_format( | ||
915 | struct hdmi_video_format *video_fmt) | ||
916 | { | ||
917 | u32 l = 0; | ||
918 | |||
919 | REG_FLD_MOD(HDMI_WP_VIDEO_CFG, video_fmt->packing_mode, 10, 8); | ||
920 | |||
921 | l |= FLD_VAL(video_fmt->y_res, 31, 16); | ||
922 | l |= FLD_VAL(video_fmt->x_res, 15, 0); | ||
923 | hdmi_write_reg(HDMI_WP_VIDEO_SIZE, l); | ||
924 | } | ||
925 | |||
926 | static void hdmi_wp_video_config_interface( | ||
927 | struct hdmi_video_interface *video_int) | ||
928 | { | ||
929 | u32 r; | ||
930 | DSSDBG("Enter hdmi_wp_video_config_interface\n"); | ||
931 | |||
932 | r = hdmi_read_reg(HDMI_WP_VIDEO_CFG); | ||
933 | r = FLD_MOD(r, video_int->vsp, 7, 7); | ||
934 | r = FLD_MOD(r, video_int->hsp, 6, 6); | ||
935 | r = FLD_MOD(r, video_int->interlacing, 3, 3); | ||
936 | r = FLD_MOD(r, video_int->tm, 1, 0); | ||
937 | hdmi_write_reg(HDMI_WP_VIDEO_CFG, r); | ||
938 | } | ||
939 | |||
940 | static void hdmi_wp_video_config_timing( | ||
941 | struct omap_video_timings *timings) | ||
942 | { | ||
943 | u32 timing_h = 0; | ||
944 | u32 timing_v = 0; | ||
945 | |||
946 | DSSDBG("Enter hdmi_wp_video_config_timing\n"); | ||
947 | |||
948 | timing_h |= FLD_VAL(timings->hbp, 31, 20); | ||
949 | timing_h |= FLD_VAL(timings->hfp, 19, 8); | ||
950 | timing_h |= FLD_VAL(timings->hsw, 7, 0); | ||
951 | hdmi_write_reg(HDMI_WP_VIDEO_TIMING_H, timing_h); | ||
952 | |||
953 | timing_v |= FLD_VAL(timings->vbp, 31, 20); | ||
954 | timing_v |= FLD_VAL(timings->vfp, 19, 8); | ||
955 | timing_v |= FLD_VAL(timings->vsw, 7, 0); | ||
956 | hdmi_write_reg(HDMI_WP_VIDEO_TIMING_V, timing_v); | ||
957 | } | ||
958 | |||
959 | static void hdmi_basic_configure(struct hdmi_config *cfg) | ||
960 | { | ||
961 | /* HDMI */ | ||
962 | struct omap_video_timings video_timing; | ||
963 | struct hdmi_video_format video_format; | ||
964 | struct hdmi_video_interface video_interface; | ||
965 | /* HDMI core */ | ||
966 | struct hdmi_core_infoframe_avi avi_cfg; | ||
967 | struct hdmi_core_video_config v_core_cfg; | ||
968 | struct hdmi_core_packet_enable_repeat repeat_cfg; | ||
969 | |||
970 | hdmi_wp_init(&video_timing, &video_format, | ||
971 | &video_interface); | ||
972 | |||
973 | hdmi_core_init(&v_core_cfg, | ||
974 | &avi_cfg, | ||
975 | &repeat_cfg); | ||
976 | |||
977 | hdmi_wp_video_init_format(&video_format, | ||
978 | &video_timing, cfg); | ||
979 | |||
980 | hdmi_wp_video_config_timing(&video_timing); | ||
981 | |||
982 | /* video config */ | ||
983 | video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422; | ||
984 | |||
985 | hdmi_wp_video_config_format(&video_format); | ||
986 | |||
987 | video_interface.vsp = cfg->timings.vsync_pol; | ||
988 | video_interface.hsp = cfg->timings.hsync_pol; | ||
989 | video_interface.interlacing = cfg->interlace; | ||
990 | video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */ | ||
991 | |||
992 | hdmi_wp_video_config_interface(&video_interface); | ||
993 | |||
994 | /* | ||
995 | * configure core video part | ||
996 | * set software reset in the core | ||
997 | */ | ||
998 | hdmi_core_swreset_assert(); | ||
999 | |||
1000 | /* power down off */ | ||
1001 | hdmi_core_powerdown_disable(); | ||
1002 | |||
1003 | v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL; | ||
1004 | v_core_cfg.hdmi_dvi = cfg->cm.mode; | ||
1005 | |||
1006 | hdmi_core_video_config(&v_core_cfg); | ||
1007 | |||
1008 | /* release software reset in the core */ | ||
1009 | hdmi_core_swreset_release(); | ||
1010 | |||
1011 | /* | ||
1012 | * configure packet | ||
1013 | * info frame video see doc CEA861-D page 65 | ||
1014 | */ | ||
1015 | avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB; | ||
1016 | avi_cfg.db1_active_info = | ||
1017 | HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF; | ||
1018 | avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO; | ||
1019 | avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0; | ||
1020 | avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO; | ||
1021 | avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO; | ||
1022 | avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME; | ||
1023 | avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO; | ||
1024 | avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601; | ||
1025 | avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT; | ||
1026 | avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO; | ||
1027 | avi_cfg.db4_videocode = cfg->cm.code; | ||
1028 | avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO; | ||
1029 | avi_cfg.db6_7_line_eoftop = 0; | ||
1030 | avi_cfg.db8_9_line_sofbottom = 0; | ||
1031 | avi_cfg.db10_11_pixel_eofleft = 0; | ||
1032 | avi_cfg.db12_13_pixel_sofright = 0; | ||
1033 | |||
1034 | hdmi_core_aux_infoframe_avi_config(avi_cfg); | ||
1035 | |||
1036 | /* enable/repeat the infoframe */ | ||
1037 | repeat_cfg.avi_infoframe = HDMI_PACKETENABLE; | ||
1038 | repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON; | ||
1039 | /* wakeup */ | ||
1040 | repeat_cfg.audio_pkt = HDMI_PACKETENABLE; | ||
1041 | repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON; | ||
1042 | hdmi_core_av_packet_config(repeat_cfg); | ||
1043 | } | ||
1044 | |||
1045 | static void update_hdmi_timings(struct hdmi_config *cfg, | ||
1046 | struct omap_video_timings *timings, int code) | ||
1047 | { | ||
1048 | cfg->timings.timings.x_res = timings->x_res; | ||
1049 | cfg->timings.timings.y_res = timings->y_res; | ||
1050 | cfg->timings.timings.hbp = timings->hbp; | ||
1051 | cfg->timings.timings.hfp = timings->hfp; | ||
1052 | cfg->timings.timings.hsw = timings->hsw; | ||
1053 | cfg->timings.timings.vbp = timings->vbp; | ||
1054 | cfg->timings.timings.vfp = timings->vfp; | ||
1055 | cfg->timings.timings.vsw = timings->vsw; | ||
1056 | cfg->timings.timings.pixel_clock = timings->pixel_clock; | ||
1057 | cfg->timings.vsync_pol = cea_vesa_timings[code].vsync_pol; | ||
1058 | cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol; | ||
1059 | } | ||
1060 | |||
1061 | static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, | ||
1062 | struct hdmi_pll_info *pi) | ||
1063 | { | ||
1064 | unsigned long clkin, refclk; | ||
1065 | u32 mf; | ||
1066 | |||
1067 | clkin = dss_clk_get_rate(DSS_CLK_SYSCK) / 10000; | ||
1068 | /* | ||
1069 | * Input clock is predivided by N + 1 | ||
1070 | * out put of which is reference clk | ||
1071 | */ | ||
1072 | pi->regn = dssdev->clocks.hdmi.regn; | ||
1073 | refclk = clkin / (pi->regn + 1); | ||
1074 | |||
1075 | /* | ||
1076 | * multiplier is pixel_clk/ref_clk | ||
1077 | * Multiplying by 100 to avoid fractional part removal | ||
1078 | */ | ||
1079 | pi->regm = (phy * 100 / (refclk)) / 100; | ||
1080 | pi->regm2 = dssdev->clocks.hdmi.regm2; | ||
1081 | |||
1082 | /* | ||
1083 | * fractional multiplier is remainder of the difference between | ||
1084 | * multiplier and actual phy(required pixel clock thus should be | ||
1085 | * multiplied by 2^18(262144) divided by the reference clock | ||
1086 | */ | ||
1087 | mf = (phy - pi->regm * refclk) * 262144; | ||
1088 | pi->regmf = mf / (refclk); | ||
1089 | |||
1090 | /* | ||
1091 | * Dcofreq should be set to 1 if required pixel clock | ||
1092 | * is greater than 1000MHz | ||
1093 | */ | ||
1094 | pi->dcofreq = phy > 1000 * 100; | ||
1095 | pi->regsd = ((pi->regm * clkin / 10) / ((pi->regn + 1) * 250) + 5) / 10; | ||
1096 | |||
1097 | DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); | ||
1098 | DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); | ||
1099 | } | ||
1100 | |||
1101 | static void hdmi_enable_clocks(int enable) | ||
1102 | { | ||
1103 | if (enable) | ||
1104 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | | ||
1105 | DSS_CLK_SYSCK | DSS_CLK_VIDFCK); | ||
1106 | else | ||
1107 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | | ||
1108 | DSS_CLK_SYSCK | DSS_CLK_VIDFCK); | ||
1109 | } | ||
1110 | |||
1111 | static int hdmi_power_on(struct omap_dss_device *dssdev) | ||
1112 | { | ||
1113 | int r, code = 0; | ||
1114 | struct hdmi_pll_info pll_data; | ||
1115 | struct omap_video_timings *p; | ||
1116 | unsigned long phy; | ||
1117 | |||
1118 | hdmi_enable_clocks(1); | ||
1119 | |||
1120 | dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); | ||
1121 | |||
1122 | p = &dssdev->panel.timings; | ||
1123 | |||
1124 | DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", | ||
1125 | dssdev->panel.timings.x_res, | ||
1126 | dssdev->panel.timings.y_res); | ||
1127 | |||
1128 | if (!hdmi.custom_set) { | ||
1129 | DSSDBG("Read EDID as no EDID is not set on poweron\n"); | ||
1130 | hdmi_read_edid(p); | ||
1131 | } | ||
1132 | code = get_timings_index(); | ||
1133 | dssdev->panel.timings = cea_vesa_timings[code].timings; | ||
1134 | update_hdmi_timings(&hdmi.cfg, p, code); | ||
1135 | |||
1136 | phy = p->pixel_clock; | ||
1137 | |||
1138 | hdmi_compute_pll(dssdev, phy, &pll_data); | ||
1139 | |||
1140 | hdmi_wp_video_start(0); | ||
1141 | |||
1142 | /* config the PLL and PHY first */ | ||
1143 | r = hdmi_pll_program(&pll_data); | ||
1144 | if (r) { | ||
1145 | DSSDBG("Failed to lock PLL\n"); | ||
1146 | goto err; | ||
1147 | } | ||
1148 | |||
1149 | r = hdmi_phy_init(); | ||
1150 | if (r) { | ||
1151 | DSSDBG("Failed to start PHY\n"); | ||
1152 | goto err; | ||
1153 | } | ||
1154 | |||
1155 | hdmi.cfg.cm.mode = hdmi.mode; | ||
1156 | hdmi.cfg.cm.code = hdmi.code; | ||
1157 | hdmi_basic_configure(&hdmi.cfg); | ||
1158 | |||
1159 | /* Make selection of HDMI in DSS */ | ||
1160 | dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); | ||
1161 | |||
1162 | /* Select the dispc clock source as PRCM clock, to ensure that it is not | ||
1163 | * DSI PLL source as the clock selected by DSI PLL might not be | ||
1164 | * sufficient for the resolution selected / that can be changed | ||
1165 | * dynamically by user. This can be moved to single location , say | ||
1166 | * Boardfile. | ||
1167 | */ | ||
1168 | dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); | ||
1169 | |||
1170 | /* bypass TV gamma table */ | ||
1171 | dispc_enable_gamma_table(0); | ||
1172 | |||
1173 | /* tv size */ | ||
1174 | dispc_set_digit_size(dssdev->panel.timings.x_res, | ||
1175 | dssdev->panel.timings.y_res); | ||
1176 | |||
1177 | dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 1); | ||
1178 | |||
1179 | hdmi_wp_video_start(1); | ||
1180 | |||
1181 | return 0; | ||
1182 | err: | ||
1183 | hdmi_enable_clocks(0); | ||
1184 | return -EIO; | ||
1185 | } | ||
1186 | |||
1187 | static void hdmi_power_off(struct omap_dss_device *dssdev) | ||
1188 | { | ||
1189 | dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); | ||
1190 | |||
1191 | hdmi_wp_video_start(0); | ||
1192 | hdmi_phy_off(); | ||
1193 | hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); | ||
1194 | hdmi_enable_clocks(0); | ||
1195 | |||
1196 | hdmi.edid_set = 0; | ||
1197 | } | ||
1198 | |||
1199 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, | ||
1200 | struct omap_video_timings *timings) | ||
1201 | { | ||
1202 | struct hdmi_cm cm; | ||
1203 | |||
1204 | cm = hdmi_get_code(timings); | ||
1205 | if (cm.code == -1) { | ||
1206 | DSSERR("Invalid timing entered\n"); | ||
1207 | return -EINVAL; | ||
1208 | } | ||
1209 | |||
1210 | return 0; | ||
1211 | |||
1212 | } | ||
1213 | |||
1214 | void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev) | ||
1215 | { | ||
1216 | struct hdmi_cm cm; | ||
1217 | |||
1218 | hdmi.custom_set = 1; | ||
1219 | cm = hdmi_get_code(&dssdev->panel.timings); | ||
1220 | hdmi.code = cm.code; | ||
1221 | hdmi.mode = cm.mode; | ||
1222 | omapdss_hdmi_display_enable(dssdev); | ||
1223 | hdmi.custom_set = 0; | ||
1224 | } | ||
1225 | |||
1226 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) | ||
1227 | { | ||
1228 | int r = 0; | ||
1229 | |||
1230 | DSSDBG("ENTER hdmi_display_enable\n"); | ||
1231 | |||
1232 | mutex_lock(&hdmi.lock); | ||
1233 | |||
1234 | r = omap_dss_start_device(dssdev); | ||
1235 | if (r) { | ||
1236 | DSSERR("failed to start device\n"); | ||
1237 | goto err0; | ||
1238 | } | ||
1239 | |||
1240 | if (dssdev->platform_enable) { | ||
1241 | r = dssdev->platform_enable(dssdev); | ||
1242 | if (r) { | ||
1243 | DSSERR("failed to enable GPIO's\n"); | ||
1244 | goto err1; | ||
1245 | } | ||
1246 | } | ||
1247 | |||
1248 | r = hdmi_power_on(dssdev); | ||
1249 | if (r) { | ||
1250 | DSSERR("failed to power on device\n"); | ||
1251 | goto err2; | ||
1252 | } | ||
1253 | |||
1254 | mutex_unlock(&hdmi.lock); | ||
1255 | return 0; | ||
1256 | |||
1257 | err2: | ||
1258 | if (dssdev->platform_disable) | ||
1259 | dssdev->platform_disable(dssdev); | ||
1260 | err1: | ||
1261 | omap_dss_stop_device(dssdev); | ||
1262 | err0: | ||
1263 | mutex_unlock(&hdmi.lock); | ||
1264 | return r; | ||
1265 | } | ||
1266 | |||
1267 | void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev) | ||
1268 | { | ||
1269 | DSSDBG("Enter hdmi_display_disable\n"); | ||
1270 | |||
1271 | mutex_lock(&hdmi.lock); | ||
1272 | |||
1273 | hdmi_power_off(dssdev); | ||
1274 | |||
1275 | if (dssdev->platform_disable) | ||
1276 | dssdev->platform_disable(dssdev); | ||
1277 | |||
1278 | omap_dss_stop_device(dssdev); | ||
1279 | |||
1280 | mutex_unlock(&hdmi.lock); | ||
1281 | } | ||
1282 | |||
1283 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
1284 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
1285 | static void hdmi_wp_audio_config_format( | ||
1286 | struct hdmi_audio_format *aud_fmt) | ||
1287 | { | ||
1288 | u32 r; | ||
1289 | |||
1290 | DSSDBG("Enter hdmi_wp_audio_config_format\n"); | ||
1291 | |||
1292 | r = hdmi_read_reg(HDMI_WP_AUDIO_CFG); | ||
1293 | r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24); | ||
1294 | r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16); | ||
1295 | r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5); | ||
1296 | r = FLD_MOD(r, aud_fmt->type, 4, 4); | ||
1297 | r = FLD_MOD(r, aud_fmt->justification, 3, 3); | ||
1298 | r = FLD_MOD(r, aud_fmt->sample_order, 2, 2); | ||
1299 | r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1); | ||
1300 | r = FLD_MOD(r, aud_fmt->sample_size, 0, 0); | ||
1301 | hdmi_write_reg(HDMI_WP_AUDIO_CFG, r); | ||
1302 | } | ||
1303 | |||
1304 | static void hdmi_wp_audio_config_dma(struct hdmi_audio_dma *aud_dma) | ||
1305 | { | ||
1306 | u32 r; | ||
1307 | |||
1308 | DSSDBG("Enter hdmi_wp_audio_config_dma\n"); | ||
1309 | |||
1310 | r = hdmi_read_reg(HDMI_WP_AUDIO_CFG2); | ||
1311 | r = FLD_MOD(r, aud_dma->transfer_size, 15, 8); | ||
1312 | r = FLD_MOD(r, aud_dma->block_size, 7, 0); | ||
1313 | hdmi_write_reg(HDMI_WP_AUDIO_CFG2, r); | ||
1314 | |||
1315 | r = hdmi_read_reg(HDMI_WP_AUDIO_CTRL); | ||
1316 | r = FLD_MOD(r, aud_dma->mode, 9, 9); | ||
1317 | r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0); | ||
1318 | hdmi_write_reg(HDMI_WP_AUDIO_CTRL, r); | ||
1319 | } | ||
1320 | |||
1321 | static void hdmi_core_audio_config(struct hdmi_core_audio_config *cfg) | ||
1322 | { | ||
1323 | u32 r; | ||
1324 | |||
1325 | /* audio clock recovery parameters */ | ||
1326 | r = hdmi_read_reg(HDMI_CORE_AV_ACR_CTRL); | ||
1327 | r = FLD_MOD(r, cfg->use_mclk, 2, 2); | ||
1328 | r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1); | ||
1329 | r = FLD_MOD(r, cfg->cts_mode, 0, 0); | ||
1330 | hdmi_write_reg(HDMI_CORE_AV_ACR_CTRL, r); | ||
1331 | |||
1332 | REG_FLD_MOD(HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0); | ||
1333 | REG_FLD_MOD(HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0); | ||
1334 | REG_FLD_MOD(HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0); | ||
1335 | |||
1336 | if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) { | ||
1337 | REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0); | ||
1338 | REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0); | ||
1339 | REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0); | ||
1340 | } else { | ||
1341 | /* | ||
1342 | * HDMI IP uses this configuration to divide the MCLK to | ||
1343 | * update CTS value. | ||
1344 | */ | ||
1345 | REG_FLD_MOD(HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0); | ||
1346 | |||
1347 | /* Configure clock for audio packets */ | ||
1348 | REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_1, | ||
1349 | cfg->aud_par_busclk, 7, 0); | ||
1350 | REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_2, | ||
1351 | (cfg->aud_par_busclk >> 8), 7, 0); | ||
1352 | REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_3, | ||
1353 | (cfg->aud_par_busclk >> 16), 7, 0); | ||
1354 | } | ||
1355 | |||
1356 | /* Override of SPDIF sample frequency with value in I2S_CHST4 */ | ||
1357 | REG_FLD_MOD(HDMI_CORE_AV_SPDIF_CTRL, cfg->fs_override, 1, 1); | ||
1358 | |||
1359 | /* I2S parameters */ | ||
1360 | REG_FLD_MOD(HDMI_CORE_AV_I2S_CHST4, cfg->freq_sample, 3, 0); | ||
1361 | |||
1362 | r = hdmi_read_reg(HDMI_CORE_AV_I2S_IN_CTRL); | ||
1363 | r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7); | ||
1364 | r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6); | ||
1365 | r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5); | ||
1366 | r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4); | ||
1367 | r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3); | ||
1368 | r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2); | ||
1369 | r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1); | ||
1370 | r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0); | ||
1371 | hdmi_write_reg(HDMI_CORE_AV_I2S_IN_CTRL, r); | ||
1372 | |||
1373 | r = hdmi_read_reg(HDMI_CORE_AV_I2S_CHST5); | ||
1374 | r = FLD_MOD(r, cfg->freq_sample, 7, 4); | ||
1375 | r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1); | ||
1376 | r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0); | ||
1377 | hdmi_write_reg(HDMI_CORE_AV_I2S_CHST5, r); | ||
1378 | |||
1379 | REG_FLD_MOD(HDMI_CORE_AV_I2S_IN_LEN, cfg->i2s_cfg.in_length_bits, 3, 0); | ||
1380 | |||
1381 | /* Audio channels and mode parameters */ | ||
1382 | REG_FLD_MOD(HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1); | ||
1383 | r = hdmi_read_reg(HDMI_CORE_AV_AUD_MODE); | ||
1384 | r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4); | ||
1385 | r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3); | ||
1386 | r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2); | ||
1387 | r = FLD_MOD(r, cfg->en_spdif, 1, 1); | ||
1388 | hdmi_write_reg(HDMI_CORE_AV_AUD_MODE, r); | ||
1389 | } | ||
1390 | |||
1391 | static void hdmi_core_audio_infoframe_config( | ||
1392 | struct hdmi_core_infoframe_audio *info_aud) | ||
1393 | { | ||
1394 | u8 val; | ||
1395 | u8 sum = 0, checksum = 0; | ||
1396 | |||
1397 | /* | ||
1398 | * Set audio info frame type, version and length as | ||
1399 | * described in HDMI 1.4a Section 8.2.2 specification. | ||
1400 | * Checksum calculation is defined in Section 5.3.5. | ||
1401 | */ | ||
1402 | hdmi_write_reg(HDMI_CORE_AV_AUDIO_TYPE, 0x84); | ||
1403 | hdmi_write_reg(HDMI_CORE_AV_AUDIO_VERS, 0x01); | ||
1404 | hdmi_write_reg(HDMI_CORE_AV_AUDIO_LEN, 0x0a); | ||
1405 | sum += 0x84 + 0x001 + 0x00a; | ||
1406 | |||
1407 | val = (info_aud->db1_coding_type << 4) | ||
1408 | | (info_aud->db1_channel_count - 1); | ||
1409 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(0), val); | ||
1410 | sum += val; | ||
1411 | |||
1412 | val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size; | ||
1413 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(1), val); | ||
1414 | sum += val; | ||
1415 | |||
1416 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(2), 0x00); | ||
1417 | |||
1418 | val = info_aud->db4_channel_alloc; | ||
1419 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(3), val); | ||
1420 | sum += val; | ||
1421 | |||
1422 | val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3); | ||
1423 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(4), val); | ||
1424 | sum += val; | ||
1425 | |||
1426 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(5), 0x00); | ||
1427 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(6), 0x00); | ||
1428 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(7), 0x00); | ||
1429 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(8), 0x00); | ||
1430 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(9), 0x00); | ||
1431 | |||
1432 | checksum = 0x100 - sum; | ||
1433 | hdmi_write_reg(HDMI_CORE_AV_AUDIO_CHSUM, checksum); | ||
1434 | |||
1435 | /* | ||
1436 | * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing | ||
1437 | * is available. | ||
1438 | */ | ||
1439 | } | ||
1440 | |||
1441 | static int hdmi_config_audio_acr(u32 sample_freq, u32 *n, u32 *cts) | ||
1442 | { | ||
1443 | u32 r; | ||
1444 | u32 deep_color = 0; | ||
1445 | u32 pclk = hdmi.cfg.timings.timings.pixel_clock; | ||
1446 | |||
1447 | if (n == NULL || cts == NULL) | ||
1448 | return -EINVAL; | ||
1449 | /* | ||
1450 | * Obtain current deep color configuration. This needed | ||
1451 | * to calculate the TMDS clock based on the pixel clock. | ||
1452 | */ | ||
1453 | r = REG_GET(HDMI_WP_VIDEO_CFG, 1, 0); | ||
1454 | switch (r) { | ||
1455 | case 1: /* No deep color selected */ | ||
1456 | deep_color = 100; | ||
1457 | break; | ||
1458 | case 2: /* 10-bit deep color selected */ | ||
1459 | deep_color = 125; | ||
1460 | break; | ||
1461 | case 3: /* 12-bit deep color selected */ | ||
1462 | deep_color = 150; | ||
1463 | break; | ||
1464 | default: | ||
1465 | return -EINVAL; | ||
1466 | } | ||
1467 | |||
1468 | switch (sample_freq) { | ||
1469 | case 32000: | ||
1470 | if ((deep_color == 125) && ((pclk == 54054) | ||
1471 | || (pclk == 74250))) | ||
1472 | *n = 8192; | ||
1473 | else | ||
1474 | *n = 4096; | ||
1475 | break; | ||
1476 | case 44100: | ||
1477 | *n = 6272; | ||
1478 | break; | ||
1479 | case 48000: | ||
1480 | if ((deep_color == 125) && ((pclk == 54054) | ||
1481 | || (pclk == 74250))) | ||
1482 | *n = 8192; | ||
1483 | else | ||
1484 | *n = 6144; | ||
1485 | break; | ||
1486 | default: | ||
1487 | *n = 0; | ||
1488 | return -EINVAL; | ||
1489 | } | ||
1490 | |||
1491 | /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */ | ||
1492 | *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10); | ||
1493 | |||
1494 | return 0; | ||
1495 | } | ||
1496 | |||
1497 | static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, | ||
1498 | struct snd_pcm_hw_params *params, | ||
1499 | struct snd_soc_dai *dai) | ||
1500 | { | ||
1501 | struct hdmi_audio_format audio_format; | ||
1502 | struct hdmi_audio_dma audio_dma; | ||
1503 | struct hdmi_core_audio_config core_cfg; | ||
1504 | struct hdmi_core_infoframe_audio aud_if_cfg; | ||
1505 | int err, n, cts; | ||
1506 | enum hdmi_core_audio_sample_freq sample_freq; | ||
1507 | |||
1508 | switch (params_format(params)) { | ||
1509 | case SNDRV_PCM_FORMAT_S16_LE: | ||
1510 | core_cfg.i2s_cfg.word_max_length = | ||
1511 | HDMI_AUDIO_I2S_MAX_WORD_20BITS; | ||
1512 | core_cfg.i2s_cfg.word_length = HDMI_AUDIO_I2S_CHST_WORD_16_BITS; | ||
1513 | core_cfg.i2s_cfg.in_length_bits = | ||
1514 | HDMI_AUDIO_I2S_INPUT_LENGTH_16; | ||
1515 | core_cfg.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT; | ||
1516 | audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES; | ||
1517 | audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS; | ||
1518 | audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT; | ||
1519 | audio_dma.transfer_size = 0x10; | ||
1520 | break; | ||
1521 | case SNDRV_PCM_FORMAT_S24_LE: | ||
1522 | core_cfg.i2s_cfg.word_max_length = | ||
1523 | HDMI_AUDIO_I2S_MAX_WORD_24BITS; | ||
1524 | core_cfg.i2s_cfg.word_length = HDMI_AUDIO_I2S_CHST_WORD_24_BITS; | ||
1525 | core_cfg.i2s_cfg.in_length_bits = | ||
1526 | HDMI_AUDIO_I2S_INPUT_LENGTH_24; | ||
1527 | audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_ONESAMPLE; | ||
1528 | audio_format.sample_size = HDMI_AUDIO_SAMPLE_24BITS; | ||
1529 | audio_format.justification = HDMI_AUDIO_JUSTIFY_RIGHT; | ||
1530 | core_cfg.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT; | ||
1531 | audio_dma.transfer_size = 0x20; | ||
1532 | break; | ||
1533 | default: | ||
1534 | return -EINVAL; | ||
1535 | } | ||
1536 | |||
1537 | switch (params_rate(params)) { | ||
1538 | case 32000: | ||
1539 | sample_freq = HDMI_AUDIO_FS_32000; | ||
1540 | break; | ||
1541 | case 44100: | ||
1542 | sample_freq = HDMI_AUDIO_FS_44100; | ||
1543 | break; | ||
1544 | case 48000: | ||
1545 | sample_freq = HDMI_AUDIO_FS_48000; | ||
1546 | break; | ||
1547 | default: | ||
1548 | return -EINVAL; | ||
1549 | } | ||
1550 | |||
1551 | err = hdmi_config_audio_acr(params_rate(params), &n, &cts); | ||
1552 | if (err < 0) | ||
1553 | return err; | ||
1554 | |||
1555 | /* Audio wrapper config */ | ||
1556 | audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL; | ||
1557 | audio_format.active_chnnls_msk = 0x03; | ||
1558 | audio_format.type = HDMI_AUDIO_TYPE_LPCM; | ||
1559 | audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST; | ||
1560 | /* Disable start/stop signals of IEC 60958 blocks */ | ||
1561 | audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF; | ||
1562 | |||
1563 | audio_dma.block_size = 0xC0; | ||
1564 | audio_dma.mode = HDMI_AUDIO_TRANSF_DMA; | ||
1565 | audio_dma.fifo_threshold = 0x20; /* in number of samples */ | ||
1566 | |||
1567 | hdmi_wp_audio_config_dma(&audio_dma); | ||
1568 | hdmi_wp_audio_config_format(&audio_format); | ||
1569 | |||
1570 | /* | ||
1571 | * I2S config | ||
1572 | */ | ||
1573 | core_cfg.i2s_cfg.en_high_bitrate_aud = false; | ||
1574 | /* Only used with high bitrate audio */ | ||
1575 | core_cfg.i2s_cfg.cbit_order = false; | ||
1576 | /* Serial data and word select should change on sck rising edge */ | ||
1577 | core_cfg.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING; | ||
1578 | core_cfg.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM; | ||
1579 | /* Set I2S word select polarity */ | ||
1580 | core_cfg.i2s_cfg.ws_polarity = HDMI_AUDIO_I2S_WS_POLARITY_LOW_IS_LEFT; | ||
1581 | core_cfg.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST; | ||
1582 | /* Set serial data to word select shift. See Phillips spec. */ | ||
1583 | core_cfg.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT; | ||
1584 | /* Enable one of the four available serial data channels */ | ||
1585 | core_cfg.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN; | ||
1586 | |||
1587 | /* Core audio config */ | ||
1588 | core_cfg.freq_sample = sample_freq; | ||
1589 | core_cfg.n = n; | ||
1590 | core_cfg.cts = cts; | ||
1591 | if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) { | ||
1592 | core_cfg.aud_par_busclk = 0; | ||
1593 | core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_SW; | ||
1594 | core_cfg.use_mclk = false; | ||
1595 | } else { | ||
1596 | core_cfg.aud_par_busclk = (((128 * 31) - 1) << 8); | ||
1597 | core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_HW; | ||
1598 | core_cfg.use_mclk = true; | ||
1599 | core_cfg.mclk_mode = HDMI_AUDIO_MCLK_128FS; | ||
1600 | } | ||
1601 | core_cfg.layout = HDMI_AUDIO_LAYOUT_2CH; | ||
1602 | core_cfg.en_spdif = false; | ||
1603 | /* Use sample frequency from channel status word */ | ||
1604 | core_cfg.fs_override = true; | ||
1605 | /* Enable ACR packets */ | ||
1606 | core_cfg.en_acr_pkt = true; | ||
1607 | /* Disable direct streaming digital audio */ | ||
1608 | core_cfg.en_dsd_audio = false; | ||
1609 | /* Use parallel audio interface */ | ||
1610 | core_cfg.en_parallel_aud_input = true; | ||
1611 | |||
1612 | hdmi_core_audio_config(&core_cfg); | ||
1613 | |||
1614 | /* | ||
1615 | * Configure packet | ||
1616 | * info frame audio see doc CEA861-D page 74 | ||
1617 | */ | ||
1618 | aud_if_cfg.db1_coding_type = HDMI_INFOFRAME_AUDIO_DB1CT_FROM_STREAM; | ||
1619 | aud_if_cfg.db1_channel_count = 2; | ||
1620 | aud_if_cfg.db2_sample_freq = HDMI_INFOFRAME_AUDIO_DB2SF_FROM_STREAM; | ||
1621 | aud_if_cfg.db2_sample_size = HDMI_INFOFRAME_AUDIO_DB2SS_FROM_STREAM; | ||
1622 | aud_if_cfg.db4_channel_alloc = 0x00; | ||
1623 | aud_if_cfg.db5_downmix_inh = false; | ||
1624 | aud_if_cfg.db5_lsv = 0; | ||
1625 | |||
1626 | hdmi_core_audio_infoframe_config(&aud_if_cfg); | ||
1627 | return 0; | ||
1628 | } | ||
1629 | |||
1630 | static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd, | ||
1631 | struct snd_soc_dai *dai) | ||
1632 | { | ||
1633 | int err = 0; | ||
1634 | switch (cmd) { | ||
1635 | case SNDRV_PCM_TRIGGER_START: | ||
1636 | case SNDRV_PCM_TRIGGER_RESUME: | ||
1637 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
1638 | REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 1, 0, 0); | ||
1639 | REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 31, 31); | ||
1640 | REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 30, 30); | ||
1641 | break; | ||
1642 | |||
1643 | case SNDRV_PCM_TRIGGER_STOP: | ||
1644 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
1645 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
1646 | REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 0, 0, 0); | ||
1647 | REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 30, 30); | ||
1648 | REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 31, 31); | ||
1649 | break; | ||
1650 | default: | ||
1651 | err = -EINVAL; | ||
1652 | } | ||
1653 | return err; | ||
1654 | } | ||
1655 | |||
1656 | static int hdmi_audio_startup(struct snd_pcm_substream *substream, | ||
1657 | struct snd_soc_dai *dai) | ||
1658 | { | ||
1659 | if (!hdmi.mode) { | ||
1660 | pr_err("Current video settings do not support audio.\n"); | ||
1661 | return -EIO; | ||
1662 | } | ||
1663 | return 0; | ||
1664 | } | ||
1665 | |||
1666 | static struct snd_soc_codec_driver hdmi_audio_codec_drv = { | ||
1667 | }; | ||
1668 | |||
1669 | static struct snd_soc_dai_ops hdmi_audio_codec_ops = { | ||
1670 | .hw_params = hdmi_audio_hw_params, | ||
1671 | .trigger = hdmi_audio_trigger, | ||
1672 | .startup = hdmi_audio_startup, | ||
1673 | }; | ||
1674 | |||
1675 | static struct snd_soc_dai_driver hdmi_codec_dai_drv = { | ||
1676 | .name = "hdmi-audio-codec", | ||
1677 | .playback = { | ||
1678 | .channels_min = 2, | ||
1679 | .channels_max = 2, | ||
1680 | .rates = SNDRV_PCM_RATE_32000 | | ||
1681 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, | ||
1682 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
1683 | SNDRV_PCM_FMTBIT_S24_LE, | ||
1684 | }, | ||
1685 | .ops = &hdmi_audio_codec_ops, | ||
1686 | }; | ||
1687 | #endif | ||
1688 | |||
1689 | /* HDMI HW IP initialisation */ | ||
1690 | static int omapdss_hdmihw_probe(struct platform_device *pdev) | ||
1691 | { | ||
1692 | struct resource *hdmi_mem; | ||
1693 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
1694 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
1695 | int ret; | ||
1696 | #endif | ||
1697 | |||
1698 | hdmi.pdata = pdev->dev.platform_data; | ||
1699 | hdmi.pdev = pdev; | ||
1700 | |||
1701 | mutex_init(&hdmi.lock); | ||
1702 | |||
1703 | hdmi_mem = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0); | ||
1704 | if (!hdmi_mem) { | ||
1705 | DSSERR("can't get IORESOURCE_MEM HDMI\n"); | ||
1706 | return -EINVAL; | ||
1707 | } | ||
1708 | |||
1709 | /* Base address taken from platform */ | ||
1710 | hdmi.base_wp = ioremap(hdmi_mem->start, resource_size(hdmi_mem)); | ||
1711 | if (!hdmi.base_wp) { | ||
1712 | DSSERR("can't ioremap WP\n"); | ||
1713 | return -ENOMEM; | ||
1714 | } | ||
1715 | |||
1716 | hdmi_panel_init(); | ||
1717 | |||
1718 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
1719 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
1720 | |||
1721 | /* Register ASoC codec DAI */ | ||
1722 | ret = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv, | ||
1723 | &hdmi_codec_dai_drv, 1); | ||
1724 | if (ret) { | ||
1725 | DSSERR("can't register ASoC HDMI audio codec\n"); | ||
1726 | return ret; | ||
1727 | } | ||
1728 | #endif | ||
1729 | return 0; | ||
1730 | } | ||
1731 | |||
1732 | static int omapdss_hdmihw_remove(struct platform_device *pdev) | ||
1733 | { | ||
1734 | hdmi_panel_exit(); | ||
1735 | |||
1736 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
1737 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
1738 | snd_soc_unregister_codec(&pdev->dev); | ||
1739 | #endif | ||
1740 | |||
1741 | iounmap(hdmi.base_wp); | ||
1742 | |||
1743 | return 0; | ||
1744 | } | ||
1745 | |||
1746 | static struct platform_driver omapdss_hdmihw_driver = { | ||
1747 | .probe = omapdss_hdmihw_probe, | ||
1748 | .remove = omapdss_hdmihw_remove, | ||
1749 | .driver = { | ||
1750 | .name = "omapdss_hdmi", | ||
1751 | .owner = THIS_MODULE, | ||
1752 | }, | ||
1753 | }; | ||
1754 | |||
1755 | int hdmi_init_platform_driver(void) | ||
1756 | { | ||
1757 | return platform_driver_register(&omapdss_hdmihw_driver); | ||
1758 | } | ||
1759 | |||
1760 | void hdmi_uninit_platform_driver(void) | ||
1761 | { | ||
1762 | return platform_driver_unregister(&omapdss_hdmihw_driver); | ||
1763 | } | ||
diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/hdmi.h new file mode 100644 index 000000000000..c885f9cb0659 --- /dev/null +++ b/drivers/video/omap2/dss/hdmi.h | |||
@@ -0,0 +1,631 @@ | |||
1 | /* | ||
2 | * hdmi.h | ||
3 | * | ||
4 | * HDMI driver definition for TI OMAP4 processors. | ||
5 | * | ||
6 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.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 | * 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 _OMAP4_DSS_HDMI_H_ | ||
22 | #define _OMAP4_DSS_HDMI_H_ | ||
23 | |||
24 | #include <linux/string.h> | ||
25 | #include <video/omapdss.h> | ||
26 | |||
27 | #define HDMI_WP 0x0 | ||
28 | #define HDMI_CORE_SYS 0x400 | ||
29 | #define HDMI_CORE_AV 0x900 | ||
30 | #define HDMI_PLLCTRL 0x200 | ||
31 | #define HDMI_PHY 0x300 | ||
32 | |||
33 | struct hdmi_reg { u16 idx; }; | ||
34 | |||
35 | #define HDMI_REG(idx) ((const struct hdmi_reg) { idx }) | ||
36 | |||
37 | /* HDMI Wrapper */ | ||
38 | #define HDMI_WP_REG(idx) HDMI_REG(HDMI_WP + idx) | ||
39 | |||
40 | #define HDMI_WP_REVISION HDMI_WP_REG(0x0) | ||
41 | #define HDMI_WP_SYSCONFIG HDMI_WP_REG(0x10) | ||
42 | #define HDMI_WP_IRQSTATUS_RAW HDMI_WP_REG(0x24) | ||
43 | #define HDMI_WP_IRQSTATUS HDMI_WP_REG(0x28) | ||
44 | #define HDMI_WP_PWR_CTRL HDMI_WP_REG(0x40) | ||
45 | #define HDMI_WP_IRQENABLE_SET HDMI_WP_REG(0x2C) | ||
46 | #define HDMI_WP_VIDEO_CFG HDMI_WP_REG(0x50) | ||
47 | #define HDMI_WP_VIDEO_SIZE HDMI_WP_REG(0x60) | ||
48 | #define HDMI_WP_VIDEO_TIMING_H HDMI_WP_REG(0x68) | ||
49 | #define HDMI_WP_VIDEO_TIMING_V HDMI_WP_REG(0x6C) | ||
50 | #define HDMI_WP_WP_CLK HDMI_WP_REG(0x70) | ||
51 | #define HDMI_WP_AUDIO_CFG HDMI_WP_REG(0x80) | ||
52 | #define HDMI_WP_AUDIO_CFG2 HDMI_WP_REG(0x84) | ||
53 | #define HDMI_WP_AUDIO_CTRL HDMI_WP_REG(0x88) | ||
54 | #define HDMI_WP_AUDIO_DATA HDMI_WP_REG(0x8C) | ||
55 | |||
56 | /* HDMI IP Core System */ | ||
57 | #define HDMI_CORE_SYS_REG(idx) HDMI_REG(HDMI_CORE_SYS + idx) | ||
58 | |||
59 | #define HDMI_CORE_SYS_VND_IDL HDMI_CORE_SYS_REG(0x0) | ||
60 | #define HDMI_CORE_SYS_DEV_IDL HDMI_CORE_SYS_REG(0x8) | ||
61 | #define HDMI_CORE_SYS_DEV_IDH HDMI_CORE_SYS_REG(0xC) | ||
62 | #define HDMI_CORE_SYS_DEV_REV HDMI_CORE_SYS_REG(0x10) | ||
63 | #define HDMI_CORE_SYS_SRST HDMI_CORE_SYS_REG(0x14) | ||
64 | #define HDMI_CORE_CTRL1 HDMI_CORE_SYS_REG(0x20) | ||
65 | #define HDMI_CORE_SYS_SYS_STAT HDMI_CORE_SYS_REG(0x24) | ||
66 | #define HDMI_CORE_SYS_VID_ACEN HDMI_CORE_SYS_REG(0x124) | ||
67 | #define HDMI_CORE_SYS_VID_MODE HDMI_CORE_SYS_REG(0x128) | ||
68 | #define HDMI_CORE_SYS_INTR_STATE HDMI_CORE_SYS_REG(0x1C0) | ||
69 | #define HDMI_CORE_SYS_INTR1 HDMI_CORE_SYS_REG(0x1C4) | ||
70 | #define HDMI_CORE_SYS_INTR2 HDMI_CORE_SYS_REG(0x1C8) | ||
71 | #define HDMI_CORE_SYS_INTR3 HDMI_CORE_SYS_REG(0x1CC) | ||
72 | #define HDMI_CORE_SYS_INTR4 HDMI_CORE_SYS_REG(0x1D0) | ||
73 | #define HDMI_CORE_SYS_UMASK1 HDMI_CORE_SYS_REG(0x1D4) | ||
74 | #define HDMI_CORE_SYS_TMDS_CTRL HDMI_CORE_SYS_REG(0x208) | ||
75 | #define HDMI_CORE_SYS_DE_DLY HDMI_CORE_SYS_REG(0xC8) | ||
76 | #define HDMI_CORE_SYS_DE_CTRL HDMI_CORE_SYS_REG(0xCC) | ||
77 | #define HDMI_CORE_SYS_DE_TOP HDMI_CORE_SYS_REG(0xD0) | ||
78 | #define HDMI_CORE_SYS_DE_CNTL HDMI_CORE_SYS_REG(0xD8) | ||
79 | #define HDMI_CORE_SYS_DE_CNTH HDMI_CORE_SYS_REG(0xDC) | ||
80 | #define HDMI_CORE_SYS_DE_LINL HDMI_CORE_SYS_REG(0xE0) | ||
81 | #define HDMI_CORE_SYS_DE_LINH_1 HDMI_CORE_SYS_REG(0xE4) | ||
82 | #define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1 | ||
83 | #define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1 | ||
84 | #define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1 | ||
85 | #define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1 | ||
86 | |||
87 | /* HDMI DDC E-DID */ | ||
88 | #define HDMI_CORE_DDC_CMD HDMI_CORE_SYS_REG(0x3CC) | ||
89 | #define HDMI_CORE_DDC_STATUS HDMI_CORE_SYS_REG(0x3C8) | ||
90 | #define HDMI_CORE_DDC_ADDR HDMI_CORE_SYS_REG(0x3B4) | ||
91 | #define HDMI_CORE_DDC_OFFSET HDMI_CORE_SYS_REG(0x3BC) | ||
92 | #define HDMI_CORE_DDC_COUNT1 HDMI_CORE_SYS_REG(0x3C0) | ||
93 | #define HDMI_CORE_DDC_COUNT2 HDMI_CORE_SYS_REG(0x3C4) | ||
94 | #define HDMI_CORE_DDC_DATA HDMI_CORE_SYS_REG(0x3D0) | ||
95 | #define HDMI_CORE_DDC_SEGM HDMI_CORE_SYS_REG(0x3B8) | ||
96 | |||
97 | /* HDMI IP Core Audio Video */ | ||
98 | #define HDMI_CORE_AV_REG(idx) HDMI_REG(HDMI_CORE_AV + idx) | ||
99 | |||
100 | #define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC) | ||
101 | #define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4) | ||
102 | #define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8) | ||
103 | #define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC) | ||
104 | #define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100) | ||
105 | #define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104) | ||
106 | #define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108) | ||
107 | #define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C) | ||
108 | #define HDMI_CORE_AV_AVI_DBYTE(n) HDMI_CORE_AV_REG(n * 4 + 0x110) | ||
109 | #define HDMI_CORE_AV_AVI_DBYTE_NELEMS HDMI_CORE_AV_REG(15) | ||
110 | #define HDMI_CORE_AV_SPD_DBYTE HDMI_CORE_AV_REG(0x190) | ||
111 | #define HDMI_CORE_AV_SPD_DBYTE_NELEMS HDMI_CORE_AV_REG(27) | ||
112 | #define HDMI_CORE_AV_AUD_DBYTE(n) HDMI_CORE_AV_REG(n * 4 + 0x210) | ||
113 | #define HDMI_CORE_AV_AUD_DBYTE_NELEMS HDMI_CORE_AV_REG(10) | ||
114 | #define HDMI_CORE_AV_MPEG_DBYTE HDMI_CORE_AV_REG(0x290) | ||
115 | #define HDMI_CORE_AV_MPEG_DBYTE_NELEMS HDMI_CORE_AV_REG(27) | ||
116 | #define HDMI_CORE_AV_GEN_DBYTE HDMI_CORE_AV_REG(0x300) | ||
117 | #define HDMI_CORE_AV_GEN_DBYTE_NELEMS HDMI_CORE_AV_REG(31) | ||
118 | #define HDMI_CORE_AV_GEN2_DBYTE HDMI_CORE_AV_REG(0x380) | ||
119 | #define HDMI_CORE_AV_GEN2_DBYTE_NELEMS HDMI_CORE_AV_REG(31) | ||
120 | #define HDMI_CORE_AV_ACR_CTRL HDMI_CORE_AV_REG(0x4) | ||
121 | #define HDMI_CORE_AV_FREQ_SVAL HDMI_CORE_AV_REG(0x8) | ||
122 | #define HDMI_CORE_AV_N_SVAL1 HDMI_CORE_AV_REG(0xC) | ||
123 | #define HDMI_CORE_AV_N_SVAL2 HDMI_CORE_AV_REG(0x10) | ||
124 | #define HDMI_CORE_AV_N_SVAL3 HDMI_CORE_AV_REG(0x14) | ||
125 | #define HDMI_CORE_AV_CTS_SVAL1 HDMI_CORE_AV_REG(0x18) | ||
126 | #define HDMI_CORE_AV_CTS_SVAL2 HDMI_CORE_AV_REG(0x1C) | ||
127 | #define HDMI_CORE_AV_CTS_SVAL3 HDMI_CORE_AV_REG(0x20) | ||
128 | #define HDMI_CORE_AV_CTS_HVAL1 HDMI_CORE_AV_REG(0x24) | ||
129 | #define HDMI_CORE_AV_CTS_HVAL2 HDMI_CORE_AV_REG(0x28) | ||
130 | #define HDMI_CORE_AV_CTS_HVAL3 HDMI_CORE_AV_REG(0x2C) | ||
131 | #define HDMI_CORE_AV_AUD_MODE HDMI_CORE_AV_REG(0x50) | ||
132 | #define HDMI_CORE_AV_SPDIF_CTRL HDMI_CORE_AV_REG(0x54) | ||
133 | #define HDMI_CORE_AV_HW_SPDIF_FS HDMI_CORE_AV_REG(0x60) | ||
134 | #define HDMI_CORE_AV_SWAP_I2S HDMI_CORE_AV_REG(0x64) | ||
135 | #define HDMI_CORE_AV_SPDIF_ERTH HDMI_CORE_AV_REG(0x6C) | ||
136 | #define HDMI_CORE_AV_I2S_IN_MAP HDMI_CORE_AV_REG(0x70) | ||
137 | #define HDMI_CORE_AV_I2S_IN_CTRL HDMI_CORE_AV_REG(0x74) | ||
138 | #define HDMI_CORE_AV_I2S_CHST0 HDMI_CORE_AV_REG(0x78) | ||
139 | #define HDMI_CORE_AV_I2S_CHST1 HDMI_CORE_AV_REG(0x7C) | ||
140 | #define HDMI_CORE_AV_I2S_CHST2 HDMI_CORE_AV_REG(0x80) | ||
141 | #define HDMI_CORE_AV_I2S_CHST4 HDMI_CORE_AV_REG(0x84) | ||
142 | #define HDMI_CORE_AV_I2S_CHST5 HDMI_CORE_AV_REG(0x88) | ||
143 | #define HDMI_CORE_AV_ASRC HDMI_CORE_AV_REG(0x8C) | ||
144 | #define HDMI_CORE_AV_I2S_IN_LEN HDMI_CORE_AV_REG(0x90) | ||
145 | #define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC) | ||
146 | #define HDMI_CORE_AV_AUDO_TXSTAT HDMI_CORE_AV_REG(0xC0) | ||
147 | #define HDMI_CORE_AV_AUD_PAR_BUSCLK_1 HDMI_CORE_AV_REG(0xCC) | ||
148 | #define HDMI_CORE_AV_AUD_PAR_BUSCLK_2 HDMI_CORE_AV_REG(0xD0) | ||
149 | #define HDMI_CORE_AV_AUD_PAR_BUSCLK_3 HDMI_CORE_AV_REG(0xD4) | ||
150 | #define HDMI_CORE_AV_TEST_TXCTRL HDMI_CORE_AV_REG(0xF0) | ||
151 | #define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4) | ||
152 | #define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8) | ||
153 | #define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC) | ||
154 | #define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100) | ||
155 | #define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104) | ||
156 | #define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108) | ||
157 | #define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C) | ||
158 | #define HDMI_CORE_AV_SPD_TYPE HDMI_CORE_AV_REG(0x180) | ||
159 | #define HDMI_CORE_AV_SPD_VERS HDMI_CORE_AV_REG(0x184) | ||
160 | #define HDMI_CORE_AV_SPD_LEN HDMI_CORE_AV_REG(0x188) | ||
161 | #define HDMI_CORE_AV_SPD_CHSUM HDMI_CORE_AV_REG(0x18C) | ||
162 | #define HDMI_CORE_AV_AUDIO_TYPE HDMI_CORE_AV_REG(0x200) | ||
163 | #define HDMI_CORE_AV_AUDIO_VERS HDMI_CORE_AV_REG(0x204) | ||
164 | #define HDMI_CORE_AV_AUDIO_LEN HDMI_CORE_AV_REG(0x208) | ||
165 | #define HDMI_CORE_AV_AUDIO_CHSUM HDMI_CORE_AV_REG(0x20C) | ||
166 | #define HDMI_CORE_AV_MPEG_TYPE HDMI_CORE_AV_REG(0x280) | ||
167 | #define HDMI_CORE_AV_MPEG_VERS HDMI_CORE_AV_REG(0x284) | ||
168 | #define HDMI_CORE_AV_MPEG_LEN HDMI_CORE_AV_REG(0x288) | ||
169 | #define HDMI_CORE_AV_MPEG_CHSUM HDMI_CORE_AV_REG(0x28C) | ||
170 | #define HDMI_CORE_AV_CP_BYTE1 HDMI_CORE_AV_REG(0x37C) | ||
171 | #define HDMI_CORE_AV_CEC_ADDR_ID HDMI_CORE_AV_REG(0x3FC) | ||
172 | #define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4 | ||
173 | #define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4 | ||
174 | #define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4 | ||
175 | #define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4 | ||
176 | |||
177 | /* PLL */ | ||
178 | #define HDMI_PLL_REG(idx) HDMI_REG(HDMI_PLLCTRL + idx) | ||
179 | |||
180 | #define PLLCTRL_PLL_CONTROL HDMI_PLL_REG(0x0) | ||
181 | #define PLLCTRL_PLL_STATUS HDMI_PLL_REG(0x4) | ||
182 | #define PLLCTRL_PLL_GO HDMI_PLL_REG(0x8) | ||
183 | #define PLLCTRL_CFG1 HDMI_PLL_REG(0xC) | ||
184 | #define PLLCTRL_CFG2 HDMI_PLL_REG(0x10) | ||
185 | #define PLLCTRL_CFG3 HDMI_PLL_REG(0x14) | ||
186 | #define PLLCTRL_CFG4 HDMI_PLL_REG(0x20) | ||
187 | |||
188 | /* HDMI PHY */ | ||
189 | #define HDMI_PHY_REG(idx) HDMI_REG(HDMI_PHY + idx) | ||
190 | |||
191 | #define HDMI_TXPHY_TX_CTRL HDMI_PHY_REG(0x0) | ||
192 | #define HDMI_TXPHY_DIGITAL_CTRL HDMI_PHY_REG(0x4) | ||
193 | #define HDMI_TXPHY_POWER_CTRL HDMI_PHY_REG(0x8) | ||
194 | #define HDMI_TXPHY_PAD_CFG_CTRL HDMI_PHY_REG(0xC) | ||
195 | |||
196 | /* HDMI EDID Length */ | ||
197 | #define HDMI_EDID_MAX_LENGTH 256 | ||
198 | #define EDID_TIMING_DESCRIPTOR_SIZE 0x12 | ||
199 | #define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36 | ||
200 | #define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80 | ||
201 | #define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4 | ||
202 | #define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4 | ||
203 | |||
204 | #define OMAP_HDMI_TIMINGS_NB 34 | ||
205 | |||
206 | #define REG_FLD_MOD(idx, val, start, end) \ | ||
207 | hdmi_write_reg(idx, FLD_MOD(hdmi_read_reg(idx), val, start, end)) | ||
208 | #define REG_GET(idx, start, end) \ | ||
209 | FLD_GET(hdmi_read_reg(idx), start, end) | ||
210 | |||
211 | /* HDMI timing structure */ | ||
212 | struct hdmi_timings { | ||
213 | struct omap_video_timings timings; | ||
214 | int vsync_pol; | ||
215 | int hsync_pol; | ||
216 | }; | ||
217 | |||
218 | enum hdmi_phy_pwr { | ||
219 | HDMI_PHYPWRCMD_OFF = 0, | ||
220 | HDMI_PHYPWRCMD_LDOON = 1, | ||
221 | HDMI_PHYPWRCMD_TXON = 2 | ||
222 | }; | ||
223 | |||
224 | enum hdmi_pll_pwr { | ||
225 | HDMI_PLLPWRCMD_ALLOFF = 0, | ||
226 | HDMI_PLLPWRCMD_PLLONLY = 1, | ||
227 | HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2, | ||
228 | HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3 | ||
229 | }; | ||
230 | |||
231 | enum hdmi_clk_refsel { | ||
232 | HDMI_REFSEL_PCLK = 0, | ||
233 | HDMI_REFSEL_REF1 = 1, | ||
234 | HDMI_REFSEL_REF2 = 2, | ||
235 | HDMI_REFSEL_SYSCLK = 3 | ||
236 | }; | ||
237 | |||
238 | enum hdmi_core_inputbus_width { | ||
239 | HDMI_INPUT_8BIT = 0, | ||
240 | HDMI_INPUT_10BIT = 1, | ||
241 | HDMI_INPUT_12BIT = 2 | ||
242 | }; | ||
243 | |||
244 | enum hdmi_core_dither_trunc { | ||
245 | HDMI_OUTPUTTRUNCATION_8BIT = 0, | ||
246 | HDMI_OUTPUTTRUNCATION_10BIT = 1, | ||
247 | HDMI_OUTPUTTRUNCATION_12BIT = 2, | ||
248 | HDMI_OUTPUTDITHER_8BIT = 3, | ||
249 | HDMI_OUTPUTDITHER_10BIT = 4, | ||
250 | HDMI_OUTPUTDITHER_12BIT = 5 | ||
251 | }; | ||
252 | |||
253 | enum hdmi_core_deepcolor_ed { | ||
254 | HDMI_DEEPCOLORPACKECTDISABLE = 0, | ||
255 | HDMI_DEEPCOLORPACKECTENABLE = 1 | ||
256 | }; | ||
257 | |||
258 | enum hdmi_core_packet_mode { | ||
259 | HDMI_PACKETMODERESERVEDVALUE = 0, | ||
260 | HDMI_PACKETMODE24BITPERPIXEL = 4, | ||
261 | HDMI_PACKETMODE30BITPERPIXEL = 5, | ||
262 | HDMI_PACKETMODE36BITPERPIXEL = 6, | ||
263 | HDMI_PACKETMODE48BITPERPIXEL = 7 | ||
264 | }; | ||
265 | |||
266 | enum hdmi_core_hdmi_dvi { | ||
267 | HDMI_DVI = 0, | ||
268 | HDMI_HDMI = 1 | ||
269 | }; | ||
270 | |||
271 | enum hdmi_core_tclkselclkmult { | ||
272 | HDMI_FPLL05IDCK = 0, | ||
273 | HDMI_FPLL10IDCK = 1, | ||
274 | HDMI_FPLL20IDCK = 2, | ||
275 | HDMI_FPLL40IDCK = 3 | ||
276 | }; | ||
277 | |||
278 | enum hdmi_core_packet_ctrl { | ||
279 | HDMI_PACKETENABLE = 1, | ||
280 | HDMI_PACKETDISABLE = 0, | ||
281 | HDMI_PACKETREPEATON = 1, | ||
282 | HDMI_PACKETREPEATOFF = 0 | ||
283 | }; | ||
284 | |||
285 | /* INFOFRAME_AVI_ and INFOFRAME_AUDIO_ definitions */ | ||
286 | enum hdmi_core_infoframe { | ||
287 | HDMI_INFOFRAME_AVI_DB1Y_RGB = 0, | ||
288 | HDMI_INFOFRAME_AVI_DB1Y_YUV422 = 1, | ||
289 | HDMI_INFOFRAME_AVI_DB1Y_YUV444 = 2, | ||
290 | HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF = 0, | ||
291 | HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_ON = 1, | ||
292 | HDMI_INFOFRAME_AVI_DB1B_NO = 0, | ||
293 | HDMI_INFOFRAME_AVI_DB1B_VERT = 1, | ||
294 | HDMI_INFOFRAME_AVI_DB1B_HORI = 2, | ||
295 | HDMI_INFOFRAME_AVI_DB1B_VERTHORI = 3, | ||
296 | HDMI_INFOFRAME_AVI_DB1S_0 = 0, | ||
297 | HDMI_INFOFRAME_AVI_DB1S_1 = 1, | ||
298 | HDMI_INFOFRAME_AVI_DB1S_2 = 2, | ||
299 | HDMI_INFOFRAME_AVI_DB2C_NO = 0, | ||
300 | HDMI_INFOFRAME_AVI_DB2C_ITU601 = 1, | ||
301 | HDMI_INFOFRAME_AVI_DB2C_ITU709 = 2, | ||
302 | HDMI_INFOFRAME_AVI_DB2C_EC_EXTENDED = 3, | ||
303 | HDMI_INFOFRAME_AVI_DB2M_NO = 0, | ||
304 | HDMI_INFOFRAME_AVI_DB2M_43 = 1, | ||
305 | HDMI_INFOFRAME_AVI_DB2M_169 = 2, | ||
306 | HDMI_INFOFRAME_AVI_DB2R_SAME = 8, | ||
307 | HDMI_INFOFRAME_AVI_DB2R_43 = 9, | ||
308 | HDMI_INFOFRAME_AVI_DB2R_169 = 10, | ||
309 | HDMI_INFOFRAME_AVI_DB2R_149 = 11, | ||
310 | HDMI_INFOFRAME_AVI_DB3ITC_NO = 0, | ||
311 | HDMI_INFOFRAME_AVI_DB3ITC_YES = 1, | ||
312 | HDMI_INFOFRAME_AVI_DB3EC_XVYUV601 = 0, | ||
313 | HDMI_INFOFRAME_AVI_DB3EC_XVYUV709 = 1, | ||
314 | HDMI_INFOFRAME_AVI_DB3Q_DEFAULT = 0, | ||
315 | HDMI_INFOFRAME_AVI_DB3Q_LR = 1, | ||
316 | HDMI_INFOFRAME_AVI_DB3Q_FR = 2, | ||
317 | HDMI_INFOFRAME_AVI_DB3SC_NO = 0, | ||
318 | HDMI_INFOFRAME_AVI_DB3SC_HORI = 1, | ||
319 | HDMI_INFOFRAME_AVI_DB3SC_VERT = 2, | ||
320 | HDMI_INFOFRAME_AVI_DB3SC_HORIVERT = 3, | ||
321 | HDMI_INFOFRAME_AVI_DB5PR_NO = 0, | ||
322 | HDMI_INFOFRAME_AVI_DB5PR_2 = 1, | ||
323 | HDMI_INFOFRAME_AVI_DB5PR_3 = 2, | ||
324 | HDMI_INFOFRAME_AVI_DB5PR_4 = 3, | ||
325 | HDMI_INFOFRAME_AVI_DB5PR_5 = 4, | ||
326 | HDMI_INFOFRAME_AVI_DB5PR_6 = 5, | ||
327 | HDMI_INFOFRAME_AVI_DB5PR_7 = 6, | ||
328 | HDMI_INFOFRAME_AVI_DB5PR_8 = 7, | ||
329 | HDMI_INFOFRAME_AVI_DB5PR_9 = 8, | ||
330 | HDMI_INFOFRAME_AVI_DB5PR_10 = 9, | ||
331 | HDMI_INFOFRAME_AUDIO_DB1CT_FROM_STREAM = 0, | ||
332 | HDMI_INFOFRAME_AUDIO_DB1CT_IEC60958 = 1, | ||
333 | HDMI_INFOFRAME_AUDIO_DB1CT_AC3 = 2, | ||
334 | HDMI_INFOFRAME_AUDIO_DB1CT_MPEG1 = 3, | ||
335 | HDMI_INFOFRAME_AUDIO_DB1CT_MP3 = 4, | ||
336 | HDMI_INFOFRAME_AUDIO_DB1CT_MPEG2_MULTICH = 5, | ||
337 | HDMI_INFOFRAME_AUDIO_DB1CT_AAC = 6, | ||
338 | HDMI_INFOFRAME_AUDIO_DB1CT_DTS = 7, | ||
339 | HDMI_INFOFRAME_AUDIO_DB1CT_ATRAC = 8, | ||
340 | HDMI_INFOFRAME_AUDIO_DB1CT_ONEBIT = 9, | ||
341 | HDMI_INFOFRAME_AUDIO_DB1CT_DOLBY_DIGITAL_PLUS = 10, | ||
342 | HDMI_INFOFRAME_AUDIO_DB1CT_DTS_HD = 11, | ||
343 | HDMI_INFOFRAME_AUDIO_DB1CT_MAT = 12, | ||
344 | HDMI_INFOFRAME_AUDIO_DB1CT_DST = 13, | ||
345 | HDMI_INFOFRAME_AUDIO_DB1CT_WMA_PRO = 14, | ||
346 | HDMI_INFOFRAME_AUDIO_DB2SF_FROM_STREAM = 0, | ||
347 | HDMI_INFOFRAME_AUDIO_DB2SF_32000 = 1, | ||
348 | HDMI_INFOFRAME_AUDIO_DB2SF_44100 = 2, | ||
349 | HDMI_INFOFRAME_AUDIO_DB2SF_48000 = 3, | ||
350 | HDMI_INFOFRAME_AUDIO_DB2SF_88200 = 4, | ||
351 | HDMI_INFOFRAME_AUDIO_DB2SF_96000 = 5, | ||
352 | HDMI_INFOFRAME_AUDIO_DB2SF_176400 = 6, | ||
353 | HDMI_INFOFRAME_AUDIO_DB2SF_192000 = 7, | ||
354 | HDMI_INFOFRAME_AUDIO_DB2SS_FROM_STREAM = 0, | ||
355 | HDMI_INFOFRAME_AUDIO_DB2SS_16BIT = 1, | ||
356 | HDMI_INFOFRAME_AUDIO_DB2SS_20BIT = 2, | ||
357 | HDMI_INFOFRAME_AUDIO_DB2SS_24BIT = 3, | ||
358 | HDMI_INFOFRAME_AUDIO_DB5_DM_INH_PERMITTED = 0, | ||
359 | HDMI_INFOFRAME_AUDIO_DB5_DM_INH_PROHIBITED = 1 | ||
360 | }; | ||
361 | |||
362 | enum hdmi_packing_mode { | ||
363 | HDMI_PACK_10b_RGB_YUV444 = 0, | ||
364 | HDMI_PACK_24b_RGB_YUV444_YUV422 = 1, | ||
365 | HDMI_PACK_20b_YUV422 = 2, | ||
366 | HDMI_PACK_ALREADYPACKED = 7 | ||
367 | }; | ||
368 | |||
369 | enum hdmi_core_audio_sample_freq { | ||
370 | HDMI_AUDIO_FS_32000 = 0x3, | ||
371 | HDMI_AUDIO_FS_44100 = 0x0, | ||
372 | HDMI_AUDIO_FS_48000 = 0x2, | ||
373 | HDMI_AUDIO_FS_88200 = 0x8, | ||
374 | HDMI_AUDIO_FS_96000 = 0xA, | ||
375 | HDMI_AUDIO_FS_176400 = 0xC, | ||
376 | HDMI_AUDIO_FS_192000 = 0xE, | ||
377 | HDMI_AUDIO_FS_NOT_INDICATED = 0x1 | ||
378 | }; | ||
379 | |||
380 | enum hdmi_core_audio_layout { | ||
381 | HDMI_AUDIO_LAYOUT_2CH = 0, | ||
382 | HDMI_AUDIO_LAYOUT_8CH = 1 | ||
383 | }; | ||
384 | |||
385 | enum hdmi_core_cts_mode { | ||
386 | HDMI_AUDIO_CTS_MODE_HW = 0, | ||
387 | HDMI_AUDIO_CTS_MODE_SW = 1 | ||
388 | }; | ||
389 | |||
390 | enum hdmi_stereo_channels { | ||
391 | HDMI_AUDIO_STEREO_NOCHANNELS = 0, | ||
392 | HDMI_AUDIO_STEREO_ONECHANNEL = 1, | ||
393 | HDMI_AUDIO_STEREO_TWOCHANNELS = 2, | ||
394 | HDMI_AUDIO_STEREO_THREECHANNELS = 3, | ||
395 | HDMI_AUDIO_STEREO_FOURCHANNELS = 4 | ||
396 | }; | ||
397 | |||
398 | enum hdmi_audio_type { | ||
399 | HDMI_AUDIO_TYPE_LPCM = 0, | ||
400 | HDMI_AUDIO_TYPE_IEC = 1 | ||
401 | }; | ||
402 | |||
403 | enum hdmi_audio_justify { | ||
404 | HDMI_AUDIO_JUSTIFY_LEFT = 0, | ||
405 | HDMI_AUDIO_JUSTIFY_RIGHT = 1 | ||
406 | }; | ||
407 | |||
408 | enum hdmi_audio_sample_order { | ||
409 | HDMI_AUDIO_SAMPLE_RIGHT_FIRST = 0, | ||
410 | HDMI_AUDIO_SAMPLE_LEFT_FIRST = 1 | ||
411 | }; | ||
412 | |||
413 | enum hdmi_audio_samples_perword { | ||
414 | HDMI_AUDIO_ONEWORD_ONESAMPLE = 0, | ||
415 | HDMI_AUDIO_ONEWORD_TWOSAMPLES = 1 | ||
416 | }; | ||
417 | |||
418 | enum hdmi_audio_sample_size { | ||
419 | HDMI_AUDIO_SAMPLE_16BITS = 0, | ||
420 | HDMI_AUDIO_SAMPLE_24BITS = 1 | ||
421 | }; | ||
422 | |||
423 | enum hdmi_audio_transf_mode { | ||
424 | HDMI_AUDIO_TRANSF_DMA = 0, | ||
425 | HDMI_AUDIO_TRANSF_IRQ = 1 | ||
426 | }; | ||
427 | |||
428 | enum hdmi_audio_blk_strt_end_sig { | ||
429 | HDMI_AUDIO_BLOCK_SIG_STARTEND_ON = 0, | ||
430 | HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF = 1 | ||
431 | }; | ||
432 | |||
433 | enum hdmi_audio_i2s_config { | ||
434 | HDMI_AUDIO_I2S_WS_POLARITY_LOW_IS_LEFT = 0, | ||
435 | HDMI_AUDIO_I2S_WS_POLARIT_YLOW_IS_RIGHT = 1, | ||
436 | HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST = 0, | ||
437 | HDMI_AUDIO_I2S_LSB_SHIFTED_FIRST = 1, | ||
438 | HDMI_AUDIO_I2S_MAX_WORD_20BITS = 0, | ||
439 | HDMI_AUDIO_I2S_MAX_WORD_24BITS = 1, | ||
440 | HDMI_AUDIO_I2S_CHST_WORD_NOT_SPECIFIED = 0, | ||
441 | HDMI_AUDIO_I2S_CHST_WORD_16_BITS = 1, | ||
442 | HDMI_AUDIO_I2S_CHST_WORD_17_BITS = 6, | ||
443 | HDMI_AUDIO_I2S_CHST_WORD_18_BITS = 2, | ||
444 | HDMI_AUDIO_I2S_CHST_WORD_19_BITS = 4, | ||
445 | HDMI_AUDIO_I2S_CHST_WORD_20_BITS_20MAX = 5, | ||
446 | HDMI_AUDIO_I2S_CHST_WORD_20_BITS_24MAX = 1, | ||
447 | HDMI_AUDIO_I2S_CHST_WORD_21_BITS = 6, | ||
448 | HDMI_AUDIO_I2S_CHST_WORD_22_BITS = 2, | ||
449 | HDMI_AUDIO_I2S_CHST_WORD_23_BITS = 4, | ||
450 | HDMI_AUDIO_I2S_CHST_WORD_24_BITS = 5, | ||
451 | HDMI_AUDIO_I2S_SCK_EDGE_FALLING = 0, | ||
452 | HDMI_AUDIO_I2S_SCK_EDGE_RISING = 1, | ||
453 | HDMI_AUDIO_I2S_VBIT_FOR_PCM = 0, | ||
454 | HDMI_AUDIO_I2S_VBIT_FOR_COMPRESSED = 1, | ||
455 | HDMI_AUDIO_I2S_INPUT_LENGTH_NA = 0, | ||
456 | HDMI_AUDIO_I2S_INPUT_LENGTH_16 = 2, | ||
457 | HDMI_AUDIO_I2S_INPUT_LENGTH_17 = 12, | ||
458 | HDMI_AUDIO_I2S_INPUT_LENGTH_18 = 4, | ||
459 | HDMI_AUDIO_I2S_INPUT_LENGTH_19 = 8, | ||
460 | HDMI_AUDIO_I2S_INPUT_LENGTH_20 = 10, | ||
461 | HDMI_AUDIO_I2S_INPUT_LENGTH_21 = 13, | ||
462 | HDMI_AUDIO_I2S_INPUT_LENGTH_22 = 5, | ||
463 | HDMI_AUDIO_I2S_INPUT_LENGTH_23 = 9, | ||
464 | HDMI_AUDIO_I2S_INPUT_LENGTH_24 = 11, | ||
465 | HDMI_AUDIO_I2S_FIRST_BIT_SHIFT = 0, | ||
466 | HDMI_AUDIO_I2S_FIRST_BIT_NO_SHIFT = 1, | ||
467 | HDMI_AUDIO_I2S_SD0_EN = 1, | ||
468 | HDMI_AUDIO_I2S_SD1_EN = 1 << 1, | ||
469 | HDMI_AUDIO_I2S_SD2_EN = 1 << 2, | ||
470 | HDMI_AUDIO_I2S_SD3_EN = 1 << 3, | ||
471 | }; | ||
472 | |||
473 | enum hdmi_audio_mclk_mode { | ||
474 | HDMI_AUDIO_MCLK_128FS = 0, | ||
475 | HDMI_AUDIO_MCLK_256FS = 1, | ||
476 | HDMI_AUDIO_MCLK_384FS = 2, | ||
477 | HDMI_AUDIO_MCLK_512FS = 3, | ||
478 | HDMI_AUDIO_MCLK_768FS = 4, | ||
479 | HDMI_AUDIO_MCLK_1024FS = 5, | ||
480 | HDMI_AUDIO_MCLK_1152FS = 6, | ||
481 | HDMI_AUDIO_MCLK_192FS = 7 | ||
482 | }; | ||
483 | |||
484 | struct hdmi_core_video_config { | ||
485 | enum hdmi_core_inputbus_width ip_bus_width; | ||
486 | enum hdmi_core_dither_trunc op_dither_truc; | ||
487 | enum hdmi_core_deepcolor_ed deep_color_pkt; | ||
488 | enum hdmi_core_packet_mode pkt_mode; | ||
489 | enum hdmi_core_hdmi_dvi hdmi_dvi; | ||
490 | enum hdmi_core_tclkselclkmult tclk_sel_clkmult; | ||
491 | }; | ||
492 | |||
493 | /* | ||
494 | * Refer to section 8.2 in HDMI 1.3 specification for | ||
495 | * details about infoframe databytes | ||
496 | */ | ||
497 | struct hdmi_core_infoframe_avi { | ||
498 | u8 db1_format; | ||
499 | /* Y0, Y1 rgb,yCbCr */ | ||
500 | u8 db1_active_info; | ||
501 | /* A0 Active information Present */ | ||
502 | u8 db1_bar_info_dv; | ||
503 | /* B0, B1 Bar info data valid */ | ||
504 | u8 db1_scan_info; | ||
505 | /* S0, S1 scan information */ | ||
506 | u8 db2_colorimetry; | ||
507 | /* C0, C1 colorimetry */ | ||
508 | u8 db2_aspect_ratio; | ||
509 | /* M0, M1 Aspect ratio (4:3, 16:9) */ | ||
510 | u8 db2_active_fmt_ar; | ||
511 | /* R0...R3 Active format aspect ratio */ | ||
512 | u8 db3_itc; | ||
513 | /* ITC IT content. */ | ||
514 | u8 db3_ec; | ||
515 | /* EC0, EC1, EC2 Extended colorimetry */ | ||
516 | u8 db3_q_range; | ||
517 | /* Q1, Q0 Quantization range */ | ||
518 | u8 db3_nup_scaling; | ||
519 | /* SC1, SC0 Non-uniform picture scaling */ | ||
520 | u8 db4_videocode; | ||
521 | /* VIC0..6 Video format identification */ | ||
522 | u8 db5_pixel_repeat; | ||
523 | /* PR0..PR3 Pixel repetition factor */ | ||
524 | u16 db6_7_line_eoftop; | ||
525 | /* Line number end of top bar */ | ||
526 | u16 db8_9_line_sofbottom; | ||
527 | /* Line number start of bottom bar */ | ||
528 | u16 db10_11_pixel_eofleft; | ||
529 | /* Pixel number end of left bar */ | ||
530 | u16 db12_13_pixel_sofright; | ||
531 | /* Pixel number start of right bar */ | ||
532 | }; | ||
533 | /* | ||
534 | * Refer to section 8.2 in HDMI 1.3 specification for | ||
535 | * details about infoframe databytes | ||
536 | */ | ||
537 | struct hdmi_core_infoframe_audio { | ||
538 | u8 db1_coding_type; | ||
539 | u8 db1_channel_count; | ||
540 | u8 db2_sample_freq; | ||
541 | u8 db2_sample_size; | ||
542 | u8 db4_channel_alloc; | ||
543 | bool db5_downmix_inh; | ||
544 | u8 db5_lsv; /* Level shift values for downmix */ | ||
545 | }; | ||
546 | |||
547 | struct hdmi_core_packet_enable_repeat { | ||
548 | u32 audio_pkt; | ||
549 | u32 audio_pkt_repeat; | ||
550 | u32 avi_infoframe; | ||
551 | u32 avi_infoframe_repeat; | ||
552 | u32 gen_cntrl_pkt; | ||
553 | u32 gen_cntrl_pkt_repeat; | ||
554 | u32 generic_pkt; | ||
555 | u32 generic_pkt_repeat; | ||
556 | }; | ||
557 | |||
558 | struct hdmi_video_format { | ||
559 | enum hdmi_packing_mode packing_mode; | ||
560 | u32 y_res; /* Line per panel */ | ||
561 | u32 x_res; /* pixel per line */ | ||
562 | }; | ||
563 | |||
564 | struct hdmi_video_interface { | ||
565 | int vsp; /* Vsync polarity */ | ||
566 | int hsp; /* Hsync polarity */ | ||
567 | int interlacing; | ||
568 | int tm; /* Timing mode */ | ||
569 | }; | ||
570 | |||
571 | struct hdmi_cm { | ||
572 | int code; | ||
573 | int mode; | ||
574 | }; | ||
575 | |||
576 | struct hdmi_config { | ||
577 | struct hdmi_timings timings; | ||
578 | u16 interlace; | ||
579 | struct hdmi_cm cm; | ||
580 | }; | ||
581 | |||
582 | struct hdmi_audio_format { | ||
583 | enum hdmi_stereo_channels stereo_channels; | ||
584 | u8 active_chnnls_msk; | ||
585 | enum hdmi_audio_type type; | ||
586 | enum hdmi_audio_justify justification; | ||
587 | enum hdmi_audio_sample_order sample_order; | ||
588 | enum hdmi_audio_samples_perword samples_per_word; | ||
589 | enum hdmi_audio_sample_size sample_size; | ||
590 | enum hdmi_audio_blk_strt_end_sig en_sig_blk_strt_end; | ||
591 | }; | ||
592 | |||
593 | struct hdmi_audio_dma { | ||
594 | u8 transfer_size; | ||
595 | u8 block_size; | ||
596 | enum hdmi_audio_transf_mode mode; | ||
597 | u16 fifo_threshold; | ||
598 | }; | ||
599 | |||
600 | struct hdmi_core_audio_i2s_config { | ||
601 | u8 word_max_length; | ||
602 | u8 word_length; | ||
603 | u8 in_length_bits; | ||
604 | u8 justification; | ||
605 | u8 en_high_bitrate_aud; | ||
606 | u8 sck_edge_mode; | ||
607 | u8 cbit_order; | ||
608 | u8 vbit; | ||
609 | u8 ws_polarity; | ||
610 | u8 direction; | ||
611 | u8 shift; | ||
612 | u8 active_sds; | ||
613 | }; | ||
614 | |||
615 | struct hdmi_core_audio_config { | ||
616 | struct hdmi_core_audio_i2s_config i2s_cfg; | ||
617 | enum hdmi_core_audio_sample_freq freq_sample; | ||
618 | bool fs_override; | ||
619 | u32 n; | ||
620 | u32 cts; | ||
621 | u32 aud_par_busclk; | ||
622 | enum hdmi_core_audio_layout layout; | ||
623 | enum hdmi_core_cts_mode cts_mode; | ||
624 | bool use_mclk; | ||
625 | enum hdmi_audio_mclk_mode mclk_mode; | ||
626 | bool en_acr_pkt; | ||
627 | bool en_dsd_audio; | ||
628 | bool en_parallel_aud_input; | ||
629 | bool en_spdif; | ||
630 | }; | ||
631 | #endif | ||
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c new file mode 100644 index 000000000000..7d4f2bd7c506 --- /dev/null +++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c | |||
@@ -0,0 +1,222 @@ | |||
1 | /* | ||
2 | * hdmi_omap4_panel.c | ||
3 | * | ||
4 | * HDMI library support functions for TI OMAP4 processors. | ||
5 | * | ||
6 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
7 | * Authors: Mythri P k <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 | #include <linux/kernel.h> | ||
23 | #include <linux/err.h> | ||
24 | #include <linux/io.h> | ||
25 | #include <linux/mutex.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <video/omapdss.h> | ||
28 | |||
29 | #include "dss.h" | ||
30 | |||
31 | static struct { | ||
32 | struct mutex hdmi_lock; | ||
33 | } hdmi; | ||
34 | |||
35 | |||
36 | static int hdmi_panel_probe(struct omap_dss_device *dssdev) | ||
37 | { | ||
38 | DSSDBG("ENTER hdmi_panel_probe\n"); | ||
39 | |||
40 | dssdev->panel.config = OMAP_DSS_LCD_TFT | | ||
41 | OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS; | ||
42 | |||
43 | /* | ||
44 | * Initialize the timings to 640 * 480 | ||
45 | * This is only for framebuffer update not for TV timing setting | ||
46 | * Setting TV timing will be done only on enable | ||
47 | */ | ||
48 | dssdev->panel.timings.x_res = 640; | ||
49 | dssdev->panel.timings.y_res = 480; | ||
50 | |||
51 | DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n", | ||
52 | dssdev->panel.timings.x_res, | ||
53 | dssdev->panel.timings.y_res); | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static void hdmi_panel_remove(struct omap_dss_device *dssdev) | ||
58 | { | ||
59 | |||
60 | } | ||
61 | |||
62 | static int hdmi_panel_enable(struct omap_dss_device *dssdev) | ||
63 | { | ||
64 | int r = 0; | ||
65 | DSSDBG("ENTER hdmi_panel_enable\n"); | ||
66 | |||
67 | mutex_lock(&hdmi.hdmi_lock); | ||
68 | |||
69 | if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { | ||
70 | r = -EINVAL; | ||
71 | goto err; | ||
72 | } | ||
73 | |||
74 | r = omapdss_hdmi_display_enable(dssdev); | ||
75 | if (r) { | ||
76 | DSSERR("failed to power on\n"); | ||
77 | goto err; | ||
78 | } | ||
79 | |||
80 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
81 | |||
82 | err: | ||
83 | mutex_unlock(&hdmi.hdmi_lock); | ||
84 | |||
85 | return r; | ||
86 | } | ||
87 | |||
88 | static void hdmi_panel_disable(struct omap_dss_device *dssdev) | ||
89 | { | ||
90 | mutex_lock(&hdmi.hdmi_lock); | ||
91 | |||
92 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | ||
93 | omapdss_hdmi_display_disable(dssdev); | ||
94 | |||
95 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | ||
96 | |||
97 | mutex_unlock(&hdmi.hdmi_lock); | ||
98 | } | ||
99 | |||
100 | static int hdmi_panel_suspend(struct omap_dss_device *dssdev) | ||
101 | { | ||
102 | int r = 0; | ||
103 | |||
104 | mutex_lock(&hdmi.hdmi_lock); | ||
105 | |||
106 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { | ||
107 | r = -EINVAL; | ||
108 | goto err; | ||
109 | } | ||
110 | |||
111 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | ||
112 | |||
113 | omapdss_hdmi_display_disable(dssdev); | ||
114 | |||
115 | err: | ||
116 | mutex_unlock(&hdmi.hdmi_lock); | ||
117 | |||
118 | return r; | ||
119 | } | ||
120 | |||
121 | static int hdmi_panel_resume(struct omap_dss_device *dssdev) | ||
122 | { | ||
123 | int r = 0; | ||
124 | |||
125 | mutex_lock(&hdmi.hdmi_lock); | ||
126 | |||
127 | if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { | ||
128 | r = -EINVAL; | ||
129 | goto err; | ||
130 | } | ||
131 | |||
132 | r = omapdss_hdmi_display_enable(dssdev); | ||
133 | if (r) { | ||
134 | DSSERR("failed to power on\n"); | ||
135 | goto err; | ||
136 | } | ||
137 | |||
138 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
139 | |||
140 | err: | ||
141 | mutex_unlock(&hdmi.hdmi_lock); | ||
142 | |||
143 | return r; | ||
144 | } | ||
145 | |||
146 | static void hdmi_get_timings(struct omap_dss_device *dssdev, | ||
147 | struct omap_video_timings *timings) | ||
148 | { | ||
149 | mutex_lock(&hdmi.hdmi_lock); | ||
150 | |||
151 | *timings = dssdev->panel.timings; | ||
152 | |||
153 | mutex_unlock(&hdmi.hdmi_lock); | ||
154 | } | ||
155 | |||
156 | static void hdmi_set_timings(struct omap_dss_device *dssdev, | ||
157 | struct omap_video_timings *timings) | ||
158 | { | ||
159 | DSSDBG("hdmi_set_timings\n"); | ||
160 | |||
161 | mutex_lock(&hdmi.hdmi_lock); | ||
162 | |||
163 | dssdev->panel.timings = *timings; | ||
164 | |||
165 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { | ||
166 | /* turn the hdmi off and on to get new timings to use */ | ||
167 | omapdss_hdmi_display_disable(dssdev); | ||
168 | omapdss_hdmi_display_set_timing(dssdev); | ||
169 | } | ||
170 | |||
171 | mutex_unlock(&hdmi.hdmi_lock); | ||
172 | } | ||
173 | |||
174 | static int hdmi_check_timings(struct omap_dss_device *dssdev, | ||
175 | struct omap_video_timings *timings) | ||
176 | { | ||
177 | int r = 0; | ||
178 | |||
179 | DSSDBG("hdmi_check_timings\n"); | ||
180 | |||
181 | mutex_lock(&hdmi.hdmi_lock); | ||
182 | |||
183 | r = omapdss_hdmi_display_check_timing(dssdev, timings); | ||
184 | if (r) { | ||
185 | DSSERR("Timing cannot be applied\n"); | ||
186 | goto err; | ||
187 | } | ||
188 | err: | ||
189 | mutex_unlock(&hdmi.hdmi_lock); | ||
190 | return r; | ||
191 | } | ||
192 | |||
193 | static struct omap_dss_driver hdmi_driver = { | ||
194 | .probe = hdmi_panel_probe, | ||
195 | .remove = hdmi_panel_remove, | ||
196 | .enable = hdmi_panel_enable, | ||
197 | .disable = hdmi_panel_disable, | ||
198 | .suspend = hdmi_panel_suspend, | ||
199 | .resume = hdmi_panel_resume, | ||
200 | .get_timings = hdmi_get_timings, | ||
201 | .set_timings = hdmi_set_timings, | ||
202 | .check_timings = hdmi_check_timings, | ||
203 | .driver = { | ||
204 | .name = "hdmi_panel", | ||
205 | .owner = THIS_MODULE, | ||
206 | }, | ||
207 | }; | ||
208 | |||
209 | int hdmi_panel_init(void) | ||
210 | { | ||
211 | mutex_init(&hdmi.hdmi_lock); | ||
212 | |||
213 | omap_dss_register_driver(&hdmi_driver); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | void hdmi_panel_exit(void) | ||
219 | { | ||
220 | omap_dss_unregister_driver(&hdmi_driver); | ||
221 | |||
222 | } | ||
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 6a649ab5539e..9aeea50e33ff 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c | |||
@@ -29,10 +29,11 @@ | |||
29 | #include <linux/spinlock.h> | 29 | #include <linux/spinlock.h> |
30 | #include <linux/jiffies.h> | 30 | #include <linux/jiffies.h> |
31 | 31 | ||
32 | #include <plat/display.h> | 32 | #include <video/omapdss.h> |
33 | #include <plat/cpu.h> | 33 | #include <plat/cpu.h> |
34 | 34 | ||
35 | #include "dss.h" | 35 | #include "dss.h" |
36 | #include "dss_features.h" | ||
36 | 37 | ||
37 | static int num_managers; | 38 | static int num_managers; |
38 | static struct list_head manager_list; | 39 | static struct list_head manager_list; |
@@ -392,6 +393,7 @@ struct overlay_cache_data { | |||
392 | 393 | ||
393 | u32 paddr; | 394 | u32 paddr; |
394 | void __iomem *vaddr; | 395 | void __iomem *vaddr; |
396 | u32 p_uv_addr; /* relevant for NV12 format only */ | ||
395 | u16 screen_width; | 397 | u16 screen_width; |
396 | u16 width; | 398 | u16 width; |
397 | u16 height; | 399 | u16 height; |
@@ -405,6 +407,7 @@ struct overlay_cache_data { | |||
405 | u16 out_width; /* if 0, out_width == width */ | 407 | u16 out_width; /* if 0, out_width == width */ |
406 | u16 out_height; /* if 0, out_height == height */ | 408 | u16 out_height; /* if 0, out_height == height */ |
407 | u8 global_alpha; | 409 | u8 global_alpha; |
410 | u8 pre_mult_alpha; | ||
408 | 411 | ||
409 | enum omap_channel channel; | 412 | enum omap_channel channel; |
410 | bool replication; | 413 | bool replication; |
@@ -448,8 +451,8 @@ struct manager_cache_data { | |||
448 | 451 | ||
449 | static struct { | 452 | static struct { |
450 | spinlock_t lock; | 453 | spinlock_t lock; |
451 | struct overlay_cache_data overlay_cache[3]; | 454 | struct overlay_cache_data overlay_cache[MAX_DSS_OVERLAYS]; |
452 | struct manager_cache_data manager_cache[2]; | 455 | struct manager_cache_data manager_cache[MAX_DSS_MANAGERS]; |
453 | 456 | ||
454 | bool irq_enabled; | 457 | bool irq_enabled; |
455 | } dss_cache; | 458 | } dss_cache; |
@@ -511,11 +514,16 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) | |||
511 | unsigned long timeout = msecs_to_jiffies(500); | 514 | unsigned long timeout = msecs_to_jiffies(500); |
512 | u32 irq; | 515 | u32 irq; |
513 | 516 | ||
514 | if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) | 517 | if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) { |
515 | irq = DISPC_IRQ_EVSYNC_ODD; | 518 | irq = DISPC_IRQ_EVSYNC_ODD; |
516 | else | 519 | } else if (mgr->device->type == OMAP_DISPLAY_TYPE_HDMI) { |
517 | irq = DISPC_IRQ_VSYNC; | 520 | irq = DISPC_IRQ_EVSYNC_EVEN; |
518 | 521 | } else { | |
522 | if (mgr->id == OMAP_DSS_CHANNEL_LCD) | ||
523 | irq = DISPC_IRQ_VSYNC; | ||
524 | else | ||
525 | irq = DISPC_IRQ_VSYNC2; | ||
526 | } | ||
519 | return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); | 527 | return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); |
520 | } | 528 | } |
521 | 529 | ||
@@ -523,7 +531,6 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) | |||
523 | { | 531 | { |
524 | unsigned long timeout = msecs_to_jiffies(500); | 532 | unsigned long timeout = msecs_to_jiffies(500); |
525 | struct manager_cache_data *mc; | 533 | struct manager_cache_data *mc; |
526 | enum omap_channel channel; | ||
527 | u32 irq; | 534 | u32 irq; |
528 | int r; | 535 | int r; |
529 | int i; | 536 | int i; |
@@ -532,9 +539,9 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) | |||
532 | if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | 539 | if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) |
533 | return 0; | 540 | return 0; |
534 | 541 | ||
535 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { | 542 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC |
543 | || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { | ||
536 | irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; | 544 | irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; |
537 | channel = OMAP_DSS_CHANNEL_DIGIT; | ||
538 | } else { | 545 | } else { |
539 | if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { | 546 | if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { |
540 | enum omap_dss_update_mode mode; | 547 | enum omap_dss_update_mode mode; |
@@ -542,11 +549,14 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) | |||
542 | if (mode != OMAP_DSS_UPDATE_AUTO) | 549 | if (mode != OMAP_DSS_UPDATE_AUTO) |
543 | return 0; | 550 | return 0; |
544 | 551 | ||
545 | irq = DISPC_IRQ_FRAMEDONE; | 552 | irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ? |
553 | DISPC_IRQ_FRAMEDONE | ||
554 | : DISPC_IRQ_FRAMEDONE2; | ||
546 | } else { | 555 | } else { |
547 | irq = DISPC_IRQ_VSYNC; | 556 | irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ? |
557 | DISPC_IRQ_VSYNC | ||
558 | : DISPC_IRQ_VSYNC2; | ||
548 | } | 559 | } |
549 | channel = OMAP_DSS_CHANNEL_LCD; | ||
550 | } | 560 | } |
551 | 561 | ||
552 | mc = &dss_cache.manager_cache[mgr->id]; | 562 | mc = &dss_cache.manager_cache[mgr->id]; |
@@ -593,7 +603,6 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) | |||
593 | int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) | 603 | int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) |
594 | { | 604 | { |
595 | unsigned long timeout = msecs_to_jiffies(500); | 605 | unsigned long timeout = msecs_to_jiffies(500); |
596 | enum omap_channel channel; | ||
597 | struct overlay_cache_data *oc; | 606 | struct overlay_cache_data *oc; |
598 | struct omap_dss_device *dssdev; | 607 | struct omap_dss_device *dssdev; |
599 | u32 irq; | 608 | u32 irq; |
@@ -608,9 +617,9 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) | |||
608 | if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | 617 | if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) |
609 | return 0; | 618 | return 0; |
610 | 619 | ||
611 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { | 620 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC |
621 | || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { | ||
612 | irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; | 622 | irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; |
613 | channel = OMAP_DSS_CHANNEL_DIGIT; | ||
614 | } else { | 623 | } else { |
615 | if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { | 624 | if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { |
616 | enum omap_dss_update_mode mode; | 625 | enum omap_dss_update_mode mode; |
@@ -618,11 +627,14 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) | |||
618 | if (mode != OMAP_DSS_UPDATE_AUTO) | 627 | if (mode != OMAP_DSS_UPDATE_AUTO) |
619 | return 0; | 628 | return 0; |
620 | 629 | ||
621 | irq = DISPC_IRQ_FRAMEDONE; | 630 | irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ? |
631 | DISPC_IRQ_FRAMEDONE | ||
632 | : DISPC_IRQ_FRAMEDONE2; | ||
622 | } else { | 633 | } else { |
623 | irq = DISPC_IRQ_VSYNC; | 634 | irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ? |
635 | DISPC_IRQ_VSYNC | ||
636 | : DISPC_IRQ_VSYNC2; | ||
624 | } | 637 | } |
625 | channel = OMAP_DSS_CHANNEL_LCD; | ||
626 | } | 638 | } |
627 | 639 | ||
628 | oc = &dss_cache.overlay_cache[ovl->id]; | 640 | oc = &dss_cache.overlay_cache[ovl->id]; |
@@ -764,10 +776,17 @@ static int configure_overlay(enum omap_plane plane) | |||
764 | } | 776 | } |
765 | 777 | ||
766 | switch (c->color_mode) { | 778 | switch (c->color_mode) { |
779 | case OMAP_DSS_COLOR_NV12: | ||
780 | bpp = 8; | ||
781 | break; | ||
767 | case OMAP_DSS_COLOR_RGB16: | 782 | case OMAP_DSS_COLOR_RGB16: |
768 | case OMAP_DSS_COLOR_ARGB16: | 783 | case OMAP_DSS_COLOR_ARGB16: |
769 | case OMAP_DSS_COLOR_YUV2: | 784 | case OMAP_DSS_COLOR_YUV2: |
770 | case OMAP_DSS_COLOR_UYVY: | 785 | case OMAP_DSS_COLOR_UYVY: |
786 | case OMAP_DSS_COLOR_RGBA16: | ||
787 | case OMAP_DSS_COLOR_RGBX16: | ||
788 | case OMAP_DSS_COLOR_ARGB16_1555: | ||
789 | case OMAP_DSS_COLOR_XRGB16_1555: | ||
771 | bpp = 16; | 790 | bpp = 16; |
772 | break; | 791 | break; |
773 | 792 | ||
@@ -841,7 +860,10 @@ static int configure_overlay(enum omap_plane plane) | |||
841 | c->rotation_type, | 860 | c->rotation_type, |
842 | c->rotation, | 861 | c->rotation, |
843 | c->mirror, | 862 | c->mirror, |
844 | c->global_alpha); | 863 | c->global_alpha, |
864 | c->pre_mult_alpha, | ||
865 | c->channel, | ||
866 | c->p_uv_addr); | ||
845 | 867 | ||
846 | if (r) { | 868 | if (r) { |
847 | /* this shouldn't happen */ | 869 | /* this shouldn't happen */ |
@@ -882,21 +904,21 @@ static int configure_dispc(void) | |||
882 | { | 904 | { |
883 | struct overlay_cache_data *oc; | 905 | struct overlay_cache_data *oc; |
884 | struct manager_cache_data *mc; | 906 | struct manager_cache_data *mc; |
885 | const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); | 907 | const int num_ovls = dss_feat_get_num_ovls(); |
886 | const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache); | 908 | const int num_mgrs = dss_feat_get_num_mgrs(); |
887 | int i; | 909 | int i; |
888 | int r; | 910 | int r; |
889 | bool mgr_busy[2]; | 911 | bool mgr_busy[MAX_DSS_MANAGERS]; |
890 | bool mgr_go[2]; | 912 | bool mgr_go[MAX_DSS_MANAGERS]; |
891 | bool busy; | 913 | bool busy; |
892 | 914 | ||
893 | r = 0; | 915 | r = 0; |
894 | busy = false; | 916 | busy = false; |
895 | 917 | ||
896 | mgr_busy[0] = dispc_go_busy(0); | 918 | for (i = 0; i < num_mgrs; i++) { |
897 | mgr_busy[1] = dispc_go_busy(1); | 919 | mgr_busy[i] = dispc_go_busy(i); |
898 | mgr_go[0] = false; | 920 | mgr_go[i] = false; |
899 | mgr_go[1] = false; | 921 | } |
900 | 922 | ||
901 | /* Commit overlay settings */ | 923 | /* Commit overlay settings */ |
902 | for (i = 0; i < num_ovls; ++i) { | 924 | for (i = 0; i < num_ovls; ++i) { |
@@ -989,7 +1011,7 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev, | |||
989 | { | 1011 | { |
990 | struct overlay_cache_data *oc; | 1012 | struct overlay_cache_data *oc; |
991 | struct manager_cache_data *mc; | 1013 | struct manager_cache_data *mc; |
992 | const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); | 1014 | const int num_ovls = dss_feat_get_num_ovls(); |
993 | struct omap_overlay_manager *mgr; | 1015 | struct omap_overlay_manager *mgr; |
994 | int i; | 1016 | int i; |
995 | u16 x, y, w, h; | 1017 | u16 x, y, w, h; |
@@ -1121,8 +1143,8 @@ void dss_start_update(struct omap_dss_device *dssdev) | |||
1121 | { | 1143 | { |
1122 | struct manager_cache_data *mc; | 1144 | struct manager_cache_data *mc; |
1123 | struct overlay_cache_data *oc; | 1145 | struct overlay_cache_data *oc; |
1124 | const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); | 1146 | const int num_ovls = dss_feat_get_num_ovls(); |
1125 | const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache); | 1147 | const int num_mgrs = dss_feat_get_num_mgrs(); |
1126 | struct omap_overlay_manager *mgr; | 1148 | struct omap_overlay_manager *mgr; |
1127 | int i; | 1149 | int i; |
1128 | 1150 | ||
@@ -1151,13 +1173,14 @@ static void dss_apply_irq_handler(void *data, u32 mask) | |||
1151 | { | 1173 | { |
1152 | struct manager_cache_data *mc; | 1174 | struct manager_cache_data *mc; |
1153 | struct overlay_cache_data *oc; | 1175 | struct overlay_cache_data *oc; |
1154 | const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); | 1176 | const int num_ovls = dss_feat_get_num_ovls(); |
1155 | const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache); | 1177 | const int num_mgrs = dss_feat_get_num_mgrs(); |
1156 | int i, r; | 1178 | int i, r; |
1157 | bool mgr_busy[2]; | 1179 | bool mgr_busy[MAX_DSS_MANAGERS]; |
1180 | u32 irq_mask; | ||
1158 | 1181 | ||
1159 | mgr_busy[0] = dispc_go_busy(0); | 1182 | for (i = 0; i < num_mgrs; i++) |
1160 | mgr_busy[1] = dispc_go_busy(1); | 1183 | mgr_busy[i] = dispc_go_busy(i); |
1161 | 1184 | ||
1162 | spin_lock(&dss_cache.lock); | 1185 | spin_lock(&dss_cache.lock); |
1163 | 1186 | ||
@@ -1178,8 +1201,8 @@ static void dss_apply_irq_handler(void *data, u32 mask) | |||
1178 | goto end; | 1201 | goto end; |
1179 | 1202 | ||
1180 | /* re-read busy flags */ | 1203 | /* re-read busy flags */ |
1181 | mgr_busy[0] = dispc_go_busy(0); | 1204 | for (i = 0; i < num_mgrs; i++) |
1182 | mgr_busy[1] = dispc_go_busy(1); | 1205 | mgr_busy[i] = dispc_go_busy(i); |
1183 | 1206 | ||
1184 | /* keep running as long as there are busy managers, so that | 1207 | /* keep running as long as there are busy managers, so that |
1185 | * we can collect overlay-applied information */ | 1208 | * we can collect overlay-applied information */ |
@@ -1188,9 +1211,12 @@ static void dss_apply_irq_handler(void *data, u32 mask) | |||
1188 | goto end; | 1211 | goto end; |
1189 | } | 1212 | } |
1190 | 1213 | ||
1191 | omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, | 1214 | irq_mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | |
1192 | DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | | 1215 | DISPC_IRQ_EVSYNC_EVEN; |
1193 | DISPC_IRQ_EVSYNC_EVEN); | 1216 | if (dss_has_feature(FEAT_MGR_LCD2)) |
1217 | irq_mask |= DISPC_IRQ_VSYNC2; | ||
1218 | |||
1219 | omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, irq_mask); | ||
1194 | dss_cache.irq_enabled = false; | 1220 | dss_cache.irq_enabled = false; |
1195 | 1221 | ||
1196 | end: | 1222 | end: |
@@ -1252,6 +1278,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
1252 | 1278 | ||
1253 | oc->paddr = ovl->info.paddr; | 1279 | oc->paddr = ovl->info.paddr; |
1254 | oc->vaddr = ovl->info.vaddr; | 1280 | oc->vaddr = ovl->info.vaddr; |
1281 | oc->p_uv_addr = ovl->info.p_uv_addr; | ||
1255 | oc->screen_width = ovl->info.screen_width; | 1282 | oc->screen_width = ovl->info.screen_width; |
1256 | oc->width = ovl->info.width; | 1283 | oc->width = ovl->info.width; |
1257 | oc->height = ovl->info.height; | 1284 | oc->height = ovl->info.height; |
@@ -1264,6 +1291,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
1264 | oc->out_width = ovl->info.out_width; | 1291 | oc->out_width = ovl->info.out_width; |
1265 | oc->out_height = ovl->info.out_height; | 1292 | oc->out_height = ovl->info.out_height; |
1266 | oc->global_alpha = ovl->info.global_alpha; | 1293 | oc->global_alpha = ovl->info.global_alpha; |
1294 | oc->pre_mult_alpha = ovl->info.pre_mult_alpha; | ||
1267 | 1295 | ||
1268 | oc->replication = | 1296 | oc->replication = |
1269 | dss_use_replication(dssdev, ovl->info.color_mode); | 1297 | dss_use_replication(dssdev, ovl->info.color_mode); |
@@ -1363,6 +1391,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
1363 | case OMAP_DISPLAY_TYPE_DBI: | 1391 | case OMAP_DISPLAY_TYPE_DBI: |
1364 | case OMAP_DISPLAY_TYPE_SDI: | 1392 | case OMAP_DISPLAY_TYPE_SDI: |
1365 | case OMAP_DISPLAY_TYPE_VENC: | 1393 | case OMAP_DISPLAY_TYPE_VENC: |
1394 | case OMAP_DISPLAY_TYPE_HDMI: | ||
1366 | default_get_overlay_fifo_thresholds(ovl->id, size, | 1395 | default_get_overlay_fifo_thresholds(ovl->id, size, |
1367 | &oc->burst_size, &oc->fifo_low, | 1396 | &oc->burst_size, &oc->fifo_low, |
1368 | &oc->fifo_high); | 1397 | &oc->fifo_high); |
@@ -1380,15 +1409,20 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
1380 | } | 1409 | } |
1381 | 1410 | ||
1382 | r = 0; | 1411 | r = 0; |
1383 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 1412 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
1384 | if (!dss_cache.irq_enabled) { | 1413 | if (!dss_cache.irq_enabled) { |
1385 | r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, | 1414 | u32 mask; |
1386 | DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | | 1415 | |
1387 | DISPC_IRQ_EVSYNC_EVEN); | 1416 | mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | |
1417 | DISPC_IRQ_EVSYNC_EVEN; | ||
1418 | if (dss_has_feature(FEAT_MGR_LCD2)) | ||
1419 | mask |= DISPC_IRQ_VSYNC2; | ||
1420 | |||
1421 | r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask); | ||
1388 | dss_cache.irq_enabled = true; | 1422 | dss_cache.irq_enabled = true; |
1389 | } | 1423 | } |
1390 | configure_dispc(); | 1424 | configure_dispc(); |
1391 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 1425 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
1392 | 1426 | ||
1393 | spin_unlock_irqrestore(&dss_cache.lock, flags); | 1427 | spin_unlock_irqrestore(&dss_cache.lock, flags); |
1394 | 1428 | ||
@@ -1461,7 +1495,7 @@ int dss_init_overlay_managers(struct platform_device *pdev) | |||
1461 | 1495 | ||
1462 | num_managers = 0; | 1496 | num_managers = 0; |
1463 | 1497 | ||
1464 | for (i = 0; i < 2; ++i) { | 1498 | for (i = 0; i < dss_feat_get_num_mgrs(); ++i) { |
1465 | struct omap_overlay_manager *mgr; | 1499 | struct omap_overlay_manager *mgr; |
1466 | mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); | 1500 | mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); |
1467 | 1501 | ||
@@ -1471,14 +1505,14 @@ int dss_init_overlay_managers(struct platform_device *pdev) | |||
1471 | case 0: | 1505 | case 0: |
1472 | mgr->name = "lcd"; | 1506 | mgr->name = "lcd"; |
1473 | mgr->id = OMAP_DSS_CHANNEL_LCD; | 1507 | mgr->id = OMAP_DSS_CHANNEL_LCD; |
1474 | mgr->supported_displays = | ||
1475 | OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | | ||
1476 | OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI; | ||
1477 | break; | 1508 | break; |
1478 | case 1: | 1509 | case 1: |
1479 | mgr->name = "tv"; | 1510 | mgr->name = "tv"; |
1480 | mgr->id = OMAP_DSS_CHANNEL_DIGIT; | 1511 | mgr->id = OMAP_DSS_CHANNEL_DIGIT; |
1481 | mgr->supported_displays = OMAP_DISPLAY_TYPE_VENC; | 1512 | break; |
1513 | case 2: | ||
1514 | mgr->name = "lcd2"; | ||
1515 | mgr->id = OMAP_DSS_CHANNEL_LCD2; | ||
1482 | break; | 1516 | break; |
1483 | } | 1517 | } |
1484 | 1518 | ||
@@ -1494,6 +1528,8 @@ int dss_init_overlay_managers(struct platform_device *pdev) | |||
1494 | mgr->disable = &dss_mgr_disable; | 1528 | mgr->disable = &dss_mgr_disable; |
1495 | 1529 | ||
1496 | mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC; | 1530 | mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC; |
1531 | mgr->supported_displays = | ||
1532 | dss_feat_get_supported_displays(mgr->id); | ||
1497 | 1533 | ||
1498 | dss_overlay_setup_dispc_manager(mgr); | 1534 | dss_overlay_setup_dispc_manager(mgr); |
1499 | 1535 | ||
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 244dca81a399..0f08025b1f0e 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c | |||
@@ -31,10 +31,11 @@ | |||
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | 33 | ||
34 | #include <plat/display.h> | 34 | #include <video/omapdss.h> |
35 | #include <plat/cpu.h> | 35 | #include <plat/cpu.h> |
36 | 36 | ||
37 | #include "dss.h" | 37 | #include "dss.h" |
38 | #include "dss_features.h" | ||
38 | 39 | ||
39 | static int num_overlays; | 40 | static int num_overlays; |
40 | static struct list_head overlay_list; | 41 | static struct list_head overlay_list; |
@@ -200,12 +201,16 @@ static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf) | |||
200 | static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, | 201 | static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, |
201 | size_t size) | 202 | size_t size) |
202 | { | 203 | { |
203 | int r; | 204 | int r, enable; |
204 | struct omap_overlay_info info; | 205 | struct omap_overlay_info info; |
205 | 206 | ||
206 | ovl->get_overlay_info(ovl, &info); | 207 | ovl->get_overlay_info(ovl, &info); |
207 | 208 | ||
208 | info.enabled = simple_strtoul(buf, NULL, 10); | 209 | r = kstrtoint(buf, 0, &enable); |
210 | if (r) | ||
211 | return r; | ||
212 | |||
213 | info.enabled = !!enable; | ||
209 | 214 | ||
210 | r = ovl->set_overlay_info(ovl, &info); | 215 | r = ovl->set_overlay_info(ovl, &info); |
211 | if (r) | 216 | if (r) |
@@ -230,17 +235,65 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, | |||
230 | const char *buf, size_t size) | 235 | const char *buf, size_t size) |
231 | { | 236 | { |
232 | int r; | 237 | int r; |
238 | u8 alpha; | ||
233 | struct omap_overlay_info info; | 239 | struct omap_overlay_info info; |
234 | 240 | ||
241 | r = kstrtou8(buf, 0, &alpha); | ||
242 | if (r) | ||
243 | return r; | ||
244 | |||
235 | ovl->get_overlay_info(ovl, &info); | 245 | ovl->get_overlay_info(ovl, &info); |
236 | 246 | ||
237 | /* Video1 plane does not support global alpha | 247 | /* Video1 plane does not support global alpha |
238 | * to always make it 255 completely opaque | 248 | * to always make it 255 completely opaque |
239 | */ | 249 | */ |
240 | if (ovl->id == OMAP_DSS_VIDEO1) | 250 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && |
251 | ovl->id == OMAP_DSS_VIDEO1) | ||
241 | info.global_alpha = 255; | 252 | info.global_alpha = 255; |
242 | else | 253 | else |
243 | info.global_alpha = simple_strtoul(buf, NULL, 10); | 254 | info.global_alpha = alpha; |
255 | |||
256 | r = ovl->set_overlay_info(ovl, &info); | ||
257 | if (r) | ||
258 | return r; | ||
259 | |||
260 | if (ovl->manager) { | ||
261 | r = ovl->manager->apply(ovl->manager); | ||
262 | if (r) | ||
263 | return r; | ||
264 | } | ||
265 | |||
266 | return size; | ||
267 | } | ||
268 | |||
269 | static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl, | ||
270 | char *buf) | ||
271 | { | ||
272 | return snprintf(buf, PAGE_SIZE, "%d\n", | ||
273 | ovl->info.pre_mult_alpha); | ||
274 | } | ||
275 | |||
276 | static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl, | ||
277 | const char *buf, size_t size) | ||
278 | { | ||
279 | int r; | ||
280 | u8 alpha; | ||
281 | struct omap_overlay_info info; | ||
282 | |||
283 | r = kstrtou8(buf, 0, &alpha); | ||
284 | if (r) | ||
285 | return r; | ||
286 | |||
287 | ovl->get_overlay_info(ovl, &info); | ||
288 | |||
289 | /* only GFX and Video2 plane support pre alpha multiplied | ||
290 | * set zero for Video1 plane | ||
291 | */ | ||
292 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && | ||
293 | ovl->id == OMAP_DSS_VIDEO1) | ||
294 | info.pre_mult_alpha = 0; | ||
295 | else | ||
296 | info.pre_mult_alpha = alpha; | ||
244 | 297 | ||
245 | r = ovl->set_overlay_info(ovl, &info); | 298 | r = ovl->set_overlay_info(ovl, &info); |
246 | if (r) | 299 | if (r) |
@@ -278,6 +331,9 @@ static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR, | |||
278 | overlay_enabled_show, overlay_enabled_store); | 331 | overlay_enabled_show, overlay_enabled_store); |
279 | static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR, | 332 | static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR, |
280 | overlay_global_alpha_show, overlay_global_alpha_store); | 333 | overlay_global_alpha_show, overlay_global_alpha_store); |
334 | static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR, | ||
335 | overlay_pre_mult_alpha_show, | ||
336 | overlay_pre_mult_alpha_store); | ||
281 | 337 | ||
282 | static struct attribute *overlay_sysfs_attrs[] = { | 338 | static struct attribute *overlay_sysfs_attrs[] = { |
283 | &overlay_attr_name.attr, | 339 | &overlay_attr_name.attr, |
@@ -288,6 +344,7 @@ static struct attribute *overlay_sysfs_attrs[] = { | |||
288 | &overlay_attr_output_size.attr, | 344 | &overlay_attr_output_size.attr, |
289 | &overlay_attr_enabled.attr, | 345 | &overlay_attr_enabled.attr, |
290 | &overlay_attr_global_alpha.attr, | 346 | &overlay_attr_global_alpha.attr, |
347 | &overlay_attr_pre_mult_alpha.attr, | ||
291 | NULL | 348 | NULL |
292 | }; | 349 | }; |
293 | 350 | ||
@@ -447,16 +504,21 @@ static int omap_dss_set_manager(struct omap_overlay *ovl, | |||
447 | 504 | ||
448 | ovl->manager = mgr; | 505 | ovl->manager = mgr; |
449 | 506 | ||
450 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 507 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
451 | /* XXX: on manual update display, in auto update mode, a bug happens | 508 | /* XXX: When there is an overlay on a DSI manual update display, and |
452 | * here. When an overlay is first enabled on LCD, then it's disabled, | 509 | * the overlay is first disabled, then moved to tv, and enabled, we |
453 | * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT | 510 | * seem to get SYNC_LOST_DIGIT error. |
454 | * errors. Waiting before changing the channel_out fixes it. I'm | 511 | * |
455 | * guessing that the overlay is still somehow being used for the LCD, | 512 | * Waiting doesn't seem to help, but updating the manual update display |
456 | * but I don't understand how or why. */ | 513 | * after disabling the overlay seems to fix this. This hints that the |
457 | msleep(40); | 514 | * overlay is perhaps somehow tied to the LCD output until the output |
515 | * is updated. | ||
516 | * | ||
517 | * Userspace workaround for this is to update the LCD after disabling | ||
518 | * the overlay, but before moving the overlay to TV. | ||
519 | */ | ||
458 | dispc_set_channel_out(ovl->id, mgr->id); | 520 | dispc_set_channel_out(ovl->id, mgr->id); |
459 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 521 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
460 | 522 | ||
461 | return 0; | 523 | return 0; |
462 | } | 524 | } |
@@ -510,11 +572,11 @@ static void omap_dss_add_overlay(struct omap_overlay *overlay) | |||
510 | list_add_tail(&overlay->list, &overlay_list); | 572 | list_add_tail(&overlay->list, &overlay_list); |
511 | } | 573 | } |
512 | 574 | ||
513 | static struct omap_overlay *dispc_overlays[3]; | 575 | static struct omap_overlay *dispc_overlays[MAX_DSS_OVERLAYS]; |
514 | 576 | ||
515 | void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr) | 577 | void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr) |
516 | { | 578 | { |
517 | mgr->num_overlays = 3; | 579 | mgr->num_overlays = dss_feat_get_num_ovls(); |
518 | mgr->overlays = dispc_overlays; | 580 | mgr->overlays = dispc_overlays; |
519 | } | 581 | } |
520 | 582 | ||
@@ -535,7 +597,7 @@ void dss_init_overlays(struct platform_device *pdev) | |||
535 | 597 | ||
536 | num_overlays = 0; | 598 | num_overlays = 0; |
537 | 599 | ||
538 | for (i = 0; i < 3; ++i) { | 600 | for (i = 0; i < dss_feat_get_num_ovls(); ++i) { |
539 | struct omap_overlay *ovl; | 601 | struct omap_overlay *ovl; |
540 | ovl = kzalloc(sizeof(*ovl), GFP_KERNEL); | 602 | ovl = kzalloc(sizeof(*ovl), GFP_KERNEL); |
541 | 603 | ||
@@ -545,18 +607,12 @@ void dss_init_overlays(struct platform_device *pdev) | |||
545 | case 0: | 607 | case 0: |
546 | ovl->name = "gfx"; | 608 | ovl->name = "gfx"; |
547 | ovl->id = OMAP_DSS_GFX; | 609 | ovl->id = OMAP_DSS_GFX; |
548 | ovl->supported_modes = cpu_is_omap34xx() ? | ||
549 | OMAP_DSS_COLOR_GFX_OMAP3 : | ||
550 | OMAP_DSS_COLOR_GFX_OMAP2; | ||
551 | ovl->caps = OMAP_DSS_OVL_CAP_DISPC; | 610 | ovl->caps = OMAP_DSS_OVL_CAP_DISPC; |
552 | ovl->info.global_alpha = 255; | 611 | ovl->info.global_alpha = 255; |
553 | break; | 612 | break; |
554 | case 1: | 613 | case 1: |
555 | ovl->name = "vid1"; | 614 | ovl->name = "vid1"; |
556 | ovl->id = OMAP_DSS_VIDEO1; | 615 | ovl->id = OMAP_DSS_VIDEO1; |
557 | ovl->supported_modes = cpu_is_omap34xx() ? | ||
558 | OMAP_DSS_COLOR_VID1_OMAP3 : | ||
559 | OMAP_DSS_COLOR_VID_OMAP2; | ||
560 | ovl->caps = OMAP_DSS_OVL_CAP_SCALE | | 616 | ovl->caps = OMAP_DSS_OVL_CAP_SCALE | |
561 | OMAP_DSS_OVL_CAP_DISPC; | 617 | OMAP_DSS_OVL_CAP_DISPC; |
562 | ovl->info.global_alpha = 255; | 618 | ovl->info.global_alpha = 255; |
@@ -564,9 +620,6 @@ void dss_init_overlays(struct platform_device *pdev) | |||
564 | case 2: | 620 | case 2: |
565 | ovl->name = "vid2"; | 621 | ovl->name = "vid2"; |
566 | ovl->id = OMAP_DSS_VIDEO2; | 622 | ovl->id = OMAP_DSS_VIDEO2; |
567 | ovl->supported_modes = cpu_is_omap34xx() ? | ||
568 | OMAP_DSS_COLOR_VID2_OMAP3 : | ||
569 | OMAP_DSS_COLOR_VID_OMAP2; | ||
570 | ovl->caps = OMAP_DSS_OVL_CAP_SCALE | | 623 | ovl->caps = OMAP_DSS_OVL_CAP_SCALE | |
571 | OMAP_DSS_OVL_CAP_DISPC; | 624 | OMAP_DSS_OVL_CAP_DISPC; |
572 | ovl->info.global_alpha = 255; | 625 | ovl->info.global_alpha = 255; |
@@ -579,6 +632,9 @@ void dss_init_overlays(struct platform_device *pdev) | |||
579 | ovl->get_overlay_info = &dss_ovl_get_overlay_info; | 632 | ovl->get_overlay_info = &dss_ovl_get_overlay_info; |
580 | ovl->wait_for_go = &dss_ovl_wait_for_go; | 633 | ovl->wait_for_go = &dss_ovl_wait_for_go; |
581 | 634 | ||
635 | ovl->supported_modes = | ||
636 | dss_feat_get_supported_color_modes(ovl->id); | ||
637 | |||
582 | omap_dss_add_overlay(ovl); | 638 | omap_dss_add_overlay(ovl); |
583 | 639 | ||
584 | r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, | 640 | r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, |
@@ -627,12 +683,23 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) | |||
627 | int i; | 683 | int i; |
628 | struct omap_overlay_manager *lcd_mgr; | 684 | struct omap_overlay_manager *lcd_mgr; |
629 | struct omap_overlay_manager *tv_mgr; | 685 | struct omap_overlay_manager *tv_mgr; |
686 | struct omap_overlay_manager *lcd2_mgr = NULL; | ||
630 | struct omap_overlay_manager *mgr = NULL; | 687 | struct omap_overlay_manager *mgr = NULL; |
631 | 688 | ||
632 | lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD); | 689 | lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD); |
633 | tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV); | 690 | tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV); |
634 | 691 | if (dss_has_feature(FEAT_MGR_LCD2)) | |
635 | if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) { | 692 | lcd2_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD2); |
693 | |||
694 | if (dssdev->channel == OMAP_DSS_CHANNEL_LCD2) { | ||
695 | if (!lcd2_mgr->device || force) { | ||
696 | if (lcd2_mgr->device) | ||
697 | lcd2_mgr->unset_device(lcd2_mgr); | ||
698 | lcd2_mgr->set_device(lcd2_mgr, dssdev); | ||
699 | mgr = lcd2_mgr; | ||
700 | } | ||
701 | } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC | ||
702 | && dssdev->type != OMAP_DISPLAY_TYPE_HDMI) { | ||
636 | if (!lcd_mgr->device || force) { | 703 | if (!lcd_mgr->device || force) { |
637 | if (lcd_mgr->device) | 704 | if (lcd_mgr->device) |
638 | lcd_mgr->unset_device(lcd_mgr); | 705 | lcd_mgr->unset_device(lcd_mgr); |
@@ -641,7 +708,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) | |||
641 | } | 708 | } |
642 | } | 709 | } |
643 | 710 | ||
644 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { | 711 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC |
712 | || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { | ||
645 | if (!tv_mgr->device || force) { | 713 | if (!tv_mgr->device || force) { |
646 | if (tv_mgr->device) | 714 | if (tv_mgr->device) |
647 | tv_mgr->unset_device(tv_mgr); | 715 | tv_mgr->unset_device(tv_mgr); |
@@ -651,7 +719,7 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) | |||
651 | } | 719 | } |
652 | 720 | ||
653 | if (mgr) { | 721 | if (mgr) { |
654 | for (i = 0; i < 3; i++) { | 722 | for (i = 0; i < dss_feat_get_num_ovls(); i++) { |
655 | struct omap_overlay *ovl; | 723 | struct omap_overlay *ovl; |
656 | ovl = omap_dss_get_overlay(i); | 724 | ovl = omap_dss_get_overlay(i); |
657 | if (!ovl->manager || force) { | 725 | if (!ovl->manager || force) { |
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index bbe62464e92d..c06fbe0bc678 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c | |||
@@ -32,12 +32,11 @@ | |||
32 | #include <linux/ktime.h> | 32 | #include <linux/ktime.h> |
33 | #include <linux/hrtimer.h> | 33 | #include <linux/hrtimer.h> |
34 | #include <linux/seq_file.h> | 34 | #include <linux/seq_file.h> |
35 | #include <linux/semaphore.h> | ||
35 | 36 | ||
36 | #include <plat/display.h> | 37 | #include <video/omapdss.h> |
37 | #include "dss.h" | 38 | #include "dss.h" |
38 | 39 | ||
39 | #define RFBI_BASE 0x48050800 | ||
40 | |||
41 | struct rfbi_reg { u16 idx; }; | 40 | struct rfbi_reg { u16 idx; }; |
42 | 41 | ||
43 | #define RFBI_REG(idx) ((const struct rfbi_reg) { idx }) | 42 | #define RFBI_REG(idx) ((const struct rfbi_reg) { idx }) |
@@ -67,9 +66,6 @@ struct rfbi_reg { u16 idx; }; | |||
67 | #define REG_FLD_MOD(idx, val, start, end) \ | 66 | #define REG_FLD_MOD(idx, val, start, end) \ |
68 | rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end)) | 67 | rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end)) |
69 | 68 | ||
70 | /* To work around an RFBI transfer rate limitation */ | ||
71 | #define OMAP_RFBI_RATE_LIMIT 1 | ||
72 | |||
73 | enum omap_rfbi_cycleformat { | 69 | enum omap_rfbi_cycleformat { |
74 | OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0, | 70 | OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0, |
75 | OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1, | 71 | OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1, |
@@ -91,15 +87,11 @@ enum omap_rfbi_parallelmode { | |||
91 | OMAP_DSS_RFBI_PARALLELMODE_16 = 3, | 87 | OMAP_DSS_RFBI_PARALLELMODE_16 = 3, |
92 | }; | 88 | }; |
93 | 89 | ||
94 | enum update_cmd { | ||
95 | RFBI_CMD_UPDATE = 0, | ||
96 | RFBI_CMD_SYNC = 1, | ||
97 | }; | ||
98 | |||
99 | static int rfbi_convert_timings(struct rfbi_timings *t); | 90 | static int rfbi_convert_timings(struct rfbi_timings *t); |
100 | static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div); | 91 | static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div); |
101 | 92 | ||
102 | static struct { | 93 | static struct { |
94 | struct platform_device *pdev; | ||
103 | void __iomem *base; | 95 | void __iomem *base; |
104 | 96 | ||
105 | unsigned long l4_khz; | 97 | unsigned long l4_khz; |
@@ -115,20 +107,9 @@ static struct { | |||
115 | 107 | ||
116 | struct omap_dss_device *dssdev[2]; | 108 | struct omap_dss_device *dssdev[2]; |
117 | 109 | ||
118 | struct kfifo cmd_fifo; | 110 | struct semaphore bus_lock; |
119 | spinlock_t cmd_lock; | ||
120 | struct completion cmd_done; | ||
121 | atomic_t cmd_fifo_full; | ||
122 | atomic_t cmd_pending; | ||
123 | } rfbi; | 111 | } rfbi; |
124 | 112 | ||
125 | struct update_region { | ||
126 | u16 x; | ||
127 | u16 y; | ||
128 | u16 w; | ||
129 | u16 h; | ||
130 | }; | ||
131 | |||
132 | static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) | 113 | static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) |
133 | { | 114 | { |
134 | __raw_writel(val, rfbi.base + idx.idx); | 115 | __raw_writel(val, rfbi.base + idx.idx); |
@@ -142,14 +123,25 @@ static inline u32 rfbi_read_reg(const struct rfbi_reg idx) | |||
142 | static void rfbi_enable_clocks(bool enable) | 123 | static void rfbi_enable_clocks(bool enable) |
143 | { | 124 | { |
144 | if (enable) | 125 | if (enable) |
145 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 126 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
146 | else | 127 | else |
147 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 128 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
129 | } | ||
130 | |||
131 | void rfbi_bus_lock(void) | ||
132 | { | ||
133 | down(&rfbi.bus_lock); | ||
134 | } | ||
135 | EXPORT_SYMBOL(rfbi_bus_lock); | ||
136 | |||
137 | void rfbi_bus_unlock(void) | ||
138 | { | ||
139 | up(&rfbi.bus_lock); | ||
148 | } | 140 | } |
141 | EXPORT_SYMBOL(rfbi_bus_unlock); | ||
149 | 142 | ||
150 | void omap_rfbi_write_command(const void *buf, u32 len) | 143 | void omap_rfbi_write_command(const void *buf, u32 len) |
151 | { | 144 | { |
152 | rfbi_enable_clocks(1); | ||
153 | switch (rfbi.parallelmode) { | 145 | switch (rfbi.parallelmode) { |
154 | case OMAP_DSS_RFBI_PARALLELMODE_8: | 146 | case OMAP_DSS_RFBI_PARALLELMODE_8: |
155 | { | 147 | { |
@@ -173,13 +165,11 @@ void omap_rfbi_write_command(const void *buf, u32 len) | |||
173 | default: | 165 | default: |
174 | BUG(); | 166 | BUG(); |
175 | } | 167 | } |
176 | rfbi_enable_clocks(0); | ||
177 | } | 168 | } |
178 | EXPORT_SYMBOL(omap_rfbi_write_command); | 169 | EXPORT_SYMBOL(omap_rfbi_write_command); |
179 | 170 | ||
180 | void omap_rfbi_read_data(void *buf, u32 len) | 171 | void omap_rfbi_read_data(void *buf, u32 len) |
181 | { | 172 | { |
182 | rfbi_enable_clocks(1); | ||
183 | switch (rfbi.parallelmode) { | 173 | switch (rfbi.parallelmode) { |
184 | case OMAP_DSS_RFBI_PARALLELMODE_8: | 174 | case OMAP_DSS_RFBI_PARALLELMODE_8: |
185 | { | 175 | { |
@@ -207,13 +197,11 @@ void omap_rfbi_read_data(void *buf, u32 len) | |||
207 | default: | 197 | default: |
208 | BUG(); | 198 | BUG(); |
209 | } | 199 | } |
210 | rfbi_enable_clocks(0); | ||
211 | } | 200 | } |
212 | EXPORT_SYMBOL(omap_rfbi_read_data); | 201 | EXPORT_SYMBOL(omap_rfbi_read_data); |
213 | 202 | ||
214 | void omap_rfbi_write_data(const void *buf, u32 len) | 203 | void omap_rfbi_write_data(const void *buf, u32 len) |
215 | { | 204 | { |
216 | rfbi_enable_clocks(1); | ||
217 | switch (rfbi.parallelmode) { | 205 | switch (rfbi.parallelmode) { |
218 | case OMAP_DSS_RFBI_PARALLELMODE_8: | 206 | case OMAP_DSS_RFBI_PARALLELMODE_8: |
219 | { | 207 | { |
@@ -238,7 +226,6 @@ void omap_rfbi_write_data(const void *buf, u32 len) | |||
238 | BUG(); | 226 | BUG(); |
239 | 227 | ||
240 | } | 228 | } |
241 | rfbi_enable_clocks(0); | ||
242 | } | 229 | } |
243 | EXPORT_SYMBOL(omap_rfbi_write_data); | 230 | EXPORT_SYMBOL(omap_rfbi_write_data); |
244 | 231 | ||
@@ -250,8 +237,6 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width, | |||
250 | int horiz_offset = scr_width - w; | 237 | int horiz_offset = scr_width - w; |
251 | int i; | 238 | int i; |
252 | 239 | ||
253 | rfbi_enable_clocks(1); | ||
254 | |||
255 | if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 && | 240 | if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 && |
256 | rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) { | 241 | rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) { |
257 | const u16 __iomem *pd = buf; | 242 | const u16 __iomem *pd = buf; |
@@ -296,13 +281,11 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width, | |||
296 | } else { | 281 | } else { |
297 | BUG(); | 282 | BUG(); |
298 | } | 283 | } |
299 | |||
300 | rfbi_enable_clocks(0); | ||
301 | } | 284 | } |
302 | EXPORT_SYMBOL(omap_rfbi_write_pixels); | 285 | EXPORT_SYMBOL(omap_rfbi_write_pixels); |
303 | 286 | ||
304 | void rfbi_transfer_area(u16 width, u16 height, | 287 | static void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, |
305 | void (callback)(void *data), void *data) | 288 | u16 height, void (*callback)(void *data), void *data) |
306 | { | 289 | { |
307 | u32 l; | 290 | u32 l; |
308 | 291 | ||
@@ -311,15 +294,13 @@ void rfbi_transfer_area(u16 width, u16 height, | |||
311 | 294 | ||
312 | DSSDBG("rfbi_transfer_area %dx%d\n", width, height); | 295 | DSSDBG("rfbi_transfer_area %dx%d\n", width, height); |
313 | 296 | ||
314 | dispc_set_lcd_size(width, height); | 297 | dispc_set_lcd_size(dssdev->manager->id, width, height); |
315 | 298 | ||
316 | dispc_enable_channel(OMAP_DSS_CHANNEL_LCD, true); | 299 | dispc_enable_channel(dssdev->manager->id, true); |
317 | 300 | ||
318 | rfbi.framedone_callback = callback; | 301 | rfbi.framedone_callback = callback; |
319 | rfbi.framedone_callback_data = data; | 302 | rfbi.framedone_callback_data = data; |
320 | 303 | ||
321 | rfbi_enable_clocks(1); | ||
322 | |||
323 | rfbi_write_reg(RFBI_PIXEL_CNT, width * height); | 304 | rfbi_write_reg(RFBI_PIXEL_CNT, width * height); |
324 | 305 | ||
325 | l = rfbi_read_reg(RFBI_CONTROL); | 306 | l = rfbi_read_reg(RFBI_CONTROL); |
@@ -338,15 +319,11 @@ static void framedone_callback(void *data, u32 mask) | |||
338 | 319 | ||
339 | REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0); | 320 | REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0); |
340 | 321 | ||
341 | rfbi_enable_clocks(0); | ||
342 | |||
343 | callback = rfbi.framedone_callback; | 322 | callback = rfbi.framedone_callback; |
344 | rfbi.framedone_callback = NULL; | 323 | rfbi.framedone_callback = NULL; |
345 | 324 | ||
346 | if (callback != NULL) | 325 | if (callback != NULL) |
347 | callback(rfbi.framedone_callback_data); | 326 | callback(rfbi.framedone_callback_data); |
348 | |||
349 | atomic_set(&rfbi.cmd_pending, 0); | ||
350 | } | 327 | } |
351 | 328 | ||
352 | #if 1 /* VERBOSE */ | 329 | #if 1 /* VERBOSE */ |
@@ -436,7 +413,7 @@ static int calc_extif_timings(struct rfbi_timings *t) | |||
436 | } | 413 | } |
437 | 414 | ||
438 | 415 | ||
439 | void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t) | 416 | static void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t) |
440 | { | 417 | { |
441 | int r; | 418 | int r; |
442 | 419 | ||
@@ -448,7 +425,6 @@ void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t) | |||
448 | 425 | ||
449 | BUG_ON(!t->converted); | 426 | BUG_ON(!t->converted); |
450 | 427 | ||
451 | rfbi_enable_clocks(1); | ||
452 | rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]); | 428 | rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]); |
453 | rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]); | 429 | rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]); |
454 | 430 | ||
@@ -457,7 +433,6 @@ void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t) | |||
457 | (t->tim[2] ? 1 : 0), 4, 4); | 433 | (t->tim[2] ? 1 : 0), 4, 4); |
458 | 434 | ||
459 | rfbi_print_timings(); | 435 | rfbi_print_timings(); |
460 | rfbi_enable_clocks(0); | ||
461 | } | 436 | } |
462 | 437 | ||
463 | static int ps_to_rfbi_ticks(int time, int div) | 438 | static int ps_to_rfbi_ticks(int time, int div) |
@@ -473,59 +448,6 @@ static int ps_to_rfbi_ticks(int time, int div) | |||
473 | return ret; | 448 | return ret; |
474 | } | 449 | } |
475 | 450 | ||
476 | #ifdef OMAP_RFBI_RATE_LIMIT | ||
477 | unsigned long rfbi_get_max_tx_rate(void) | ||
478 | { | ||
479 | unsigned long l4_rate, dss1_rate; | ||
480 | int min_l4_ticks = 0; | ||
481 | int i; | ||
482 | |||
483 | /* According to TI this can't be calculated so make the | ||
484 | * adjustments for a couple of known frequencies and warn for | ||
485 | * others. | ||
486 | */ | ||
487 | static const struct { | ||
488 | unsigned long l4_clk; /* HZ */ | ||
489 | unsigned long dss1_clk; /* HZ */ | ||
490 | unsigned long min_l4_ticks; | ||
491 | } ftab[] = { | ||
492 | { 55, 132, 7, }, /* 7.86 MPix/s */ | ||
493 | { 110, 110, 12, }, /* 9.16 MPix/s */ | ||
494 | { 110, 132, 10, }, /* 11 Mpix/s */ | ||
495 | { 120, 120, 10, }, /* 12 Mpix/s */ | ||
496 | { 133, 133, 10, }, /* 13.3 Mpix/s */ | ||
497 | }; | ||
498 | |||
499 | l4_rate = rfbi.l4_khz / 1000; | ||
500 | dss1_rate = dss_clk_get_rate(DSS_CLK_FCK1) / 1000000; | ||
501 | |||
502 | for (i = 0; i < ARRAY_SIZE(ftab); i++) { | ||
503 | /* Use a window instead of an exact match, to account | ||
504 | * for different DPLL multiplier / divider pairs. | ||
505 | */ | ||
506 | if (abs(ftab[i].l4_clk - l4_rate) < 3 && | ||
507 | abs(ftab[i].dss1_clk - dss1_rate) < 3) { | ||
508 | min_l4_ticks = ftab[i].min_l4_ticks; | ||
509 | break; | ||
510 | } | ||
511 | } | ||
512 | if (i == ARRAY_SIZE(ftab)) { | ||
513 | /* Can't be sure, return anyway the maximum not | ||
514 | * rate-limited. This might cause a problem only for the | ||
515 | * tearing synchronisation. | ||
516 | */ | ||
517 | DSSERR("can't determine maximum RFBI transfer rate\n"); | ||
518 | return rfbi.l4_khz * 1000; | ||
519 | } | ||
520 | return rfbi.l4_khz * 1000 / min_l4_ticks; | ||
521 | } | ||
522 | #else | ||
523 | int rfbi_get_max_tx_rate(void) | ||
524 | { | ||
525 | return rfbi.l4_khz * 1000; | ||
526 | } | ||
527 | #endif | ||
528 | |||
529 | static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div) | 451 | static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div) |
530 | { | 452 | { |
531 | *clk_period = 1000000000 / rfbi.l4_khz; | 453 | *clk_period = 1000000000 / rfbi.l4_khz; |
@@ -645,7 +567,6 @@ int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode, | |||
645 | DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n", | 567 | DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n", |
646 | mode, hs, vs, hs_pol_inv, vs_pol_inv); | 568 | mode, hs, vs, hs_pol_inv, vs_pol_inv); |
647 | 569 | ||
648 | rfbi_enable_clocks(1); | ||
649 | rfbi_write_reg(RFBI_HSYNC_WIDTH, hs); | 570 | rfbi_write_reg(RFBI_HSYNC_WIDTH, hs); |
650 | rfbi_write_reg(RFBI_VSYNC_WIDTH, vs); | 571 | rfbi_write_reg(RFBI_VSYNC_WIDTH, vs); |
651 | 572 | ||
@@ -658,7 +579,6 @@ int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode, | |||
658 | l &= ~(1 << 20); | 579 | l &= ~(1 << 20); |
659 | else | 580 | else |
660 | l |= 1 << 20; | 581 | l |= 1 << 20; |
661 | rfbi_enable_clocks(0); | ||
662 | 582 | ||
663 | return 0; | 583 | return 0; |
664 | } | 584 | } |
@@ -673,7 +593,6 @@ int omap_rfbi_enable_te(bool enable, unsigned line) | |||
673 | if (line > (1 << 11) - 1) | 593 | if (line > (1 << 11) - 1) |
674 | return -EINVAL; | 594 | return -EINVAL; |
675 | 595 | ||
676 | rfbi_enable_clocks(1); | ||
677 | l = rfbi_read_reg(RFBI_CONFIG(0)); | 596 | l = rfbi_read_reg(RFBI_CONFIG(0)); |
678 | l &= ~(0x3 << 2); | 597 | l &= ~(0x3 << 2); |
679 | if (enable) { | 598 | if (enable) { |
@@ -683,50 +602,12 @@ int omap_rfbi_enable_te(bool enable, unsigned line) | |||
683 | rfbi.te_enabled = 0; | 602 | rfbi.te_enabled = 0; |
684 | rfbi_write_reg(RFBI_CONFIG(0), l); | 603 | rfbi_write_reg(RFBI_CONFIG(0), l); |
685 | rfbi_write_reg(RFBI_LINE_NUMBER, line); | 604 | rfbi_write_reg(RFBI_LINE_NUMBER, line); |
686 | rfbi_enable_clocks(0); | ||
687 | 605 | ||
688 | return 0; | 606 | return 0; |
689 | } | 607 | } |
690 | EXPORT_SYMBOL(omap_rfbi_enable_te); | 608 | EXPORT_SYMBOL(omap_rfbi_enable_te); |
691 | 609 | ||
692 | #if 0 | 610 | static int rfbi_configure(int rfbi_module, int bpp, int lines) |
693 | static void rfbi_enable_config(int enable1, int enable2) | ||
694 | { | ||
695 | u32 l; | ||
696 | int cs = 0; | ||
697 | |||
698 | if (enable1) | ||
699 | cs |= 1<<0; | ||
700 | if (enable2) | ||
701 | cs |= 1<<1; | ||
702 | |||
703 | rfbi_enable_clocks(1); | ||
704 | |||
705 | l = rfbi_read_reg(RFBI_CONTROL); | ||
706 | |||
707 | l = FLD_MOD(l, cs, 3, 2); | ||
708 | l = FLD_MOD(l, 0, 1, 1); | ||
709 | |||
710 | rfbi_write_reg(RFBI_CONTROL, l); | ||
711 | |||
712 | |||
713 | l = rfbi_read_reg(RFBI_CONFIG(0)); | ||
714 | l = FLD_MOD(l, 0, 3, 2); /* TRIGGERMODE: ITE */ | ||
715 | /*l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */ | ||
716 | /*l |= FLD_VAL(0, 8, 7); */ /* L4FORMAT, 1pix/L4 */ | ||
717 | |||
718 | l = FLD_MOD(l, 0, 16, 16); /* A0POLARITY */ | ||
719 | l = FLD_MOD(l, 1, 20, 20); /* TE_VSYNC_POLARITY */ | ||
720 | l = FLD_MOD(l, 1, 21, 21); /* HSYNCPOLARITY */ | ||
721 | |||
722 | l = FLD_MOD(l, OMAP_DSS_RFBI_PARALLELMODE_8, 1, 0); | ||
723 | rfbi_write_reg(RFBI_CONFIG(0), l); | ||
724 | |||
725 | rfbi_enable_clocks(0); | ||
726 | } | ||
727 | #endif | ||
728 | |||
729 | int rfbi_configure(int rfbi_module, int bpp, int lines) | ||
730 | { | 611 | { |
731 | u32 l; | 612 | u32 l; |
732 | int cycle1 = 0, cycle2 = 0, cycle3 = 0; | 613 | int cycle1 = 0, cycle2 = 0, cycle3 = 0; |
@@ -822,8 +703,6 @@ int rfbi_configure(int rfbi_module, int bpp, int lines) | |||
822 | break; | 703 | break; |
823 | } | 704 | } |
824 | 705 | ||
825 | rfbi_enable_clocks(1); | ||
826 | |||
827 | REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */ | 706 | REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */ |
828 | 707 | ||
829 | l = 0; | 708 | l = 0; |
@@ -857,11 +736,15 @@ int rfbi_configure(int rfbi_module, int bpp, int lines) | |||
857 | DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n", | 736 | DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n", |
858 | bpp, lines, cycle1, cycle2, cycle3); | 737 | bpp, lines, cycle1, cycle2, cycle3); |
859 | 738 | ||
860 | rfbi_enable_clocks(0); | ||
861 | |||
862 | return 0; | 739 | return 0; |
863 | } | 740 | } |
864 | EXPORT_SYMBOL(rfbi_configure); | 741 | |
742 | int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size, | ||
743 | int data_lines) | ||
744 | { | ||
745 | return rfbi_configure(dssdev->phy.rfbi.channel, pixel_size, data_lines); | ||
746 | } | ||
747 | EXPORT_SYMBOL(omap_rfbi_configure); | ||
865 | 748 | ||
866 | int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, | 749 | int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, |
867 | u16 *x, u16 *y, u16 *w, u16 *h) | 750 | u16 *x, u16 *y, u16 *w, u16 *h) |
@@ -887,7 +770,7 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, | |||
887 | 770 | ||
888 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 771 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { |
889 | dss_setup_partial_planes(dssdev, x, y, w, h, true); | 772 | dss_setup_partial_planes(dssdev, x, y, w, h, true); |
890 | dispc_set_lcd_size(*w, *h); | 773 | dispc_set_lcd_size(dssdev->manager->id, *w, *h); |
891 | } | 774 | } |
892 | 775 | ||
893 | return 0; | 776 | return 0; |
@@ -899,7 +782,7 @@ int omap_rfbi_update(struct omap_dss_device *dssdev, | |||
899 | void (*callback)(void *), void *data) | 782 | void (*callback)(void *), void *data) |
900 | { | 783 | { |
901 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 784 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { |
902 | rfbi_transfer_area(w, h, callback, data); | 785 | rfbi_transfer_area(dssdev, w, h, callback, data); |
903 | } else { | 786 | } else { |
904 | struct omap_overlay *ovl; | 787 | struct omap_overlay *ovl; |
905 | void __iomem *addr; | 788 | void __iomem *addr; |
@@ -922,7 +805,7 @@ void rfbi_dump_regs(struct seq_file *s) | |||
922 | { | 805 | { |
923 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r)) | 806 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r)) |
924 | 807 | ||
925 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 808 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
926 | 809 | ||
927 | DUMPREG(RFBI_REVISION); | 810 | DUMPREG(RFBI_REVISION); |
928 | DUMPREG(RFBI_SYSCONFIG); | 811 | DUMPREG(RFBI_SYSCONFIG); |
@@ -953,58 +836,16 @@ void rfbi_dump_regs(struct seq_file *s) | |||
953 | DUMPREG(RFBI_VSYNC_WIDTH); | 836 | DUMPREG(RFBI_VSYNC_WIDTH); |
954 | DUMPREG(RFBI_HSYNC_WIDTH); | 837 | DUMPREG(RFBI_HSYNC_WIDTH); |
955 | 838 | ||
956 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 839 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
957 | #undef DUMPREG | 840 | #undef DUMPREG |
958 | } | 841 | } |
959 | 842 | ||
960 | int rfbi_init(void) | ||
961 | { | ||
962 | u32 rev; | ||
963 | u32 l; | ||
964 | |||
965 | spin_lock_init(&rfbi.cmd_lock); | ||
966 | |||
967 | init_completion(&rfbi.cmd_done); | ||
968 | atomic_set(&rfbi.cmd_fifo_full, 0); | ||
969 | atomic_set(&rfbi.cmd_pending, 0); | ||
970 | |||
971 | rfbi.base = ioremap(RFBI_BASE, SZ_256); | ||
972 | if (!rfbi.base) { | ||
973 | DSSERR("can't ioremap RFBI\n"); | ||
974 | return -ENOMEM; | ||
975 | } | ||
976 | |||
977 | rfbi_enable_clocks(1); | ||
978 | |||
979 | msleep(10); | ||
980 | |||
981 | rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000; | ||
982 | |||
983 | /* Enable autoidle and smart-idle */ | ||
984 | l = rfbi_read_reg(RFBI_SYSCONFIG); | ||
985 | l |= (1 << 0) | (2 << 3); | ||
986 | rfbi_write_reg(RFBI_SYSCONFIG, l); | ||
987 | |||
988 | rev = rfbi_read_reg(RFBI_REVISION); | ||
989 | printk(KERN_INFO "OMAP RFBI rev %d.%d\n", | ||
990 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | ||
991 | |||
992 | rfbi_enable_clocks(0); | ||
993 | |||
994 | return 0; | ||
995 | } | ||
996 | |||
997 | void rfbi_exit(void) | ||
998 | { | ||
999 | DSSDBG("rfbi_exit\n"); | ||
1000 | |||
1001 | iounmap(rfbi.base); | ||
1002 | } | ||
1003 | |||
1004 | int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) | 843 | int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) |
1005 | { | 844 | { |
1006 | int r; | 845 | int r; |
1007 | 846 | ||
847 | rfbi_enable_clocks(1); | ||
848 | |||
1008 | r = omap_dss_start_device(dssdev); | 849 | r = omap_dss_start_device(dssdev); |
1009 | if (r) { | 850 | if (r) { |
1010 | DSSERR("failed to start device\n"); | 851 | DSSERR("failed to start device\n"); |
@@ -1018,11 +859,13 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) | |||
1018 | goto err1; | 859 | goto err1; |
1019 | } | 860 | } |
1020 | 861 | ||
1021 | dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT); | 862 | dispc_set_lcd_display_type(dssdev->manager->id, |
863 | OMAP_DSS_LCD_DISPLAY_TFT); | ||
1022 | 864 | ||
1023 | dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_RFBI); | 865 | dispc_set_parallel_interface_mode(dssdev->manager->id, |
866 | OMAP_DSS_PARALLELMODE_RFBI); | ||
1024 | 867 | ||
1025 | dispc_set_tft_data_lines(dssdev->ctrl.pixel_size); | 868 | dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size); |
1026 | 869 | ||
1027 | rfbi_configure(dssdev->phy.rfbi.channel, | 870 | rfbi_configure(dssdev->phy.rfbi.channel, |
1028 | dssdev->ctrl.pixel_size, | 871 | dssdev->ctrl.pixel_size, |
@@ -1045,6 +888,8 @@ void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev) | |||
1045 | omap_dispc_unregister_isr(framedone_callback, NULL, | 888 | omap_dispc_unregister_isr(framedone_callback, NULL, |
1046 | DISPC_IRQ_FRAMEDONE); | 889 | DISPC_IRQ_FRAMEDONE); |
1047 | omap_dss_stop_device(dssdev); | 890 | omap_dss_stop_device(dssdev); |
891 | |||
892 | rfbi_enable_clocks(0); | ||
1048 | } | 893 | } |
1049 | EXPORT_SYMBOL(omapdss_rfbi_display_disable); | 894 | EXPORT_SYMBOL(omapdss_rfbi_display_disable); |
1050 | 895 | ||
@@ -1054,3 +899,70 @@ int rfbi_init_display(struct omap_dss_device *dssdev) | |||
1054 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; | 899 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; |
1055 | return 0; | 900 | return 0; |
1056 | } | 901 | } |
902 | |||
903 | /* RFBI HW IP initialisation */ | ||
904 | static int omap_rfbihw_probe(struct platform_device *pdev) | ||
905 | { | ||
906 | u32 rev; | ||
907 | u32 l; | ||
908 | struct resource *rfbi_mem; | ||
909 | |||
910 | rfbi.pdev = pdev; | ||
911 | |||
912 | sema_init(&rfbi.bus_lock, 1); | ||
913 | |||
914 | rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0); | ||
915 | if (!rfbi_mem) { | ||
916 | DSSERR("can't get IORESOURCE_MEM RFBI\n"); | ||
917 | return -EINVAL; | ||
918 | } | ||
919 | rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem)); | ||
920 | if (!rfbi.base) { | ||
921 | DSSERR("can't ioremap RFBI\n"); | ||
922 | return -ENOMEM; | ||
923 | } | ||
924 | |||
925 | rfbi_enable_clocks(1); | ||
926 | |||
927 | msleep(10); | ||
928 | |||
929 | rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000; | ||
930 | |||
931 | /* Enable autoidle and smart-idle */ | ||
932 | l = rfbi_read_reg(RFBI_SYSCONFIG); | ||
933 | l |= (1 << 0) | (2 << 3); | ||
934 | rfbi_write_reg(RFBI_SYSCONFIG, l); | ||
935 | |||
936 | rev = rfbi_read_reg(RFBI_REVISION); | ||
937 | dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n", | ||
938 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | ||
939 | |||
940 | rfbi_enable_clocks(0); | ||
941 | |||
942 | return 0; | ||
943 | } | ||
944 | |||
945 | static int omap_rfbihw_remove(struct platform_device *pdev) | ||
946 | { | ||
947 | iounmap(rfbi.base); | ||
948 | return 0; | ||
949 | } | ||
950 | |||
951 | static struct platform_driver omap_rfbihw_driver = { | ||
952 | .probe = omap_rfbihw_probe, | ||
953 | .remove = omap_rfbihw_remove, | ||
954 | .driver = { | ||
955 | .name = "omapdss_rfbi", | ||
956 | .owner = THIS_MODULE, | ||
957 | }, | ||
958 | }; | ||
959 | |||
960 | int rfbi_init_platform_driver(void) | ||
961 | { | ||
962 | return platform_driver_register(&omap_rfbihw_driver); | ||
963 | } | ||
964 | |||
965 | void rfbi_uninit_platform_driver(void) | ||
966 | { | ||
967 | return platform_driver_unregister(&omap_rfbihw_driver); | ||
968 | } | ||
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index ee07a3cc22ef..0bd4b0350f80 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c | |||
@@ -25,22 +25,25 @@ | |||
25 | #include <linux/err.h> | 25 | #include <linux/err.h> |
26 | #include <linux/regulator/consumer.h> | 26 | #include <linux/regulator/consumer.h> |
27 | 27 | ||
28 | #include <plat/display.h> | 28 | #include <video/omapdss.h> |
29 | #include <plat/cpu.h> | 29 | #include <plat/cpu.h> |
30 | #include "dss.h" | 30 | #include "dss.h" |
31 | 31 | ||
32 | static struct { | 32 | static struct { |
33 | bool skip_init; | ||
34 | bool update_enabled; | 33 | bool update_enabled; |
35 | struct regulator *vdds_sdi_reg; | 34 | struct regulator *vdds_sdi_reg; |
36 | } sdi; | 35 | } sdi; |
37 | 36 | ||
38 | static void sdi_basic_init(void) | 37 | static void sdi_basic_init(struct omap_dss_device *dssdev) |
38 | |||
39 | { | 39 | { |
40 | dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS); | 40 | dispc_set_parallel_interface_mode(dssdev->manager->id, |
41 | OMAP_DSS_PARALLELMODE_BYPASS); | ||
42 | |||
43 | dispc_set_lcd_display_type(dssdev->manager->id, | ||
44 | OMAP_DSS_LCD_DISPLAY_TFT); | ||
41 | 45 | ||
42 | dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT); | 46 | dispc_set_tft_data_lines(dssdev->manager->id, 24); |
43 | dispc_set_tft_data_lines(24); | ||
44 | dispc_lcd_enable_signal_polarity(1); | 47 | dispc_lcd_enable_signal_polarity(1); |
45 | } | 48 | } |
46 | 49 | ||
@@ -64,26 +67,18 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
64 | if (r) | 67 | if (r) |
65 | goto err1; | 68 | goto err1; |
66 | 69 | ||
67 | /* In case of skip_init sdi_init has already enabled the clocks */ | 70 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
68 | if (!sdi.skip_init) | ||
69 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | ||
70 | 71 | ||
71 | sdi_basic_init(); | 72 | sdi_basic_init(dssdev); |
72 | 73 | ||
73 | /* 15.5.9.1.2 */ | 74 | /* 15.5.9.1.2 */ |
74 | dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF; | 75 | dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF; |
75 | 76 | ||
76 | dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi, | 77 | dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, |
77 | dssdev->panel.acb); | 78 | dssdev->panel.acbi, dssdev->panel.acb); |
78 | |||
79 | if (!sdi.skip_init) { | ||
80 | r = dss_calc_clock_div(1, t->pixel_clock * 1000, | ||
81 | &dss_cinfo, &dispc_cinfo); | ||
82 | } else { | ||
83 | r = dss_get_clock_div(&dss_cinfo); | ||
84 | r = dispc_get_clock_div(&dispc_cinfo); | ||
85 | } | ||
86 | 79 | ||
80 | r = dss_calc_clock_div(1, t->pixel_clock * 1000, | ||
81 | &dss_cinfo, &dispc_cinfo); | ||
87 | if (r) | 82 | if (r) |
88 | goto err2; | 83 | goto err2; |
89 | 84 | ||
@@ -102,31 +97,27 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
102 | } | 97 | } |
103 | 98 | ||
104 | 99 | ||
105 | dispc_set_lcd_timings(t); | 100 | dispc_set_lcd_timings(dssdev->manager->id, t); |
106 | 101 | ||
107 | r = dss_set_clock_div(&dss_cinfo); | 102 | r = dss_set_clock_div(&dss_cinfo); |
108 | if (r) | 103 | if (r) |
109 | goto err2; | 104 | goto err2; |
110 | 105 | ||
111 | r = dispc_set_clock_div(&dispc_cinfo); | 106 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); |
112 | if (r) | 107 | if (r) |
113 | goto err2; | 108 | goto err2; |
114 | 109 | ||
115 | if (!sdi.skip_init) { | 110 | dss_sdi_init(dssdev->phy.sdi.datapairs); |
116 | dss_sdi_init(dssdev->phy.sdi.datapairs); | 111 | r = dss_sdi_enable(); |
117 | r = dss_sdi_enable(); | 112 | if (r) |
118 | if (r) | 113 | goto err1; |
119 | goto err1; | 114 | mdelay(2); |
120 | mdelay(2); | ||
121 | } | ||
122 | 115 | ||
123 | dssdev->manager->enable(dssdev->manager); | 116 | dssdev->manager->enable(dssdev->manager); |
124 | 117 | ||
125 | sdi.skip_init = 0; | ||
126 | |||
127 | return 0; | 118 | return 0; |
128 | err2: | 119 | err2: |
129 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 120 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
130 | regulator_disable(sdi.vdds_sdi_reg); | 121 | regulator_disable(sdi.vdds_sdi_reg); |
131 | err1: | 122 | err1: |
132 | omap_dss_stop_device(dssdev); | 123 | omap_dss_stop_device(dssdev); |
@@ -141,7 +132,7 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) | |||
141 | 132 | ||
142 | dss_sdi_disable(); | 133 | dss_sdi_disable(); |
143 | 134 | ||
144 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 135 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
145 | 136 | ||
146 | regulator_disable(sdi.vdds_sdi_reg); | 137 | regulator_disable(sdi.vdds_sdi_reg); |
147 | 138 | ||
@@ -153,25 +144,24 @@ int sdi_init_display(struct omap_dss_device *dssdev) | |||
153 | { | 144 | { |
154 | DSSDBG("SDI init\n"); | 145 | DSSDBG("SDI init\n"); |
155 | 146 | ||
147 | if (sdi.vdds_sdi_reg == NULL) { | ||
148 | struct regulator *vdds_sdi; | ||
149 | |||
150 | vdds_sdi = dss_get_vdds_sdi(); | ||
151 | |||
152 | if (IS_ERR(vdds_sdi)) { | ||
153 | DSSERR("can't get VDDS_SDI regulator\n"); | ||
154 | return PTR_ERR(vdds_sdi); | ||
155 | } | ||
156 | |||
157 | sdi.vdds_sdi_reg = vdds_sdi; | ||
158 | } | ||
159 | |||
156 | return 0; | 160 | return 0; |
157 | } | 161 | } |
158 | 162 | ||
159 | int sdi_init(bool skip_init) | 163 | int sdi_init(void) |
160 | { | 164 | { |
161 | /* we store this for first display enable, then clear it */ | ||
162 | sdi.skip_init = skip_init; | ||
163 | |||
164 | sdi.vdds_sdi_reg = dss_get_vdds_sdi(); | ||
165 | if (IS_ERR(sdi.vdds_sdi_reg)) { | ||
166 | DSSERR("can't get VDDS_SDI regulator\n"); | ||
167 | return PTR_ERR(sdi.vdds_sdi_reg); | ||
168 | } | ||
169 | /* | ||
170 | * Enable clocks already here, otherwise there would be a toggle | ||
171 | * of them until sdi_display_enable is called. | ||
172 | */ | ||
173 | if (skip_init) | ||
174 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | ||
175 | return 0; | 165 | return 0; |
176 | } | 166 | } |
177 | 167 | ||
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index eff35050e28a..980f919ed987 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c | |||
@@ -34,13 +34,11 @@ | |||
34 | #include <linux/platform_device.h> | 34 | #include <linux/platform_device.h> |
35 | #include <linux/regulator/consumer.h> | 35 | #include <linux/regulator/consumer.h> |
36 | 36 | ||
37 | #include <plat/display.h> | 37 | #include <video/omapdss.h> |
38 | #include <plat/cpu.h> | 38 | #include <plat/cpu.h> |
39 | 39 | ||
40 | #include "dss.h" | 40 | #include "dss.h" |
41 | 41 | ||
42 | #define VENC_BASE 0x48050C00 | ||
43 | |||
44 | /* Venc registers */ | 42 | /* Venc registers */ |
45 | #define VENC_REV_ID 0x00 | 43 | #define VENC_REV_ID 0x00 |
46 | #define VENC_STATUS 0x04 | 44 | #define VENC_STATUS 0x04 |
@@ -289,6 +287,7 @@ const struct omap_video_timings omap_dss_ntsc_timings = { | |||
289 | EXPORT_SYMBOL(omap_dss_ntsc_timings); | 287 | EXPORT_SYMBOL(omap_dss_ntsc_timings); |
290 | 288 | ||
291 | static struct { | 289 | static struct { |
290 | struct platform_device *pdev; | ||
292 | void __iomem *base; | 291 | void __iomem *base; |
293 | struct mutex venc_lock; | 292 | struct mutex venc_lock; |
294 | u32 wss_data; | 293 | u32 wss_data; |
@@ -374,18 +373,21 @@ static void venc_reset(void) | |||
374 | } | 373 | } |
375 | } | 374 | } |
376 | 375 | ||
376 | #ifdef CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET | ||
377 | /* the magical sleep that makes things work */ | 377 | /* the magical sleep that makes things work */ |
378 | /* XXX more info? What bug this circumvents? */ | ||
378 | msleep(20); | 379 | msleep(20); |
380 | #endif | ||
379 | } | 381 | } |
380 | 382 | ||
381 | static void venc_enable_clocks(int enable) | 383 | static void venc_enable_clocks(int enable) |
382 | { | 384 | { |
383 | if (enable) | 385 | if (enable) |
384 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M | | 386 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK | |
385 | DSS_CLK_96M); | 387 | DSS_CLK_VIDFCK); |
386 | else | 388 | else |
387 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M | | 389 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK | |
388 | DSS_CLK_96M); | 390 | DSS_CLK_VIDFCK); |
389 | } | 391 | } |
390 | 392 | ||
391 | static const struct venc_config *venc_timings_to_config( | 393 | static const struct venc_config *venc_timings_to_config( |
@@ -474,6 +476,12 @@ static int venc_panel_enable(struct omap_dss_device *dssdev) | |||
474 | 476 | ||
475 | mutex_lock(&venc.venc_lock); | 477 | mutex_lock(&venc.venc_lock); |
476 | 478 | ||
479 | r = omap_dss_start_device(dssdev); | ||
480 | if (r) { | ||
481 | DSSERR("failed to start device\n"); | ||
482 | goto err0; | ||
483 | } | ||
484 | |||
477 | if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { | 485 | if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { |
478 | r = -EINVAL; | 486 | r = -EINVAL; |
479 | goto err1; | 487 | goto err1; |
@@ -485,10 +493,11 @@ static int venc_panel_enable(struct omap_dss_device *dssdev) | |||
485 | 493 | ||
486 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | 494 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; |
487 | 495 | ||
488 | /* wait couple of vsyncs until enabling the LCD */ | 496 | mutex_unlock(&venc.venc_lock); |
489 | msleep(50); | 497 | return 0; |
490 | |||
491 | err1: | 498 | err1: |
499 | omap_dss_stop_device(dssdev); | ||
500 | err0: | ||
492 | mutex_unlock(&venc.venc_lock); | 501 | mutex_unlock(&venc.venc_lock); |
493 | 502 | ||
494 | return r; | 503 | return r; |
@@ -511,10 +520,9 @@ static void venc_panel_disable(struct omap_dss_device *dssdev) | |||
511 | 520 | ||
512 | venc_power_off(dssdev); | 521 | venc_power_off(dssdev); |
513 | 522 | ||
514 | /* wait at least 5 vsyncs after disabling the LCD */ | ||
515 | msleep(100); | ||
516 | |||
517 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | 523 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; |
524 | |||
525 | omap_dss_stop_device(dssdev); | ||
518 | end: | 526 | end: |
519 | mutex_unlock(&venc.venc_lock); | 527 | mutex_unlock(&venc.venc_lock); |
520 | } | 528 | } |
@@ -641,50 +649,23 @@ static struct omap_dss_driver venc_driver = { | |||
641 | }; | 649 | }; |
642 | /* driver end */ | 650 | /* driver end */ |
643 | 651 | ||
644 | 652 | int venc_init_display(struct omap_dss_device *dssdev) | |
645 | |||
646 | int venc_init(struct platform_device *pdev) | ||
647 | { | 653 | { |
648 | u8 rev_id; | 654 | DSSDBG("init_display\n"); |
649 | 655 | ||
650 | mutex_init(&venc.venc_lock); | 656 | if (venc.vdda_dac_reg == NULL) { |
657 | struct regulator *vdda_dac; | ||
651 | 658 | ||
652 | venc.wss_data = 0; | 659 | vdda_dac = regulator_get(&venc.pdev->dev, "vdda_dac"); |
653 | 660 | ||
654 | venc.base = ioremap(VENC_BASE, SZ_1K); | 661 | if (IS_ERR(vdda_dac)) { |
655 | if (!venc.base) { | 662 | DSSERR("can't get VDDA_DAC regulator\n"); |
656 | DSSERR("can't ioremap VENC\n"); | 663 | return PTR_ERR(vdda_dac); |
657 | return -ENOMEM; | 664 | } |
658 | } | ||
659 | 665 | ||
660 | venc.vdda_dac_reg = dss_get_vdda_dac(); | 666 | venc.vdda_dac_reg = vdda_dac; |
661 | if (IS_ERR(venc.vdda_dac_reg)) { | ||
662 | iounmap(venc.base); | ||
663 | DSSERR("can't get VDDA_DAC regulator\n"); | ||
664 | return PTR_ERR(venc.vdda_dac_reg); | ||
665 | } | 667 | } |
666 | 668 | ||
667 | venc_enable_clocks(1); | ||
668 | |||
669 | rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); | ||
670 | printk(KERN_INFO "OMAP VENC rev %d\n", rev_id); | ||
671 | |||
672 | venc_enable_clocks(0); | ||
673 | |||
674 | return omap_dss_register_driver(&venc_driver); | ||
675 | } | ||
676 | |||
677 | void venc_exit(void) | ||
678 | { | ||
679 | omap_dss_unregister_driver(&venc_driver); | ||
680 | |||
681 | iounmap(venc.base); | ||
682 | } | ||
683 | |||
684 | int venc_init_display(struct omap_dss_device *dssdev) | ||
685 | { | ||
686 | DSSDBG("init_display\n"); | ||
687 | |||
688 | return 0; | 669 | return 0; |
689 | } | 670 | } |
690 | 671 | ||
@@ -740,3 +721,73 @@ void venc_dump_regs(struct seq_file *s) | |||
740 | 721 | ||
741 | #undef DUMPREG | 722 | #undef DUMPREG |
742 | } | 723 | } |
724 | |||
725 | /* VENC HW IP initialisation */ | ||
726 | static int omap_venchw_probe(struct platform_device *pdev) | ||
727 | { | ||
728 | u8 rev_id; | ||
729 | struct resource *venc_mem; | ||
730 | |||
731 | venc.pdev = pdev; | ||
732 | |||
733 | mutex_init(&venc.venc_lock); | ||
734 | |||
735 | venc.wss_data = 0; | ||
736 | |||
737 | venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0); | ||
738 | if (!venc_mem) { | ||
739 | DSSERR("can't get IORESOURCE_MEM VENC\n"); | ||
740 | return -EINVAL; | ||
741 | } | ||
742 | venc.base = ioremap(venc_mem->start, resource_size(venc_mem)); | ||
743 | if (!venc.base) { | ||
744 | DSSERR("can't ioremap VENC\n"); | ||
745 | return -ENOMEM; | ||
746 | } | ||
747 | |||
748 | venc_enable_clocks(1); | ||
749 | |||
750 | rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); | ||
751 | dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id); | ||
752 | |||
753 | venc_enable_clocks(0); | ||
754 | |||
755 | return omap_dss_register_driver(&venc_driver); | ||
756 | } | ||
757 | |||
758 | static int omap_venchw_remove(struct platform_device *pdev) | ||
759 | { | ||
760 | if (venc.vdda_dac_reg != NULL) { | ||
761 | regulator_put(venc.vdda_dac_reg); | ||
762 | venc.vdda_dac_reg = NULL; | ||
763 | } | ||
764 | omap_dss_unregister_driver(&venc_driver); | ||
765 | |||
766 | iounmap(venc.base); | ||
767 | return 0; | ||
768 | } | ||
769 | |||
770 | static struct platform_driver omap_venchw_driver = { | ||
771 | .probe = omap_venchw_probe, | ||
772 | .remove = omap_venchw_remove, | ||
773 | .driver = { | ||
774 | .name = "omapdss_venc", | ||
775 | .owner = THIS_MODULE, | ||
776 | }, | ||
777 | }; | ||
778 | |||
779 | int venc_init_platform_driver(void) | ||
780 | { | ||
781 | if (cpu_is_omap44xx()) | ||
782 | return 0; | ||
783 | |||
784 | return platform_driver_register(&omap_venchw_driver); | ||
785 | } | ||
786 | |||
787 | void venc_uninit_platform_driver(void) | ||
788 | { | ||
789 | if (cpu_is_omap44xx()) | ||
790 | return; | ||
791 | |||
792 | return platform_driver_unregister(&omap_venchw_driver); | ||
793 | } | ||