aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2/dss
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-12-11 00:55:17 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-11 00:55:17 -0500
commitaa2cf420593b67cc93de7a3f675b2a88eba0505f (patch)
treedfb3c73a8a3987c3b3ba08083f379ebc90942e03 /drivers/video/omap2/dss
parentd71cb81af3817193bc605de061da0499934263a6 (diff)
parent178ff4c9175db447f93b7343954b1d44707c881b (diff)
Merge branch 'for-linus' of git://gitorious.org/linux-omap-dss2/linux
* 'for-linus' of git://gitorious.org/linux-omap-dss2/linux: MAINTAINERS: Add OMAP2/3 DSS and OMAPFB maintainer OMAP: SDP: Enable DSS2 for OMAP3 SDP board OMAP: DSS2: Taal DSI command mode panel driver OMAP: DSS2: Add generic and Sharp panel drivers OMAP: DSS2: omapfb driver OMAP: DSS2: DSI driver OMAP: DSS2: SDI driver OMAP: DSS2: RFBI driver OMAP: DSS2: Video encoder driver OMAP: DSS2: DPI driver OMAP: DSS2: DISPC OMAP: DSS2: Add more core files OMAP: DSS2: Display Subsystem Driver core OMAP: DSS2: Documentation for DSS2 OMAP: Add support for VRFB rotation engine OMAP: Add VRAM manager OMAP: OMAPFB: add omapdss device OMAP: OMAPFB: split omapfb.h OMAP2: Add funcs for writing SMS_ROT_* registers
Diffstat (limited to 'drivers/video/omap2/dss')
-rw-r--r--drivers/video/omap2/dss/Kconfig89
-rw-r--r--drivers/video/omap2/dss/Makefile6
-rw-r--r--drivers/video/omap2/dss/core.c919
-rw-r--r--drivers/video/omap2/dss/dispc.c3091
-rw-r--r--drivers/video/omap2/dss/display.c671
-rw-r--r--drivers/video/omap2/dss/dpi.c399
-rw-r--r--drivers/video/omap2/dss/dsi.c3710
-rw-r--r--drivers/video/omap2/dss/dss.c596
-rw-r--r--drivers/video/omap2/dss/dss.h370
-rw-r--r--drivers/video/omap2/dss/manager.c1487
-rw-r--r--drivers/video/omap2/dss/overlay.c680
-rw-r--r--drivers/video/omap2/dss/rfbi.c1309
-rw-r--r--drivers/video/omap2/dss/sdi.c277
-rw-r--r--drivers/video/omap2/dss/venc.c797
14 files changed, 14401 insertions, 0 deletions
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
new file mode 100644
index 000000000000..71d8dec30635
--- /dev/null
+++ b/drivers/video/omap2/dss/Kconfig
@@ -0,0 +1,89 @@
1menuconfig OMAP2_DSS
2 tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)"
3 depends on ARCH_OMAP2 || ARCH_OMAP3
4 help
5 OMAP2/3 Display Subsystem support.
6
7if OMAP2_DSS
8
9config OMAP2_VRAM_SIZE
10 int "VRAM size (MB)"
11 range 0 32
12 default 0
13 help
14 The amount of SDRAM to reserve at boot time for video RAM use.
15 This VRAM will be used by omapfb and other drivers that need
16 large continuous RAM area for video use.
17
18 You can also set this with "vram=<bytes>" kernel argument, or
19 in the board file.
20
21config OMAP2_DSS_DEBUG_SUPPORT
22 bool "Debug support"
23 default y
24 help
25 This enables debug messages. You need to enable printing
26 with 'debug' module parameter.
27
28config OMAP2_DSS_RFBI
29 bool "RFBI support"
30 default n
31 help
32 MIPI DBI, or RFBI (Remote Framebuffer Interface), support.
33
34config OMAP2_DSS_VENC
35 bool "VENC support"
36 default y
37 help
38 OMAP Video Encoder support.
39
40config OMAP2_DSS_SDI
41 bool "SDI support"
42 depends on ARCH_OMAP3
43 default n
44 help
45 SDI (Serial Display Interface) support.
46
47config OMAP2_DSS_DSI
48 bool "DSI support"
49 depends on ARCH_OMAP3
50 default n
51 help
52 MIPI DSI support.
53
54config OMAP2_DSS_USE_DSI_PLL
55 bool "Use DSI PLL for PCLK (EXPERIMENTAL)"
56 default n
57 depends on OMAP2_DSS_DSI
58 help
59 Use DSI PLL to generate pixel clock. Currently only for DPI output.
60 DSI PLL can be used to generate higher and more precise pixel clocks.
61
62config OMAP2_DSS_FAKE_VSYNC
63 bool "Fake VSYNC irq from manual update displays"
64 default n
65 help
66 If this is selected, DSI will generate a fake DISPC VSYNC interrupt
67 when DSI has sent a frame. This is only needed with DSI or RFBI
68 displays using manual mode, and you want VSYNC to, for example,
69 time animation.
70
71config OMAP2_DSS_MIN_FCK_PER_PCK
72 int "Minimum FCK/PCK ratio (for scaling)"
73 range 0 32
74 default 0
75 help
76 This can be used to adjust the minimum FCK/PCK ratio.
77
78 With this you can make sure that DISPC FCK is at least
79 n x PCK. Video plane scaling requires higher FCK than
80 normally.
81
82 If this is set to 0, there's no extra constraint on the
83 DISPC FCK. However, the FCK will at minimum be
84 2xPCK (if active matrix) or 3xPCK (if passive matrix).
85
86 Max FCK is 173MHz, so this doesn't work if your PCK
87 is very high.
88
89endif
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
new file mode 100644
index 000000000000..980c72c2db98
--- /dev/null
+++ b/drivers/video/omap2/dss/Makefile
@@ -0,0 +1,6 @@
1obj-$(CONFIG_OMAP2_DSS) += omapdss.o
2omapdss-y := core.o dss.o dispc.o dpi.o display.o manager.o overlay.o
3omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
4omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
5omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
6omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
new file mode 100644
index 000000000000..29497a0c9a91
--- /dev/null
+++ b/drivers/video/omap2/dss/core.c
@@ -0,0 +1,919 @@
1/*
2 * linux/drivers/video/omap2/dss/core.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#define DSS_SUBSYS_NAME "CORE"
24
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/clk.h>
28#include <linux/err.h>
29#include <linux/platform_device.h>
30#include <linux/seq_file.h>
31#include <linux/debugfs.h>
32#include <linux/io.h>
33#include <linux/device.h>
34
35#include <plat/display.h>
36#include <plat/clock.h>
37
38#include "dss.h"
39
40static struct {
41 struct platform_device *pdev;
42 int ctx_id;
43
44 struct clk *dss_ick;
45 struct clk *dss1_fck;
46 struct clk *dss2_fck;
47 struct clk *dss_54m_fck;
48 struct clk *dss_96m_fck;
49 unsigned num_clks_enabled;
50} core;
51
52static void dss_clk_enable_all_no_ctx(void);
53static void dss_clk_disable_all_no_ctx(void);
54static void dss_clk_enable_no_ctx(enum dss_clock clks);
55static void dss_clk_disable_no_ctx(enum dss_clock clks);
56
57static char *def_disp_name;
58module_param_named(def_disp, def_disp_name, charp, 0);
59MODULE_PARM_DESC(def_disp_name, "default display name");
60
61#ifdef DEBUG
62unsigned int dss_debug;
63module_param_named(debug, dss_debug, bool, 0644);
64#endif
65
66/* CONTEXT */
67static int dss_get_ctx_id(void)
68{
69 struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
70 int r;
71
72 if (!pdata->get_last_off_on_transaction_id)
73 return 0;
74 r = pdata->get_last_off_on_transaction_id(&core.pdev->dev);
75 if (r < 0) {
76 dev_err(&core.pdev->dev, "getting transaction ID failed, "
77 "will force context restore\n");
78 r = -1;
79 }
80 return r;
81}
82
83int dss_need_ctx_restore(void)
84{
85 int id = dss_get_ctx_id();
86
87 if (id < 0 || id != core.ctx_id) {
88 DSSDBG("ctx id %d -> id %d\n",
89 core.ctx_id, id);
90 core.ctx_id = id;
91 return 1;
92 } else {
93 return 0;
94 }
95}
96
97static void save_all_ctx(void)
98{
99 DSSDBG("save context\n");
100
101 dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
102
103 dss_save_context();
104 dispc_save_context();
105#ifdef CONFIG_OMAP2_DSS_DSI
106 dsi_save_context();
107#endif
108
109 dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
110}
111
112static void restore_all_ctx(void)
113{
114 DSSDBG("restore context\n");
115
116 dss_clk_enable_all_no_ctx();
117
118 dss_restore_context();
119 dispc_restore_context();
120#ifdef CONFIG_OMAP2_DSS_DSI
121 dsi_restore_context();
122#endif
123
124 dss_clk_disable_all_no_ctx();
125}
126
127/* CLOCKS */
128static void core_dump_clocks(struct seq_file *s)
129{
130 int i;
131 struct clk *clocks[5] = {
132 core.dss_ick,
133 core.dss1_fck,
134 core.dss2_fck,
135 core.dss_54m_fck,
136 core.dss_96m_fck
137 };
138
139 seq_printf(s, "- CORE -\n");
140
141 seq_printf(s, "internal clk count\t\t%u\n", core.num_clks_enabled);
142
143 for (i = 0; i < 5; i++) {
144 if (!clocks[i])
145 continue;
146 seq_printf(s, "%-15s\t%lu\t%d\n",
147 clocks[i]->name,
148 clk_get_rate(clocks[i]),
149 clocks[i]->usecount);
150 }
151}
152
153static int dss_get_clock(struct clk **clock, const char *clk_name)
154{
155 struct clk *clk;
156
157 clk = clk_get(&core.pdev->dev, clk_name);
158
159 if (IS_ERR(clk)) {
160 DSSERR("can't get clock %s", clk_name);
161 return PTR_ERR(clk);
162 }
163
164 *clock = clk;
165
166 DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
167
168 return 0;
169}
170
171static int dss_get_clocks(void)
172{
173 int r;
174
175 core.dss_ick = NULL;
176 core.dss1_fck = NULL;
177 core.dss2_fck = NULL;
178 core.dss_54m_fck = NULL;
179 core.dss_96m_fck = NULL;
180
181 r = dss_get_clock(&core.dss_ick, "ick");
182 if (r)
183 goto err;
184
185 r = dss_get_clock(&core.dss1_fck, "dss1_fck");
186 if (r)
187 goto err;
188
189 r = dss_get_clock(&core.dss2_fck, "dss2_fck");
190 if (r)
191 goto err;
192
193 r = dss_get_clock(&core.dss_54m_fck, "tv_fck");
194 if (r)
195 goto err;
196
197 r = dss_get_clock(&core.dss_96m_fck, "video_fck");
198 if (r)
199 goto err;
200
201 return 0;
202
203err:
204 if (core.dss_ick)
205 clk_put(core.dss_ick);
206 if (core.dss1_fck)
207 clk_put(core.dss1_fck);
208 if (core.dss2_fck)
209 clk_put(core.dss2_fck);
210 if (core.dss_54m_fck)
211 clk_put(core.dss_54m_fck);
212 if (core.dss_96m_fck)
213 clk_put(core.dss_96m_fck);
214
215 return r;
216}
217
218static void dss_put_clocks(void)
219{
220 if (core.dss_96m_fck)
221 clk_put(core.dss_96m_fck);
222 clk_put(core.dss_54m_fck);
223 clk_put(core.dss1_fck);
224 clk_put(core.dss2_fck);
225 clk_put(core.dss_ick);
226}
227
228unsigned long dss_clk_get_rate(enum dss_clock clk)
229{
230 switch (clk) {
231 case DSS_CLK_ICK:
232 return clk_get_rate(core.dss_ick);
233 case DSS_CLK_FCK1:
234 return clk_get_rate(core.dss1_fck);
235 case DSS_CLK_FCK2:
236 return clk_get_rate(core.dss2_fck);
237 case DSS_CLK_54M:
238 return clk_get_rate(core.dss_54m_fck);
239 case DSS_CLK_96M:
240 return clk_get_rate(core.dss_96m_fck);
241 }
242
243 BUG();
244 return 0;
245}
246
247static unsigned count_clk_bits(enum dss_clock clks)
248{
249 unsigned num_clks = 0;
250
251 if (clks & DSS_CLK_ICK)
252 ++num_clks;
253 if (clks & DSS_CLK_FCK1)
254 ++num_clks;
255 if (clks & DSS_CLK_FCK2)
256 ++num_clks;
257 if (clks & DSS_CLK_54M)
258 ++num_clks;
259 if (clks & DSS_CLK_96M)
260 ++num_clks;
261
262 return num_clks;
263}
264
265static void dss_clk_enable_no_ctx(enum dss_clock clks)
266{
267 unsigned num_clks = count_clk_bits(clks);
268
269 if (clks & DSS_CLK_ICK)
270 clk_enable(core.dss_ick);
271 if (clks & DSS_CLK_FCK1)
272 clk_enable(core.dss1_fck);
273 if (clks & DSS_CLK_FCK2)
274 clk_enable(core.dss2_fck);
275 if (clks & DSS_CLK_54M)
276 clk_enable(core.dss_54m_fck);
277 if (clks & DSS_CLK_96M)
278 clk_enable(core.dss_96m_fck);
279
280 core.num_clks_enabled += num_clks;
281}
282
283void dss_clk_enable(enum dss_clock clks)
284{
285 dss_clk_enable_no_ctx(clks);
286
287 if (cpu_is_omap34xx() && dss_need_ctx_restore())
288 restore_all_ctx();
289}
290
291static void dss_clk_disable_no_ctx(enum dss_clock clks)
292{
293 unsigned num_clks = count_clk_bits(clks);
294
295 if (clks & DSS_CLK_ICK)
296 clk_disable(core.dss_ick);
297 if (clks & DSS_CLK_FCK1)
298 clk_disable(core.dss1_fck);
299 if (clks & DSS_CLK_FCK2)
300 clk_disable(core.dss2_fck);
301 if (clks & DSS_CLK_54M)
302 clk_disable(core.dss_54m_fck);
303 if (clks & DSS_CLK_96M)
304 clk_disable(core.dss_96m_fck);
305
306 core.num_clks_enabled -= num_clks;
307}
308
309void dss_clk_disable(enum dss_clock clks)
310{
311 if (cpu_is_omap34xx()) {
312 unsigned num_clks = count_clk_bits(clks);
313
314 BUG_ON(core.num_clks_enabled < num_clks);
315
316 if (core.num_clks_enabled == num_clks)
317 save_all_ctx();
318 }
319
320 dss_clk_disable_no_ctx(clks);
321}
322
323static void dss_clk_enable_all_no_ctx(void)
324{
325 enum dss_clock clks;
326
327 clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
328 if (cpu_is_omap34xx())
329 clks |= DSS_CLK_96M;
330 dss_clk_enable_no_ctx(clks);
331}
332
333static void dss_clk_disable_all_no_ctx(void)
334{
335 enum dss_clock clks;
336
337 clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
338 if (cpu_is_omap34xx())
339 clks |= DSS_CLK_96M;
340 dss_clk_disable_no_ctx(clks);
341}
342
343static void dss_clk_disable_all(void)
344{
345 enum dss_clock clks;
346
347 clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
348 if (cpu_is_omap34xx())
349 clks |= DSS_CLK_96M;
350 dss_clk_disable(clks);
351}
352
353/* DEBUGFS */
354#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
355static void dss_debug_dump_clocks(struct seq_file *s)
356{
357 core_dump_clocks(s);
358 dss_dump_clocks(s);
359 dispc_dump_clocks(s);
360#ifdef CONFIG_OMAP2_DSS_DSI
361 dsi_dump_clocks(s);
362#endif
363}
364
365static int dss_debug_show(struct seq_file *s, void *unused)
366{
367 void (*func)(struct seq_file *) = s->private;
368 func(s);
369 return 0;
370}
371
372static int dss_debug_open(struct inode *inode, struct file *file)
373{
374 return single_open(file, dss_debug_show, inode->i_private);
375}
376
377static const struct file_operations dss_debug_fops = {
378 .open = dss_debug_open,
379 .read = seq_read,
380 .llseek = seq_lseek,
381 .release = single_release,
382};
383
384static struct dentry *dss_debugfs_dir;
385
386static int dss_initialize_debugfs(void)
387{
388 dss_debugfs_dir = debugfs_create_dir("omapdss", NULL);
389 if (IS_ERR(dss_debugfs_dir)) {
390 int err = PTR_ERR(dss_debugfs_dir);
391 dss_debugfs_dir = NULL;
392 return err;
393 }
394
395 debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
396 &dss_debug_dump_clocks, &dss_debug_fops);
397
398 debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir,
399 &dss_dump_regs, &dss_debug_fops);
400 debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir,
401 &dispc_dump_regs, &dss_debug_fops);
402#ifdef CONFIG_OMAP2_DSS_RFBI
403 debugfs_create_file("rfbi", S_IRUGO, dss_debugfs_dir,
404 &rfbi_dump_regs, &dss_debug_fops);
405#endif
406#ifdef CONFIG_OMAP2_DSS_DSI
407 debugfs_create_file("dsi", S_IRUGO, dss_debugfs_dir,
408 &dsi_dump_regs, &dss_debug_fops);
409#endif
410#ifdef CONFIG_OMAP2_DSS_VENC
411 debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir,
412 &venc_dump_regs, &dss_debug_fops);
413#endif
414 return 0;
415}
416
417static void dss_uninitialize_debugfs(void)
418{
419 if (dss_debugfs_dir)
420 debugfs_remove_recursive(dss_debugfs_dir);
421}
422#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
423
424/* PLATFORM DEVICE */
425static int omap_dss_probe(struct platform_device *pdev)
426{
427 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
428 int skip_init = 0;
429 int r;
430 int i;
431
432 core.pdev = pdev;
433
434 dss_init_overlay_managers(pdev);
435 dss_init_overlays(pdev);
436
437 r = dss_get_clocks();
438 if (r)
439 goto fail0;
440
441 dss_clk_enable_all_no_ctx();
442
443 core.ctx_id = dss_get_ctx_id();
444 DSSDBG("initial ctx id %u\n", core.ctx_id);
445
446#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
447 /* DISPC_CONTROL */
448 if (omap_readl(0x48050440) & 1) /* LCD enabled? */
449 skip_init = 1;
450#endif
451
452 r = dss_init(skip_init);
453 if (r) {
454 DSSERR("Failed to initialize DSS\n");
455 goto fail0;
456 }
457
458#ifdef CONFIG_OMAP2_DSS_RFBI
459 r = rfbi_init();
460 if (r) {
461 DSSERR("Failed to initialize rfbi\n");
462 goto fail0;
463 }
464#endif
465
466 r = dpi_init();
467 if (r) {
468 DSSERR("Failed to initialize dpi\n");
469 goto fail0;
470 }
471
472 r = dispc_init();
473 if (r) {
474 DSSERR("Failed to initialize dispc\n");
475 goto fail0;
476 }
477#ifdef CONFIG_OMAP2_DSS_VENC
478 r = venc_init(pdev);
479 if (r) {
480 DSSERR("Failed to initialize venc\n");
481 goto fail0;
482 }
483#endif
484 if (cpu_is_omap34xx()) {
485#ifdef CONFIG_OMAP2_DSS_SDI
486 r = sdi_init(skip_init);
487 if (r) {
488 DSSERR("Failed to initialize SDI\n");
489 goto fail0;
490 }
491#endif
492#ifdef CONFIG_OMAP2_DSS_DSI
493 r = dsi_init(pdev);
494 if (r) {
495 DSSERR("Failed to initialize DSI\n");
496 goto fail0;
497 }
498#endif
499 }
500
501#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
502 r = dss_initialize_debugfs();
503 if (r)
504 goto fail0;
505#endif
506
507 for (i = 0; i < pdata->num_devices; ++i) {
508 struct omap_dss_device *dssdev = pdata->devices[i];
509
510 r = omap_dss_register_device(dssdev);
511 if (r)
512 DSSERR("device reg failed %d\n", i);
513
514 if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0)
515 pdata->default_device = dssdev;
516 }
517
518 dss_clk_disable_all();
519
520 return 0;
521
522 /* XXX fail correctly */
523fail0:
524 return r;
525}
526
527static int omap_dss_remove(struct platform_device *pdev)
528{
529 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
530 int i;
531 int c;
532
533#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
534 dss_uninitialize_debugfs();
535#endif
536
537#ifdef CONFIG_OMAP2_DSS_VENC
538 venc_exit();
539#endif
540 dispc_exit();
541 dpi_exit();
542#ifdef CONFIG_OMAP2_DSS_RFBI
543 rfbi_exit();
544#endif
545 if (cpu_is_omap34xx()) {
546#ifdef CONFIG_OMAP2_DSS_DSI
547 dsi_exit();
548#endif
549#ifdef CONFIG_OMAP2_DSS_SDI
550 sdi_exit();
551#endif
552 }
553
554 dss_exit();
555
556 /* these should be removed at some point */
557 c = core.dss_ick->usecount;
558 if (c > 0) {
559 DSSERR("warning: dss_ick usecount %d, disabling\n", c);
560 while (c-- > 0)
561 clk_disable(core.dss_ick);
562 }
563
564 c = core.dss1_fck->usecount;
565 if (c > 0) {
566 DSSERR("warning: dss1_fck usecount %d, disabling\n", c);
567 while (c-- > 0)
568 clk_disable(core.dss1_fck);
569 }
570
571 c = core.dss2_fck->usecount;
572 if (c > 0) {
573 DSSERR("warning: dss2_fck usecount %d, disabling\n", c);
574 while (c-- > 0)
575 clk_disable(core.dss2_fck);
576 }
577
578 c = core.dss_54m_fck->usecount;
579 if (c > 0) {
580 DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c);
581 while (c-- > 0)
582 clk_disable(core.dss_54m_fck);
583 }
584
585 if (core.dss_96m_fck) {
586 c = core.dss_96m_fck->usecount;
587 if (c > 0) {
588 DSSERR("warning: dss_96m_fck usecount %d, disabling\n",
589 c);
590 while (c-- > 0)
591 clk_disable(core.dss_96m_fck);
592 }
593 }
594
595 dss_put_clocks();
596
597 dss_uninit_overlays(pdev);
598 dss_uninit_overlay_managers(pdev);
599
600 for (i = 0; i < pdata->num_devices; ++i)
601 omap_dss_unregister_device(pdata->devices[i]);
602
603 return 0;
604}
605
606static void omap_dss_shutdown(struct platform_device *pdev)
607{
608 DSSDBG("shutdown\n");
609 dss_disable_all_devices();
610}
611
612static int omap_dss_suspend(struct platform_device *pdev, pm_message_t state)
613{
614 DSSDBG("suspend %d\n", state.event);
615
616 return dss_suspend_all_devices();
617}
618
619static int omap_dss_resume(struct platform_device *pdev)
620{
621 DSSDBG("resume\n");
622
623 return dss_resume_all_devices();
624}
625
626static struct platform_driver omap_dss_driver = {
627 .probe = omap_dss_probe,
628 .remove = omap_dss_remove,
629 .shutdown = omap_dss_shutdown,
630 .suspend = omap_dss_suspend,
631 .resume = omap_dss_resume,
632 .driver = {
633 .name = "omapdss",
634 .owner = THIS_MODULE,
635 },
636};
637
638/* BUS */
639static int dss_bus_match(struct device *dev, struct device_driver *driver)
640{
641 struct omap_dss_device *dssdev = to_dss_device(dev);
642
643 DSSDBG("bus_match. dev %s/%s, drv %s\n",
644 dev_name(dev), dssdev->driver_name, driver->name);
645
646 return strcmp(dssdev->driver_name, driver->name) == 0;
647}
648
649static ssize_t device_name_show(struct device *dev,
650 struct device_attribute *attr, char *buf)
651{
652 struct omap_dss_device *dssdev = to_dss_device(dev);
653 return snprintf(buf, PAGE_SIZE, "%s\n",
654 dssdev->name ?
655 dssdev->name : "");
656}
657
658static struct device_attribute default_dev_attrs[] = {
659 __ATTR(name, S_IRUGO, device_name_show, NULL),
660 __ATTR_NULL,
661};
662
663static ssize_t driver_name_show(struct device_driver *drv, char *buf)
664{
665 struct omap_dss_driver *dssdrv = to_dss_driver(drv);
666 return snprintf(buf, PAGE_SIZE, "%s\n",
667 dssdrv->driver.name ?
668 dssdrv->driver.name : "");
669}
670static struct driver_attribute default_drv_attrs[] = {
671 __ATTR(name, S_IRUGO, driver_name_show, NULL),
672 __ATTR_NULL,
673};
674
675static struct bus_type dss_bus_type = {
676 .name = "omapdss",
677 .match = dss_bus_match,
678 .dev_attrs = default_dev_attrs,
679 .drv_attrs = default_drv_attrs,
680};
681
682static void dss_bus_release(struct device *dev)
683{
684 DSSDBG("bus_release\n");
685}
686
687static struct device dss_bus = {
688 .release = dss_bus_release,
689};
690
691struct bus_type *dss_get_bus(void)
692{
693 return &dss_bus_type;
694}
695
696/* DRIVER */
697static int dss_driver_probe(struct device *dev)
698{
699 int r;
700 struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
701 struct omap_dss_device *dssdev = to_dss_device(dev);
702 struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
703 bool force;
704
705 DSSDBG("driver_probe: dev %s/%s, drv %s\n",
706 dev_name(dev), dssdev->driver_name,
707 dssdrv->driver.name);
708
709 dss_init_device(core.pdev, dssdev);
710
711 /* skip this if the device is behind a ctrl */
712 if (!dssdev->panel.ctrl) {
713 force = pdata->default_device == dssdev;
714 dss_recheck_connections(dssdev, force);
715 }
716
717 r = dssdrv->probe(dssdev);
718
719 if (r) {
720 DSSERR("driver probe failed: %d\n", r);
721 return r;
722 }
723
724 DSSDBG("probe done for device %s\n", dev_name(dev));
725
726 dssdev->driver = dssdrv;
727
728 return 0;
729}
730
731static int dss_driver_remove(struct device *dev)
732{
733 struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
734 struct omap_dss_device *dssdev = to_dss_device(dev);
735
736 DSSDBG("driver_remove: dev %s/%s\n", dev_name(dev),
737 dssdev->driver_name);
738
739 dssdrv->remove(dssdev);
740
741 dss_uninit_device(core.pdev, dssdev);
742
743 dssdev->driver = NULL;
744
745 return 0;
746}
747
748int omap_dss_register_driver(struct omap_dss_driver *dssdriver)
749{
750 dssdriver->driver.bus = &dss_bus_type;
751 dssdriver->driver.probe = dss_driver_probe;
752 dssdriver->driver.remove = dss_driver_remove;
753 return driver_register(&dssdriver->driver);
754}
755EXPORT_SYMBOL(omap_dss_register_driver);
756
757void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver)
758{
759 driver_unregister(&dssdriver->driver);
760}
761EXPORT_SYMBOL(omap_dss_unregister_driver);
762
763/* DEVICE */
764static void reset_device(struct device *dev, int check)
765{
766 u8 *dev_p = (u8 *)dev;
767 u8 *dev_end = dev_p + sizeof(*dev);
768 void *saved_pdata;
769
770 saved_pdata = dev->platform_data;
771 if (check) {
772 /*
773 * Check if there is any other setting than platform_data
774 * in struct device; warn that these will be reset by our
775 * init.
776 */
777 dev->platform_data = NULL;
778 while (dev_p < dev_end) {
779 if (*dev_p) {
780 WARN("%s: struct device fields will be "
781 "discarded\n",
782 __func__);
783 break;
784 }
785 dev_p++;
786 }
787 }
788 memset(dev, 0, sizeof(*dev));
789 dev->platform_data = saved_pdata;
790}
791
792
793static void omap_dss_dev_release(struct device *dev)
794{
795 reset_device(dev, 0);
796}
797
798int omap_dss_register_device(struct omap_dss_device *dssdev)
799{
800 static int dev_num;
801 static int panel_num;
802 int r;
803
804 WARN_ON(!dssdev->driver_name);
805
806 reset_device(&dssdev->dev, 1);
807 dssdev->dev.bus = &dss_bus_type;
808 dssdev->dev.parent = &dss_bus;
809 dssdev->dev.release = omap_dss_dev_release;
810 dev_set_name(&dssdev->dev, "display%d", dev_num++);
811 r = device_register(&dssdev->dev);
812 if (r)
813 return r;
814
815 if (dssdev->ctrl.panel) {
816 struct omap_dss_device *panel = dssdev->ctrl.panel;
817
818 panel->panel.ctrl = dssdev;
819
820 reset_device(&panel->dev, 1);
821 panel->dev.bus = &dss_bus_type;
822 panel->dev.parent = &dssdev->dev;
823 panel->dev.release = omap_dss_dev_release;
824 dev_set_name(&panel->dev, "panel%d", panel_num++);
825 r = device_register(&panel->dev);
826 if (r)
827 return r;
828 }
829
830 return 0;
831}
832
833void omap_dss_unregister_device(struct omap_dss_device *dssdev)
834{
835 device_unregister(&dssdev->dev);
836
837 if (dssdev->ctrl.panel) {
838 struct omap_dss_device *panel = dssdev->ctrl.panel;
839 device_unregister(&panel->dev);
840 }
841}
842
843/* BUS */
844static int omap_dss_bus_register(void)
845{
846 int r;
847
848 r = bus_register(&dss_bus_type);
849 if (r) {
850 DSSERR("bus register failed\n");
851 return r;
852 }
853
854 dev_set_name(&dss_bus, "omapdss");
855 r = device_register(&dss_bus);
856 if (r) {
857 DSSERR("bus driver register failed\n");
858 bus_unregister(&dss_bus_type);
859 return r;
860 }
861
862 return 0;
863}
864
865/* INIT */
866
867#ifdef CONFIG_OMAP2_DSS_MODULE
868static void omap_dss_bus_unregister(void)
869{
870 device_unregister(&dss_bus);
871
872 bus_unregister(&dss_bus_type);
873}
874
875static int __init omap_dss_init(void)
876{
877 int r;
878
879 r = omap_dss_bus_register();
880 if (r)
881 return r;
882
883 r = platform_driver_register(&omap_dss_driver);
884 if (r) {
885 omap_dss_bus_unregister();
886 return r;
887 }
888
889 return 0;
890}
891
892static void __exit omap_dss_exit(void)
893{
894 platform_driver_unregister(&omap_dss_driver);
895
896 omap_dss_bus_unregister();
897}
898
899module_init(omap_dss_init);
900module_exit(omap_dss_exit);
901#else
902static int __init omap_dss_init(void)
903{
904 return omap_dss_bus_register();
905}
906
907static int __init omap_dss_init2(void)
908{
909 return platform_driver_register(&omap_dss_driver);
910}
911
912core_initcall(omap_dss_init);
913device_initcall(omap_dss_init2);
914#endif
915
916MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
917MODULE_DESCRIPTION("OMAP2/3 Display Subsystem");
918MODULE_LICENSE("GPL v2");
919
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
new file mode 100644
index 000000000000..6dabf4b2f005
--- /dev/null
+++ b/drivers/video/omap2/dss/dispc.c
@@ -0,0 +1,3091 @@
1/*
2 * linux/drivers/video/omap2/dss/dispc.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#define DSS_SUBSYS_NAME "DISPC"
24
25#include <linux/kernel.h>
26#include <linux/dma-mapping.h>
27#include <linux/vmalloc.h>
28#include <linux/clk.h>
29#include <linux/io.h>
30#include <linux/jiffies.h>
31#include <linux/seq_file.h>
32#include <linux/delay.h>
33#include <linux/workqueue.h>
34
35#include <plat/sram.h>
36#include <plat/clock.h>
37
38#include <plat/display.h>
39
40#include "dss.h"
41
42/* DISPC */
43#define DISPC_BASE 0x48050400
44
45#define DISPC_SZ_REGS SZ_1K
46
47struct dispc_reg { u16 idx; };
48
49#define DISPC_REG(idx) ((const struct dispc_reg) { idx })
50
51/* DISPC common */
52#define DISPC_REVISION DISPC_REG(0x0000)
53#define DISPC_SYSCONFIG DISPC_REG(0x0010)
54#define DISPC_SYSSTATUS DISPC_REG(0x0014)
55#define DISPC_IRQSTATUS DISPC_REG(0x0018)
56#define DISPC_IRQENABLE DISPC_REG(0x001C)
57#define DISPC_CONTROL DISPC_REG(0x0040)
58#define DISPC_CONFIG DISPC_REG(0x0044)
59#define DISPC_CAPABLE DISPC_REG(0x0048)
60#define DISPC_DEFAULT_COLOR0 DISPC_REG(0x004C)
61#define DISPC_DEFAULT_COLOR1 DISPC_REG(0x0050)
62#define DISPC_TRANS_COLOR0 DISPC_REG(0x0054)
63#define DISPC_TRANS_COLOR1 DISPC_REG(0x0058)
64#define DISPC_LINE_STATUS DISPC_REG(0x005C)
65#define DISPC_LINE_NUMBER DISPC_REG(0x0060)
66#define DISPC_TIMING_H DISPC_REG(0x0064)
67#define DISPC_TIMING_V DISPC_REG(0x0068)
68#define DISPC_POL_FREQ DISPC_REG(0x006C)
69#define DISPC_DIVISOR DISPC_REG(0x0070)
70#define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074)
71#define DISPC_SIZE_DIG DISPC_REG(0x0078)
72#define DISPC_SIZE_LCD DISPC_REG(0x007C)
73
74/* DISPC GFX plane */
75#define DISPC_GFX_BA0 DISPC_REG(0x0080)
76#define DISPC_GFX_BA1 DISPC_REG(0x0084)
77#define DISPC_GFX_POSITION DISPC_REG(0x0088)
78#define DISPC_GFX_SIZE DISPC_REG(0x008C)
79#define DISPC_GFX_ATTRIBUTES DISPC_REG(0x00A0)
80#define DISPC_GFX_FIFO_THRESHOLD DISPC_REG(0x00A4)
81#define DISPC_GFX_FIFO_SIZE_STATUS DISPC_REG(0x00A8)
82#define DISPC_GFX_ROW_INC DISPC_REG(0x00AC)
83#define DISPC_GFX_PIXEL_INC DISPC_REG(0x00B0)
84#define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4)
85#define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8)
86
87#define DISPC_DATA_CYCLE1 DISPC_REG(0x01D4)
88#define DISPC_DATA_CYCLE2 DISPC_REG(0x01D8)
89#define DISPC_DATA_CYCLE3 DISPC_REG(0x01DC)
90
91#define DISPC_CPR_COEF_R DISPC_REG(0x0220)
92#define DISPC_CPR_COEF_G DISPC_REG(0x0224)
93#define DISPC_CPR_COEF_B DISPC_REG(0x0228)
94
95#define DISPC_GFX_PRELOAD DISPC_REG(0x022C)
96
97/* DISPC Video plane, n = 0 for VID1 and n = 1 for VID2 */
98#define DISPC_VID_REG(n, idx) DISPC_REG(0x00BC + (n)*0x90 + idx)
99
100#define DISPC_VID_BA0(n) DISPC_VID_REG(n, 0x0000)
101#define DISPC_VID_BA1(n) DISPC_VID_REG(n, 0x0004)
102#define DISPC_VID_POSITION(n) DISPC_VID_REG(n, 0x0008)
103#define DISPC_VID_SIZE(n) DISPC_VID_REG(n, 0x000C)
104#define DISPC_VID_ATTRIBUTES(n) DISPC_VID_REG(n, 0x0010)
105#define DISPC_VID_FIFO_THRESHOLD(n) DISPC_VID_REG(n, 0x0014)
106#define DISPC_VID_FIFO_SIZE_STATUS(n) DISPC_VID_REG(n, 0x0018)
107#define DISPC_VID_ROW_INC(n) DISPC_VID_REG(n, 0x001C)
108#define DISPC_VID_PIXEL_INC(n) DISPC_VID_REG(n, 0x0020)
109#define DISPC_VID_FIR(n) DISPC_VID_REG(n, 0x0024)
110#define DISPC_VID_PICTURE_SIZE(n) DISPC_VID_REG(n, 0x0028)
111#define DISPC_VID_ACCU0(n) DISPC_VID_REG(n, 0x002C)
112#define DISPC_VID_ACCU1(n) DISPC_VID_REG(n, 0x0030)
113
114/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
115#define DISPC_VID_FIR_COEF_H(n, i) DISPC_REG(0x00F0 + (n)*0x90 + (i)*0x8)
116/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
117#define DISPC_VID_FIR_COEF_HV(n, i) DISPC_REG(0x00F4 + (n)*0x90 + (i)*0x8)
118/* coef index i = {0, 1, 2, 3, 4} */
119#define DISPC_VID_CONV_COEF(n, i) DISPC_REG(0x0130 + (n)*0x90 + (i)*0x4)
120/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
121#define DISPC_VID_FIR_COEF_V(n, i) DISPC_REG(0x01E0 + (n)*0x20 + (i)*0x4)
122
123#define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04)
124
125
126#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
127 DISPC_IRQ_OCP_ERR | \
128 DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
129 DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
130 DISPC_IRQ_SYNC_LOST | \
131 DISPC_IRQ_SYNC_LOST_DIGIT)
132
133#define DISPC_MAX_NR_ISRS 8
134
135struct omap_dispc_isr_data {
136 omap_dispc_isr_t isr;
137 void *arg;
138 u32 mask;
139};
140
141#define REG_GET(idx, start, end) \
142 FLD_GET(dispc_read_reg(idx), start, end)
143
144#define REG_FLD_MOD(idx, val, start, end) \
145 dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
146
147static const struct dispc_reg dispc_reg_att[] = { DISPC_GFX_ATTRIBUTES,
148 DISPC_VID_ATTRIBUTES(0),
149 DISPC_VID_ATTRIBUTES(1) };
150
151static struct {
152 void __iomem *base;
153
154 u32 fifo_size[3];
155
156 spinlock_t irq_lock;
157 u32 irq_error_mask;
158 struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
159 u32 error_irqs;
160 struct work_struct error_work;
161
162 u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
163} dispc;
164
165static void _omap_dispc_set_irqs(void);
166
167static inline void dispc_write_reg(const struct dispc_reg idx, u32 val)
168{
169 __raw_writel(val, dispc.base + idx.idx);
170}
171
172static inline u32 dispc_read_reg(const struct dispc_reg idx)
173{
174 return __raw_readl(dispc.base + idx.idx);
175}
176
177#define SR(reg) \
178 dispc.ctx[(DISPC_##reg).idx / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
179#define RR(reg) \
180 dispc_write_reg(DISPC_##reg, dispc.ctx[(DISPC_##reg).idx / sizeof(u32)])
181
182void dispc_save_context(void)
183{
184 if (cpu_is_omap24xx())
185 return;
186
187 SR(SYSCONFIG);
188 SR(IRQENABLE);
189 SR(CONTROL);
190 SR(CONFIG);
191 SR(DEFAULT_COLOR0);
192 SR(DEFAULT_COLOR1);
193 SR(TRANS_COLOR0);
194 SR(TRANS_COLOR1);
195 SR(LINE_NUMBER);
196 SR(TIMING_H);
197 SR(TIMING_V);
198 SR(POL_FREQ);
199 SR(DIVISOR);
200 SR(GLOBAL_ALPHA);
201 SR(SIZE_DIG);
202 SR(SIZE_LCD);
203
204 SR(GFX_BA0);
205 SR(GFX_BA1);
206 SR(GFX_POSITION);
207 SR(GFX_SIZE);
208 SR(GFX_ATTRIBUTES);
209 SR(GFX_FIFO_THRESHOLD);
210 SR(GFX_ROW_INC);
211 SR(GFX_PIXEL_INC);
212 SR(GFX_WINDOW_SKIP);
213 SR(GFX_TABLE_BA);
214
215 SR(DATA_CYCLE1);
216 SR(DATA_CYCLE2);
217 SR(DATA_CYCLE3);
218
219 SR(CPR_COEF_R);
220 SR(CPR_COEF_G);
221 SR(CPR_COEF_B);
222
223 SR(GFX_PRELOAD);
224
225 /* VID1 */
226 SR(VID_BA0(0));
227 SR(VID_BA1(0));
228 SR(VID_POSITION(0));
229 SR(VID_SIZE(0));
230 SR(VID_ATTRIBUTES(0));
231 SR(VID_FIFO_THRESHOLD(0));
232 SR(VID_ROW_INC(0));
233 SR(VID_PIXEL_INC(0));
234 SR(VID_FIR(0));
235 SR(VID_PICTURE_SIZE(0));
236 SR(VID_ACCU0(0));
237 SR(VID_ACCU1(0));
238
239 SR(VID_FIR_COEF_H(0, 0));
240 SR(VID_FIR_COEF_H(0, 1));
241 SR(VID_FIR_COEF_H(0, 2));
242 SR(VID_FIR_COEF_H(0, 3));
243 SR(VID_FIR_COEF_H(0, 4));
244 SR(VID_FIR_COEF_H(0, 5));
245 SR(VID_FIR_COEF_H(0, 6));
246 SR(VID_FIR_COEF_H(0, 7));
247
248 SR(VID_FIR_COEF_HV(0, 0));
249 SR(VID_FIR_COEF_HV(0, 1));
250 SR(VID_FIR_COEF_HV(0, 2));
251 SR(VID_FIR_COEF_HV(0, 3));
252 SR(VID_FIR_COEF_HV(0, 4));
253 SR(VID_FIR_COEF_HV(0, 5));
254 SR(VID_FIR_COEF_HV(0, 6));
255 SR(VID_FIR_COEF_HV(0, 7));
256
257 SR(VID_CONV_COEF(0, 0));
258 SR(VID_CONV_COEF(0, 1));
259 SR(VID_CONV_COEF(0, 2));
260 SR(VID_CONV_COEF(0, 3));
261 SR(VID_CONV_COEF(0, 4));
262
263 SR(VID_FIR_COEF_V(0, 0));
264 SR(VID_FIR_COEF_V(0, 1));
265 SR(VID_FIR_COEF_V(0, 2));
266 SR(VID_FIR_COEF_V(0, 3));
267 SR(VID_FIR_COEF_V(0, 4));
268 SR(VID_FIR_COEF_V(0, 5));
269 SR(VID_FIR_COEF_V(0, 6));
270 SR(VID_FIR_COEF_V(0, 7));
271
272 SR(VID_PRELOAD(0));
273
274 /* VID2 */
275 SR(VID_BA0(1));
276 SR(VID_BA1(1));
277 SR(VID_POSITION(1));
278 SR(VID_SIZE(1));
279 SR(VID_ATTRIBUTES(1));
280 SR(VID_FIFO_THRESHOLD(1));
281 SR(VID_ROW_INC(1));
282 SR(VID_PIXEL_INC(1));
283 SR(VID_FIR(1));
284 SR(VID_PICTURE_SIZE(1));
285 SR(VID_ACCU0(1));
286 SR(VID_ACCU1(1));
287
288 SR(VID_FIR_COEF_H(1, 0));
289 SR(VID_FIR_COEF_H(1, 1));
290 SR(VID_FIR_COEF_H(1, 2));
291 SR(VID_FIR_COEF_H(1, 3));
292 SR(VID_FIR_COEF_H(1, 4));
293 SR(VID_FIR_COEF_H(1, 5));
294 SR(VID_FIR_COEF_H(1, 6));
295 SR(VID_FIR_COEF_H(1, 7));
296
297 SR(VID_FIR_COEF_HV(1, 0));
298 SR(VID_FIR_COEF_HV(1, 1));
299 SR(VID_FIR_COEF_HV(1, 2));
300 SR(VID_FIR_COEF_HV(1, 3));
301 SR(VID_FIR_COEF_HV(1, 4));
302 SR(VID_FIR_COEF_HV(1, 5));
303 SR(VID_FIR_COEF_HV(1, 6));
304 SR(VID_FIR_COEF_HV(1, 7));
305
306 SR(VID_CONV_COEF(1, 0));
307 SR(VID_CONV_COEF(1, 1));
308 SR(VID_CONV_COEF(1, 2));
309 SR(VID_CONV_COEF(1, 3));
310 SR(VID_CONV_COEF(1, 4));
311
312 SR(VID_FIR_COEF_V(1, 0));
313 SR(VID_FIR_COEF_V(1, 1));
314 SR(VID_FIR_COEF_V(1, 2));
315 SR(VID_FIR_COEF_V(1, 3));
316 SR(VID_FIR_COEF_V(1, 4));
317 SR(VID_FIR_COEF_V(1, 5));
318 SR(VID_FIR_COEF_V(1, 6));
319 SR(VID_FIR_COEF_V(1, 7));
320
321 SR(VID_PRELOAD(1));
322}
323
324void dispc_restore_context(void)
325{
326 RR(SYSCONFIG);
327 RR(IRQENABLE);
328 /*RR(CONTROL);*/
329 RR(CONFIG);
330 RR(DEFAULT_COLOR0);
331 RR(DEFAULT_COLOR1);
332 RR(TRANS_COLOR0);
333 RR(TRANS_COLOR1);
334 RR(LINE_NUMBER);
335 RR(TIMING_H);
336 RR(TIMING_V);
337 RR(POL_FREQ);
338 RR(DIVISOR);
339 RR(GLOBAL_ALPHA);
340 RR(SIZE_DIG);
341 RR(SIZE_LCD);
342
343 RR(GFX_BA0);
344 RR(GFX_BA1);
345 RR(GFX_POSITION);
346 RR(GFX_SIZE);
347 RR(GFX_ATTRIBUTES);
348 RR(GFX_FIFO_THRESHOLD);
349 RR(GFX_ROW_INC);
350 RR(GFX_PIXEL_INC);
351 RR(GFX_WINDOW_SKIP);
352 RR(GFX_TABLE_BA);
353
354 RR(DATA_CYCLE1);
355 RR(DATA_CYCLE2);
356 RR(DATA_CYCLE3);
357
358 RR(CPR_COEF_R);
359 RR(CPR_COEF_G);
360 RR(CPR_COEF_B);
361
362 RR(GFX_PRELOAD);
363
364 /* VID1 */
365 RR(VID_BA0(0));
366 RR(VID_BA1(0));
367 RR(VID_POSITION(0));
368 RR(VID_SIZE(0));
369 RR(VID_ATTRIBUTES(0));
370 RR(VID_FIFO_THRESHOLD(0));
371 RR(VID_ROW_INC(0));
372 RR(VID_PIXEL_INC(0));
373 RR(VID_FIR(0));
374 RR(VID_PICTURE_SIZE(0));
375 RR(VID_ACCU0(0));
376 RR(VID_ACCU1(0));
377
378 RR(VID_FIR_COEF_H(0, 0));
379 RR(VID_FIR_COEF_H(0, 1));
380 RR(VID_FIR_COEF_H(0, 2));
381 RR(VID_FIR_COEF_H(0, 3));
382 RR(VID_FIR_COEF_H(0, 4));
383 RR(VID_FIR_COEF_H(0, 5));
384 RR(VID_FIR_COEF_H(0, 6));
385 RR(VID_FIR_COEF_H(0, 7));
386
387 RR(VID_FIR_COEF_HV(0, 0));
388 RR(VID_FIR_COEF_HV(0, 1));
389 RR(VID_FIR_COEF_HV(0, 2));
390 RR(VID_FIR_COEF_HV(0, 3));
391 RR(VID_FIR_COEF_HV(0, 4));
392 RR(VID_FIR_COEF_HV(0, 5));
393 RR(VID_FIR_COEF_HV(0, 6));
394 RR(VID_FIR_COEF_HV(0, 7));
395
396 RR(VID_CONV_COEF(0, 0));
397 RR(VID_CONV_COEF(0, 1));
398 RR(VID_CONV_COEF(0, 2));
399 RR(VID_CONV_COEF(0, 3));
400 RR(VID_CONV_COEF(0, 4));
401
402 RR(VID_FIR_COEF_V(0, 0));
403 RR(VID_FIR_COEF_V(0, 1));
404 RR(VID_FIR_COEF_V(0, 2));
405 RR(VID_FIR_COEF_V(0, 3));
406 RR(VID_FIR_COEF_V(0, 4));
407 RR(VID_FIR_COEF_V(0, 5));
408 RR(VID_FIR_COEF_V(0, 6));
409 RR(VID_FIR_COEF_V(0, 7));
410
411 RR(VID_PRELOAD(0));
412
413 /* VID2 */
414 RR(VID_BA0(1));
415 RR(VID_BA1(1));
416 RR(VID_POSITION(1));
417 RR(VID_SIZE(1));
418 RR(VID_ATTRIBUTES(1));
419 RR(VID_FIFO_THRESHOLD(1));
420 RR(VID_ROW_INC(1));
421 RR(VID_PIXEL_INC(1));
422 RR(VID_FIR(1));
423 RR(VID_PICTURE_SIZE(1));
424 RR(VID_ACCU0(1));
425 RR(VID_ACCU1(1));
426
427 RR(VID_FIR_COEF_H(1, 0));
428 RR(VID_FIR_COEF_H(1, 1));
429 RR(VID_FIR_COEF_H(1, 2));
430 RR(VID_FIR_COEF_H(1, 3));
431 RR(VID_FIR_COEF_H(1, 4));
432 RR(VID_FIR_COEF_H(1, 5));
433 RR(VID_FIR_COEF_H(1, 6));
434 RR(VID_FIR_COEF_H(1, 7));
435
436 RR(VID_FIR_COEF_HV(1, 0));
437 RR(VID_FIR_COEF_HV(1, 1));
438 RR(VID_FIR_COEF_HV(1, 2));
439 RR(VID_FIR_COEF_HV(1, 3));
440 RR(VID_FIR_COEF_HV(1, 4));
441 RR(VID_FIR_COEF_HV(1, 5));
442 RR(VID_FIR_COEF_HV(1, 6));
443 RR(VID_FIR_COEF_HV(1, 7));
444
445 RR(VID_CONV_COEF(1, 0));
446 RR(VID_CONV_COEF(1, 1));
447 RR(VID_CONV_COEF(1, 2));
448 RR(VID_CONV_COEF(1, 3));
449 RR(VID_CONV_COEF(1, 4));
450
451 RR(VID_FIR_COEF_V(1, 0));
452 RR(VID_FIR_COEF_V(1, 1));
453 RR(VID_FIR_COEF_V(1, 2));
454 RR(VID_FIR_COEF_V(1, 3));
455 RR(VID_FIR_COEF_V(1, 4));
456 RR(VID_FIR_COEF_V(1, 5));
457 RR(VID_FIR_COEF_V(1, 6));
458 RR(VID_FIR_COEF_V(1, 7));
459
460 RR(VID_PRELOAD(1));
461
462 /* enable last, because LCD & DIGIT enable are here */
463 RR(CONTROL);
464}
465
466#undef SR
467#undef RR
468
469static inline void enable_clocks(bool enable)
470{
471 if (enable)
472 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
473 else
474 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
475}
476
477bool dispc_go_busy(enum omap_channel channel)
478{
479 int bit;
480
481 if (channel == OMAP_DSS_CHANNEL_LCD)
482 bit = 5; /* GOLCD */
483 else
484 bit = 6; /* GODIGIT */
485
486 return REG_GET(DISPC_CONTROL, bit, bit) == 1;
487}
488
489void dispc_go(enum omap_channel channel)
490{
491 int bit;
492
493 enable_clocks(1);
494
495 if (channel == OMAP_DSS_CHANNEL_LCD)
496 bit = 0; /* LCDENABLE */
497 else
498 bit = 1; /* DIGITALENABLE */
499
500 /* if the channel is not enabled, we don't need GO */
501 if (REG_GET(DISPC_CONTROL, bit, bit) == 0)
502 goto end;
503
504 if (channel == OMAP_DSS_CHANNEL_LCD)
505 bit = 5; /* GOLCD */
506 else
507 bit = 6; /* GODIGIT */
508
509 if (REG_GET(DISPC_CONTROL, bit, bit) == 1) {
510 DSSERR("GO bit not down for channel %d\n", channel);
511 goto end;
512 }
513
514 DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : "DIGIT");
515
516 REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
517end:
518 enable_clocks(0);
519}
520
521static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
522{
523 BUG_ON(plane == OMAP_DSS_GFX);
524
525 dispc_write_reg(DISPC_VID_FIR_COEF_H(plane-1, reg), value);
526}
527
528static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
529{
530 BUG_ON(plane == OMAP_DSS_GFX);
531
532 dispc_write_reg(DISPC_VID_FIR_COEF_HV(plane-1, reg), value);
533}
534
535static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value)
536{
537 BUG_ON(plane == OMAP_DSS_GFX);
538
539 dispc_write_reg(DISPC_VID_FIR_COEF_V(plane-1, reg), value);
540}
541
542static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
543 int vscaleup, int five_taps)
544{
545 /* Coefficients for horizontal up-sampling */
546 static const u32 coef_hup[8] = {
547 0x00800000,
548 0x0D7CF800,
549 0x1E70F5FF,
550 0x335FF5FE,
551 0xF74949F7,
552 0xF55F33FB,
553 0xF5701EFE,
554 0xF87C0DFF,
555 };
556
557 /* Coefficients for horizontal down-sampling */
558 static const u32 coef_hdown[8] = {
559 0x24382400,
560 0x28371FFE,
561 0x2C361BFB,
562 0x303516F9,
563 0x11343311,
564 0x1635300C,
565 0x1B362C08,
566 0x1F372804,
567 };
568
569 /* Coefficients for horizontal and vertical up-sampling */
570 static const u32 coef_hvup[2][8] = {
571 {
572 0x00800000,
573 0x037B02FF,
574 0x0C6F05FE,
575 0x205907FB,
576 0x00404000,
577 0x075920FE,
578 0x056F0CFF,
579 0x027B0300,
580 },
581 {
582 0x00800000,
583 0x0D7CF8FF,
584 0x1E70F5FE,
585 0x335FF5FB,
586 0xF7404000,
587 0xF55F33FE,
588 0xF5701EFF,
589 0xF87C0D00,
590 },
591 };
592
593 /* Coefficients for horizontal and vertical down-sampling */
594 static const u32 coef_hvdown[2][8] = {
595 {
596 0x24382400,
597 0x28391F04,
598 0x2D381B08,
599 0x3237170C,
600 0x123737F7,
601 0x173732F9,
602 0x1B382DFB,
603 0x1F3928FE,
604 },
605 {
606 0x24382400,
607 0x28371F04,
608 0x2C361B08,
609 0x3035160C,
610 0x113433F7,
611 0x163530F9,
612 0x1B362CFB,
613 0x1F3728FE,
614 },
615 };
616
617 /* Coefficients for vertical up-sampling */
618 static const u32 coef_vup[8] = {
619 0x00000000,
620 0x0000FF00,
621 0x0000FEFF,
622 0x0000FBFE,
623 0x000000F7,
624 0x0000FEFB,
625 0x0000FFFE,
626 0x000000FF,
627 };
628
629
630 /* Coefficients for vertical down-sampling */
631 static const u32 coef_vdown[8] = {
632 0x00000000,
633 0x000004FE,
634 0x000008FB,
635 0x00000CF9,
636 0x0000F711,
637 0x0000F90C,
638 0x0000FB08,
639 0x0000FE04,
640 };
641
642 const u32 *h_coef;
643 const u32 *hv_coef;
644 const u32 *hv_coef_mod;
645 const u32 *v_coef;
646 int i;
647
648 if (hscaleup)
649 h_coef = coef_hup;
650 else
651 h_coef = coef_hdown;
652
653 if (vscaleup) {
654 hv_coef = coef_hvup[five_taps];
655 v_coef = coef_vup;
656
657 if (hscaleup)
658 hv_coef_mod = NULL;
659 else
660 hv_coef_mod = coef_hvdown[five_taps];
661 } else {
662 hv_coef = coef_hvdown[five_taps];
663 v_coef = coef_vdown;
664
665 if (hscaleup)
666 hv_coef_mod = coef_hvup[five_taps];
667 else
668 hv_coef_mod = NULL;
669 }
670
671 for (i = 0; i < 8; i++) {
672 u32 h, hv;
673
674 h = h_coef[i];
675
676 hv = hv_coef[i];
677
678 if (hv_coef_mod) {
679 hv &= 0xffffff00;
680 hv |= (hv_coef_mod[i] & 0xff);
681 }
682
683 _dispc_write_firh_reg(plane, i, h);
684 _dispc_write_firhv_reg(plane, i, hv);
685 }
686
687 if (!five_taps)
688 return;
689
690 for (i = 0; i < 8; i++) {
691 u32 v;
692 v = v_coef[i];
693 _dispc_write_firv_reg(plane, i, v);
694 }
695}
696
697static void _dispc_setup_color_conv_coef(void)
698{
699 const struct color_conv_coef {
700 int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
701 int full_range;
702 } ctbl_bt601_5 = {
703 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
704 };
705
706 const struct color_conv_coef *ct;
707
708#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
709
710 ct = &ctbl_bt601_5;
711
712 dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct->rcr, ct->ry));
713 dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct->gy, ct->rcb));
714 dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct->gcb, ct->gcr));
715 dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct->bcr, ct->by));
716 dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0, ct->bcb));
717
718 dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct->rcr, ct->ry));
719 dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct->gy, ct->rcb));
720 dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct->gcb, ct->gcr));
721 dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct->bcr, ct->by));
722 dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0, ct->bcb));
723
724#undef CVAL
725
726 REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct->full_range, 11, 11);
727 REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct->full_range, 11, 11);
728}
729
730
731static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr)
732{
733 const struct dispc_reg ba0_reg[] = { DISPC_GFX_BA0,
734 DISPC_VID_BA0(0),
735 DISPC_VID_BA0(1) };
736
737 dispc_write_reg(ba0_reg[plane], paddr);
738}
739
740static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr)
741{
742 const struct dispc_reg ba1_reg[] = { DISPC_GFX_BA1,
743 DISPC_VID_BA1(0),
744 DISPC_VID_BA1(1) };
745
746 dispc_write_reg(ba1_reg[plane], paddr);
747}
748
749static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y)
750{
751 const struct dispc_reg pos_reg[] = { DISPC_GFX_POSITION,
752 DISPC_VID_POSITION(0),
753 DISPC_VID_POSITION(1) };
754
755 u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
756 dispc_write_reg(pos_reg[plane], val);
757}
758
759static void _dispc_set_pic_size(enum omap_plane plane, int width, int height)
760{
761 const struct dispc_reg siz_reg[] = { DISPC_GFX_SIZE,
762 DISPC_VID_PICTURE_SIZE(0),
763 DISPC_VID_PICTURE_SIZE(1) };
764 u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
765 dispc_write_reg(siz_reg[plane], val);
766}
767
768static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
769{
770 u32 val;
771 const struct dispc_reg vsi_reg[] = { DISPC_VID_SIZE(0),
772 DISPC_VID_SIZE(1) };
773
774 BUG_ON(plane == OMAP_DSS_GFX);
775
776 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
777 dispc_write_reg(vsi_reg[plane-1], val);
778}
779
780static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
781{
782
783 BUG_ON(plane == OMAP_DSS_VIDEO1);
784
785 if (cpu_is_omap24xx())
786 return;
787
788 if (plane == OMAP_DSS_GFX)
789 REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0);
790 else if (plane == OMAP_DSS_VIDEO2)
791 REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16);
792}
793
794static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc)
795{
796 const struct dispc_reg ri_reg[] = { DISPC_GFX_PIXEL_INC,
797 DISPC_VID_PIXEL_INC(0),
798 DISPC_VID_PIXEL_INC(1) };
799
800 dispc_write_reg(ri_reg[plane], inc);
801}
802
803static void _dispc_set_row_inc(enum omap_plane plane, s32 inc)
804{
805 const struct dispc_reg ri_reg[] = { DISPC_GFX_ROW_INC,
806 DISPC_VID_ROW_INC(0),
807 DISPC_VID_ROW_INC(1) };
808
809 dispc_write_reg(ri_reg[plane], inc);
810}
811
812static void _dispc_set_color_mode(enum omap_plane plane,
813 enum omap_color_mode color_mode)
814{
815 u32 m = 0;
816
817 switch (color_mode) {
818 case OMAP_DSS_COLOR_CLUT1:
819 m = 0x0; break;
820 case OMAP_DSS_COLOR_CLUT2:
821 m = 0x1; break;
822 case OMAP_DSS_COLOR_CLUT4:
823 m = 0x2; break;
824 case OMAP_DSS_COLOR_CLUT8:
825 m = 0x3; break;
826 case OMAP_DSS_COLOR_RGB12U:
827 m = 0x4; break;
828 case OMAP_DSS_COLOR_ARGB16:
829 m = 0x5; break;
830 case OMAP_DSS_COLOR_RGB16:
831 m = 0x6; break;
832 case OMAP_DSS_COLOR_RGB24U:
833 m = 0x8; break;
834 case OMAP_DSS_COLOR_RGB24P:
835 m = 0x9; break;
836 case OMAP_DSS_COLOR_YUV2:
837 m = 0xa; break;
838 case OMAP_DSS_COLOR_UYVY:
839 m = 0xb; break;
840 case OMAP_DSS_COLOR_ARGB32:
841 m = 0xc; break;
842 case OMAP_DSS_COLOR_RGBA32:
843 m = 0xd; break;
844 case OMAP_DSS_COLOR_RGBX32:
845 m = 0xe; break;
846 default:
847 BUG(); break;
848 }
849
850 REG_FLD_MOD(dispc_reg_att[plane], m, 4, 1);
851}
852
853static void _dispc_set_channel_out(enum omap_plane plane,
854 enum omap_channel channel)
855{
856 int shift;
857 u32 val;
858
859 switch (plane) {
860 case OMAP_DSS_GFX:
861 shift = 8;
862 break;
863 case OMAP_DSS_VIDEO1:
864 case OMAP_DSS_VIDEO2:
865 shift = 16;
866 break;
867 default:
868 BUG();
869 return;
870 }
871
872 val = dispc_read_reg(dispc_reg_att[plane]);
873 val = FLD_MOD(val, channel, shift, shift);
874 dispc_write_reg(dispc_reg_att[plane], val);
875}
876
877void dispc_set_burst_size(enum omap_plane plane,
878 enum omap_burst_size burst_size)
879{
880 int shift;
881 u32 val;
882
883 enable_clocks(1);
884
885 switch (plane) {
886 case OMAP_DSS_GFX:
887 shift = 6;
888 break;
889 case OMAP_DSS_VIDEO1:
890 case OMAP_DSS_VIDEO2:
891 shift = 14;
892 break;
893 default:
894 BUG();
895 return;
896 }
897
898 val = dispc_read_reg(dispc_reg_att[plane]);
899 val = FLD_MOD(val, burst_size, shift+1, shift);
900 dispc_write_reg(dispc_reg_att[plane], val);
901
902 enable_clocks(0);
903}
904
905static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
906{
907 u32 val;
908
909 BUG_ON(plane == OMAP_DSS_GFX);
910
911 val = dispc_read_reg(dispc_reg_att[plane]);
912 val = FLD_MOD(val, enable, 9, 9);
913 dispc_write_reg(dispc_reg_att[plane], val);
914}
915
916void dispc_enable_replication(enum omap_plane plane, bool enable)
917{
918 int bit;
919
920 if (plane == OMAP_DSS_GFX)
921 bit = 5;
922 else
923 bit = 10;
924
925 enable_clocks(1);
926 REG_FLD_MOD(dispc_reg_att[plane], enable, bit, bit);
927 enable_clocks(0);
928}
929
930void dispc_set_lcd_size(u16 width, u16 height)
931{
932 u32 val;
933 BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
934 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
935 enable_clocks(1);
936 dispc_write_reg(DISPC_SIZE_LCD, val);
937 enable_clocks(0);
938}
939
940void dispc_set_digit_size(u16 width, u16 height)
941{
942 u32 val;
943 BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
944 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
945 enable_clocks(1);
946 dispc_write_reg(DISPC_SIZE_DIG, val);
947 enable_clocks(0);
948}
949
950static void dispc_read_plane_fifo_sizes(void)
951{
952 const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,
953 DISPC_VID_FIFO_SIZE_STATUS(0),
954 DISPC_VID_FIFO_SIZE_STATUS(1) };
955 u32 size;
956 int plane;
957
958 enable_clocks(1);
959
960 for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
961 if (cpu_is_omap24xx())
962 size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0);
963 else if (cpu_is_omap34xx())
964 size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0);
965 else
966 BUG();
967
968 dispc.fifo_size[plane] = size;
969 }
970
971 enable_clocks(0);
972}
973
974u32 dispc_get_plane_fifo_size(enum omap_plane plane)
975{
976 return dispc.fifo_size[plane];
977}
978
979void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
980{
981 const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
982 DISPC_VID_FIFO_THRESHOLD(0),
983 DISPC_VID_FIFO_THRESHOLD(1) };
984 enable_clocks(1);
985
986 DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
987 plane,
988 REG_GET(ftrs_reg[plane], 11, 0),
989 REG_GET(ftrs_reg[plane], 27, 16),
990 low, high);
991
992 if (cpu_is_omap24xx())
993 dispc_write_reg(ftrs_reg[plane],
994 FLD_VAL(high, 24, 16) | FLD_VAL(low, 8, 0));
995 else
996 dispc_write_reg(ftrs_reg[plane],
997 FLD_VAL(high, 27, 16) | FLD_VAL(low, 11, 0));
998
999 enable_clocks(0);
1000}
1001
1002void dispc_enable_fifomerge(bool enable)
1003{
1004 enable_clocks(1);
1005
1006 DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
1007 REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
1008
1009 enable_clocks(0);
1010}
1011
1012static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc)
1013{
1014 u32 val;
1015 const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0),
1016 DISPC_VID_FIR(1) };
1017
1018 BUG_ON(plane == OMAP_DSS_GFX);
1019
1020 if (cpu_is_omap24xx())
1021 val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0);
1022 else
1023 val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0);
1024 dispc_write_reg(fir_reg[plane-1], val);
1025}
1026
1027static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
1028{
1029 u32 val;
1030 const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0),
1031 DISPC_VID_ACCU0(1) };
1032
1033 BUG_ON(plane == OMAP_DSS_GFX);
1034
1035 val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
1036 dispc_write_reg(ac0_reg[plane-1], val);
1037}
1038
1039static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
1040{
1041 u32 val;
1042 const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0),
1043 DISPC_VID_ACCU1(1) };
1044
1045 BUG_ON(plane == OMAP_DSS_GFX);
1046
1047 val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
1048 dispc_write_reg(ac1_reg[plane-1], val);
1049}
1050
1051
1052static void _dispc_set_scaling(enum omap_plane plane,
1053 u16 orig_width, u16 orig_height,
1054 u16 out_width, u16 out_height,
1055 bool ilace, bool five_taps,
1056 bool fieldmode)
1057{
1058 int fir_hinc;
1059 int fir_vinc;
1060 int hscaleup, vscaleup;
1061 int accu0 = 0;
1062 int accu1 = 0;
1063 u32 l;
1064
1065 BUG_ON(plane == OMAP_DSS_GFX);
1066
1067 hscaleup = orig_width <= out_width;
1068 vscaleup = orig_height <= out_height;
1069
1070 _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps);
1071
1072 if (!orig_width || orig_width == out_width)
1073 fir_hinc = 0;
1074 else
1075 fir_hinc = 1024 * orig_width / out_width;
1076
1077 if (!orig_height || orig_height == out_height)
1078 fir_vinc = 0;
1079 else
1080 fir_vinc = 1024 * orig_height / out_height;
1081
1082 _dispc_set_fir(plane, fir_hinc, fir_vinc);
1083
1084 l = dispc_read_reg(dispc_reg_att[plane]);
1085 l &= ~((0x0f << 5) | (0x3 << 21));
1086
1087 l |= fir_hinc ? (1 << 5) : 0;
1088 l |= fir_vinc ? (1 << 6) : 0;
1089
1090 l |= hscaleup ? 0 : (1 << 7);
1091 l |= vscaleup ? 0 : (1 << 8);
1092
1093 l |= five_taps ? (1 << 21) : 0;
1094 l |= five_taps ? (1 << 22) : 0;
1095
1096 dispc_write_reg(dispc_reg_att[plane], l);
1097
1098 /*
1099 * field 0 = even field = bottom field
1100 * field 1 = odd field = top field
1101 */
1102 if (ilace && !fieldmode) {
1103 accu1 = 0;
1104 accu0 = (fir_vinc / 2) & 0x3ff;
1105 if (accu0 >= 1024/2) {
1106 accu1 = 1024/2;
1107 accu0 -= accu1;
1108 }
1109 }
1110
1111 _dispc_set_vid_accu0(plane, 0, accu0);
1112 _dispc_set_vid_accu1(plane, 0, accu1);
1113}
1114
1115static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
1116 bool mirroring, enum omap_color_mode color_mode)
1117{
1118 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1119 color_mode == OMAP_DSS_COLOR_UYVY) {
1120 int vidrot = 0;
1121
1122 if (mirroring) {
1123 switch (rotation) {
1124 case OMAP_DSS_ROT_0:
1125 vidrot = 2;
1126 break;
1127 case OMAP_DSS_ROT_90:
1128 vidrot = 1;
1129 break;
1130 case OMAP_DSS_ROT_180:
1131 vidrot = 0;
1132 break;
1133 case OMAP_DSS_ROT_270:
1134 vidrot = 3;
1135 break;
1136 }
1137 } else {
1138 switch (rotation) {
1139 case OMAP_DSS_ROT_0:
1140 vidrot = 0;
1141 break;
1142 case OMAP_DSS_ROT_90:
1143 vidrot = 1;
1144 break;
1145 case OMAP_DSS_ROT_180:
1146 vidrot = 2;
1147 break;
1148 case OMAP_DSS_ROT_270:
1149 vidrot = 3;
1150 break;
1151 }
1152 }
1153
1154 REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12);
1155
1156 if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270)
1157 REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18);
1158 else
1159 REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18);
1160 } else {
1161 REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12);
1162 REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18);
1163 }
1164}
1165
1166static int color_mode_to_bpp(enum omap_color_mode color_mode)
1167{
1168 switch (color_mode) {
1169 case OMAP_DSS_COLOR_CLUT1:
1170 return 1;
1171 case OMAP_DSS_COLOR_CLUT2:
1172 return 2;
1173 case OMAP_DSS_COLOR_CLUT4:
1174 return 4;
1175 case OMAP_DSS_COLOR_CLUT8:
1176 return 8;
1177 case OMAP_DSS_COLOR_RGB12U:
1178 case OMAP_DSS_COLOR_RGB16:
1179 case OMAP_DSS_COLOR_ARGB16:
1180 case OMAP_DSS_COLOR_YUV2:
1181 case OMAP_DSS_COLOR_UYVY:
1182 return 16;
1183 case OMAP_DSS_COLOR_RGB24P:
1184 return 24;
1185 case OMAP_DSS_COLOR_RGB24U:
1186 case OMAP_DSS_COLOR_ARGB32:
1187 case OMAP_DSS_COLOR_RGBA32:
1188 case OMAP_DSS_COLOR_RGBX32:
1189 return 32;
1190 default:
1191 BUG();
1192 }
1193}
1194
1195static s32 pixinc(int pixels, u8 ps)
1196{
1197 if (pixels == 1)
1198 return 1;
1199 else if (pixels > 1)
1200 return 1 + (pixels - 1) * ps;
1201 else if (pixels < 0)
1202 return 1 - (-pixels + 1) * ps;
1203 else
1204 BUG();
1205}
1206
1207static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
1208 u16 screen_width,
1209 u16 width, u16 height,
1210 enum omap_color_mode color_mode, bool fieldmode,
1211 unsigned int field_offset,
1212 unsigned *offset0, unsigned *offset1,
1213 s32 *row_inc, s32 *pix_inc)
1214{
1215 u8 ps;
1216
1217 /* FIXME CLUT formats */
1218 switch (color_mode) {
1219 case OMAP_DSS_COLOR_CLUT1:
1220 case OMAP_DSS_COLOR_CLUT2:
1221 case OMAP_DSS_COLOR_CLUT4:
1222 case OMAP_DSS_COLOR_CLUT8:
1223 BUG();
1224 return;
1225 case OMAP_DSS_COLOR_YUV2:
1226 case OMAP_DSS_COLOR_UYVY:
1227 ps = 4;
1228 break;
1229 default:
1230 ps = color_mode_to_bpp(color_mode) / 8;
1231 break;
1232 }
1233
1234 DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
1235 width, height);
1236
1237 /*
1238 * field 0 = even field = bottom field
1239 * field 1 = odd field = top field
1240 */
1241 switch (rotation + mirror * 4) {
1242 case OMAP_DSS_ROT_0:
1243 case OMAP_DSS_ROT_180:
1244 /*
1245 * If the pixel format is YUV or UYVY divide the width
1246 * of the image by 2 for 0 and 180 degree rotation.
1247 */
1248 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1249 color_mode == OMAP_DSS_COLOR_UYVY)
1250 width = width >> 1;
1251 case OMAP_DSS_ROT_90:
1252 case OMAP_DSS_ROT_270:
1253 *offset1 = 0;
1254 if (field_offset)
1255 *offset0 = field_offset * screen_width * ps;
1256 else
1257 *offset0 = 0;
1258
1259 *row_inc = pixinc(1 + (screen_width - width) +
1260 (fieldmode ? screen_width : 0),
1261 ps);
1262 *pix_inc = pixinc(1, ps);
1263 break;
1264
1265 case OMAP_DSS_ROT_0 + 4:
1266 case OMAP_DSS_ROT_180 + 4:
1267 /* If the pixel format is YUV or UYVY divide the width
1268 * of the image by 2 for 0 degree and 180 degree
1269 */
1270 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1271 color_mode == OMAP_DSS_COLOR_UYVY)
1272 width = width >> 1;
1273 case OMAP_DSS_ROT_90 + 4:
1274 case OMAP_DSS_ROT_270 + 4:
1275 *offset1 = 0;
1276 if (field_offset)
1277 *offset0 = field_offset * screen_width * ps;
1278 else
1279 *offset0 = 0;
1280 *row_inc = pixinc(1 - (screen_width + width) -
1281 (fieldmode ? screen_width : 0),
1282 ps);
1283 *pix_inc = pixinc(1, ps);
1284 break;
1285
1286 default:
1287 BUG();
1288 }
1289}
1290
1291static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1292 u16 screen_width,
1293 u16 width, u16 height,
1294 enum omap_color_mode color_mode, bool fieldmode,
1295 unsigned int field_offset,
1296 unsigned *offset0, unsigned *offset1,
1297 s32 *row_inc, s32 *pix_inc)
1298{
1299 u8 ps;
1300 u16 fbw, fbh;
1301
1302 /* FIXME CLUT formats */
1303 switch (color_mode) {
1304 case OMAP_DSS_COLOR_CLUT1:
1305 case OMAP_DSS_COLOR_CLUT2:
1306 case OMAP_DSS_COLOR_CLUT4:
1307 case OMAP_DSS_COLOR_CLUT8:
1308 BUG();
1309 return;
1310 default:
1311 ps = color_mode_to_bpp(color_mode) / 8;
1312 break;
1313 }
1314
1315 DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
1316 width, height);
1317
1318 /* width & height are overlay sizes, convert to fb sizes */
1319
1320 if (rotation == OMAP_DSS_ROT_0 || rotation == OMAP_DSS_ROT_180) {
1321 fbw = width;
1322 fbh = height;
1323 } else {
1324 fbw = height;
1325 fbh = width;
1326 }
1327
1328 /*
1329 * field 0 = even field = bottom field
1330 * field 1 = odd field = top field
1331 */
1332 switch (rotation + mirror * 4) {
1333 case OMAP_DSS_ROT_0:
1334 *offset1 = 0;
1335 if (field_offset)
1336 *offset0 = *offset1 + field_offset * screen_width * ps;
1337 else
1338 *offset0 = *offset1;
1339 *row_inc = pixinc(1 + (screen_width - fbw) +
1340 (fieldmode ? screen_width : 0),
1341 ps);
1342 *pix_inc = pixinc(1, ps);
1343 break;
1344 case OMAP_DSS_ROT_90:
1345 *offset1 = screen_width * (fbh - 1) * ps;
1346 if (field_offset)
1347 *offset0 = *offset1 + field_offset * ps;
1348 else
1349 *offset0 = *offset1;
1350 *row_inc = pixinc(screen_width * (fbh - 1) + 1 +
1351 (fieldmode ? 1 : 0), ps);
1352 *pix_inc = pixinc(-screen_width, ps);
1353 break;
1354 case OMAP_DSS_ROT_180:
1355 *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
1356 if (field_offset)
1357 *offset0 = *offset1 - field_offset * screen_width * ps;
1358 else
1359 *offset0 = *offset1;
1360 *row_inc = pixinc(-1 -
1361 (screen_width - fbw) -
1362 (fieldmode ? screen_width : 0),
1363 ps);
1364 *pix_inc = pixinc(-1, ps);
1365 break;
1366 case OMAP_DSS_ROT_270:
1367 *offset1 = (fbw - 1) * ps;
1368 if (field_offset)
1369 *offset0 = *offset1 - field_offset * ps;
1370 else
1371 *offset0 = *offset1;
1372 *row_inc = pixinc(-screen_width * (fbh - 1) - 1 -
1373 (fieldmode ? 1 : 0), ps);
1374 *pix_inc = pixinc(screen_width, ps);
1375 break;
1376
1377 /* mirroring */
1378 case OMAP_DSS_ROT_0 + 4:
1379 *offset1 = (fbw - 1) * ps;
1380 if (field_offset)
1381 *offset0 = *offset1 + field_offset * screen_width * ps;
1382 else
1383 *offset0 = *offset1;
1384 *row_inc = pixinc(screen_width * 2 - 1 +
1385 (fieldmode ? screen_width : 0),
1386 ps);
1387 *pix_inc = pixinc(-1, ps);
1388 break;
1389
1390 case OMAP_DSS_ROT_90 + 4:
1391 *offset1 = 0;
1392 if (field_offset)
1393 *offset0 = *offset1 + field_offset * ps;
1394 else
1395 *offset0 = *offset1;
1396 *row_inc = pixinc(-screen_width * (fbh - 1) + 1 +
1397 (fieldmode ? 1 : 0),
1398 ps);
1399 *pix_inc = pixinc(screen_width, ps);
1400 break;
1401
1402 case OMAP_DSS_ROT_180 + 4:
1403 *offset1 = screen_width * (fbh - 1) * ps;
1404 if (field_offset)
1405 *offset0 = *offset1 - field_offset * screen_width * ps;
1406 else
1407 *offset0 = *offset1;
1408 *row_inc = pixinc(1 - screen_width * 2 -
1409 (fieldmode ? screen_width : 0),
1410 ps);
1411 *pix_inc = pixinc(1, ps);
1412 break;
1413
1414 case OMAP_DSS_ROT_270 + 4:
1415 *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
1416 if (field_offset)
1417 *offset0 = *offset1 - field_offset * ps;
1418 else
1419 *offset0 = *offset1;
1420 *row_inc = pixinc(screen_width * (fbh - 1) - 1 -
1421 (fieldmode ? 1 : 0),
1422 ps);
1423 *pix_inc = pixinc(-screen_width, ps);
1424 break;
1425
1426 default:
1427 BUG();
1428 }
1429}
1430
1431static unsigned long calc_fclk_five_taps(u16 width, u16 height,
1432 u16 out_width, u16 out_height, enum omap_color_mode color_mode)
1433{
1434 u32 fclk = 0;
1435 /* FIXME venc pclk? */
1436 u64 tmp, pclk = dispc_pclk_rate();
1437
1438 if (height > out_height) {
1439 /* FIXME get real display PPL */
1440 unsigned int ppl = 800;
1441
1442 tmp = pclk * height * out_width;
1443 do_div(tmp, 2 * out_height * ppl);
1444 fclk = tmp;
1445
1446 if (height > 2 * out_height && ppl != out_width) {
1447 tmp = pclk * (height - 2 * out_height) * out_width;
1448 do_div(tmp, 2 * out_height * (ppl - out_width));
1449 fclk = max(fclk, (u32) tmp);
1450 }
1451 }
1452
1453 if (width > out_width) {
1454 tmp = pclk * width;
1455 do_div(tmp, out_width);
1456 fclk = max(fclk, (u32) tmp);
1457
1458 if (color_mode == OMAP_DSS_COLOR_RGB24U)
1459 fclk <<= 1;
1460 }
1461
1462 return fclk;
1463}
1464
1465static unsigned long calc_fclk(u16 width, u16 height,
1466 u16 out_width, u16 out_height)
1467{
1468 unsigned int hf, vf;
1469
1470 /*
1471 * FIXME how to determine the 'A' factor
1472 * for the no downscaling case ?
1473 */
1474
1475 if (width > 3 * out_width)
1476 hf = 4;
1477 else if (width > 2 * out_width)
1478 hf = 3;
1479 else if (width > out_width)
1480 hf = 2;
1481 else
1482 hf = 1;
1483
1484 if (height > out_height)
1485 vf = 2;
1486 else
1487 vf = 1;
1488
1489 /* FIXME venc pclk? */
1490 return dispc_pclk_rate() * vf * hf;
1491}
1492
1493void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out)
1494{
1495 enable_clocks(1);
1496 _dispc_set_channel_out(plane, channel_out);
1497 enable_clocks(0);
1498}
1499
1500static int _dispc_setup_plane(enum omap_plane plane,
1501 u32 paddr, u16 screen_width,
1502 u16 pos_x, u16 pos_y,
1503 u16 width, u16 height,
1504 u16 out_width, u16 out_height,
1505 enum omap_color_mode color_mode,
1506 bool ilace,
1507 enum omap_dss_rotation_type rotation_type,
1508 u8 rotation, int mirror,
1509 u8 global_alpha)
1510{
1511 const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
1512 bool five_taps = 0;
1513 bool fieldmode = 0;
1514 int cconv = 0;
1515 unsigned offset0, offset1;
1516 s32 row_inc;
1517 s32 pix_inc;
1518 u16 frame_height = height;
1519 unsigned int field_offset = 0;
1520
1521 if (paddr == 0)
1522 return -EINVAL;
1523
1524 if (ilace && height == out_height)
1525 fieldmode = 1;
1526
1527 if (ilace) {
1528 if (fieldmode)
1529 height /= 2;
1530 pos_y /= 2;
1531 out_height /= 2;
1532
1533 DSSDBG("adjusting for ilace: height %d, pos_y %d, "
1534 "out_height %d\n",
1535 height, pos_y, out_height);
1536 }
1537
1538 if (plane == OMAP_DSS_GFX) {
1539 if (width != out_width || height != out_height)
1540 return -EINVAL;
1541
1542 switch (color_mode) {
1543 case OMAP_DSS_COLOR_ARGB16:
1544 case OMAP_DSS_COLOR_ARGB32:
1545 case OMAP_DSS_COLOR_RGBA32:
1546 case OMAP_DSS_COLOR_RGBX32:
1547 if (cpu_is_omap24xx())
1548 return -EINVAL;
1549 /* fall through */
1550 case OMAP_DSS_COLOR_RGB12U:
1551 case OMAP_DSS_COLOR_RGB16:
1552 case OMAP_DSS_COLOR_RGB24P:
1553 case OMAP_DSS_COLOR_RGB24U:
1554 break;
1555
1556 default:
1557 return -EINVAL;
1558 }
1559 } else {
1560 /* video plane */
1561
1562 unsigned long fclk = 0;
1563
1564 if (out_width < width / maxdownscale ||
1565 out_width > width * 8)
1566 return -EINVAL;
1567
1568 if (out_height < height / maxdownscale ||
1569 out_height > height * 8)
1570 return -EINVAL;
1571
1572 switch (color_mode) {
1573 case OMAP_DSS_COLOR_RGBX32:
1574 case OMAP_DSS_COLOR_RGB12U:
1575 if (cpu_is_omap24xx())
1576 return -EINVAL;
1577 /* fall through */
1578 case OMAP_DSS_COLOR_RGB16:
1579 case OMAP_DSS_COLOR_RGB24P:
1580 case OMAP_DSS_COLOR_RGB24U:
1581 break;
1582
1583 case OMAP_DSS_COLOR_ARGB16:
1584 case OMAP_DSS_COLOR_ARGB32:
1585 case OMAP_DSS_COLOR_RGBA32:
1586 if (cpu_is_omap24xx())
1587 return -EINVAL;
1588 if (plane == OMAP_DSS_VIDEO1)
1589 return -EINVAL;
1590 break;
1591
1592 case OMAP_DSS_COLOR_YUV2:
1593 case OMAP_DSS_COLOR_UYVY:
1594 cconv = 1;
1595 break;
1596
1597 default:
1598 return -EINVAL;
1599 }
1600
1601 /* Must use 5-tap filter? */
1602 five_taps = height > out_height * 2;
1603
1604 if (!five_taps) {
1605 fclk = calc_fclk(width, height,
1606 out_width, out_height);
1607
1608 /* Try 5-tap filter if 3-tap fclk is too high */
1609 if (cpu_is_omap34xx() && height > out_height &&
1610 fclk > dispc_fclk_rate())
1611 five_taps = true;
1612 }
1613
1614 if (width > (2048 >> five_taps)) {
1615 DSSERR("failed to set up scaling, fclk too low\n");
1616 return -EINVAL;
1617 }
1618
1619 if (five_taps)
1620 fclk = calc_fclk_five_taps(width, height,
1621 out_width, out_height, color_mode);
1622
1623 DSSDBG("required fclk rate = %lu Hz\n", fclk);
1624 DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
1625
1626 if (fclk > dispc_fclk_rate()) {
1627 DSSERR("failed to set up scaling, "
1628 "required fclk rate = %lu Hz, "
1629 "current fclk rate = %lu Hz\n",
1630 fclk, dispc_fclk_rate());
1631 return -EINVAL;
1632 }
1633 }
1634
1635 if (ilace && !fieldmode) {
1636 /*
1637 * when downscaling the bottom field may have to start several
1638 * source lines below the top field. Unfortunately ACCUI
1639 * registers will only hold the fractional part of the offset
1640 * so the integer part must be added to the base address of the
1641 * bottom field.
1642 */
1643 if (!height || height == out_height)
1644 field_offset = 0;
1645 else
1646 field_offset = height / out_height / 2;
1647 }
1648
1649 /* Fields are independent but interleaved in memory. */
1650 if (fieldmode)
1651 field_offset = 1;
1652
1653 if (rotation_type == OMAP_DSS_ROT_DMA)
1654 calc_dma_rotation_offset(rotation, mirror,
1655 screen_width, width, frame_height, color_mode,
1656 fieldmode, field_offset,
1657 &offset0, &offset1, &row_inc, &pix_inc);
1658 else
1659 calc_vrfb_rotation_offset(rotation, mirror,
1660 screen_width, width, frame_height, color_mode,
1661 fieldmode, field_offset,
1662 &offset0, &offset1, &row_inc, &pix_inc);
1663
1664 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
1665 offset0, offset1, row_inc, pix_inc);
1666
1667 _dispc_set_color_mode(plane, color_mode);
1668
1669 _dispc_set_plane_ba0(plane, paddr + offset0);
1670 _dispc_set_plane_ba1(plane, paddr + offset1);
1671
1672 _dispc_set_row_inc(plane, row_inc);
1673 _dispc_set_pix_inc(plane, pix_inc);
1674
1675 DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height,
1676 out_width, out_height);
1677
1678 _dispc_set_plane_pos(plane, pos_x, pos_y);
1679
1680 _dispc_set_pic_size(plane, width, height);
1681
1682 if (plane != OMAP_DSS_GFX) {
1683 _dispc_set_scaling(plane, width, height,
1684 out_width, out_height,
1685 ilace, five_taps, fieldmode);
1686 _dispc_set_vid_size(plane, out_width, out_height);
1687 _dispc_set_vid_color_conv(plane, cconv);
1688 }
1689
1690 _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode);
1691
1692 if (plane != OMAP_DSS_VIDEO1)
1693 _dispc_setup_global_alpha(plane, global_alpha);
1694
1695 return 0;
1696}
1697
1698static void _dispc_enable_plane(enum omap_plane plane, bool enable)
1699{
1700 REG_FLD_MOD(dispc_reg_att[plane], enable ? 1 : 0, 0, 0);
1701}
1702
1703static void dispc_disable_isr(void *data, u32 mask)
1704{
1705 struct completion *compl = data;
1706 complete(compl);
1707}
1708
1709static void _enable_lcd_out(bool enable)
1710{
1711 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
1712}
1713
1714void dispc_enable_lcd_out(bool enable)
1715{
1716 struct completion frame_done_completion;
1717 bool is_on;
1718 int r;
1719
1720 enable_clocks(1);
1721
1722 /* When we disable LCD output, we need to wait until frame is done.
1723 * Otherwise the DSS is still working, and turning off the clocks
1724 * prevents DSS from going to OFF mode */
1725 is_on = REG_GET(DISPC_CONTROL, 0, 0);
1726
1727 if (!enable && is_on) {
1728 init_completion(&frame_done_completion);
1729
1730 r = omap_dispc_register_isr(dispc_disable_isr,
1731 &frame_done_completion,
1732 DISPC_IRQ_FRAMEDONE);
1733
1734 if (r)
1735 DSSERR("failed to register FRAMEDONE isr\n");
1736 }
1737
1738 _enable_lcd_out(enable);
1739
1740 if (!enable && is_on) {
1741 if (!wait_for_completion_timeout(&frame_done_completion,
1742 msecs_to_jiffies(100)))
1743 DSSERR("timeout waiting for FRAME DONE\n");
1744
1745 r = omap_dispc_unregister_isr(dispc_disable_isr,
1746 &frame_done_completion,
1747 DISPC_IRQ_FRAMEDONE);
1748
1749 if (r)
1750 DSSERR("failed to unregister FRAMEDONE isr\n");
1751 }
1752
1753 enable_clocks(0);
1754}
1755
1756static void _enable_digit_out(bool enable)
1757{
1758 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
1759}
1760
1761void dispc_enable_digit_out(bool enable)
1762{
1763 struct completion frame_done_completion;
1764 int r;
1765
1766 enable_clocks(1);
1767
1768 if (REG_GET(DISPC_CONTROL, 1, 1) == enable) {
1769 enable_clocks(0);
1770 return;
1771 }
1772
1773 if (enable) {
1774 unsigned long flags;
1775 /* When we enable digit output, we'll get an extra digit
1776 * sync lost interrupt, that we need to ignore */
1777 spin_lock_irqsave(&dispc.irq_lock, flags);
1778 dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
1779 _omap_dispc_set_irqs();
1780 spin_unlock_irqrestore(&dispc.irq_lock, flags);
1781 }
1782
1783 /* When we disable digit output, we need to wait until fields are done.
1784 * Otherwise the DSS is still working, and turning off the clocks
1785 * prevents DSS from going to OFF mode. And when enabling, we need to
1786 * wait for the extra sync losts */
1787 init_completion(&frame_done_completion);
1788
1789 r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion,
1790 DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
1791 if (r)
1792 DSSERR("failed to register EVSYNC isr\n");
1793
1794 _enable_digit_out(enable);
1795
1796 /* XXX I understand from TRM that we should only wait for the
1797 * current field to complete. But it seems we have to wait
1798 * for both fields */
1799 if (!wait_for_completion_timeout(&frame_done_completion,
1800 msecs_to_jiffies(100)))
1801 DSSERR("timeout waiting for EVSYNC\n");
1802
1803 if (!wait_for_completion_timeout(&frame_done_completion,
1804 msecs_to_jiffies(100)))
1805 DSSERR("timeout waiting for EVSYNC\n");
1806
1807 r = omap_dispc_unregister_isr(dispc_disable_isr,
1808 &frame_done_completion,
1809 DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
1810 if (r)
1811 DSSERR("failed to unregister EVSYNC isr\n");
1812
1813 if (enable) {
1814 unsigned long flags;
1815 spin_lock_irqsave(&dispc.irq_lock, flags);
1816 dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
1817 dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
1818 _omap_dispc_set_irqs();
1819 spin_unlock_irqrestore(&dispc.irq_lock, flags);
1820 }
1821
1822 enable_clocks(0);
1823}
1824
1825void dispc_lcd_enable_signal_polarity(bool act_high)
1826{
1827 enable_clocks(1);
1828 REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
1829 enable_clocks(0);
1830}
1831
1832void dispc_lcd_enable_signal(bool enable)
1833{
1834 enable_clocks(1);
1835 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
1836 enable_clocks(0);
1837}
1838
1839void dispc_pck_free_enable(bool enable)
1840{
1841 enable_clocks(1);
1842 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
1843 enable_clocks(0);
1844}
1845
1846void dispc_enable_fifohandcheck(bool enable)
1847{
1848 enable_clocks(1);
1849 REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
1850 enable_clocks(0);
1851}
1852
1853
1854void dispc_set_lcd_display_type(enum omap_lcd_display_type type)
1855{
1856 int mode;
1857
1858 switch (type) {
1859 case OMAP_DSS_LCD_DISPLAY_STN:
1860 mode = 0;
1861 break;
1862
1863 case OMAP_DSS_LCD_DISPLAY_TFT:
1864 mode = 1;
1865 break;
1866
1867 default:
1868 BUG();
1869 return;
1870 }
1871
1872 enable_clocks(1);
1873 REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
1874 enable_clocks(0);
1875}
1876
1877void dispc_set_loadmode(enum omap_dss_load_mode mode)
1878{
1879 enable_clocks(1);
1880 REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
1881 enable_clocks(0);
1882}
1883
1884
1885void dispc_set_default_color(enum omap_channel channel, u32 color)
1886{
1887 const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
1888 DISPC_DEFAULT_COLOR1 };
1889
1890 enable_clocks(1);
1891 dispc_write_reg(def_reg[channel], color);
1892 enable_clocks(0);
1893}
1894
1895u32 dispc_get_default_color(enum omap_channel channel)
1896{
1897 const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
1898 DISPC_DEFAULT_COLOR1 };
1899 u32 l;
1900
1901 BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT &&
1902 channel != OMAP_DSS_CHANNEL_LCD);
1903
1904 enable_clocks(1);
1905 l = dispc_read_reg(def_reg[channel]);
1906 enable_clocks(0);
1907
1908 return l;
1909}
1910
1911void dispc_set_trans_key(enum omap_channel ch,
1912 enum omap_dss_trans_key_type type,
1913 u32 trans_key)
1914{
1915 const struct dispc_reg tr_reg[] = {
1916 DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 };
1917
1918 enable_clocks(1);
1919 if (ch == OMAP_DSS_CHANNEL_LCD)
1920 REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
1921 else /* OMAP_DSS_CHANNEL_DIGIT */
1922 REG_FLD_MOD(DISPC_CONFIG, type, 13, 13);
1923
1924 dispc_write_reg(tr_reg[ch], trans_key);
1925 enable_clocks(0);
1926}
1927
1928void dispc_get_trans_key(enum omap_channel ch,
1929 enum omap_dss_trans_key_type *type,
1930 u32 *trans_key)
1931{
1932 const struct dispc_reg tr_reg[] = {
1933 DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 };
1934
1935 enable_clocks(1);
1936 if (type) {
1937 if (ch == OMAP_DSS_CHANNEL_LCD)
1938 *type = REG_GET(DISPC_CONFIG, 11, 11);
1939 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
1940 *type = REG_GET(DISPC_CONFIG, 13, 13);
1941 else
1942 BUG();
1943 }
1944
1945 if (trans_key)
1946 *trans_key = dispc_read_reg(tr_reg[ch]);
1947 enable_clocks(0);
1948}
1949
1950void dispc_enable_trans_key(enum omap_channel ch, bool enable)
1951{
1952 enable_clocks(1);
1953 if (ch == OMAP_DSS_CHANNEL_LCD)
1954 REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
1955 else /* OMAP_DSS_CHANNEL_DIGIT */
1956 REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
1957 enable_clocks(0);
1958}
1959void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
1960{
1961 if (cpu_is_omap24xx())
1962 return;
1963
1964 enable_clocks(1);
1965 if (ch == OMAP_DSS_CHANNEL_LCD)
1966 REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
1967 else /* OMAP_DSS_CHANNEL_DIGIT */
1968 REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
1969 enable_clocks(0);
1970}
1971bool dispc_alpha_blending_enabled(enum omap_channel ch)
1972{
1973 bool enabled;
1974
1975 if (cpu_is_omap24xx())
1976 return false;
1977
1978 enable_clocks(1);
1979 if (ch == OMAP_DSS_CHANNEL_LCD)
1980 enabled = REG_GET(DISPC_CONFIG, 18, 18);
1981 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
1982 enabled = REG_GET(DISPC_CONFIG, 18, 18);
1983 else
1984 BUG();
1985 enable_clocks(0);
1986
1987 return enabled;
1988
1989}
1990
1991
1992bool dispc_trans_key_enabled(enum omap_channel ch)
1993{
1994 bool enabled;
1995
1996 enable_clocks(1);
1997 if (ch == OMAP_DSS_CHANNEL_LCD)
1998 enabled = REG_GET(DISPC_CONFIG, 10, 10);
1999 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2000 enabled = REG_GET(DISPC_CONFIG, 12, 12);
2001 else
2002 BUG();
2003 enable_clocks(0);
2004
2005 return enabled;
2006}
2007
2008
2009void dispc_set_tft_data_lines(u8 data_lines)
2010{
2011 int code;
2012
2013 switch (data_lines) {
2014 case 12:
2015 code = 0;
2016 break;
2017 case 16:
2018 code = 1;
2019 break;
2020 case 18:
2021 code = 2;
2022 break;
2023 case 24:
2024 code = 3;
2025 break;
2026 default:
2027 BUG();
2028 return;
2029 }
2030
2031 enable_clocks(1);
2032 REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
2033 enable_clocks(0);
2034}
2035
2036void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode)
2037{
2038 u32 l;
2039 int stallmode;
2040 int gpout0 = 1;
2041 int gpout1;
2042
2043 switch (mode) {
2044 case OMAP_DSS_PARALLELMODE_BYPASS:
2045 stallmode = 0;
2046 gpout1 = 1;
2047 break;
2048
2049 case OMAP_DSS_PARALLELMODE_RFBI:
2050 stallmode = 1;
2051 gpout1 = 0;
2052 break;
2053
2054 case OMAP_DSS_PARALLELMODE_DSI:
2055 stallmode = 1;
2056 gpout1 = 1;
2057 break;
2058
2059 default:
2060 BUG();
2061 return;
2062 }
2063
2064 enable_clocks(1);
2065
2066 l = dispc_read_reg(DISPC_CONTROL);
2067
2068 l = FLD_MOD(l, stallmode, 11, 11);
2069 l = FLD_MOD(l, gpout0, 15, 15);
2070 l = FLD_MOD(l, gpout1, 16, 16);
2071
2072 dispc_write_reg(DISPC_CONTROL, l);
2073
2074 enable_clocks(0);
2075}
2076
2077static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
2078 int vsw, int vfp, int vbp)
2079{
2080 if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
2081 if (hsw < 1 || hsw > 64 ||
2082 hfp < 1 || hfp > 256 ||
2083 hbp < 1 || hbp > 256 ||
2084 vsw < 1 || vsw > 64 ||
2085 vfp < 0 || vfp > 255 ||
2086 vbp < 0 || vbp > 255)
2087 return false;
2088 } else {
2089 if (hsw < 1 || hsw > 256 ||
2090 hfp < 1 || hfp > 4096 ||
2091 hbp < 1 || hbp > 4096 ||
2092 vsw < 1 || vsw > 256 ||
2093 vfp < 0 || vfp > 4095 ||
2094 vbp < 0 || vbp > 4095)
2095 return false;
2096 }
2097
2098 return true;
2099}
2100
2101bool dispc_lcd_timings_ok(struct omap_video_timings *timings)
2102{
2103 return _dispc_lcd_timings_ok(timings->hsw, timings->hfp,
2104 timings->hbp, timings->vsw,
2105 timings->vfp, timings->vbp);
2106}
2107
2108static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp,
2109 int vsw, int vfp, int vbp)
2110{
2111 u32 timing_h, timing_v;
2112
2113 if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
2114 timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) |
2115 FLD_VAL(hbp-1, 27, 20);
2116
2117 timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) |
2118 FLD_VAL(vbp, 27, 20);
2119 } else {
2120 timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) |
2121 FLD_VAL(hbp-1, 31, 20);
2122
2123 timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) |
2124 FLD_VAL(vbp, 31, 20);
2125 }
2126
2127 enable_clocks(1);
2128 dispc_write_reg(DISPC_TIMING_H, timing_h);
2129 dispc_write_reg(DISPC_TIMING_V, timing_v);
2130 enable_clocks(0);
2131}
2132
2133/* change name to mode? */
2134void dispc_set_lcd_timings(struct omap_video_timings *timings)
2135{
2136 unsigned xtot, ytot;
2137 unsigned long ht, vt;
2138
2139 if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp,
2140 timings->hbp, timings->vsw,
2141 timings->vfp, timings->vbp))
2142 BUG();
2143
2144 _dispc_set_lcd_timings(timings->hsw, timings->hfp, timings->hbp,
2145 timings->vsw, timings->vfp, timings->vbp);
2146
2147 dispc_set_lcd_size(timings->x_res, timings->y_res);
2148
2149 xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp;
2150 ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp;
2151
2152 ht = (timings->pixel_clock * 1000) / xtot;
2153 vt = (timings->pixel_clock * 1000) / xtot / ytot;
2154
2155 DSSDBG("xres %u yres %u\n", timings->x_res, timings->y_res);
2156 DSSDBG("pck %u\n", timings->pixel_clock);
2157 DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
2158 timings->hsw, timings->hfp, timings->hbp,
2159 timings->vsw, timings->vfp, timings->vbp);
2160
2161 DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
2162}
2163
2164static void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div)
2165{
2166 BUG_ON(lck_div < 1);
2167 BUG_ON(pck_div < 2);
2168
2169 enable_clocks(1);
2170 dispc_write_reg(DISPC_DIVISOR,
2171 FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
2172 enable_clocks(0);
2173}
2174
2175static void dispc_get_lcd_divisor(int *lck_div, int *pck_div)
2176{
2177 u32 l;
2178 l = dispc_read_reg(DISPC_DIVISOR);
2179 *lck_div = FLD_GET(l, 23, 16);
2180 *pck_div = FLD_GET(l, 7, 0);
2181}
2182
2183unsigned long dispc_fclk_rate(void)
2184{
2185 unsigned long r = 0;
2186
2187 if (dss_get_dispc_clk_source() == 0)
2188 r = dss_clk_get_rate(DSS_CLK_FCK1);
2189 else
2190#ifdef CONFIG_OMAP2_DSS_DSI
2191 r = dsi_get_dsi1_pll_rate();
2192#else
2193 BUG();
2194#endif
2195 return r;
2196}
2197
2198unsigned long dispc_lclk_rate(void)
2199{
2200 int lcd;
2201 unsigned long r;
2202 u32 l;
2203
2204 l = dispc_read_reg(DISPC_DIVISOR);
2205
2206 lcd = FLD_GET(l, 23, 16);
2207
2208 r = dispc_fclk_rate();
2209
2210 return r / lcd;
2211}
2212
2213unsigned long dispc_pclk_rate(void)
2214{
2215 int lcd, pcd;
2216 unsigned long r;
2217 u32 l;
2218
2219 l = dispc_read_reg(DISPC_DIVISOR);
2220
2221 lcd = FLD_GET(l, 23, 16);
2222 pcd = FLD_GET(l, 7, 0);
2223
2224 r = dispc_fclk_rate();
2225
2226 return r / lcd / pcd;
2227}
2228
2229void dispc_dump_clocks(struct seq_file *s)
2230{
2231 int lcd, pcd;
2232
2233 enable_clocks(1);
2234
2235 dispc_get_lcd_divisor(&lcd, &pcd);
2236
2237 seq_printf(s, "- DISPC -\n");
2238
2239 seq_printf(s, "dispc fclk source = %s\n",
2240 dss_get_dispc_clk_source() == 0 ?
2241 "dss1_alwon_fclk" : "dsi1_pll_fclk");
2242
2243 seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate());
2244 seq_printf(s, "lck\t\t%-16lulck div\t%u\n", dispc_lclk_rate(), lcd);
2245 seq_printf(s, "pck\t\t%-16lupck div\t%u\n", dispc_pclk_rate(), pcd);
2246
2247 enable_clocks(0);
2248}
2249
2250void dispc_dump_regs(struct seq_file *s)
2251{
2252#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r))
2253
2254 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
2255
2256 DUMPREG(DISPC_REVISION);
2257 DUMPREG(DISPC_SYSCONFIG);
2258 DUMPREG(DISPC_SYSSTATUS);
2259 DUMPREG(DISPC_IRQSTATUS);
2260 DUMPREG(DISPC_IRQENABLE);
2261 DUMPREG(DISPC_CONTROL);
2262 DUMPREG(DISPC_CONFIG);
2263 DUMPREG(DISPC_CAPABLE);
2264 DUMPREG(DISPC_DEFAULT_COLOR0);
2265 DUMPREG(DISPC_DEFAULT_COLOR1);
2266 DUMPREG(DISPC_TRANS_COLOR0);
2267 DUMPREG(DISPC_TRANS_COLOR1);
2268 DUMPREG(DISPC_LINE_STATUS);
2269 DUMPREG(DISPC_LINE_NUMBER);
2270 DUMPREG(DISPC_TIMING_H);
2271 DUMPREG(DISPC_TIMING_V);
2272 DUMPREG(DISPC_POL_FREQ);
2273 DUMPREG(DISPC_DIVISOR);
2274 DUMPREG(DISPC_GLOBAL_ALPHA);
2275 DUMPREG(DISPC_SIZE_DIG);
2276 DUMPREG(DISPC_SIZE_LCD);
2277
2278 DUMPREG(DISPC_GFX_BA0);
2279 DUMPREG(DISPC_GFX_BA1);
2280 DUMPREG(DISPC_GFX_POSITION);
2281 DUMPREG(DISPC_GFX_SIZE);
2282 DUMPREG(DISPC_GFX_ATTRIBUTES);
2283 DUMPREG(DISPC_GFX_FIFO_THRESHOLD);
2284 DUMPREG(DISPC_GFX_FIFO_SIZE_STATUS);
2285 DUMPREG(DISPC_GFX_ROW_INC);
2286 DUMPREG(DISPC_GFX_PIXEL_INC);
2287 DUMPREG(DISPC_GFX_WINDOW_SKIP);
2288 DUMPREG(DISPC_GFX_TABLE_BA);
2289
2290 DUMPREG(DISPC_DATA_CYCLE1);
2291 DUMPREG(DISPC_DATA_CYCLE2);
2292 DUMPREG(DISPC_DATA_CYCLE3);
2293
2294 DUMPREG(DISPC_CPR_COEF_R);
2295 DUMPREG(DISPC_CPR_COEF_G);
2296 DUMPREG(DISPC_CPR_COEF_B);
2297
2298 DUMPREG(DISPC_GFX_PRELOAD);
2299
2300 DUMPREG(DISPC_VID_BA0(0));
2301 DUMPREG(DISPC_VID_BA1(0));
2302 DUMPREG(DISPC_VID_POSITION(0));
2303 DUMPREG(DISPC_VID_SIZE(0));
2304 DUMPREG(DISPC_VID_ATTRIBUTES(0));
2305 DUMPREG(DISPC_VID_FIFO_THRESHOLD(0));
2306 DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(0));
2307 DUMPREG(DISPC_VID_ROW_INC(0));
2308 DUMPREG(DISPC_VID_PIXEL_INC(0));
2309 DUMPREG(DISPC_VID_FIR(0));
2310 DUMPREG(DISPC_VID_PICTURE_SIZE(0));
2311 DUMPREG(DISPC_VID_ACCU0(0));
2312 DUMPREG(DISPC_VID_ACCU1(0));
2313
2314 DUMPREG(DISPC_VID_BA0(1));
2315 DUMPREG(DISPC_VID_BA1(1));
2316 DUMPREG(DISPC_VID_POSITION(1));
2317 DUMPREG(DISPC_VID_SIZE(1));
2318 DUMPREG(DISPC_VID_ATTRIBUTES(1));
2319 DUMPREG(DISPC_VID_FIFO_THRESHOLD(1));
2320 DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(1));
2321 DUMPREG(DISPC_VID_ROW_INC(1));
2322 DUMPREG(DISPC_VID_PIXEL_INC(1));
2323 DUMPREG(DISPC_VID_FIR(1));
2324 DUMPREG(DISPC_VID_PICTURE_SIZE(1));
2325 DUMPREG(DISPC_VID_ACCU0(1));
2326 DUMPREG(DISPC_VID_ACCU1(1));
2327
2328 DUMPREG(DISPC_VID_FIR_COEF_H(0, 0));
2329 DUMPREG(DISPC_VID_FIR_COEF_H(0, 1));
2330 DUMPREG(DISPC_VID_FIR_COEF_H(0, 2));
2331 DUMPREG(DISPC_VID_FIR_COEF_H(0, 3));
2332 DUMPREG(DISPC_VID_FIR_COEF_H(0, 4));
2333 DUMPREG(DISPC_VID_FIR_COEF_H(0, 5));
2334 DUMPREG(DISPC_VID_FIR_COEF_H(0, 6));
2335 DUMPREG(DISPC_VID_FIR_COEF_H(0, 7));
2336 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 0));
2337 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 1));
2338 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 2));
2339 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 3));
2340 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 4));
2341 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 5));
2342 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 6));
2343 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 7));
2344 DUMPREG(DISPC_VID_CONV_COEF(0, 0));
2345 DUMPREG(DISPC_VID_CONV_COEF(0, 1));
2346 DUMPREG(DISPC_VID_CONV_COEF(0, 2));
2347 DUMPREG(DISPC_VID_CONV_COEF(0, 3));
2348 DUMPREG(DISPC_VID_CONV_COEF(0, 4));
2349 DUMPREG(DISPC_VID_FIR_COEF_V(0, 0));
2350 DUMPREG(DISPC_VID_FIR_COEF_V(0, 1));
2351 DUMPREG(DISPC_VID_FIR_COEF_V(0, 2));
2352 DUMPREG(DISPC_VID_FIR_COEF_V(0, 3));
2353 DUMPREG(DISPC_VID_FIR_COEF_V(0, 4));
2354 DUMPREG(DISPC_VID_FIR_COEF_V(0, 5));
2355 DUMPREG(DISPC_VID_FIR_COEF_V(0, 6));
2356 DUMPREG(DISPC_VID_FIR_COEF_V(0, 7));
2357
2358 DUMPREG(DISPC_VID_FIR_COEF_H(1, 0));
2359 DUMPREG(DISPC_VID_FIR_COEF_H(1, 1));
2360 DUMPREG(DISPC_VID_FIR_COEF_H(1, 2));
2361 DUMPREG(DISPC_VID_FIR_COEF_H(1, 3));
2362 DUMPREG(DISPC_VID_FIR_COEF_H(1, 4));
2363 DUMPREG(DISPC_VID_FIR_COEF_H(1, 5));
2364 DUMPREG(DISPC_VID_FIR_COEF_H(1, 6));
2365 DUMPREG(DISPC_VID_FIR_COEF_H(1, 7));
2366 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 0));
2367 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 1));
2368 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 2));
2369 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 3));
2370 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 4));
2371 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 5));
2372 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 6));
2373 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 7));
2374 DUMPREG(DISPC_VID_CONV_COEF(1, 0));
2375 DUMPREG(DISPC_VID_CONV_COEF(1, 1));
2376 DUMPREG(DISPC_VID_CONV_COEF(1, 2));
2377 DUMPREG(DISPC_VID_CONV_COEF(1, 3));
2378 DUMPREG(DISPC_VID_CONV_COEF(1, 4));
2379 DUMPREG(DISPC_VID_FIR_COEF_V(1, 0));
2380 DUMPREG(DISPC_VID_FIR_COEF_V(1, 1));
2381 DUMPREG(DISPC_VID_FIR_COEF_V(1, 2));
2382 DUMPREG(DISPC_VID_FIR_COEF_V(1, 3));
2383 DUMPREG(DISPC_VID_FIR_COEF_V(1, 4));
2384 DUMPREG(DISPC_VID_FIR_COEF_V(1, 5));
2385 DUMPREG(DISPC_VID_FIR_COEF_V(1, 6));
2386 DUMPREG(DISPC_VID_FIR_COEF_V(1, 7));
2387
2388 DUMPREG(DISPC_VID_PRELOAD(0));
2389 DUMPREG(DISPC_VID_PRELOAD(1));
2390
2391 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
2392#undef DUMPREG
2393}
2394
2395static void _dispc_set_pol_freq(bool onoff, bool rf, bool ieo, bool ipc,
2396 bool ihs, bool ivs, u8 acbi, u8 acb)
2397{
2398 u32 l = 0;
2399
2400 DSSDBG("onoff %d rf %d ieo %d ipc %d ihs %d ivs %d acbi %d acb %d\n",
2401 onoff, rf, ieo, ipc, ihs, ivs, acbi, acb);
2402
2403 l |= FLD_VAL(onoff, 17, 17);
2404 l |= FLD_VAL(rf, 16, 16);
2405 l |= FLD_VAL(ieo, 15, 15);
2406 l |= FLD_VAL(ipc, 14, 14);
2407 l |= FLD_VAL(ihs, 13, 13);
2408 l |= FLD_VAL(ivs, 12, 12);
2409 l |= FLD_VAL(acbi, 11, 8);
2410 l |= FLD_VAL(acb, 7, 0);
2411
2412 enable_clocks(1);
2413 dispc_write_reg(DISPC_POL_FREQ, l);
2414 enable_clocks(0);
2415}
2416
2417void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb)
2418{
2419 _dispc_set_pol_freq((config & OMAP_DSS_LCD_ONOFF) != 0,
2420 (config & OMAP_DSS_LCD_RF) != 0,
2421 (config & OMAP_DSS_LCD_IEO) != 0,
2422 (config & OMAP_DSS_LCD_IPC) != 0,
2423 (config & OMAP_DSS_LCD_IHS) != 0,
2424 (config & OMAP_DSS_LCD_IVS) != 0,
2425 acbi, acb);
2426}
2427
2428/* with fck as input clock rate, find dispc dividers that produce req_pck */
2429void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
2430 struct dispc_clock_info *cinfo)
2431{
2432 u16 pcd_min = is_tft ? 2 : 3;
2433 unsigned long best_pck;
2434 u16 best_ld, cur_ld;
2435 u16 best_pd, cur_pd;
2436
2437 best_pck = 0;
2438 best_ld = 0;
2439 best_pd = 0;
2440
2441 for (cur_ld = 1; cur_ld <= 255; ++cur_ld) {
2442 unsigned long lck = fck / cur_ld;
2443
2444 for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) {
2445 unsigned long pck = lck / cur_pd;
2446 long old_delta = abs(best_pck - req_pck);
2447 long new_delta = abs(pck - req_pck);
2448
2449 if (best_pck == 0 || new_delta < old_delta) {
2450 best_pck = pck;
2451 best_ld = cur_ld;
2452 best_pd = cur_pd;
2453
2454 if (pck == req_pck)
2455 goto found;
2456 }
2457
2458 if (pck < req_pck)
2459 break;
2460 }
2461
2462 if (lck / pcd_min < req_pck)
2463 break;
2464 }
2465
2466found:
2467 cinfo->lck_div = best_ld;
2468 cinfo->pck_div = best_pd;
2469 cinfo->lck = fck / cinfo->lck_div;
2470 cinfo->pck = cinfo->lck / cinfo->pck_div;
2471}
2472
2473/* calculate clock rates using dividers in cinfo */
2474int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
2475 struct dispc_clock_info *cinfo)
2476{
2477 if (cinfo->lck_div > 255 || cinfo->lck_div == 0)
2478 return -EINVAL;
2479 if (cinfo->pck_div < 2 || cinfo->pck_div > 255)
2480 return -EINVAL;
2481
2482 cinfo->lck = dispc_fclk_rate / cinfo->lck_div;
2483 cinfo->pck = cinfo->lck / cinfo->pck_div;
2484
2485 return 0;
2486}
2487
2488int dispc_set_clock_div(struct dispc_clock_info *cinfo)
2489{
2490 DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);
2491 DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div);
2492
2493 dispc_set_lcd_divisor(cinfo->lck_div, cinfo->pck_div);
2494
2495 return 0;
2496}
2497
2498int dispc_get_clock_div(struct dispc_clock_info *cinfo)
2499{
2500 unsigned long fck;
2501
2502 fck = dispc_fclk_rate();
2503
2504 cinfo->lck_div = REG_GET(DISPC_DIVISOR, 23, 16);
2505 cinfo->pck_div = REG_GET(DISPC_DIVISOR, 7, 0);
2506
2507 cinfo->lck = fck / cinfo->lck_div;
2508 cinfo->pck = cinfo->lck / cinfo->pck_div;
2509
2510 return 0;
2511}
2512
2513/* dispc.irq_lock has to be locked by the caller */
2514static void _omap_dispc_set_irqs(void)
2515{
2516 u32 mask;
2517 u32 old_mask;
2518 int i;
2519 struct omap_dispc_isr_data *isr_data;
2520
2521 mask = dispc.irq_error_mask;
2522
2523 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
2524 isr_data = &dispc.registered_isr[i];
2525
2526 if (isr_data->isr == NULL)
2527 continue;
2528
2529 mask |= isr_data->mask;
2530 }
2531
2532 enable_clocks(1);
2533
2534 old_mask = dispc_read_reg(DISPC_IRQENABLE);
2535 /* clear the irqstatus for newly enabled irqs */
2536 dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
2537
2538 dispc_write_reg(DISPC_IRQENABLE, mask);
2539
2540 enable_clocks(0);
2541}
2542
2543int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
2544{
2545 int i;
2546 int ret;
2547 unsigned long flags;
2548 struct omap_dispc_isr_data *isr_data;
2549
2550 if (isr == NULL)
2551 return -EINVAL;
2552
2553 spin_lock_irqsave(&dispc.irq_lock, flags);
2554
2555 /* check for duplicate entry */
2556 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
2557 isr_data = &dispc.registered_isr[i];
2558 if (isr_data->isr == isr && isr_data->arg == arg &&
2559 isr_data->mask == mask) {
2560 ret = -EINVAL;
2561 goto err;
2562 }
2563 }
2564
2565 isr_data = NULL;
2566 ret = -EBUSY;
2567
2568 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
2569 isr_data = &dispc.registered_isr[i];
2570
2571 if (isr_data->isr != NULL)
2572 continue;
2573
2574 isr_data->isr = isr;
2575 isr_data->arg = arg;
2576 isr_data->mask = mask;
2577 ret = 0;
2578
2579 break;
2580 }
2581
2582 _omap_dispc_set_irqs();
2583
2584 spin_unlock_irqrestore(&dispc.irq_lock, flags);
2585
2586 return 0;
2587err:
2588 spin_unlock_irqrestore(&dispc.irq_lock, flags);
2589
2590 return ret;
2591}
2592EXPORT_SYMBOL(omap_dispc_register_isr);
2593
2594int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
2595{
2596 int i;
2597 unsigned long flags;
2598 int ret = -EINVAL;
2599 struct omap_dispc_isr_data *isr_data;
2600
2601 spin_lock_irqsave(&dispc.irq_lock, flags);
2602
2603 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
2604 isr_data = &dispc.registered_isr[i];
2605 if (isr_data->isr != isr || isr_data->arg != arg ||
2606 isr_data->mask != mask)
2607 continue;
2608
2609 /* found the correct isr */
2610
2611 isr_data->isr = NULL;
2612 isr_data->arg = NULL;
2613 isr_data->mask = 0;
2614
2615 ret = 0;
2616 break;
2617 }
2618
2619 if (ret == 0)
2620 _omap_dispc_set_irqs();
2621
2622 spin_unlock_irqrestore(&dispc.irq_lock, flags);
2623
2624 return ret;
2625}
2626EXPORT_SYMBOL(omap_dispc_unregister_isr);
2627
2628#ifdef DEBUG
2629static void print_irq_status(u32 status)
2630{
2631 if ((status & dispc.irq_error_mask) == 0)
2632 return;
2633
2634 printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status);
2635
2636#define PIS(x) \
2637 if (status & DISPC_IRQ_##x) \
2638 printk(#x " ");
2639 PIS(GFX_FIFO_UNDERFLOW);
2640 PIS(OCP_ERR);
2641 PIS(VID1_FIFO_UNDERFLOW);
2642 PIS(VID2_FIFO_UNDERFLOW);
2643 PIS(SYNC_LOST);
2644 PIS(SYNC_LOST_DIGIT);
2645#undef PIS
2646
2647 printk("\n");
2648}
2649#endif
2650
2651/* Called from dss.c. Note that we don't touch clocks here,
2652 * but we presume they are on because we got an IRQ. However,
2653 * an irq handler may turn the clocks off, so we may not have
2654 * clock later in the function. */
2655void dispc_irq_handler(void)
2656{
2657 int i;
2658 u32 irqstatus;
2659 u32 handledirqs = 0;
2660 u32 unhandled_errors;
2661 struct omap_dispc_isr_data *isr_data;
2662 struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
2663
2664 spin_lock(&dispc.irq_lock);
2665
2666 irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
2667
2668#ifdef DEBUG
2669 if (dss_debug)
2670 print_irq_status(irqstatus);
2671#endif
2672 /* Ack the interrupt. Do it here before clocks are possibly turned
2673 * off */
2674 dispc_write_reg(DISPC_IRQSTATUS, irqstatus);
2675 /* flush posted write */
2676 dispc_read_reg(DISPC_IRQSTATUS);
2677
2678 /* make a copy and unlock, so that isrs can unregister
2679 * themselves */
2680 memcpy(registered_isr, dispc.registered_isr,
2681 sizeof(registered_isr));
2682
2683 spin_unlock(&dispc.irq_lock);
2684
2685 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
2686 isr_data = &registered_isr[i];
2687
2688 if (!isr_data->isr)
2689 continue;
2690
2691 if (isr_data->mask & irqstatus) {
2692 isr_data->isr(isr_data->arg, irqstatus);
2693 handledirqs |= isr_data->mask;
2694 }
2695 }
2696
2697 spin_lock(&dispc.irq_lock);
2698
2699 unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask;
2700
2701 if (unhandled_errors) {
2702 dispc.error_irqs |= unhandled_errors;
2703
2704 dispc.irq_error_mask &= ~unhandled_errors;
2705 _omap_dispc_set_irqs();
2706
2707 schedule_work(&dispc.error_work);
2708 }
2709
2710 spin_unlock(&dispc.irq_lock);
2711}
2712
2713static void dispc_error_worker(struct work_struct *work)
2714{
2715 int i;
2716 u32 errors;
2717 unsigned long flags;
2718
2719 spin_lock_irqsave(&dispc.irq_lock, flags);
2720 errors = dispc.error_irqs;
2721 dispc.error_irqs = 0;
2722 spin_unlock_irqrestore(&dispc.irq_lock, flags);
2723
2724 if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) {
2725 DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n");
2726 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
2727 struct omap_overlay *ovl;
2728 ovl = omap_dss_get_overlay(i);
2729
2730 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
2731 continue;
2732
2733 if (ovl->id == 0) {
2734 dispc_enable_plane(ovl->id, 0);
2735 dispc_go(ovl->manager->id);
2736 mdelay(50);
2737 break;
2738 }
2739 }
2740 }
2741
2742 if (errors & DISPC_IRQ_VID1_FIFO_UNDERFLOW) {
2743 DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n");
2744 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
2745 struct omap_overlay *ovl;
2746 ovl = omap_dss_get_overlay(i);
2747
2748 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
2749 continue;
2750
2751 if (ovl->id == 1) {
2752 dispc_enable_plane(ovl->id, 0);
2753 dispc_go(ovl->manager->id);
2754 mdelay(50);
2755 break;
2756 }
2757 }
2758 }
2759
2760 if (errors & DISPC_IRQ_VID2_FIFO_UNDERFLOW) {
2761 DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n");
2762 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
2763 struct omap_overlay *ovl;
2764 ovl = omap_dss_get_overlay(i);
2765
2766 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
2767 continue;
2768
2769 if (ovl->id == 2) {
2770 dispc_enable_plane(ovl->id, 0);
2771 dispc_go(ovl->manager->id);
2772 mdelay(50);
2773 break;
2774 }
2775 }
2776 }
2777
2778 if (errors & DISPC_IRQ_SYNC_LOST) {
2779 struct omap_overlay_manager *manager = NULL;
2780 bool enable = false;
2781
2782 DSSERR("SYNC_LOST, disabling LCD\n");
2783
2784 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
2785 struct omap_overlay_manager *mgr;
2786 mgr = omap_dss_get_overlay_manager(i);
2787
2788 if (mgr->id == OMAP_DSS_CHANNEL_LCD) {
2789 manager = mgr;
2790 enable = mgr->device->state ==
2791 OMAP_DSS_DISPLAY_ACTIVE;
2792 mgr->device->disable(mgr->device);
2793 break;
2794 }
2795 }
2796
2797 if (manager) {
2798 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
2799 struct omap_overlay *ovl;
2800 ovl = omap_dss_get_overlay(i);
2801
2802 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
2803 continue;
2804
2805 if (ovl->id != 0 && ovl->manager == manager)
2806 dispc_enable_plane(ovl->id, 0);
2807 }
2808
2809 dispc_go(manager->id);
2810 mdelay(50);
2811 if (enable)
2812 manager->device->enable(manager->device);
2813 }
2814 }
2815
2816 if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) {
2817 struct omap_overlay_manager *manager = NULL;
2818 bool enable = false;
2819
2820 DSSERR("SYNC_LOST_DIGIT, disabling TV\n");
2821
2822 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
2823 struct omap_overlay_manager *mgr;
2824 mgr = omap_dss_get_overlay_manager(i);
2825
2826 if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) {
2827 manager = mgr;
2828 enable = mgr->device->state ==
2829 OMAP_DSS_DISPLAY_ACTIVE;
2830 mgr->device->disable(mgr->device);
2831 break;
2832 }
2833 }
2834
2835 if (manager) {
2836 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
2837 struct omap_overlay *ovl;
2838 ovl = omap_dss_get_overlay(i);
2839
2840 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
2841 continue;
2842
2843 if (ovl->id != 0 && ovl->manager == manager)
2844 dispc_enable_plane(ovl->id, 0);
2845 }
2846
2847 dispc_go(manager->id);
2848 mdelay(50);
2849 if (enable)
2850 manager->device->enable(manager->device);
2851 }
2852 }
2853
2854 if (errors & DISPC_IRQ_OCP_ERR) {
2855 DSSERR("OCP_ERR\n");
2856 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
2857 struct omap_overlay_manager *mgr;
2858 mgr = omap_dss_get_overlay_manager(i);
2859
2860 if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC)
2861 mgr->device->disable(mgr->device);
2862 }
2863 }
2864
2865 spin_lock_irqsave(&dispc.irq_lock, flags);
2866 dispc.irq_error_mask |= errors;
2867 _omap_dispc_set_irqs();
2868 spin_unlock_irqrestore(&dispc.irq_lock, flags);
2869}
2870
2871int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
2872{
2873 void dispc_irq_wait_handler(void *data, u32 mask)
2874 {
2875 complete((struct completion *)data);
2876 }
2877
2878 int r;
2879 DECLARE_COMPLETION_ONSTACK(completion);
2880
2881 r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
2882 irqmask);
2883
2884 if (r)
2885 return r;
2886
2887 timeout = wait_for_completion_timeout(&completion, timeout);
2888
2889 omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
2890
2891 if (timeout == 0)
2892 return -ETIMEDOUT;
2893
2894 if (timeout == -ERESTARTSYS)
2895 return -ERESTARTSYS;
2896
2897 return 0;
2898}
2899
2900int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
2901 unsigned long timeout)
2902{
2903 void dispc_irq_wait_handler(void *data, u32 mask)
2904 {
2905 complete((struct completion *)data);
2906 }
2907
2908 int r;
2909 DECLARE_COMPLETION_ONSTACK(completion);
2910
2911 r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
2912 irqmask);
2913
2914 if (r)
2915 return r;
2916
2917 timeout = wait_for_completion_interruptible_timeout(&completion,
2918 timeout);
2919
2920 omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
2921
2922 if (timeout == 0)
2923 return -ETIMEDOUT;
2924
2925 if (timeout == -ERESTARTSYS)
2926 return -ERESTARTSYS;
2927
2928 return 0;
2929}
2930
2931#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
2932void dispc_fake_vsync_irq(void)
2933{
2934 u32 irqstatus = DISPC_IRQ_VSYNC;
2935 int i;
2936
2937 local_irq_disable();
2938
2939 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
2940 struct omap_dispc_isr_data *isr_data;
2941 isr_data = &dispc.registered_isr[i];
2942
2943 if (!isr_data->isr)
2944 continue;
2945
2946 if (isr_data->mask & irqstatus)
2947 isr_data->isr(isr_data->arg, irqstatus);
2948 }
2949
2950 local_irq_enable();
2951}
2952#endif
2953
2954static void _omap_dispc_initialize_irq(void)
2955{
2956 unsigned long flags;
2957
2958 spin_lock_irqsave(&dispc.irq_lock, flags);
2959
2960 memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr));
2961
2962 dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
2963
2964 /* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
2965 * so clear it */
2966 dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS));
2967
2968 _omap_dispc_set_irqs();
2969
2970 spin_unlock_irqrestore(&dispc.irq_lock, flags);
2971}
2972
2973void dispc_enable_sidle(void)
2974{
2975 REG_FLD_MOD(DISPC_SYSCONFIG, 2, 4, 3); /* SIDLEMODE: smart idle */
2976}
2977
2978void dispc_disable_sidle(void)
2979{
2980 REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */
2981}
2982
2983static void _omap_dispc_initial_config(void)
2984{
2985 u32 l;
2986
2987 l = dispc_read_reg(DISPC_SYSCONFIG);
2988 l = FLD_MOD(l, 2, 13, 12); /* MIDLEMODE: smart standby */
2989 l = FLD_MOD(l, 2, 4, 3); /* SIDLEMODE: smart idle */
2990 l = FLD_MOD(l, 1, 2, 2); /* ENWAKEUP */
2991 l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */
2992 dispc_write_reg(DISPC_SYSCONFIG, l);
2993
2994 /* FUNCGATED */
2995 REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
2996
2997 /* L3 firewall setting: enable access to OCM RAM */
2998 /* XXX this should be somewhere in plat-omap */
2999 if (cpu_is_omap24xx())
3000 __raw_writel(0x402000b0, OMAP2_L3_IO_ADDRESS(0x680050a0));
3001
3002 _dispc_setup_color_conv_coef();
3003
3004 dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
3005
3006 dispc_read_plane_fifo_sizes();
3007}
3008
3009int dispc_init(void)
3010{
3011 u32 rev;
3012
3013 spin_lock_init(&dispc.irq_lock);
3014
3015 INIT_WORK(&dispc.error_work, dispc_error_worker);
3016
3017 dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS);
3018 if (!dispc.base) {
3019 DSSERR("can't ioremap DISPC\n");
3020 return -ENOMEM;
3021 }
3022
3023 enable_clocks(1);
3024
3025 _omap_dispc_initial_config();
3026
3027 _omap_dispc_initialize_irq();
3028
3029 dispc_save_context();
3030
3031 rev = dispc_read_reg(DISPC_REVISION);
3032 printk(KERN_INFO "OMAP DISPC rev %d.%d\n",
3033 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
3034
3035 enable_clocks(0);
3036
3037 return 0;
3038}
3039
3040void dispc_exit(void)
3041{
3042 iounmap(dispc.base);
3043}
3044
3045int dispc_enable_plane(enum omap_plane plane, bool enable)
3046{
3047 DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
3048
3049 enable_clocks(1);
3050 _dispc_enable_plane(plane, enable);
3051 enable_clocks(0);
3052
3053 return 0;
3054}
3055
3056int dispc_setup_plane(enum omap_plane plane,
3057 u32 paddr, u16 screen_width,
3058 u16 pos_x, u16 pos_y,
3059 u16 width, u16 height,
3060 u16 out_width, u16 out_height,
3061 enum omap_color_mode color_mode,
3062 bool ilace,
3063 enum omap_dss_rotation_type rotation_type,
3064 u8 rotation, bool mirror, u8 global_alpha)
3065{
3066 int r = 0;
3067
3068 DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> "
3069 "%dx%d, ilace %d, cmode %x, rot %d, mir %d\n",
3070 plane, paddr, screen_width, pos_x, pos_y,
3071 width, height,
3072 out_width, out_height,
3073 ilace, color_mode,
3074 rotation, mirror);
3075
3076 enable_clocks(1);
3077
3078 r = _dispc_setup_plane(plane,
3079 paddr, screen_width,
3080 pos_x, pos_y,
3081 width, height,
3082 out_width, out_height,
3083 color_mode, ilace,
3084 rotation_type,
3085 rotation, mirror,
3086 global_alpha);
3087
3088 enable_clocks(0);
3089
3090 return r;
3091}
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
new file mode 100644
index 000000000000..3b92b84b9560
--- /dev/null
+++ b/drivers/video/omap2/dss/display.c
@@ -0,0 +1,671 @@
1/*
2 * linux/drivers/video/omap2/dss/display.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#define DSS_SUBSYS_NAME "DISPLAY"
24
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/jiffies.h>
28#include <linux/list.h>
29#include <linux/platform_device.h>
30
31#include <plat/display.h>
32#include "dss.h"
33
34static LIST_HEAD(display_list);
35
36static ssize_t display_enabled_show(struct device *dev,
37 struct device_attribute *attr, char *buf)
38{
39 struct omap_dss_device *dssdev = to_dss_device(dev);
40 bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED;
41
42 return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
43}
44
45static ssize_t display_enabled_store(struct device *dev,
46 struct device_attribute *attr,
47 const char *buf, size_t size)
48{
49 struct omap_dss_device *dssdev = to_dss_device(dev);
50 bool enabled, r;
51
52 enabled = simple_strtoul(buf, NULL, 10);
53
54 if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
55 if (enabled) {
56 r = dssdev->enable(dssdev);
57 if (r)
58 return r;
59 } else {
60 dssdev->disable(dssdev);
61 }
62 }
63
64 return size;
65}
66
67static ssize_t display_upd_mode_show(struct device *dev,
68 struct device_attribute *attr, char *buf)
69{
70 struct omap_dss_device *dssdev = to_dss_device(dev);
71 enum omap_dss_update_mode mode = OMAP_DSS_UPDATE_AUTO;
72 if (dssdev->get_update_mode)
73 mode = dssdev->get_update_mode(dssdev);
74 return snprintf(buf, PAGE_SIZE, "%d\n", mode);
75}
76
77static ssize_t display_upd_mode_store(struct device *dev,
78 struct device_attribute *attr,
79 const char *buf, size_t size)
80{
81 struct omap_dss_device *dssdev = to_dss_device(dev);
82 int val, r;
83 enum omap_dss_update_mode mode;
84
85 val = simple_strtoul(buf, NULL, 10);
86
87 switch (val) {
88 case OMAP_DSS_UPDATE_DISABLED:
89 case OMAP_DSS_UPDATE_AUTO:
90 case OMAP_DSS_UPDATE_MANUAL:
91 mode = (enum omap_dss_update_mode)val;
92 break;
93 default:
94 return -EINVAL;
95 }
96
97 r = dssdev->set_update_mode(dssdev, mode);
98 if (r)
99 return r;
100
101 return size;
102}
103
104static ssize_t display_tear_show(struct device *dev,
105 struct device_attribute *attr, char *buf)
106{
107 struct omap_dss_device *dssdev = to_dss_device(dev);
108 return snprintf(buf, PAGE_SIZE, "%d\n",
109 dssdev->get_te ? dssdev->get_te(dssdev) : 0);
110}
111
112static ssize_t display_tear_store(struct device *dev,
113 struct device_attribute *attr, const char *buf, size_t size)
114{
115 struct omap_dss_device *dssdev = to_dss_device(dev);
116 unsigned long te;
117 int r;
118
119 if (!dssdev->enable_te || !dssdev->get_te)
120 return -ENOENT;
121
122 te = simple_strtoul(buf, NULL, 0);
123
124 r = dssdev->enable_te(dssdev, te);
125 if (r)
126 return r;
127
128 return size;
129}
130
131static ssize_t display_timings_show(struct device *dev,
132 struct device_attribute *attr, char *buf)
133{
134 struct omap_dss_device *dssdev = to_dss_device(dev);
135 struct omap_video_timings t;
136
137 if (!dssdev->get_timings)
138 return -ENOENT;
139
140 dssdev->get_timings(dssdev, &t);
141
142 return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
143 t.pixel_clock,
144 t.x_res, t.hfp, t.hbp, t.hsw,
145 t.y_res, t.vfp, t.vbp, t.vsw);
146}
147
148static ssize_t display_timings_store(struct device *dev,
149 struct device_attribute *attr, const char *buf, size_t size)
150{
151 struct omap_dss_device *dssdev = to_dss_device(dev);
152 struct omap_video_timings t;
153 int r, found;
154
155 if (!dssdev->set_timings || !dssdev->check_timings)
156 return -ENOENT;
157
158 found = 0;
159#ifdef CONFIG_OMAP2_DSS_VENC
160 if (strncmp("pal", buf, 3) == 0) {
161 t = omap_dss_pal_timings;
162 found = 1;
163 } else if (strncmp("ntsc", buf, 4) == 0) {
164 t = omap_dss_ntsc_timings;
165 found = 1;
166 }
167#endif
168 if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
169 &t.pixel_clock,
170 &t.x_res, &t.hfp, &t.hbp, &t.hsw,
171 &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
172 return -EINVAL;
173
174 r = dssdev->check_timings(dssdev, &t);
175 if (r)
176 return r;
177
178 dssdev->set_timings(dssdev, &t);
179
180 return size;
181}
182
183static ssize_t display_rotate_show(struct device *dev,
184 struct device_attribute *attr, char *buf)
185{
186 struct omap_dss_device *dssdev = to_dss_device(dev);
187 int rotate;
188 if (!dssdev->get_rotate)
189 return -ENOENT;
190 rotate = dssdev->get_rotate(dssdev);
191 return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
192}
193
194static ssize_t display_rotate_store(struct device *dev,
195 struct device_attribute *attr, const char *buf, size_t size)
196{
197 struct omap_dss_device *dssdev = to_dss_device(dev);
198 unsigned long rot;
199 int r;
200
201 if (!dssdev->set_rotate || !dssdev->get_rotate)
202 return -ENOENT;
203
204 rot = simple_strtoul(buf, NULL, 0);
205
206 r = dssdev->set_rotate(dssdev, rot);
207 if (r)
208 return r;
209
210 return size;
211}
212
213static ssize_t display_mirror_show(struct device *dev,
214 struct device_attribute *attr, char *buf)
215{
216 struct omap_dss_device *dssdev = to_dss_device(dev);
217 int mirror;
218 if (!dssdev->get_mirror)
219 return -ENOENT;
220 mirror = dssdev->get_mirror(dssdev);
221 return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
222}
223
224static ssize_t display_mirror_store(struct device *dev,
225 struct device_attribute *attr, const char *buf, size_t size)
226{
227 struct omap_dss_device *dssdev = to_dss_device(dev);
228 unsigned long mirror;
229 int r;
230
231 if (!dssdev->set_mirror || !dssdev->get_mirror)
232 return -ENOENT;
233
234 mirror = simple_strtoul(buf, NULL, 0);
235
236 r = dssdev->set_mirror(dssdev, mirror);
237 if (r)
238 return r;
239
240 return size;
241}
242
243static ssize_t display_wss_show(struct device *dev,
244 struct device_attribute *attr, char *buf)
245{
246 struct omap_dss_device *dssdev = to_dss_device(dev);
247 unsigned int wss;
248
249 if (!dssdev->get_wss)
250 return -ENOENT;
251
252 wss = dssdev->get_wss(dssdev);
253
254 return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
255}
256
257static ssize_t display_wss_store(struct device *dev,
258 struct device_attribute *attr, const char *buf, size_t size)
259{
260 struct omap_dss_device *dssdev = to_dss_device(dev);
261 unsigned long wss;
262 int r;
263
264 if (!dssdev->get_wss || !dssdev->set_wss)
265 return -ENOENT;
266
267 if (strict_strtoul(buf, 0, &wss))
268 return -EINVAL;
269
270 if (wss > 0xfffff)
271 return -EINVAL;
272
273 r = dssdev->set_wss(dssdev, wss);
274 if (r)
275 return r;
276
277 return size;
278}
279
280static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
281 display_enabled_show, display_enabled_store);
282static DEVICE_ATTR(update_mode, S_IRUGO|S_IWUSR,
283 display_upd_mode_show, display_upd_mode_store);
284static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
285 display_tear_show, display_tear_store);
286static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
287 display_timings_show, display_timings_store);
288static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
289 display_rotate_show, display_rotate_store);
290static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
291 display_mirror_show, display_mirror_store);
292static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
293 display_wss_show, display_wss_store);
294
295static struct device_attribute *display_sysfs_attrs[] = {
296 &dev_attr_enabled,
297 &dev_attr_update_mode,
298 &dev_attr_tear_elim,
299 &dev_attr_timings,
300 &dev_attr_rotate,
301 &dev_attr_mirror,
302 &dev_attr_wss,
303 NULL
304};
305
306static void default_get_resolution(struct omap_dss_device *dssdev,
307 u16 *xres, u16 *yres)
308{
309 *xres = dssdev->panel.timings.x_res;
310 *yres = dssdev->panel.timings.y_res;
311}
312
313void default_get_overlay_fifo_thresholds(enum omap_plane plane,
314 u32 fifo_size, enum omap_burst_size *burst_size,
315 u32 *fifo_low, u32 *fifo_high)
316{
317 unsigned burst_size_bytes;
318
319 *burst_size = OMAP_DSS_BURST_16x32;
320 burst_size_bytes = 16 * 32 / 8;
321
322 *fifo_high = fifo_size - 1;
323 *fifo_low = fifo_size - burst_size_bytes;
324}
325
326static int default_wait_vsync(struct omap_dss_device *dssdev)
327{
328 unsigned long timeout = msecs_to_jiffies(500);
329 u32 irq;
330
331 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
332 irq = DISPC_IRQ_EVSYNC_ODD;
333 else
334 irq = DISPC_IRQ_VSYNC;
335
336 return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
337}
338
339static int default_get_recommended_bpp(struct omap_dss_device *dssdev)
340{
341 if (dssdev->panel.recommended_bpp)
342 return dssdev->panel.recommended_bpp;
343
344 switch (dssdev->type) {
345 case OMAP_DISPLAY_TYPE_DPI:
346 if (dssdev->phy.dpi.data_lines == 24)
347 return 24;
348 else
349 return 16;
350
351 case OMAP_DISPLAY_TYPE_DBI:
352 case OMAP_DISPLAY_TYPE_DSI:
353 if (dssdev->ctrl.pixel_size == 24)
354 return 24;
355 else
356 return 16;
357 case OMAP_DISPLAY_TYPE_VENC:
358 case OMAP_DISPLAY_TYPE_SDI:
359 return 24;
360 return 24;
361 default:
362 BUG();
363 }
364}
365
366/* Checks if replication logic should be used. Only use for active matrix,
367 * when overlay is in RGB12U or RGB16 mode, and LCD interface is
368 * 18bpp or 24bpp */
369bool dss_use_replication(struct omap_dss_device *dssdev,
370 enum omap_color_mode mode)
371{
372 int bpp;
373
374 if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16)
375 return false;
376
377 if (dssdev->type == OMAP_DISPLAY_TYPE_DPI &&
378 (dssdev->panel.config & OMAP_DSS_LCD_TFT) == 0)
379 return false;
380
381 switch (dssdev->type) {
382 case OMAP_DISPLAY_TYPE_DPI:
383 bpp = dssdev->phy.dpi.data_lines;
384 break;
385 case OMAP_DISPLAY_TYPE_VENC:
386 case OMAP_DISPLAY_TYPE_SDI:
387 bpp = 24;
388 break;
389 case OMAP_DISPLAY_TYPE_DBI:
390 case OMAP_DISPLAY_TYPE_DSI:
391 bpp = dssdev->ctrl.pixel_size;
392 break;
393 default:
394 BUG();
395 }
396
397 return bpp > 16;
398}
399
400void dss_init_device(struct platform_device *pdev,
401 struct omap_dss_device *dssdev)
402{
403 struct device_attribute *attr;
404 int i;
405 int r;
406
407 switch (dssdev->type) {
408 case OMAP_DISPLAY_TYPE_DPI:
409#ifdef CONFIG_OMAP2_DSS_RFBI
410 case OMAP_DISPLAY_TYPE_DBI:
411#endif
412#ifdef CONFIG_OMAP2_DSS_SDI
413 case OMAP_DISPLAY_TYPE_SDI:
414#endif
415#ifdef CONFIG_OMAP2_DSS_DSI
416 case OMAP_DISPLAY_TYPE_DSI:
417#endif
418#ifdef CONFIG_OMAP2_DSS_VENC
419 case OMAP_DISPLAY_TYPE_VENC:
420#endif
421 break;
422 default:
423 DSSERR("Support for display '%s' not compiled in.\n",
424 dssdev->name);
425 return;
426 }
427
428 dssdev->get_resolution = default_get_resolution;
429 dssdev->get_recommended_bpp = default_get_recommended_bpp;
430 dssdev->wait_vsync = default_wait_vsync;
431
432 switch (dssdev->type) {
433 case OMAP_DISPLAY_TYPE_DPI:
434 r = dpi_init_display(dssdev);
435 break;
436#ifdef CONFIG_OMAP2_DSS_RFBI
437 case OMAP_DISPLAY_TYPE_DBI:
438 r = rfbi_init_display(dssdev);
439 break;
440#endif
441#ifdef CONFIG_OMAP2_DSS_VENC
442 case OMAP_DISPLAY_TYPE_VENC:
443 r = venc_init_display(dssdev);
444 break;
445#endif
446#ifdef CONFIG_OMAP2_DSS_SDI
447 case OMAP_DISPLAY_TYPE_SDI:
448 r = sdi_init_display(dssdev);
449 break;
450#endif
451#ifdef CONFIG_OMAP2_DSS_DSI
452 case OMAP_DISPLAY_TYPE_DSI:
453 r = dsi_init_display(dssdev);
454 break;
455#endif
456 default:
457 BUG();
458 }
459
460 if (r) {
461 DSSERR("failed to init display %s\n", dssdev->name);
462 return;
463 }
464
465 /* create device sysfs files */
466 i = 0;
467 while ((attr = display_sysfs_attrs[i++]) != NULL) {
468 r = device_create_file(&dssdev->dev, attr);
469 if (r)
470 DSSERR("failed to create sysfs file\n");
471 }
472
473 /* create display? sysfs links */
474 r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
475 dev_name(&dssdev->dev));
476 if (r)
477 DSSERR("failed to create sysfs display link\n");
478}
479
480void dss_uninit_device(struct platform_device *pdev,
481 struct omap_dss_device *dssdev)
482{
483 struct device_attribute *attr;
484 int i = 0;
485
486 sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
487
488 while ((attr = display_sysfs_attrs[i++]) != NULL)
489 device_remove_file(&dssdev->dev, attr);
490
491 if (dssdev->manager)
492 dssdev->manager->unset_device(dssdev->manager);
493}
494
495static int dss_suspend_device(struct device *dev, void *data)
496{
497 int r;
498 struct omap_dss_device *dssdev = to_dss_device(dev);
499
500 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
501 dssdev->activate_after_resume = false;
502 return 0;
503 }
504
505 if (!dssdev->suspend) {
506 DSSERR("display '%s' doesn't implement suspend\n",
507 dssdev->name);
508 return -ENOSYS;
509 }
510
511 r = dssdev->suspend(dssdev);
512 if (r)
513 return r;
514
515 dssdev->activate_after_resume = true;
516
517 return 0;
518}
519
520int dss_suspend_all_devices(void)
521{
522 int r;
523 struct bus_type *bus = dss_get_bus();
524
525 r = bus_for_each_dev(bus, NULL, NULL, dss_suspend_device);
526 if (r) {
527 /* resume all displays that were suspended */
528 dss_resume_all_devices();
529 return r;
530 }
531
532 return 0;
533}
534
535static int dss_resume_device(struct device *dev, void *data)
536{
537 int r;
538 struct omap_dss_device *dssdev = to_dss_device(dev);
539
540 if (dssdev->activate_after_resume && dssdev->resume) {
541 r = dssdev->resume(dssdev);
542 if (r)
543 return r;
544 }
545
546 dssdev->activate_after_resume = false;
547
548 return 0;
549}
550
551int dss_resume_all_devices(void)
552{
553 struct bus_type *bus = dss_get_bus();
554
555 return bus_for_each_dev(bus, NULL, NULL, dss_resume_device);
556}
557
558static int dss_disable_device(struct device *dev, void *data)
559{
560 struct omap_dss_device *dssdev = to_dss_device(dev);
561 dssdev->disable(dssdev);
562 return 0;
563}
564
565void dss_disable_all_devices(void)
566{
567 struct bus_type *bus = dss_get_bus();
568 bus_for_each_dev(bus, NULL, NULL, dss_disable_device);
569}
570
571
572void omap_dss_get_device(struct omap_dss_device *dssdev)
573{
574 get_device(&dssdev->dev);
575}
576EXPORT_SYMBOL(omap_dss_get_device);
577
578void omap_dss_put_device(struct omap_dss_device *dssdev)
579{
580 put_device(&dssdev->dev);
581}
582EXPORT_SYMBOL(omap_dss_put_device);
583
584/* ref count of the found device is incremented. ref count
585 * of from-device is decremented. */
586struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from)
587{
588 struct device *dev;
589 struct device *dev_start = NULL;
590 struct omap_dss_device *dssdev = NULL;
591
592 int match(struct device *dev, void *data)
593 {
594 /* skip panels connected to controllers */
595 if (to_dss_device(dev)->panel.ctrl)
596 return 0;
597
598 return 1;
599 }
600
601 if (from)
602 dev_start = &from->dev;
603 dev = bus_find_device(dss_get_bus(), dev_start, NULL, match);
604 if (dev)
605 dssdev = to_dss_device(dev);
606 if (from)
607 put_device(&from->dev);
608
609 return dssdev;
610}
611EXPORT_SYMBOL(omap_dss_get_next_device);
612
613struct omap_dss_device *omap_dss_find_device(void *data,
614 int (*match)(struct omap_dss_device *dssdev, void *data))
615{
616 struct omap_dss_device *dssdev = NULL;
617
618 while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL) {
619 if (match(dssdev, data))
620 return dssdev;
621 }
622
623 return NULL;
624}
625EXPORT_SYMBOL(omap_dss_find_device);
626
627int omap_dss_start_device(struct omap_dss_device *dssdev)
628{
629 int r;
630
631 if (!dssdev->driver) {
632 DSSDBG("no driver\n");
633 r = -ENODEV;
634 goto err0;
635 }
636
637 if (dssdev->ctrl.panel && !dssdev->ctrl.panel->driver) {
638 DSSDBG("no panel driver\n");
639 r = -ENODEV;
640 goto err0;
641 }
642
643 if (!try_module_get(dssdev->dev.driver->owner)) {
644 r = -ENODEV;
645 goto err0;
646 }
647
648 if (dssdev->ctrl.panel) {
649 if (!try_module_get(dssdev->ctrl.panel->dev.driver->owner)) {
650 r = -ENODEV;
651 goto err1;
652 }
653 }
654
655 return 0;
656err1:
657 module_put(dssdev->dev.driver->owner);
658err0:
659 return r;
660}
661EXPORT_SYMBOL(omap_dss_start_device);
662
663void omap_dss_stop_device(struct omap_dss_device *dssdev)
664{
665 if (dssdev->ctrl.panel)
666 module_put(dssdev->ctrl.panel->dev.driver->owner);
667
668 module_put(dssdev->dev.driver->owner);
669}
670EXPORT_SYMBOL(omap_dss_stop_device);
671
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
new file mode 100644
index 000000000000..2d71031baa25
--- /dev/null
+++ b/drivers/video/omap2/dss/dpi.c
@@ -0,0 +1,399 @@
1/*
2 * linux/drivers/video/omap2/dss/dpi.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#define DSS_SUBSYS_NAME "DPI"
24
25#include <linux/kernel.h>
26#include <linux/clk.h>
27#include <linux/delay.h>
28#include <linux/errno.h>
29
30#include <plat/display.h>
31#include <plat/cpu.h>
32
33#include "dss.h"
34
35static struct {
36 int update_enabled;
37} dpi;
38
39#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
40static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req,
41 unsigned long *fck, int *lck_div, int *pck_div)
42{
43 struct dsi_clock_info dsi_cinfo;
44 struct dispc_clock_info dispc_cinfo;
45 int r;
46
47 r = dsi_pll_calc_clock_div_pck(is_tft, pck_req, &dsi_cinfo,
48 &dispc_cinfo);
49 if (r)
50 return r;
51
52 r = dsi_pll_set_clock_div(&dsi_cinfo);
53 if (r)
54 return r;
55
56 dss_select_clk_source(0, 1);
57
58 r = dispc_set_clock_div(&dispc_cinfo);
59 if (r)
60 return r;
61
62 *fck = dsi_cinfo.dsi1_pll_fclk;
63 *lck_div = dispc_cinfo.lck_div;
64 *pck_div = dispc_cinfo.pck_div;
65
66 return 0;
67}
68#else
69static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req,
70 unsigned long *fck, int *lck_div, int *pck_div)
71{
72 struct dss_clock_info dss_cinfo;
73 struct dispc_clock_info dispc_cinfo;
74 int r;
75
76 r = dss_calc_clock_div(is_tft, pck_req, &dss_cinfo, &dispc_cinfo);
77 if (r)
78 return r;
79
80 r = dss_set_clock_div(&dss_cinfo);
81 if (r)
82 return r;
83
84 r = dispc_set_clock_div(&dispc_cinfo);
85 if (r)
86 return r;
87
88 *fck = dss_cinfo.fck;
89 *lck_div = dispc_cinfo.lck_div;
90 *pck_div = dispc_cinfo.pck_div;
91
92 return 0;
93}
94#endif
95
96static int dpi_set_mode(struct omap_dss_device *dssdev)
97{
98 struct omap_video_timings *t = &dssdev->panel.timings;
99 int lck_div, pck_div;
100 unsigned long fck;
101 unsigned long pck;
102 bool is_tft;
103 int r = 0;
104
105 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
106
107 dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi,
108 dssdev->panel.acb);
109
110 is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
111
112#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
113 r = dpi_set_dsi_clk(is_tft, t->pixel_clock * 1000,
114 &fck, &lck_div, &pck_div);
115#else
116 r = dpi_set_dispc_clk(is_tft, t->pixel_clock * 1000,
117 &fck, &lck_div, &pck_div);
118#endif
119 if (r)
120 goto err0;
121
122 pck = fck / lck_div / pck_div / 1000;
123
124 if (pck != t->pixel_clock) {
125 DSSWARN("Could not find exact pixel clock. "
126 "Requested %d kHz, got %lu kHz\n",
127 t->pixel_clock, pck);
128
129 t->pixel_clock = pck;
130 }
131
132 dispc_set_lcd_timings(t);
133
134err0:
135 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
136 return r;
137}
138
139static int dpi_basic_init(struct omap_dss_device *dssdev)
140{
141 bool is_tft;
142
143 is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
144
145 dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
146 dispc_set_lcd_display_type(is_tft ? OMAP_DSS_LCD_DISPLAY_TFT :
147 OMAP_DSS_LCD_DISPLAY_STN);
148 dispc_set_tft_data_lines(dssdev->phy.dpi.data_lines);
149
150 return 0;
151}
152
153static int dpi_display_enable(struct omap_dss_device *dssdev)
154{
155 int r;
156
157 r = omap_dss_start_device(dssdev);
158 if (r) {
159 DSSERR("failed to start device\n");
160 goto err0;
161 }
162
163 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
164 DSSERR("display already enabled\n");
165 r = -EINVAL;
166 goto err1;
167 }
168
169 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
170
171 r = dpi_basic_init(dssdev);
172 if (r)
173 goto err2;
174
175#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
176 dss_clk_enable(DSS_CLK_FCK2);
177 r = dsi_pll_init(dssdev, 0, 1);
178 if (r)
179 goto err3;
180#endif
181 r = dpi_set_mode(dssdev);
182 if (r)
183 goto err4;
184
185 mdelay(2);
186
187 dispc_enable_lcd_out(1);
188
189 r = dssdev->driver->enable(dssdev);
190 if (r)
191 goto err5;
192
193 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
194
195 return 0;
196
197err5:
198 dispc_enable_lcd_out(0);
199err4:
200#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
201 dsi_pll_uninit();
202err3:
203 dss_clk_disable(DSS_CLK_FCK2);
204#endif
205err2:
206 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
207err1:
208 omap_dss_stop_device(dssdev);
209err0:
210 return r;
211}
212
213static int dpi_display_resume(struct omap_dss_device *dssdev);
214
215static void dpi_display_disable(struct omap_dss_device *dssdev)
216{
217 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
218 return;
219
220 if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
221 dpi_display_resume(dssdev);
222
223 dssdev->driver->disable(dssdev);
224
225 dispc_enable_lcd_out(0);
226
227#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
228 dss_select_clk_source(0, 0);
229 dsi_pll_uninit();
230 dss_clk_disable(DSS_CLK_FCK2);
231#endif
232
233 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
234
235 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
236
237 omap_dss_stop_device(dssdev);
238}
239
240static int dpi_display_suspend(struct omap_dss_device *dssdev)
241{
242 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
243 return -EINVAL;
244
245 DSSDBG("dpi_display_suspend\n");
246
247 if (dssdev->driver->suspend)
248 dssdev->driver->suspend(dssdev);
249
250 dispc_enable_lcd_out(0);
251
252 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
253
254 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
255
256 return 0;
257}
258
259static int dpi_display_resume(struct omap_dss_device *dssdev)
260{
261 if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
262 return -EINVAL;
263
264 DSSDBG("dpi_display_resume\n");
265
266 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
267
268 dispc_enable_lcd_out(1);
269
270 if (dssdev->driver->resume)
271 dssdev->driver->resume(dssdev);
272
273 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
274
275 return 0;
276}
277
278static void dpi_set_timings(struct omap_dss_device *dssdev,
279 struct omap_video_timings *timings)
280{
281 DSSDBG("dpi_set_timings\n");
282 dssdev->panel.timings = *timings;
283 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
284 dpi_set_mode(dssdev);
285 dispc_go(OMAP_DSS_CHANNEL_LCD);
286 }
287}
288
289static int dpi_check_timings(struct omap_dss_device *dssdev,
290 struct omap_video_timings *timings)
291{
292 bool is_tft;
293 int r;
294 int lck_div, pck_div;
295 unsigned long fck;
296 unsigned long pck;
297
298 if (!dispc_lcd_timings_ok(timings))
299 return -EINVAL;
300
301 if (timings->pixel_clock == 0)
302 return -EINVAL;
303
304 is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
305
306#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
307 {
308 struct dsi_clock_info dsi_cinfo;
309 struct dispc_clock_info dispc_cinfo;
310 r = dsi_pll_calc_clock_div_pck(is_tft,
311 timings->pixel_clock * 1000,
312 &dsi_cinfo, &dispc_cinfo);
313
314 if (r)
315 return r;
316
317 fck = dsi_cinfo.dsi1_pll_fclk;
318 lck_div = dispc_cinfo.lck_div;
319 pck_div = dispc_cinfo.pck_div;
320 }
321#else
322 {
323 struct dss_clock_info dss_cinfo;
324 struct dispc_clock_info dispc_cinfo;
325 r = dss_calc_clock_div(is_tft, timings->pixel_clock * 1000,
326 &dss_cinfo, &dispc_cinfo);
327
328 if (r)
329 return r;
330
331 fck = dss_cinfo.fck;
332 lck_div = dispc_cinfo.lck_div;
333 pck_div = dispc_cinfo.pck_div;
334 }
335#endif
336
337 pck = fck / lck_div / pck_div / 1000;
338
339 timings->pixel_clock = pck;
340
341 return 0;
342}
343
344static void dpi_get_timings(struct omap_dss_device *dssdev,
345 struct omap_video_timings *timings)
346{
347 *timings = dssdev->panel.timings;
348}
349
350static int dpi_display_set_update_mode(struct omap_dss_device *dssdev,
351 enum omap_dss_update_mode mode)
352{
353 if (mode == OMAP_DSS_UPDATE_MANUAL)
354 return -EINVAL;
355
356 if (mode == OMAP_DSS_UPDATE_DISABLED) {
357 dispc_enable_lcd_out(0);
358 dpi.update_enabled = 0;
359 } else {
360 dispc_enable_lcd_out(1);
361 dpi.update_enabled = 1;
362 }
363
364 return 0;
365}
366
367static enum omap_dss_update_mode dpi_display_get_update_mode(
368 struct omap_dss_device *dssdev)
369{
370 return dpi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
371 OMAP_DSS_UPDATE_DISABLED;
372}
373
374int dpi_init_display(struct omap_dss_device *dssdev)
375{
376 DSSDBG("init_display\n");
377
378 dssdev->enable = dpi_display_enable;
379 dssdev->disable = dpi_display_disable;
380 dssdev->suspend = dpi_display_suspend;
381 dssdev->resume = dpi_display_resume;
382 dssdev->set_timings = dpi_set_timings;
383 dssdev->check_timings = dpi_check_timings;
384 dssdev->get_timings = dpi_get_timings;
385 dssdev->set_update_mode = dpi_display_set_update_mode;
386 dssdev->get_update_mode = dpi_display_get_update_mode;
387
388 return 0;
389}
390
391int dpi_init(void)
392{
393 return 0;
394}
395
396void dpi_exit(void)
397{
398}
399
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
new file mode 100644
index 000000000000..5936487b5def
--- /dev/null
+++ b/drivers/video/omap2/dss/dsi.c
@@ -0,0 +1,3710 @@
1/*
2 * linux/drivers/video/omap2/dss/dsi.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#define DSS_SUBSYS_NAME "DSI"
21
22#include <linux/kernel.h>
23#include <linux/io.h>
24#include <linux/clk.h>
25#include <linux/device.h>
26#include <linux/err.h>
27#include <linux/interrupt.h>
28#include <linux/delay.h>
29#include <linux/mutex.h>
30#include <linux/seq_file.h>
31#include <linux/platform_device.h>
32#include <linux/regulator/consumer.h>
33#include <linux/kthread.h>
34#include <linux/wait.h>
35
36#include <plat/display.h>
37#include <plat/clock.h>
38
39#include "dss.h"
40
41/*#define VERBOSE_IRQ*/
42#define DSI_CATCH_MISSING_TE
43
44#define DSI_BASE 0x4804FC00
45
46struct dsi_reg { u16 idx; };
47
48#define DSI_REG(idx) ((const struct dsi_reg) { idx })
49
50#define DSI_SZ_REGS SZ_1K
51/* DSI Protocol Engine */
52
53#define DSI_REVISION DSI_REG(0x0000)
54#define DSI_SYSCONFIG DSI_REG(0x0010)
55#define DSI_SYSSTATUS DSI_REG(0x0014)
56#define DSI_IRQSTATUS DSI_REG(0x0018)
57#define DSI_IRQENABLE DSI_REG(0x001C)
58#define DSI_CTRL DSI_REG(0x0040)
59#define DSI_COMPLEXIO_CFG1 DSI_REG(0x0048)
60#define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(0x004C)
61#define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(0x0050)
62#define DSI_CLK_CTRL DSI_REG(0x0054)
63#define DSI_TIMING1 DSI_REG(0x0058)
64#define DSI_TIMING2 DSI_REG(0x005C)
65#define DSI_VM_TIMING1 DSI_REG(0x0060)
66#define DSI_VM_TIMING2 DSI_REG(0x0064)
67#define DSI_VM_TIMING3 DSI_REG(0x0068)
68#define DSI_CLK_TIMING DSI_REG(0x006C)
69#define DSI_TX_FIFO_VC_SIZE DSI_REG(0x0070)
70#define DSI_RX_FIFO_VC_SIZE DSI_REG(0x0074)
71#define DSI_COMPLEXIO_CFG2 DSI_REG(0x0078)
72#define DSI_RX_FIFO_VC_FULLNESS DSI_REG(0x007C)
73#define DSI_VM_TIMING4 DSI_REG(0x0080)
74#define DSI_TX_FIFO_VC_EMPTINESS DSI_REG(0x0084)
75#define DSI_VM_TIMING5 DSI_REG(0x0088)
76#define DSI_VM_TIMING6 DSI_REG(0x008C)
77#define DSI_VM_TIMING7 DSI_REG(0x0090)
78#define DSI_STOPCLK_TIMING DSI_REG(0x0094)
79#define DSI_VC_CTRL(n) DSI_REG(0x0100 + (n * 0x20))
80#define DSI_VC_TE(n) DSI_REG(0x0104 + (n * 0x20))
81#define DSI_VC_LONG_PACKET_HEADER(n) DSI_REG(0x0108 + (n * 0x20))
82#define DSI_VC_LONG_PACKET_PAYLOAD(n) DSI_REG(0x010C + (n * 0x20))
83#define DSI_VC_SHORT_PACKET_HEADER(n) DSI_REG(0x0110 + (n * 0x20))
84#define DSI_VC_IRQSTATUS(n) DSI_REG(0x0118 + (n * 0x20))
85#define DSI_VC_IRQENABLE(n) DSI_REG(0x011C + (n * 0x20))
86
87/* DSIPHY_SCP */
88
89#define DSI_DSIPHY_CFG0 DSI_REG(0x200 + 0x0000)
90#define DSI_DSIPHY_CFG1 DSI_REG(0x200 + 0x0004)
91#define DSI_DSIPHY_CFG2 DSI_REG(0x200 + 0x0008)
92#define DSI_DSIPHY_CFG5 DSI_REG(0x200 + 0x0014)
93
94/* DSI_PLL_CTRL_SCP */
95
96#define DSI_PLL_CONTROL DSI_REG(0x300 + 0x0000)
97#define DSI_PLL_STATUS DSI_REG(0x300 + 0x0004)
98#define DSI_PLL_GO DSI_REG(0x300 + 0x0008)
99#define DSI_PLL_CONFIGURATION1 DSI_REG(0x300 + 0x000C)
100#define DSI_PLL_CONFIGURATION2 DSI_REG(0x300 + 0x0010)
101
102#define REG_GET(idx, start, end) \
103 FLD_GET(dsi_read_reg(idx), start, end)
104
105#define REG_FLD_MOD(idx, val, start, end) \
106 dsi_write_reg(idx, FLD_MOD(dsi_read_reg(idx), val, start, end))
107
108/* Global interrupts */
109#define DSI_IRQ_VC0 (1 << 0)
110#define DSI_IRQ_VC1 (1 << 1)
111#define DSI_IRQ_VC2 (1 << 2)
112#define DSI_IRQ_VC3 (1 << 3)
113#define DSI_IRQ_WAKEUP (1 << 4)
114#define DSI_IRQ_RESYNC (1 << 5)
115#define DSI_IRQ_PLL_LOCK (1 << 7)
116#define DSI_IRQ_PLL_UNLOCK (1 << 8)
117#define DSI_IRQ_PLL_RECALL (1 << 9)
118#define DSI_IRQ_COMPLEXIO_ERR (1 << 10)
119#define DSI_IRQ_HS_TX_TIMEOUT (1 << 14)
120#define DSI_IRQ_LP_RX_TIMEOUT (1 << 15)
121#define DSI_IRQ_TE_TRIGGER (1 << 16)
122#define DSI_IRQ_ACK_TRIGGER (1 << 17)
123#define DSI_IRQ_SYNC_LOST (1 << 18)
124#define DSI_IRQ_LDO_POWER_GOOD (1 << 19)
125#define DSI_IRQ_TA_TIMEOUT (1 << 20)
126#define DSI_IRQ_ERROR_MASK \
127 (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \
128 DSI_IRQ_TA_TIMEOUT)
129#define DSI_IRQ_CHANNEL_MASK 0xf
130
131/* Virtual channel interrupts */
132#define DSI_VC_IRQ_CS (1 << 0)
133#define DSI_VC_IRQ_ECC_CORR (1 << 1)
134#define DSI_VC_IRQ_PACKET_SENT (1 << 2)
135#define DSI_VC_IRQ_FIFO_TX_OVF (1 << 3)
136#define DSI_VC_IRQ_FIFO_RX_OVF (1 << 4)
137#define DSI_VC_IRQ_BTA (1 << 5)
138#define DSI_VC_IRQ_ECC_NO_CORR (1 << 6)
139#define DSI_VC_IRQ_FIFO_TX_UDF (1 << 7)
140#define DSI_VC_IRQ_PP_BUSY_CHANGE (1 << 8)
141#define DSI_VC_IRQ_ERROR_MASK \
142 (DSI_VC_IRQ_CS | DSI_VC_IRQ_ECC_CORR | DSI_VC_IRQ_FIFO_TX_OVF | \
143 DSI_VC_IRQ_FIFO_RX_OVF | DSI_VC_IRQ_ECC_NO_CORR | \
144 DSI_VC_IRQ_FIFO_TX_UDF)
145
146/* ComplexIO interrupts */
147#define DSI_CIO_IRQ_ERRSYNCESC1 (1 << 0)
148#define DSI_CIO_IRQ_ERRSYNCESC2 (1 << 1)
149#define DSI_CIO_IRQ_ERRSYNCESC3 (1 << 2)
150#define DSI_CIO_IRQ_ERRESC1 (1 << 5)
151#define DSI_CIO_IRQ_ERRESC2 (1 << 6)
152#define DSI_CIO_IRQ_ERRESC3 (1 << 7)
153#define DSI_CIO_IRQ_ERRCONTROL1 (1 << 10)
154#define DSI_CIO_IRQ_ERRCONTROL2 (1 << 11)
155#define DSI_CIO_IRQ_ERRCONTROL3 (1 << 12)
156#define DSI_CIO_IRQ_STATEULPS1 (1 << 15)
157#define DSI_CIO_IRQ_STATEULPS2 (1 << 16)
158#define DSI_CIO_IRQ_STATEULPS3 (1 << 17)
159#define DSI_CIO_IRQ_ERRCONTENTIONLP0_1 (1 << 20)
160#define DSI_CIO_IRQ_ERRCONTENTIONLP1_1 (1 << 21)
161#define DSI_CIO_IRQ_ERRCONTENTIONLP0_2 (1 << 22)
162#define DSI_CIO_IRQ_ERRCONTENTIONLP1_2 (1 << 23)
163#define DSI_CIO_IRQ_ERRCONTENTIONLP0_3 (1 << 24)
164#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25)
165#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30)
166#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31)
167
168#define DSI_DT_DCS_SHORT_WRITE_0 0x05
169#define DSI_DT_DCS_SHORT_WRITE_1 0x15
170#define DSI_DT_DCS_READ 0x06
171#define DSI_DT_SET_MAX_RET_PKG_SIZE 0x37
172#define DSI_DT_NULL_PACKET 0x09
173#define DSI_DT_DCS_LONG_WRITE 0x39
174
175#define DSI_DT_RX_ACK_WITH_ERR 0x02
176#define DSI_DT_RX_DCS_LONG_READ 0x1c
177#define DSI_DT_RX_SHORT_READ_1 0x21
178#define DSI_DT_RX_SHORT_READ_2 0x22
179
180#define FINT_MAX 2100000
181#define FINT_MIN 750000
182#define REGN_MAX (1 << 7)
183#define REGM_MAX ((1 << 11) - 1)
184#define REGM3_MAX (1 << 4)
185#define REGM4_MAX (1 << 4)
186#define LP_DIV_MAX ((1 << 13) - 1)
187
188enum fifo_size {
189 DSI_FIFO_SIZE_0 = 0,
190 DSI_FIFO_SIZE_32 = 1,
191 DSI_FIFO_SIZE_64 = 2,
192 DSI_FIFO_SIZE_96 = 3,
193 DSI_FIFO_SIZE_128 = 4,
194};
195
196enum dsi_vc_mode {
197 DSI_VC_MODE_L4 = 0,
198 DSI_VC_MODE_VP,
199};
200
201struct dsi_update_region {
202 bool dirty;
203 u16 x, y, w, h;
204 struct omap_dss_device *device;
205};
206
207static struct
208{
209 void __iomem *base;
210
211 struct dsi_clock_info current_cinfo;
212
213 struct regulator *vdds_dsi_reg;
214
215 struct {
216 enum dsi_vc_mode mode;
217 struct omap_dss_device *dssdev;
218 enum fifo_size fifo_size;
219 int dest_per; /* destination peripheral 0-3 */
220 } vc[4];
221
222 struct mutex lock;
223 struct mutex bus_lock;
224
225 unsigned pll_locked;
226
227 struct completion bta_completion;
228
229 struct task_struct *thread;
230 wait_queue_head_t waitqueue;
231
232 spinlock_t update_lock;
233 bool framedone_received;
234 struct dsi_update_region update_region;
235 struct dsi_update_region active_update_region;
236 struct completion update_completion;
237
238 enum omap_dss_update_mode user_update_mode;
239 enum omap_dss_update_mode update_mode;
240 bool te_enabled;
241 bool use_ext_te;
242
243#ifdef DSI_CATCH_MISSING_TE
244 struct timer_list te_timer;
245#endif
246
247 unsigned long cache_req_pck;
248 unsigned long cache_clk_freq;
249 struct dsi_clock_info cache_cinfo;
250
251 u32 errors;
252 spinlock_t errors_lock;
253#ifdef DEBUG
254 ktime_t perf_setup_time;
255 ktime_t perf_start_time;
256 ktime_t perf_start_time_auto;
257 int perf_measure_frames;
258#endif
259 int debug_read;
260 int debug_write;
261} dsi;
262
263#ifdef DEBUG
264static unsigned int dsi_perf;
265module_param_named(dsi_perf, dsi_perf, bool, 0644);
266#endif
267
268static inline void dsi_write_reg(const struct dsi_reg idx, u32 val)
269{
270 __raw_writel(val, dsi.base + idx.idx);
271}
272
273static inline u32 dsi_read_reg(const struct dsi_reg idx)
274{
275 return __raw_readl(dsi.base + idx.idx);
276}
277
278
279void dsi_save_context(void)
280{
281}
282
283void dsi_restore_context(void)
284{
285}
286
287void dsi_bus_lock(void)
288{
289 mutex_lock(&dsi.bus_lock);
290}
291EXPORT_SYMBOL(dsi_bus_lock);
292
293void dsi_bus_unlock(void)
294{
295 mutex_unlock(&dsi.bus_lock);
296}
297EXPORT_SYMBOL(dsi_bus_unlock);
298
299static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum,
300 int value)
301{
302 int t = 100000;
303
304 while (REG_GET(idx, bitnum, bitnum) != value) {
305 if (--t == 0)
306 return !value;
307 }
308
309 return value;
310}
311
312#ifdef DEBUG
313static void dsi_perf_mark_setup(void)
314{
315 dsi.perf_setup_time = ktime_get();
316}
317
318static void dsi_perf_mark_start(void)
319{
320 dsi.perf_start_time = ktime_get();
321}
322
323static void dsi_perf_mark_start_auto(void)
324{
325 dsi.perf_measure_frames = 0;
326 dsi.perf_start_time_auto = ktime_get();
327}
328
329static void dsi_perf_show(const char *name)
330{
331 ktime_t t, setup_time, trans_time;
332 u32 total_bytes;
333 u32 setup_us, trans_us, total_us;
334
335 if (!dsi_perf)
336 return;
337
338 if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED)
339 return;
340
341 t = ktime_get();
342
343 setup_time = ktime_sub(dsi.perf_start_time, dsi.perf_setup_time);
344 setup_us = (u32)ktime_to_us(setup_time);
345 if (setup_us == 0)
346 setup_us = 1;
347
348 trans_time = ktime_sub(t, dsi.perf_start_time);
349 trans_us = (u32)ktime_to_us(trans_time);
350 if (trans_us == 0)
351 trans_us = 1;
352
353 total_us = setup_us + trans_us;
354
355 total_bytes = dsi.active_update_region.w *
356 dsi.active_update_region.h *
357 dsi.active_update_region.device->ctrl.pixel_size / 8;
358
359 if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) {
360 static u32 s_total_trans_us, s_total_setup_us;
361 static u32 s_min_trans_us = 0xffffffff, s_min_setup_us;
362 static u32 s_max_trans_us, s_max_setup_us;
363 const int numframes = 100;
364 ktime_t total_time_auto;
365 u32 total_time_auto_us;
366
367 dsi.perf_measure_frames++;
368
369 if (setup_us < s_min_setup_us)
370 s_min_setup_us = setup_us;
371
372 if (setup_us > s_max_setup_us)
373 s_max_setup_us = setup_us;
374
375 s_total_setup_us += setup_us;
376
377 if (trans_us < s_min_trans_us)
378 s_min_trans_us = trans_us;
379
380 if (trans_us > s_max_trans_us)
381 s_max_trans_us = trans_us;
382
383 s_total_trans_us += trans_us;
384
385 if (dsi.perf_measure_frames < numframes)
386 return;
387
388 total_time_auto = ktime_sub(t, dsi.perf_start_time_auto);
389 total_time_auto_us = (u32)ktime_to_us(total_time_auto);
390
391 printk(KERN_INFO "DSI(%s): %u fps, setup %u/%u/%u, "
392 "trans %u/%u/%u\n",
393 name,
394 1000 * 1000 * numframes / total_time_auto_us,
395 s_min_setup_us,
396 s_max_setup_us,
397 s_total_setup_us / numframes,
398 s_min_trans_us,
399 s_max_trans_us,
400 s_total_trans_us / numframes);
401
402 s_total_setup_us = 0;
403 s_min_setup_us = 0xffffffff;
404 s_max_setup_us = 0;
405 s_total_trans_us = 0;
406 s_min_trans_us = 0xffffffff;
407 s_max_trans_us = 0;
408 dsi_perf_mark_start_auto();
409 } else {
410 printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
411 "%u bytes, %u kbytes/sec\n",
412 name,
413 setup_us,
414 trans_us,
415 total_us,
416 1000*1000 / total_us,
417 total_bytes,
418 total_bytes * 1000 / total_us);
419 }
420}
421#else
422#define dsi_perf_mark_setup()
423#define dsi_perf_mark_start()
424#define dsi_perf_mark_start_auto()
425#define dsi_perf_show(x)
426#endif
427
428static void print_irq_status(u32 status)
429{
430#ifndef VERBOSE_IRQ
431 if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
432 return;
433#endif
434 printk(KERN_DEBUG "DSI IRQ: 0x%x: ", status);
435
436#define PIS(x) \
437 if (status & DSI_IRQ_##x) \
438 printk(#x " ");
439#ifdef VERBOSE_IRQ
440 PIS(VC0);
441 PIS(VC1);
442 PIS(VC2);
443 PIS(VC3);
444#endif
445 PIS(WAKEUP);
446 PIS(RESYNC);
447 PIS(PLL_LOCK);
448 PIS(PLL_UNLOCK);
449 PIS(PLL_RECALL);
450 PIS(COMPLEXIO_ERR);
451 PIS(HS_TX_TIMEOUT);
452 PIS(LP_RX_TIMEOUT);
453 PIS(TE_TRIGGER);
454 PIS(ACK_TRIGGER);
455 PIS(SYNC_LOST);
456 PIS(LDO_POWER_GOOD);
457 PIS(TA_TIMEOUT);
458#undef PIS
459
460 printk("\n");
461}
462
463static void print_irq_status_vc(int channel, u32 status)
464{
465#ifndef VERBOSE_IRQ
466 if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
467 return;
468#endif
469 printk(KERN_DEBUG "DSI VC(%d) IRQ 0x%x: ", channel, status);
470
471#define PIS(x) \
472 if (status & DSI_VC_IRQ_##x) \
473 printk(#x " ");
474 PIS(CS);
475 PIS(ECC_CORR);
476#ifdef VERBOSE_IRQ
477 PIS(PACKET_SENT);
478#endif
479 PIS(FIFO_TX_OVF);
480 PIS(FIFO_RX_OVF);
481 PIS(BTA);
482 PIS(ECC_NO_CORR);
483 PIS(FIFO_TX_UDF);
484 PIS(PP_BUSY_CHANGE);
485#undef PIS
486 printk("\n");
487}
488
489static void print_irq_status_cio(u32 status)
490{
491 printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status);
492
493#define PIS(x) \
494 if (status & DSI_CIO_IRQ_##x) \
495 printk(#x " ");
496 PIS(ERRSYNCESC1);
497 PIS(ERRSYNCESC2);
498 PIS(ERRSYNCESC3);
499 PIS(ERRESC1);
500 PIS(ERRESC2);
501 PIS(ERRESC3);
502 PIS(ERRCONTROL1);
503 PIS(ERRCONTROL2);
504 PIS(ERRCONTROL3);
505 PIS(STATEULPS1);
506 PIS(STATEULPS2);
507 PIS(STATEULPS3);
508 PIS(ERRCONTENTIONLP0_1);
509 PIS(ERRCONTENTIONLP1_1);
510 PIS(ERRCONTENTIONLP0_2);
511 PIS(ERRCONTENTIONLP1_2);
512 PIS(ERRCONTENTIONLP0_3);
513 PIS(ERRCONTENTIONLP1_3);
514 PIS(ULPSACTIVENOT_ALL0);
515 PIS(ULPSACTIVENOT_ALL1);
516#undef PIS
517
518 printk("\n");
519}
520
521static int debug_irq;
522
523/* called from dss */
524void dsi_irq_handler(void)
525{
526 u32 irqstatus, vcstatus, ciostatus;
527 int i;
528
529 irqstatus = dsi_read_reg(DSI_IRQSTATUS);
530
531 if (irqstatus & DSI_IRQ_ERROR_MASK) {
532 DSSERR("DSI error, irqstatus %x\n", irqstatus);
533 print_irq_status(irqstatus);
534 spin_lock(&dsi.errors_lock);
535 dsi.errors |= irqstatus & DSI_IRQ_ERROR_MASK;
536 spin_unlock(&dsi.errors_lock);
537 } else if (debug_irq) {
538 print_irq_status(irqstatus);
539 }
540
541#ifdef DSI_CATCH_MISSING_TE
542 if (irqstatus & DSI_IRQ_TE_TRIGGER)
543 del_timer(&dsi.te_timer);
544#endif
545
546 for (i = 0; i < 4; ++i) {
547 if ((irqstatus & (1<<i)) == 0)
548 continue;
549
550 vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i));
551
552 if (vcstatus & DSI_VC_IRQ_BTA)
553 complete(&dsi.bta_completion);
554
555 if (vcstatus & DSI_VC_IRQ_ERROR_MASK) {
556 DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
557 i, vcstatus);
558 print_irq_status_vc(i, vcstatus);
559 } else if (debug_irq) {
560 print_irq_status_vc(i, vcstatus);
561 }
562
563 dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus);
564 /* flush posted write */
565 dsi_read_reg(DSI_VC_IRQSTATUS(i));
566 }
567
568 if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) {
569 ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
570
571 dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus);
572 /* flush posted write */
573 dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
574
575 DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
576 print_irq_status_cio(ciostatus);
577 }
578
579 dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
580 /* flush posted write */
581 dsi_read_reg(DSI_IRQSTATUS);
582}
583
584
585static void _dsi_initialize_irq(void)
586{
587 u32 l;
588 int i;
589
590 /* disable all interrupts */
591 dsi_write_reg(DSI_IRQENABLE, 0);
592 for (i = 0; i < 4; ++i)
593 dsi_write_reg(DSI_VC_IRQENABLE(i), 0);
594 dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0);
595
596 /* clear interrupt status */
597 l = dsi_read_reg(DSI_IRQSTATUS);
598 dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK);
599
600 for (i = 0; i < 4; ++i) {
601 l = dsi_read_reg(DSI_VC_IRQSTATUS(i));
602 dsi_write_reg(DSI_VC_IRQSTATUS(i), l);
603 }
604
605 l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
606 dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l);
607
608 /* enable error irqs */
609 l = DSI_IRQ_ERROR_MASK;
610#ifdef DSI_CATCH_MISSING_TE
611 l |= DSI_IRQ_TE_TRIGGER;
612#endif
613 dsi_write_reg(DSI_IRQENABLE, l);
614
615 l = DSI_VC_IRQ_ERROR_MASK;
616 for (i = 0; i < 4; ++i)
617 dsi_write_reg(DSI_VC_IRQENABLE(i), l);
618
619 /* XXX zonda responds incorrectly, causing control error:
620 Exit from LP-ESC mode to LP11 uses wrong transition states on the
621 data lines LP0 and LN0. */
622 dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE,
623 -1 & (~DSI_CIO_IRQ_ERRCONTROL2));
624}
625
626static u32 dsi_get_errors(void)
627{
628 unsigned long flags;
629 u32 e;
630 spin_lock_irqsave(&dsi.errors_lock, flags);
631 e = dsi.errors;
632 dsi.errors = 0;
633 spin_unlock_irqrestore(&dsi.errors_lock, flags);
634 return e;
635}
636
637static void dsi_vc_enable_bta_irq(int channel)
638{
639 u32 l;
640
641 dsi_write_reg(DSI_VC_IRQSTATUS(channel), DSI_VC_IRQ_BTA);
642
643 l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
644 l |= DSI_VC_IRQ_BTA;
645 dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
646}
647
648static void dsi_vc_disable_bta_irq(int channel)
649{
650 u32 l;
651
652 l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
653 l &= ~DSI_VC_IRQ_BTA;
654 dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
655}
656
657/* DSI func clock. this could also be DSI2_PLL_FCLK */
658static inline void enable_clocks(bool enable)
659{
660 if (enable)
661 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
662 else
663 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
664}
665
666/* source clock for DSI PLL. this could also be PCLKFREE */
667static inline void dsi_enable_pll_clock(bool enable)
668{
669 if (enable)
670 dss_clk_enable(DSS_CLK_FCK2);
671 else
672 dss_clk_disable(DSS_CLK_FCK2);
673
674 if (enable && dsi.pll_locked) {
675 if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1)
676 DSSERR("cannot lock PLL when enabling clocks\n");
677 }
678}
679
680#ifdef DEBUG
681static void _dsi_print_reset_status(void)
682{
683 u32 l;
684
685 if (!dss_debug)
686 return;
687
688 /* A dummy read using the SCP interface to any DSIPHY register is
689 * required after DSIPHY reset to complete the reset of the DSI complex
690 * I/O. */
691 l = dsi_read_reg(DSI_DSIPHY_CFG5);
692
693 printk(KERN_DEBUG "DSI resets: ");
694
695 l = dsi_read_reg(DSI_PLL_STATUS);
696 printk("PLL (%d) ", FLD_GET(l, 0, 0));
697
698 l = dsi_read_reg(DSI_COMPLEXIO_CFG1);
699 printk("CIO (%d) ", FLD_GET(l, 29, 29));
700
701 l = dsi_read_reg(DSI_DSIPHY_CFG5);
702 printk("PHY (%x, %d, %d, %d)\n",
703 FLD_GET(l, 28, 26),
704 FLD_GET(l, 29, 29),
705 FLD_GET(l, 30, 30),
706 FLD_GET(l, 31, 31));
707}
708#else
709#define _dsi_print_reset_status()
710#endif
711
712static inline int dsi_if_enable(bool enable)
713{
714 DSSDBG("dsi_if_enable(%d)\n", enable);
715
716 enable = enable ? 1 : 0;
717 REG_FLD_MOD(DSI_CTRL, enable, 0, 0); /* IF_EN */
718
719 if (wait_for_bit_change(DSI_CTRL, 0, enable) != enable) {
720 DSSERR("Failed to set dsi_if_enable to %d\n", enable);
721 return -EIO;
722 }
723
724 return 0;
725}
726
727unsigned long dsi_get_dsi1_pll_rate(void)
728{
729 return dsi.current_cinfo.dsi1_pll_fclk;
730}
731
732static unsigned long dsi_get_dsi2_pll_rate(void)
733{
734 return dsi.current_cinfo.dsi2_pll_fclk;
735}
736
737static unsigned long dsi_get_txbyteclkhs(void)
738{
739 return dsi.current_cinfo.clkin4ddr / 16;
740}
741
742static unsigned long dsi_fclk_rate(void)
743{
744 unsigned long r;
745
746 if (dss_get_dsi_clk_source() == 0) {
747 /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */
748 r = dss_clk_get_rate(DSS_CLK_FCK1);
749 } else {
750 /* DSI FCLK source is DSI2_PLL_FCLK */
751 r = dsi_get_dsi2_pll_rate();
752 }
753
754 return r;
755}
756
757static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev)
758{
759 unsigned long dsi_fclk;
760 unsigned lp_clk_div;
761 unsigned long lp_clk;
762
763 lp_clk_div = dssdev->phy.dsi.div.lp_clk_div;
764
765 if (lp_clk_div == 0 || lp_clk_div > LP_DIV_MAX)
766 return -EINVAL;
767
768 dsi_fclk = dsi_fclk_rate();
769
770 lp_clk = dsi_fclk / 2 / lp_clk_div;
771
772 DSSDBG("LP_CLK_DIV %u, LP_CLK %lu\n", lp_clk_div, lp_clk);
773 dsi.current_cinfo.lp_clk = lp_clk;
774 dsi.current_cinfo.lp_clk_div = lp_clk_div;
775
776 REG_FLD_MOD(DSI_CLK_CTRL, lp_clk_div, 12, 0); /* LP_CLK_DIVISOR */
777
778 REG_FLD_MOD(DSI_CLK_CTRL, dsi_fclk > 30000000 ? 1 : 0,
779 21, 21); /* LP_RX_SYNCHRO_ENABLE */
780
781 return 0;
782}
783
784
785enum dsi_pll_power_state {
786 DSI_PLL_POWER_OFF = 0x0,
787 DSI_PLL_POWER_ON_HSCLK = 0x1,
788 DSI_PLL_POWER_ON_ALL = 0x2,
789 DSI_PLL_POWER_ON_DIV = 0x3,
790};
791
792static int dsi_pll_power(enum dsi_pll_power_state state)
793{
794 int t = 0;
795
796 REG_FLD_MOD(DSI_CLK_CTRL, state, 31, 30); /* PLL_PWR_CMD */
797
798 /* PLL_PWR_STATUS */
799 while (FLD_GET(dsi_read_reg(DSI_CLK_CTRL), 29, 28) != state) {
800 udelay(1);
801 if (t++ > 1000) {
802 DSSERR("Failed to set DSI PLL power mode to %d\n",
803 state);
804 return -ENODEV;
805 }
806 }
807
808 return 0;
809}
810
811/* calculate clock rates using dividers in cinfo */
812static int dsi_calc_clock_rates(struct dsi_clock_info *cinfo)
813{
814 if (cinfo->regn == 0 || cinfo->regn > REGN_MAX)
815 return -EINVAL;
816
817 if (cinfo->regm == 0 || cinfo->regm > REGM_MAX)
818 return -EINVAL;
819
820 if (cinfo->regm3 > REGM3_MAX)
821 return -EINVAL;
822
823 if (cinfo->regm4 > REGM4_MAX)
824 return -EINVAL;
825
826 if (cinfo->use_dss2_fck) {
827 cinfo->clkin = dss_clk_get_rate(DSS_CLK_FCK2);
828 /* XXX it is unclear if highfreq should be used
829 * with DSS2_FCK source also */
830 cinfo->highfreq = 0;
831 } else {
832 cinfo->clkin = dispc_pclk_rate();
833
834 if (cinfo->clkin < 32000000)
835 cinfo->highfreq = 0;
836 else
837 cinfo->highfreq = 1;
838 }
839
840 cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1));
841
842 if (cinfo->fint > FINT_MAX || cinfo->fint < FINT_MIN)
843 return -EINVAL;
844
845 cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint;
846
847 if (cinfo->clkin4ddr > 1800 * 1000 * 1000)
848 return -EINVAL;
849
850 if (cinfo->regm3 > 0)
851 cinfo->dsi1_pll_fclk = cinfo->clkin4ddr / cinfo->regm3;
852 else
853 cinfo->dsi1_pll_fclk = 0;
854
855 if (cinfo->regm4 > 0)
856 cinfo->dsi2_pll_fclk = cinfo->clkin4ddr / cinfo->regm4;
857 else
858 cinfo->dsi2_pll_fclk = 0;
859
860 return 0;
861}
862
863int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck,
864 struct dsi_clock_info *dsi_cinfo,
865 struct dispc_clock_info *dispc_cinfo)
866{
867 struct dsi_clock_info cur, best;
868 struct dispc_clock_info best_dispc;
869 int min_fck_per_pck;
870 int match = 0;
871 unsigned long dss_clk_fck2;
872
873 dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2);
874
875 if (req_pck == dsi.cache_req_pck &&
876 dsi.cache_cinfo.clkin == dss_clk_fck2) {
877 DSSDBG("DSI clock info found from cache\n");
878 *dsi_cinfo = dsi.cache_cinfo;
879 dispc_find_clk_divs(is_tft, req_pck, dsi_cinfo->dsi1_pll_fclk,
880 dispc_cinfo);
881 return 0;
882 }
883
884 min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
885
886 if (min_fck_per_pck &&
887 req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
888 DSSERR("Requested pixel clock not possible with the current "
889 "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
890 "the constraint off.\n");
891 min_fck_per_pck = 0;
892 }
893
894 DSSDBG("dsi_pll_calc\n");
895
896retry:
897 memset(&best, 0, sizeof(best));
898 memset(&best_dispc, 0, sizeof(best_dispc));
899
900 memset(&cur, 0, sizeof(cur));
901 cur.clkin = dss_clk_fck2;
902 cur.use_dss2_fck = 1;
903 cur.highfreq = 0;
904
905 /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
906 /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
907 /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
908 for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) {
909 if (cur.highfreq == 0)
910 cur.fint = cur.clkin / cur.regn;
911 else
912 cur.fint = cur.clkin / (2 * cur.regn);
913
914 if (cur.fint > FINT_MAX || cur.fint < FINT_MIN)
915 continue;
916
917 /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
918 for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) {
919 unsigned long a, b;
920
921 a = 2 * cur.regm * (cur.clkin/1000);
922 b = cur.regn * (cur.highfreq + 1);
923 cur.clkin4ddr = a / b * 1000;
924
925 if (cur.clkin4ddr > 1800 * 1000 * 1000)
926 break;
927
928 /* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3 < 173MHz */
929 for (cur.regm3 = 1; cur.regm3 < REGM3_MAX;
930 ++cur.regm3) {
931 struct dispc_clock_info cur_dispc;
932 cur.dsi1_pll_fclk = cur.clkin4ddr / cur.regm3;
933
934 /* this will narrow down the search a bit,
935 * but still give pixclocks below what was
936 * requested */
937 if (cur.dsi1_pll_fclk < req_pck)
938 break;
939
940 if (cur.dsi1_pll_fclk > DISPC_MAX_FCK)
941 continue;
942
943 if (min_fck_per_pck &&
944 cur.dsi1_pll_fclk <
945 req_pck * min_fck_per_pck)
946 continue;
947
948 match = 1;
949
950 dispc_find_clk_divs(is_tft, req_pck,
951 cur.dsi1_pll_fclk,
952 &cur_dispc);
953
954 if (abs(cur_dispc.pck - req_pck) <
955 abs(best_dispc.pck - req_pck)) {
956 best = cur;
957 best_dispc = cur_dispc;
958
959 if (cur_dispc.pck == req_pck)
960 goto found;
961 }
962 }
963 }
964 }
965found:
966 if (!match) {
967 if (min_fck_per_pck) {
968 DSSERR("Could not find suitable clock settings.\n"
969 "Turning FCK/PCK constraint off and"
970 "trying again.\n");
971 min_fck_per_pck = 0;
972 goto retry;
973 }
974
975 DSSERR("Could not find suitable clock settings.\n");
976
977 return -EINVAL;
978 }
979
980 /* DSI2_PLL_FCLK (regm4) is not used */
981 best.regm4 = 0;
982 best.dsi2_pll_fclk = 0;
983
984 if (dsi_cinfo)
985 *dsi_cinfo = best;
986 if (dispc_cinfo)
987 *dispc_cinfo = best_dispc;
988
989 dsi.cache_req_pck = req_pck;
990 dsi.cache_clk_freq = 0;
991 dsi.cache_cinfo = best;
992
993 return 0;
994}
995
996int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo)
997{
998 int r = 0;
999 u32 l;
1000 int f;
1001
1002 DSSDBGF();
1003
1004 dsi.current_cinfo.fint = cinfo->fint;
1005 dsi.current_cinfo.clkin4ddr = cinfo->clkin4ddr;
1006 dsi.current_cinfo.dsi1_pll_fclk = cinfo->dsi1_pll_fclk;
1007 dsi.current_cinfo.dsi2_pll_fclk = cinfo->dsi2_pll_fclk;
1008
1009 dsi.current_cinfo.regn = cinfo->regn;
1010 dsi.current_cinfo.regm = cinfo->regm;
1011 dsi.current_cinfo.regm3 = cinfo->regm3;
1012 dsi.current_cinfo.regm4 = cinfo->regm4;
1013
1014 DSSDBG("DSI Fint %ld\n", cinfo->fint);
1015
1016 DSSDBG("clkin (%s) rate %ld, highfreq %d\n",
1017 cinfo->use_dss2_fck ? "dss2_fck" : "pclkfree",
1018 cinfo->clkin,
1019 cinfo->highfreq);
1020
1021 /* DSIPHY == CLKIN4DDR */
1022 DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu / %d = %lu\n",
1023 cinfo->regm,
1024 cinfo->regn,
1025 cinfo->clkin,
1026 cinfo->highfreq + 1,
1027 cinfo->clkin4ddr);
1028
1029 DSSDBG("Data rate on 1 DSI lane %ld Mbps\n",
1030 cinfo->clkin4ddr / 1000 / 1000 / 2);
1031
1032 DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4);
1033
1034 DSSDBG("regm3 = %d, dsi1_pll_fclk = %lu\n",
1035 cinfo->regm3, cinfo->dsi1_pll_fclk);
1036 DSSDBG("regm4 = %d, dsi2_pll_fclk = %lu\n",
1037 cinfo->regm4, cinfo->dsi2_pll_fclk);
1038
1039 REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */
1040
1041 l = dsi_read_reg(DSI_PLL_CONFIGURATION1);
1042 l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */
1043 l = FLD_MOD(l, cinfo->regn - 1, 7, 1); /* DSI_PLL_REGN */
1044 l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */
1045 l = FLD_MOD(l, cinfo->regm3 > 0 ? cinfo->regm3 - 1 : 0,
1046 22, 19); /* DSI_CLOCK_DIV */
1047 l = FLD_MOD(l, cinfo->regm4 > 0 ? cinfo->regm4 - 1 : 0,
1048 26, 23); /* DSIPROTO_CLOCK_DIV */
1049 dsi_write_reg(DSI_PLL_CONFIGURATION1, l);
1050
1051 BUG_ON(cinfo->fint < 750000 || cinfo->fint > 2100000);
1052 if (cinfo->fint < 1000000)
1053 f = 0x3;
1054 else if (cinfo->fint < 1250000)
1055 f = 0x4;
1056 else if (cinfo->fint < 1500000)
1057 f = 0x5;
1058 else if (cinfo->fint < 1750000)
1059 f = 0x6;
1060 else
1061 f = 0x7;
1062
1063 l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
1064 l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */
1065 l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1,
1066 11, 11); /* DSI_PLL_CLKSEL */
1067 l = FLD_MOD(l, cinfo->highfreq,
1068 12, 12); /* DSI_PLL_HIGHFREQ */
1069 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
1070 l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */
1071 l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */
1072 dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
1073
1074 REG_FLD_MOD(DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */
1075
1076 if (wait_for_bit_change(DSI_PLL_GO, 0, 0) != 0) {
1077 DSSERR("dsi pll go bit not going down.\n");
1078 r = -EIO;
1079 goto err;
1080 }
1081
1082 if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) {
1083 DSSERR("cannot lock PLL\n");
1084 r = -EIO;
1085 goto err;
1086 }
1087
1088 dsi.pll_locked = 1;
1089
1090 l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
1091 l = FLD_MOD(l, 0, 0, 0); /* DSI_PLL_IDLE */
1092 l = FLD_MOD(l, 0, 5, 5); /* DSI_PLL_PLLLPMODE */
1093 l = FLD_MOD(l, 0, 6, 6); /* DSI_PLL_LOWCURRSTBY */
1094 l = FLD_MOD(l, 0, 7, 7); /* DSI_PLL_TIGHTPHASELOCK */
1095 l = FLD_MOD(l, 0, 8, 8); /* DSI_PLL_DRIFTGUARDEN */
1096 l = FLD_MOD(l, 0, 10, 9); /* DSI_PLL_LOCKSEL */
1097 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
1098 l = FLD_MOD(l, 1, 14, 14); /* DSIPHY_CLKINEN */
1099 l = FLD_MOD(l, 0, 15, 15); /* DSI_BYPASSEN */
1100 l = FLD_MOD(l, 1, 16, 16); /* DSS_CLOCK_EN */
1101 l = FLD_MOD(l, 0, 17, 17); /* DSS_CLOCK_PWDN */
1102 l = FLD_MOD(l, 1, 18, 18); /* DSI_PROTO_CLOCK_EN */
1103 l = FLD_MOD(l, 0, 19, 19); /* DSI_PROTO_CLOCK_PWDN */
1104 l = FLD_MOD(l, 0, 20, 20); /* DSI_HSDIVBYPASS */
1105 dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
1106
1107 DSSDBG("PLL config done\n");
1108err:
1109 return r;
1110}
1111
1112int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk,
1113 bool enable_hsdiv)
1114{
1115 int r = 0;
1116 enum dsi_pll_power_state pwstate;
1117
1118 DSSDBG("PLL init\n");
1119
1120 enable_clocks(1);
1121 dsi_enable_pll_clock(1);
1122
1123 r = regulator_enable(dsi.vdds_dsi_reg);
1124 if (r)
1125 goto err0;
1126
1127 /* XXX PLL does not come out of reset without this... */
1128 dispc_pck_free_enable(1);
1129
1130 if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) {
1131 DSSERR("PLL not coming out of reset.\n");
1132 r = -ENODEV;
1133 goto err1;
1134 }
1135
1136 /* XXX ... but if left on, we get problems when planes do not
1137 * fill the whole display. No idea about this */
1138 dispc_pck_free_enable(0);
1139
1140 if (enable_hsclk && enable_hsdiv)
1141 pwstate = DSI_PLL_POWER_ON_ALL;
1142 else if (enable_hsclk)
1143 pwstate = DSI_PLL_POWER_ON_HSCLK;
1144 else if (enable_hsdiv)
1145 pwstate = DSI_PLL_POWER_ON_DIV;
1146 else
1147 pwstate = DSI_PLL_POWER_OFF;
1148
1149 r = dsi_pll_power(pwstate);
1150
1151 if (r)
1152 goto err1;
1153
1154 DSSDBG("PLL init done\n");
1155
1156 return 0;
1157err1:
1158 regulator_disable(dsi.vdds_dsi_reg);
1159err0:
1160 enable_clocks(0);
1161 dsi_enable_pll_clock(0);
1162 return r;
1163}
1164
1165void dsi_pll_uninit(void)
1166{
1167 enable_clocks(0);
1168 dsi_enable_pll_clock(0);
1169
1170 dsi.pll_locked = 0;
1171 dsi_pll_power(DSI_PLL_POWER_OFF);
1172 regulator_disable(dsi.vdds_dsi_reg);
1173 DSSDBG("PLL uninit done\n");
1174}
1175
1176void dsi_dump_clocks(struct seq_file *s)
1177{
1178 int clksel;
1179 struct dsi_clock_info *cinfo = &dsi.current_cinfo;
1180
1181 enable_clocks(1);
1182
1183 clksel = REG_GET(DSI_PLL_CONFIGURATION2, 11, 11);
1184
1185 seq_printf(s, "- DSI PLL -\n");
1186
1187 seq_printf(s, "dsi pll source = %s\n",
1188 clksel == 0 ?
1189 "dss2_alwon_fclk" : "pclkfree");
1190
1191 seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn);
1192
1193 seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n",
1194 cinfo->clkin4ddr, cinfo->regm);
1195
1196 seq_printf(s, "dsi1_pll_fck\t%-16luregm3 %u\t(%s)\n",
1197 cinfo->dsi1_pll_fclk,
1198 cinfo->regm3,
1199 dss_get_dispc_clk_source() == 0 ? "off" : "on");
1200
1201 seq_printf(s, "dsi2_pll_fck\t%-16luregm4 %u\t(%s)\n",
1202 cinfo->dsi2_pll_fclk,
1203 cinfo->regm4,
1204 dss_get_dsi_clk_source() == 0 ? "off" : "on");
1205
1206 seq_printf(s, "- DSI -\n");
1207
1208 seq_printf(s, "dsi fclk source = %s\n",
1209 dss_get_dsi_clk_source() == 0 ?
1210 "dss1_alwon_fclk" : "dsi2_pll_fclk");
1211
1212 seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate());
1213
1214 seq_printf(s, "DDR_CLK\t\t%lu\n",
1215 cinfo->clkin4ddr / 4);
1216
1217 seq_printf(s, "TxByteClkHS\t%lu\n", dsi_get_txbyteclkhs());
1218
1219 seq_printf(s, "LP_CLK\t\t%lu\n", cinfo->lp_clk);
1220
1221 seq_printf(s, "VP_CLK\t\t%lu\n"
1222 "VP_PCLK\t\t%lu\n",
1223 dispc_lclk_rate(),
1224 dispc_pclk_rate());
1225
1226 enable_clocks(0);
1227}
1228
1229void dsi_dump_regs(struct seq_file *s)
1230{
1231#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r))
1232
1233 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
1234
1235 DUMPREG(DSI_REVISION);
1236 DUMPREG(DSI_SYSCONFIG);
1237 DUMPREG(DSI_SYSSTATUS);
1238 DUMPREG(DSI_IRQSTATUS);
1239 DUMPREG(DSI_IRQENABLE);
1240 DUMPREG(DSI_CTRL);
1241 DUMPREG(DSI_COMPLEXIO_CFG1);
1242 DUMPREG(DSI_COMPLEXIO_IRQ_STATUS);
1243 DUMPREG(DSI_COMPLEXIO_IRQ_ENABLE);
1244 DUMPREG(DSI_CLK_CTRL);
1245 DUMPREG(DSI_TIMING1);
1246 DUMPREG(DSI_TIMING2);
1247 DUMPREG(DSI_VM_TIMING1);
1248 DUMPREG(DSI_VM_TIMING2);
1249 DUMPREG(DSI_VM_TIMING3);
1250 DUMPREG(DSI_CLK_TIMING);
1251 DUMPREG(DSI_TX_FIFO_VC_SIZE);
1252 DUMPREG(DSI_RX_FIFO_VC_SIZE);
1253 DUMPREG(DSI_COMPLEXIO_CFG2);
1254 DUMPREG(DSI_RX_FIFO_VC_FULLNESS);
1255 DUMPREG(DSI_VM_TIMING4);
1256 DUMPREG(DSI_TX_FIFO_VC_EMPTINESS);
1257 DUMPREG(DSI_VM_TIMING5);
1258 DUMPREG(DSI_VM_TIMING6);
1259 DUMPREG(DSI_VM_TIMING7);
1260 DUMPREG(DSI_STOPCLK_TIMING);
1261
1262 DUMPREG(DSI_VC_CTRL(0));
1263 DUMPREG(DSI_VC_TE(0));
1264 DUMPREG(DSI_VC_LONG_PACKET_HEADER(0));
1265 DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(0));
1266 DUMPREG(DSI_VC_SHORT_PACKET_HEADER(0));
1267 DUMPREG(DSI_VC_IRQSTATUS(0));
1268 DUMPREG(DSI_VC_IRQENABLE(0));
1269
1270 DUMPREG(DSI_VC_CTRL(1));
1271 DUMPREG(DSI_VC_TE(1));
1272 DUMPREG(DSI_VC_LONG_PACKET_HEADER(1));
1273 DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(1));
1274 DUMPREG(DSI_VC_SHORT_PACKET_HEADER(1));
1275 DUMPREG(DSI_VC_IRQSTATUS(1));
1276 DUMPREG(DSI_VC_IRQENABLE(1));
1277
1278 DUMPREG(DSI_VC_CTRL(2));
1279 DUMPREG(DSI_VC_TE(2));
1280 DUMPREG(DSI_VC_LONG_PACKET_HEADER(2));
1281 DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(2));
1282 DUMPREG(DSI_VC_SHORT_PACKET_HEADER(2));
1283 DUMPREG(DSI_VC_IRQSTATUS(2));
1284 DUMPREG(DSI_VC_IRQENABLE(2));
1285
1286 DUMPREG(DSI_VC_CTRL(3));
1287 DUMPREG(DSI_VC_TE(3));
1288 DUMPREG(DSI_VC_LONG_PACKET_HEADER(3));
1289 DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(3));
1290 DUMPREG(DSI_VC_SHORT_PACKET_HEADER(3));
1291 DUMPREG(DSI_VC_IRQSTATUS(3));
1292 DUMPREG(DSI_VC_IRQENABLE(3));
1293
1294 DUMPREG(DSI_DSIPHY_CFG0);
1295 DUMPREG(DSI_DSIPHY_CFG1);
1296 DUMPREG(DSI_DSIPHY_CFG2);
1297 DUMPREG(DSI_DSIPHY_CFG5);
1298
1299 DUMPREG(DSI_PLL_CONTROL);
1300 DUMPREG(DSI_PLL_STATUS);
1301 DUMPREG(DSI_PLL_GO);
1302 DUMPREG(DSI_PLL_CONFIGURATION1);
1303 DUMPREG(DSI_PLL_CONFIGURATION2);
1304
1305 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
1306#undef DUMPREG
1307}
1308
1309enum dsi_complexio_power_state {
1310 DSI_COMPLEXIO_POWER_OFF = 0x0,
1311 DSI_COMPLEXIO_POWER_ON = 0x1,
1312 DSI_COMPLEXIO_POWER_ULPS = 0x2,
1313};
1314
1315static int dsi_complexio_power(enum dsi_complexio_power_state state)
1316{
1317 int t = 0;
1318
1319 /* PWR_CMD */
1320 REG_FLD_MOD(DSI_COMPLEXIO_CFG1, state, 28, 27);
1321
1322 /* PWR_STATUS */
1323 while (FLD_GET(dsi_read_reg(DSI_COMPLEXIO_CFG1), 26, 25) != state) {
1324 udelay(1);
1325 if (t++ > 1000) {
1326 DSSERR("failed to set complexio power state to "
1327 "%d\n", state);
1328 return -ENODEV;
1329 }
1330 }
1331
1332 return 0;
1333}
1334
1335static void dsi_complexio_config(struct omap_dss_device *dssdev)
1336{
1337 u32 r;
1338
1339 int clk_lane = dssdev->phy.dsi.clk_lane;
1340 int data1_lane = dssdev->phy.dsi.data1_lane;
1341 int data2_lane = dssdev->phy.dsi.data2_lane;
1342 int clk_pol = dssdev->phy.dsi.clk_pol;
1343 int data1_pol = dssdev->phy.dsi.data1_pol;
1344 int data2_pol = dssdev->phy.dsi.data2_pol;
1345
1346 r = dsi_read_reg(DSI_COMPLEXIO_CFG1);
1347 r = FLD_MOD(r, clk_lane, 2, 0);
1348 r = FLD_MOD(r, clk_pol, 3, 3);
1349 r = FLD_MOD(r, data1_lane, 6, 4);
1350 r = FLD_MOD(r, data1_pol, 7, 7);
1351 r = FLD_MOD(r, data2_lane, 10, 8);
1352 r = FLD_MOD(r, data2_pol, 11, 11);
1353 dsi_write_reg(DSI_COMPLEXIO_CFG1, r);
1354
1355 /* The configuration of the DSI complex I/O (number of data lanes,
1356 position, differential order) should not be changed while
1357 DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for
1358 the hardware to take into account a new configuration of the complex
1359 I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to
1360 follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1,
1361 then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set
1362 DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the
1363 DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the
1364 DSI complex I/O configuration is unknown. */
1365
1366 /*
1367 REG_FLD_MOD(DSI_CTRL, 1, 0, 0);
1368 REG_FLD_MOD(DSI_CTRL, 0, 0, 0);
1369 REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20);
1370 REG_FLD_MOD(DSI_CTRL, 1, 0, 0);
1371 */
1372}
1373
1374static inline unsigned ns2ddr(unsigned ns)
1375{
1376 /* convert time in ns to ddr ticks, rounding up */
1377 unsigned long ddr_clk = dsi.current_cinfo.clkin4ddr / 4;
1378 return (ns * (ddr_clk / 1000 / 1000) + 999) / 1000;
1379}
1380
1381static inline unsigned ddr2ns(unsigned ddr)
1382{
1383 unsigned long ddr_clk = dsi.current_cinfo.clkin4ddr / 4;
1384 return ddr * 1000 * 1000 / (ddr_clk / 1000);
1385}
1386
1387static void dsi_complexio_timings(void)
1388{
1389 u32 r;
1390 u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit;
1391 u32 tlpx_half, tclk_trail, tclk_zero;
1392 u32 tclk_prepare;
1393
1394 /* calculate timings */
1395
1396 /* 1 * DDR_CLK = 2 * UI */
1397
1398 /* min 40ns + 4*UI max 85ns + 6*UI */
1399 ths_prepare = ns2ddr(70) + 2;
1400
1401 /* min 145ns + 10*UI */
1402 ths_prepare_ths_zero = ns2ddr(175) + 2;
1403
1404 /* min max(8*UI, 60ns+4*UI) */
1405 ths_trail = ns2ddr(60) + 5;
1406
1407 /* min 100ns */
1408 ths_exit = ns2ddr(145);
1409
1410 /* tlpx min 50n */
1411 tlpx_half = ns2ddr(25);
1412
1413 /* min 60ns */
1414 tclk_trail = ns2ddr(60) + 2;
1415
1416 /* min 38ns, max 95ns */
1417 tclk_prepare = ns2ddr(65);
1418
1419 /* min tclk-prepare + tclk-zero = 300ns */
1420 tclk_zero = ns2ddr(260);
1421
1422 DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n",
1423 ths_prepare, ddr2ns(ths_prepare),
1424 ths_prepare_ths_zero, ddr2ns(ths_prepare_ths_zero));
1425 DSSDBG("ths_trail %u (%uns), ths_exit %u (%uns)\n",
1426 ths_trail, ddr2ns(ths_trail),
1427 ths_exit, ddr2ns(ths_exit));
1428
1429 DSSDBG("tlpx_half %u (%uns), tclk_trail %u (%uns), "
1430 "tclk_zero %u (%uns)\n",
1431 tlpx_half, ddr2ns(tlpx_half),
1432 tclk_trail, ddr2ns(tclk_trail),
1433 tclk_zero, ddr2ns(tclk_zero));
1434 DSSDBG("tclk_prepare %u (%uns)\n",
1435 tclk_prepare, ddr2ns(tclk_prepare));
1436
1437 /* program timings */
1438
1439 r = dsi_read_reg(DSI_DSIPHY_CFG0);
1440 r = FLD_MOD(r, ths_prepare, 31, 24);
1441 r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16);
1442 r = FLD_MOD(r, ths_trail, 15, 8);
1443 r = FLD_MOD(r, ths_exit, 7, 0);
1444 dsi_write_reg(DSI_DSIPHY_CFG0, r);
1445
1446 r = dsi_read_reg(DSI_DSIPHY_CFG1);
1447 r = FLD_MOD(r, tlpx_half, 22, 16);
1448 r = FLD_MOD(r, tclk_trail, 15, 8);
1449 r = FLD_MOD(r, tclk_zero, 7, 0);
1450 dsi_write_reg(DSI_DSIPHY_CFG1, r);
1451
1452 r = dsi_read_reg(DSI_DSIPHY_CFG2);
1453 r = FLD_MOD(r, tclk_prepare, 7, 0);
1454 dsi_write_reg(DSI_DSIPHY_CFG2, r);
1455}
1456
1457
1458static int dsi_complexio_init(struct omap_dss_device *dssdev)
1459{
1460 int r = 0;
1461
1462 DSSDBG("dsi_complexio_init\n");
1463
1464 /* CIO_CLK_ICG, enable L3 clk to CIO */
1465 REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14);
1466
1467 /* A dummy read using the SCP interface to any DSIPHY register is
1468 * required after DSIPHY reset to complete the reset of the DSI complex
1469 * I/O. */
1470 dsi_read_reg(DSI_DSIPHY_CFG5);
1471
1472 if (wait_for_bit_change(DSI_DSIPHY_CFG5, 30, 1) != 1) {
1473 DSSERR("ComplexIO PHY not coming out of reset.\n");
1474 r = -ENODEV;
1475 goto err;
1476 }
1477
1478 dsi_complexio_config(dssdev);
1479
1480 r = dsi_complexio_power(DSI_COMPLEXIO_POWER_ON);
1481
1482 if (r)
1483 goto err;
1484
1485 if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 29, 1) != 1) {
1486 DSSERR("ComplexIO not coming out of reset.\n");
1487 r = -ENODEV;
1488 goto err;
1489 }
1490
1491 if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) {
1492 DSSERR("ComplexIO LDO power down.\n");
1493 r = -ENODEV;
1494 goto err;
1495 }
1496
1497 dsi_complexio_timings();
1498
1499 /*
1500 The configuration of the DSI complex I/O (number of data lanes,
1501 position, differential order) should not be changed while
1502 DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. For the
1503 hardware to recognize a new configuration of the complex I/O (done
1504 in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to follow
1505 this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, next
1506 reset the DSS.DSI_CTRL[0] IF_EN to 0, then set DSS.DSI_CLK_CTRL[20]
1507 LP_CLK_ENABLE to 1, and finally, set again the DSS.DSI_CTRL[0] IF_EN
1508 bit to 1. If the sequence is not followed, the DSi complex I/O
1509 configuration is undetermined.
1510 */
1511 dsi_if_enable(1);
1512 dsi_if_enable(0);
1513 REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
1514 dsi_if_enable(1);
1515 dsi_if_enable(0);
1516
1517 DSSDBG("CIO init done\n");
1518err:
1519 return r;
1520}
1521
1522static void dsi_complexio_uninit(void)
1523{
1524 dsi_complexio_power(DSI_COMPLEXIO_POWER_OFF);
1525}
1526
1527static int _dsi_wait_reset(void)
1528{
1529 int i = 0;
1530
1531 while (REG_GET(DSI_SYSSTATUS, 0, 0) == 0) {
1532 if (i++ > 5) {
1533 DSSERR("soft reset failed\n");
1534 return -ENODEV;
1535 }
1536 udelay(1);
1537 }
1538
1539 return 0;
1540}
1541
1542static int _dsi_reset(void)
1543{
1544 /* Soft reset */
1545 REG_FLD_MOD(DSI_SYSCONFIG, 1, 1, 1);
1546 return _dsi_wait_reset();
1547}
1548
1549static void dsi_reset_tx_fifo(int channel)
1550{
1551 u32 mask;
1552 u32 l;
1553
1554 /* set fifosize of the channel to 0, then return the old size */
1555 l = dsi_read_reg(DSI_TX_FIFO_VC_SIZE);
1556
1557 mask = FLD_MASK((8 * channel) + 7, (8 * channel) + 4);
1558 dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l & ~mask);
1559
1560 dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l);
1561}
1562
1563static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2,
1564 enum fifo_size size3, enum fifo_size size4)
1565{
1566 u32 r = 0;
1567 int add = 0;
1568 int i;
1569
1570 dsi.vc[0].fifo_size = size1;
1571 dsi.vc[1].fifo_size = size2;
1572 dsi.vc[2].fifo_size = size3;
1573 dsi.vc[3].fifo_size = size4;
1574
1575 for (i = 0; i < 4; i++) {
1576 u8 v;
1577 int size = dsi.vc[i].fifo_size;
1578
1579 if (add + size > 4) {
1580 DSSERR("Illegal FIFO configuration\n");
1581 BUG();
1582 }
1583
1584 v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
1585 r |= v << (8 * i);
1586 /*DSSDBG("TX FIFO vc %d: size %d, add %d\n", i, size, add); */
1587 add += size;
1588 }
1589
1590 dsi_write_reg(DSI_TX_FIFO_VC_SIZE, r);
1591}
1592
1593static void dsi_config_rx_fifo(enum fifo_size size1, enum fifo_size size2,
1594 enum fifo_size size3, enum fifo_size size4)
1595{
1596 u32 r = 0;
1597 int add = 0;
1598 int i;
1599
1600 dsi.vc[0].fifo_size = size1;
1601 dsi.vc[1].fifo_size = size2;
1602 dsi.vc[2].fifo_size = size3;
1603 dsi.vc[3].fifo_size = size4;
1604
1605 for (i = 0; i < 4; i++) {
1606 u8 v;
1607 int size = dsi.vc[i].fifo_size;
1608
1609 if (add + size > 4) {
1610 DSSERR("Illegal FIFO configuration\n");
1611 BUG();
1612 }
1613
1614 v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
1615 r |= v << (8 * i);
1616 /*DSSDBG("RX FIFO vc %d: size %d, add %d\n", i, size, add); */
1617 add += size;
1618 }
1619
1620 dsi_write_reg(DSI_RX_FIFO_VC_SIZE, r);
1621}
1622
1623static int dsi_force_tx_stop_mode_io(void)
1624{
1625 u32 r;
1626
1627 r = dsi_read_reg(DSI_TIMING1);
1628 r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
1629 dsi_write_reg(DSI_TIMING1, r);
1630
1631 if (wait_for_bit_change(DSI_TIMING1, 15, 0) != 0) {
1632 DSSERR("TX_STOP bit not going down\n");
1633 return -EIO;
1634 }
1635
1636 return 0;
1637}
1638
1639static void dsi_vc_print_status(int channel)
1640{
1641 u32 r;
1642
1643 r = dsi_read_reg(DSI_VC_CTRL(channel));
1644 DSSDBG("vc %d: TX_FIFO_NOT_EMPTY %d, BTA_EN %d, VC_BUSY %d, "
1645 "TX_FIFO_FULL %d, RX_FIFO_NOT_EMPTY %d, ",
1646 channel,
1647 FLD_GET(r, 5, 5),
1648 FLD_GET(r, 6, 6),
1649 FLD_GET(r, 15, 15),
1650 FLD_GET(r, 16, 16),
1651 FLD_GET(r, 20, 20));
1652
1653 r = dsi_read_reg(DSI_TX_FIFO_VC_EMPTINESS);
1654 DSSDBG("EMPTINESS %d\n", (r >> (8 * channel)) & 0xff);
1655}
1656
1657static int dsi_vc_enable(int channel, bool enable)
1658{
1659 if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
1660 DSSDBG("dsi_vc_enable channel %d, enable %d\n",
1661 channel, enable);
1662
1663 enable = enable ? 1 : 0;
1664
1665 REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 0, 0);
1666
1667 if (wait_for_bit_change(DSI_VC_CTRL(channel), 0, enable) != enable) {
1668 DSSERR("Failed to set dsi_vc_enable to %d\n", enable);
1669 return -EIO;
1670 }
1671
1672 return 0;
1673}
1674
1675static void dsi_vc_initial_config(int channel)
1676{
1677 u32 r;
1678
1679 DSSDBGF("%d", channel);
1680
1681 r = dsi_read_reg(DSI_VC_CTRL(channel));
1682
1683 if (FLD_GET(r, 15, 15)) /* VC_BUSY */
1684 DSSERR("VC(%d) busy when trying to configure it!\n",
1685 channel);
1686
1687 r = FLD_MOD(r, 0, 1, 1); /* SOURCE, 0 = L4 */
1688 r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN */
1689 r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */
1690 r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */
1691 r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
1692 r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
1693 r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */
1694
1695 r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
1696 r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
1697
1698 dsi_write_reg(DSI_VC_CTRL(channel), r);
1699
1700 dsi.vc[channel].mode = DSI_VC_MODE_L4;
1701}
1702
1703static void dsi_vc_config_l4(int channel)
1704{
1705 if (dsi.vc[channel].mode == DSI_VC_MODE_L4)
1706 return;
1707
1708 DSSDBGF("%d", channel);
1709
1710 dsi_vc_enable(channel, 0);
1711
1712 if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */
1713 DSSERR("vc(%d) busy when trying to config for L4\n", channel);
1714
1715 REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */
1716
1717 dsi_vc_enable(channel, 1);
1718
1719 dsi.vc[channel].mode = DSI_VC_MODE_L4;
1720}
1721
1722static void dsi_vc_config_vp(int channel)
1723{
1724 if (dsi.vc[channel].mode == DSI_VC_MODE_VP)
1725 return;
1726
1727 DSSDBGF("%d", channel);
1728
1729 dsi_vc_enable(channel, 0);
1730
1731 if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */
1732 DSSERR("vc(%d) busy when trying to config for VP\n", channel);
1733
1734 REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */
1735
1736 dsi_vc_enable(channel, 1);
1737
1738 dsi.vc[channel].mode = DSI_VC_MODE_VP;
1739}
1740
1741
1742static void dsi_vc_enable_hs(int channel, bool enable)
1743{
1744 DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
1745
1746 dsi_vc_enable(channel, 0);
1747 dsi_if_enable(0);
1748
1749 REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 9, 9);
1750
1751 dsi_vc_enable(channel, 1);
1752 dsi_if_enable(1);
1753
1754 dsi_force_tx_stop_mode_io();
1755}
1756
1757static void dsi_vc_flush_long_data(int channel)
1758{
1759 while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
1760 u32 val;
1761 val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
1762 DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n",
1763 (val >> 0) & 0xff,
1764 (val >> 8) & 0xff,
1765 (val >> 16) & 0xff,
1766 (val >> 24) & 0xff);
1767 }
1768}
1769
1770static void dsi_show_rx_ack_with_err(u16 err)
1771{
1772 DSSERR("\tACK with ERROR (%#x):\n", err);
1773 if (err & (1 << 0))
1774 DSSERR("\t\tSoT Error\n");
1775 if (err & (1 << 1))
1776 DSSERR("\t\tSoT Sync Error\n");
1777 if (err & (1 << 2))
1778 DSSERR("\t\tEoT Sync Error\n");
1779 if (err & (1 << 3))
1780 DSSERR("\t\tEscape Mode Entry Command Error\n");
1781 if (err & (1 << 4))
1782 DSSERR("\t\tLP Transmit Sync Error\n");
1783 if (err & (1 << 5))
1784 DSSERR("\t\tHS Receive Timeout Error\n");
1785 if (err & (1 << 6))
1786 DSSERR("\t\tFalse Control Error\n");
1787 if (err & (1 << 7))
1788 DSSERR("\t\t(reserved7)\n");
1789 if (err & (1 << 8))
1790 DSSERR("\t\tECC Error, single-bit (corrected)\n");
1791 if (err & (1 << 9))
1792 DSSERR("\t\tECC Error, multi-bit (not corrected)\n");
1793 if (err & (1 << 10))
1794 DSSERR("\t\tChecksum Error\n");
1795 if (err & (1 << 11))
1796 DSSERR("\t\tData type not recognized\n");
1797 if (err & (1 << 12))
1798 DSSERR("\t\tInvalid VC ID\n");
1799 if (err & (1 << 13))
1800 DSSERR("\t\tInvalid Transmission Length\n");
1801 if (err & (1 << 14))
1802 DSSERR("\t\t(reserved14)\n");
1803 if (err & (1 << 15))
1804 DSSERR("\t\tDSI Protocol Violation\n");
1805}
1806
1807static u16 dsi_vc_flush_receive_data(int channel)
1808{
1809 /* RX_FIFO_NOT_EMPTY */
1810 while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
1811 u32 val;
1812 u8 dt;
1813 val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
1814 DSSDBG("\trawval %#08x\n", val);
1815 dt = FLD_GET(val, 5, 0);
1816 if (dt == DSI_DT_RX_ACK_WITH_ERR) {
1817 u16 err = FLD_GET(val, 23, 8);
1818 dsi_show_rx_ack_with_err(err);
1819 } else if (dt == DSI_DT_RX_SHORT_READ_1) {
1820 DSSDBG("\tDCS short response, 1 byte: %#x\n",
1821 FLD_GET(val, 23, 8));
1822 } else if (dt == DSI_DT_RX_SHORT_READ_2) {
1823 DSSDBG("\tDCS short response, 2 byte: %#x\n",
1824 FLD_GET(val, 23, 8));
1825 } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
1826 DSSDBG("\tDCS long response, len %d\n",
1827 FLD_GET(val, 23, 8));
1828 dsi_vc_flush_long_data(channel);
1829 } else {
1830 DSSERR("\tunknown datatype 0x%02x\n", dt);
1831 }
1832 }
1833 return 0;
1834}
1835
1836static int dsi_vc_send_bta(int channel)
1837{
1838 if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO &&
1839 (dsi.debug_write || dsi.debug_read))
1840 DSSDBG("dsi_vc_send_bta %d\n", channel);
1841
1842 WARN_ON(!mutex_is_locked(&dsi.bus_lock));
1843
1844 if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */
1845 DSSERR("rx fifo not empty when sending BTA, dumping data:\n");
1846 dsi_vc_flush_receive_data(channel);
1847 }
1848
1849 REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */
1850
1851 return 0;
1852}
1853
1854int dsi_vc_send_bta_sync(int channel)
1855{
1856 int r = 0;
1857 u32 err;
1858
1859 INIT_COMPLETION(dsi.bta_completion);
1860
1861 dsi_vc_enable_bta_irq(channel);
1862
1863 r = dsi_vc_send_bta(channel);
1864 if (r)
1865 goto err;
1866
1867 if (wait_for_completion_timeout(&dsi.bta_completion,
1868 msecs_to_jiffies(500)) == 0) {
1869 DSSERR("Failed to receive BTA\n");
1870 r = -EIO;
1871 goto err;
1872 }
1873
1874 err = dsi_get_errors();
1875 if (err) {
1876 DSSERR("Error while sending BTA: %x\n", err);
1877 r = -EIO;
1878 goto err;
1879 }
1880err:
1881 dsi_vc_disable_bta_irq(channel);
1882
1883 return r;
1884}
1885EXPORT_SYMBOL(dsi_vc_send_bta_sync);
1886
1887static inline void dsi_vc_write_long_header(int channel, u8 data_type,
1888 u16 len, u8 ecc)
1889{
1890 u32 val;
1891 u8 data_id;
1892
1893 WARN_ON(!mutex_is_locked(&dsi.bus_lock));
1894
1895 /*data_id = data_type | channel << 6; */
1896 data_id = data_type | dsi.vc[channel].dest_per << 6;
1897
1898 val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) |
1899 FLD_VAL(ecc, 31, 24);
1900
1901 dsi_write_reg(DSI_VC_LONG_PACKET_HEADER(channel), val);
1902}
1903
1904static inline void dsi_vc_write_long_payload(int channel,
1905 u8 b1, u8 b2, u8 b3, u8 b4)
1906{
1907 u32 val;
1908
1909 val = b4 << 24 | b3 << 16 | b2 << 8 | b1 << 0;
1910
1911/* DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n",
1912 b1, b2, b3, b4, val); */
1913
1914 dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(channel), val);
1915}
1916
1917static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len,
1918 u8 ecc)
1919{
1920 /*u32 val; */
1921 int i;
1922 u8 *p;
1923 int r = 0;
1924 u8 b1, b2, b3, b4;
1925
1926 if (dsi.debug_write)
1927 DSSDBG("dsi_vc_send_long, %d bytes\n", len);
1928
1929 /* len + header */
1930 if (dsi.vc[channel].fifo_size * 32 * 4 < len + 4) {
1931 DSSERR("unable to send long packet: packet too long.\n");
1932 return -EINVAL;
1933 }
1934
1935 dsi_vc_config_l4(channel);
1936
1937 dsi_vc_write_long_header(channel, data_type, len, ecc);
1938
1939 /*dsi_vc_print_status(0); */
1940
1941 p = data;
1942 for (i = 0; i < len >> 2; i++) {
1943 if (dsi.debug_write)
1944 DSSDBG("\tsending full packet %d\n", i);
1945 /*dsi_vc_print_status(0); */
1946
1947 b1 = *p++;
1948 b2 = *p++;
1949 b3 = *p++;
1950 b4 = *p++;
1951
1952 dsi_vc_write_long_payload(channel, b1, b2, b3, b4);
1953 }
1954
1955 i = len % 4;
1956 if (i) {
1957 b1 = 0; b2 = 0; b3 = 0;
1958
1959 if (dsi.debug_write)
1960 DSSDBG("\tsending remainder bytes %d\n", i);
1961
1962 switch (i) {
1963 case 3:
1964 b1 = *p++;
1965 b2 = *p++;
1966 b3 = *p++;
1967 break;
1968 case 2:
1969 b1 = *p++;
1970 b2 = *p++;
1971 break;
1972 case 1:
1973 b1 = *p++;
1974 break;
1975 }
1976
1977 dsi_vc_write_long_payload(channel, b1, b2, b3, 0);
1978 }
1979
1980 return r;
1981}
1982
1983static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc)
1984{
1985 u32 r;
1986 u8 data_id;
1987
1988 WARN_ON(!mutex_is_locked(&dsi.bus_lock));
1989
1990 if (dsi.debug_write)
1991 DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n",
1992 channel,
1993 data_type, data & 0xff, (data >> 8) & 0xff);
1994
1995 dsi_vc_config_l4(channel);
1996
1997 if (FLD_GET(dsi_read_reg(DSI_VC_CTRL(channel)), 16, 16)) {
1998 DSSERR("ERROR FIFO FULL, aborting transfer\n");
1999 return -EINVAL;
2000 }
2001
2002 data_id = data_type | channel << 6;
2003
2004 r = (data_id << 0) | (data << 8) | (ecc << 24);
2005
2006 dsi_write_reg(DSI_VC_SHORT_PACKET_HEADER(channel), r);
2007
2008 return 0;
2009}
2010
2011int dsi_vc_send_null(int channel)
2012{
2013 u8 nullpkg[] = {0, 0, 0, 0};
2014 return dsi_vc_send_long(0, DSI_DT_NULL_PACKET, nullpkg, 4, 0);
2015}
2016EXPORT_SYMBOL(dsi_vc_send_null);
2017
2018int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len)
2019{
2020 int r;
2021
2022 BUG_ON(len == 0);
2023
2024 if (len == 1) {
2025 r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_0,
2026 data[0], 0);
2027 } else if (len == 2) {
2028 r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_1,
2029 data[0] | (data[1] << 8), 0);
2030 } else {
2031 /* 0x39 = DCS Long Write */
2032 r = dsi_vc_send_long(channel, DSI_DT_DCS_LONG_WRITE,
2033 data, len, 0);
2034 }
2035
2036 return r;
2037}
2038EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
2039
2040int dsi_vc_dcs_write(int channel, u8 *data, int len)
2041{
2042 int r;
2043
2044 r = dsi_vc_dcs_write_nosync(channel, data, len);
2045 if (r)
2046 return r;
2047
2048 r = dsi_vc_send_bta_sync(channel);
2049
2050 return r;
2051}
2052EXPORT_SYMBOL(dsi_vc_dcs_write);
2053
2054int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
2055{
2056 u32 val;
2057 u8 dt;
2058 int r;
2059
2060 if (dsi.debug_read)
2061 DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %u)\n", channel, dcs_cmd);
2062
2063 r = dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0);
2064 if (r)
2065 return r;
2066
2067 r = dsi_vc_send_bta_sync(channel);
2068 if (r)
2069 return r;
2070
2071 /* RX_FIFO_NOT_EMPTY */
2072 if (REG_GET(DSI_VC_CTRL(channel), 20, 20) == 0) {
2073 DSSERR("RX fifo empty when trying to read.\n");
2074 return -EIO;
2075 }
2076
2077 val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
2078 if (dsi.debug_read)
2079 DSSDBG("\theader: %08x\n", val);
2080 dt = FLD_GET(val, 5, 0);
2081 if (dt == DSI_DT_RX_ACK_WITH_ERR) {
2082 u16 err = FLD_GET(val, 23, 8);
2083 dsi_show_rx_ack_with_err(err);
2084 return -EIO;
2085
2086 } else if (dt == DSI_DT_RX_SHORT_READ_1) {
2087 u8 data = FLD_GET(val, 15, 8);
2088 if (dsi.debug_read)
2089 DSSDBG("\tDCS short response, 1 byte: %02x\n", data);
2090
2091 if (buflen < 1)
2092 return -EIO;
2093
2094 buf[0] = data;
2095
2096 return 1;
2097 } else if (dt == DSI_DT_RX_SHORT_READ_2) {
2098 u16 data = FLD_GET(val, 23, 8);
2099 if (dsi.debug_read)
2100 DSSDBG("\tDCS short response, 2 byte: %04x\n", data);
2101
2102 if (buflen < 2)
2103 return -EIO;
2104
2105 buf[0] = data & 0xff;
2106 buf[1] = (data >> 8) & 0xff;
2107
2108 return 2;
2109 } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
2110 int w;
2111 int len = FLD_GET(val, 23, 8);
2112 if (dsi.debug_read)
2113 DSSDBG("\tDCS long response, len %d\n", len);
2114
2115 if (len > buflen)
2116 return -EIO;
2117
2118 /* two byte checksum ends the packet, not included in len */
2119 for (w = 0; w < len + 2;) {
2120 int b;
2121 val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
2122 if (dsi.debug_read)
2123 DSSDBG("\t\t%02x %02x %02x %02x\n",
2124 (val >> 0) & 0xff,
2125 (val >> 8) & 0xff,
2126 (val >> 16) & 0xff,
2127 (val >> 24) & 0xff);
2128
2129 for (b = 0; b < 4; ++b) {
2130 if (w < len)
2131 buf[w] = (val >> (b * 8)) & 0xff;
2132 /* we discard the 2 byte checksum */
2133 ++w;
2134 }
2135 }
2136
2137 return len;
2138
2139 } else {
2140 DSSERR("\tunknown datatype 0x%02x\n", dt);
2141 return -EIO;
2142 }
2143}
2144EXPORT_SYMBOL(dsi_vc_dcs_read);
2145
2146
2147int dsi_vc_set_max_rx_packet_size(int channel, u16 len)
2148{
2149 int r;
2150 r = dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE,
2151 len, 0);
2152
2153 if (r)
2154 return r;
2155
2156 r = dsi_vc_send_bta_sync(channel);
2157
2158 return r;
2159}
2160EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size);
2161
2162static void dsi_set_lp_rx_timeout(unsigned long ns)
2163{
2164 u32 r;
2165 unsigned x4, x16;
2166 unsigned long fck;
2167 unsigned long ticks;
2168
2169 /* ticks in DSI_FCK */
2170
2171 fck = dsi_fclk_rate();
2172 ticks = (fck / 1000 / 1000) * ns / 1000;
2173 x4 = 0;
2174 x16 = 0;
2175
2176 if (ticks > 0x1fff) {
2177 ticks = (fck / 1000 / 1000) * ns / 1000 / 4;
2178 x4 = 1;
2179 x16 = 0;
2180 }
2181
2182 if (ticks > 0x1fff) {
2183 ticks = (fck / 1000 / 1000) * ns / 1000 / 16;
2184 x4 = 0;
2185 x16 = 1;
2186 }
2187
2188 if (ticks > 0x1fff) {
2189 ticks = (fck / 1000 / 1000) * ns / 1000 / (4 * 16);
2190 x4 = 1;
2191 x16 = 1;
2192 }
2193
2194 if (ticks > 0x1fff) {
2195 DSSWARN("LP_TX_TO over limit, setting it to max\n");
2196 ticks = 0x1fff;
2197 x4 = 1;
2198 x16 = 1;
2199 }
2200
2201 r = dsi_read_reg(DSI_TIMING2);
2202 r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */
2203 r = FLD_MOD(r, x16, 14, 14); /* LP_RX_TO_X16 */
2204 r = FLD_MOD(r, x4, 13, 13); /* LP_RX_TO_X4 */
2205 r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */
2206 dsi_write_reg(DSI_TIMING2, r);
2207
2208 DSSDBG("LP_RX_TO %lu ns (%#lx ticks%s%s)\n",
2209 (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
2210 (fck / 1000 / 1000),
2211 ticks, x4 ? " x4" : "", x16 ? " x16" : "");
2212}
2213
2214static void dsi_set_ta_timeout(unsigned long ns)
2215{
2216 u32 r;
2217 unsigned x8, x16;
2218 unsigned long fck;
2219 unsigned long ticks;
2220
2221 /* ticks in DSI_FCK */
2222 fck = dsi_fclk_rate();
2223 ticks = (fck / 1000 / 1000) * ns / 1000;
2224 x8 = 0;
2225 x16 = 0;
2226
2227 if (ticks > 0x1fff) {
2228 ticks = (fck / 1000 / 1000) * ns / 1000 / 8;
2229 x8 = 1;
2230 x16 = 0;
2231 }
2232
2233 if (ticks > 0x1fff) {
2234 ticks = (fck / 1000 / 1000) * ns / 1000 / 16;
2235 x8 = 0;
2236 x16 = 1;
2237 }
2238
2239 if (ticks > 0x1fff) {
2240 ticks = (fck / 1000 / 1000) * ns / 1000 / (8 * 16);
2241 x8 = 1;
2242 x16 = 1;
2243 }
2244
2245 if (ticks > 0x1fff) {
2246 DSSWARN("TA_TO over limit, setting it to max\n");
2247 ticks = 0x1fff;
2248 x8 = 1;
2249 x16 = 1;
2250 }
2251
2252 r = dsi_read_reg(DSI_TIMING1);
2253 r = FLD_MOD(r, 1, 31, 31); /* TA_TO */
2254 r = FLD_MOD(r, x16, 30, 30); /* TA_TO_X16 */
2255 r = FLD_MOD(r, x8, 29, 29); /* TA_TO_X8 */
2256 r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */
2257 dsi_write_reg(DSI_TIMING1, r);
2258
2259 DSSDBG("TA_TO %lu ns (%#lx ticks%s%s)\n",
2260 (ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1) * 1000) /
2261 (fck / 1000 / 1000),
2262 ticks, x8 ? " x8" : "", x16 ? " x16" : "");
2263}
2264
2265static void dsi_set_stop_state_counter(unsigned long ns)
2266{
2267 u32 r;
2268 unsigned x4, x16;
2269 unsigned long fck;
2270 unsigned long ticks;
2271
2272 /* ticks in DSI_FCK */
2273
2274 fck = dsi_fclk_rate();
2275 ticks = (fck / 1000 / 1000) * ns / 1000;
2276 x4 = 0;
2277 x16 = 0;
2278
2279 if (ticks > 0x1fff) {
2280 ticks = (fck / 1000 / 1000) * ns / 1000 / 4;
2281 x4 = 1;
2282 x16 = 0;
2283 }
2284
2285 if (ticks > 0x1fff) {
2286 ticks = (fck / 1000 / 1000) * ns / 1000 / 16;
2287 x4 = 0;
2288 x16 = 1;
2289 }
2290
2291 if (ticks > 0x1fff) {
2292 ticks = (fck / 1000 / 1000) * ns / 1000 / (4 * 16);
2293 x4 = 1;
2294 x16 = 1;
2295 }
2296
2297 if (ticks > 0x1fff) {
2298 DSSWARN("STOP_STATE_COUNTER_IO over limit, "
2299 "setting it to max\n");
2300 ticks = 0x1fff;
2301 x4 = 1;
2302 x16 = 1;
2303 }
2304
2305 r = dsi_read_reg(DSI_TIMING1);
2306 r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
2307 r = FLD_MOD(r, x16, 14, 14); /* STOP_STATE_X16_IO */
2308 r = FLD_MOD(r, x4, 13, 13); /* STOP_STATE_X4_IO */
2309 r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */
2310 dsi_write_reg(DSI_TIMING1, r);
2311
2312 DSSDBG("STOP_STATE_COUNTER %lu ns (%#lx ticks%s%s)\n",
2313 (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
2314 (fck / 1000 / 1000),
2315 ticks, x4 ? " x4" : "", x16 ? " x16" : "");
2316}
2317
2318static void dsi_set_hs_tx_timeout(unsigned long ns)
2319{
2320 u32 r;
2321 unsigned x4, x16;
2322 unsigned long fck;
2323 unsigned long ticks;
2324
2325 /* ticks in TxByteClkHS */
2326
2327 fck = dsi_get_txbyteclkhs();
2328 ticks = (fck / 1000 / 1000) * ns / 1000;
2329 x4 = 0;
2330 x16 = 0;
2331
2332 if (ticks > 0x1fff) {
2333 ticks = (fck / 1000 / 1000) * ns / 1000 / 4;
2334 x4 = 1;
2335 x16 = 0;
2336 }
2337
2338 if (ticks > 0x1fff) {
2339 ticks = (fck / 1000 / 1000) * ns / 1000 / 16;
2340 x4 = 0;
2341 x16 = 1;
2342 }
2343
2344 if (ticks > 0x1fff) {
2345 ticks = (fck / 1000 / 1000) * ns / 1000 / (4 * 16);
2346 x4 = 1;
2347 x16 = 1;
2348 }
2349
2350 if (ticks > 0x1fff) {
2351 DSSWARN("HS_TX_TO over limit, setting it to max\n");
2352 ticks = 0x1fff;
2353 x4 = 1;
2354 x16 = 1;
2355 }
2356
2357 r = dsi_read_reg(DSI_TIMING2);
2358 r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */
2359 r = FLD_MOD(r, x16, 30, 30); /* HS_TX_TO_X16 */
2360 r = FLD_MOD(r, x4, 29, 29); /* HS_TX_TO_X8 (4 really) */
2361 r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */
2362 dsi_write_reg(DSI_TIMING2, r);
2363
2364 DSSDBG("HS_TX_TO %lu ns (%#lx ticks%s%s)\n",
2365 (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
2366 (fck / 1000 / 1000),
2367 ticks, x4 ? " x4" : "", x16 ? " x16" : "");
2368}
2369static int dsi_proto_config(struct omap_dss_device *dssdev)
2370{
2371 u32 r;
2372 int buswidth = 0;
2373
2374 dsi_config_tx_fifo(DSI_FIFO_SIZE_128,
2375 DSI_FIFO_SIZE_0,
2376 DSI_FIFO_SIZE_0,
2377 DSI_FIFO_SIZE_0);
2378
2379 dsi_config_rx_fifo(DSI_FIFO_SIZE_128,
2380 DSI_FIFO_SIZE_0,
2381 DSI_FIFO_SIZE_0,
2382 DSI_FIFO_SIZE_0);
2383
2384 /* XXX what values for the timeouts? */
2385 dsi_set_stop_state_counter(1000);
2386 dsi_set_ta_timeout(6400000);
2387 dsi_set_lp_rx_timeout(48000);
2388 dsi_set_hs_tx_timeout(1000000);
2389
2390 switch (dssdev->ctrl.pixel_size) {
2391 case 16:
2392 buswidth = 0;
2393 break;
2394 case 18:
2395 buswidth = 1;
2396 break;
2397 case 24:
2398 buswidth = 2;
2399 break;
2400 default:
2401 BUG();
2402 }
2403
2404 r = dsi_read_reg(DSI_CTRL);
2405 r = FLD_MOD(r, 1, 1, 1); /* CS_RX_EN */
2406 r = FLD_MOD(r, 1, 2, 2); /* ECC_RX_EN */
2407 r = FLD_MOD(r, 1, 3, 3); /* TX_FIFO_ARBITRATION */
2408 r = FLD_MOD(r, 1, 4, 4); /* VP_CLK_RATIO, always 1, see errata*/
2409 r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */
2410 r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */
2411 r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */
2412 r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */
2413 r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */
2414 r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */
2415 r = FLD_MOD(r, 0, 25, 25); /* DCS_CMD_CODE, 1=start, 0=continue */
2416
2417 dsi_write_reg(DSI_CTRL, r);
2418
2419 dsi_vc_initial_config(0);
2420
2421 /* set all vc targets to peripheral 0 */
2422 dsi.vc[0].dest_per = 0;
2423 dsi.vc[1].dest_per = 0;
2424 dsi.vc[2].dest_per = 0;
2425 dsi.vc[3].dest_per = 0;
2426
2427 return 0;
2428}
2429
2430static void dsi_proto_timings(struct omap_dss_device *dssdev)
2431{
2432 unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
2433 unsigned tclk_pre, tclk_post;
2434 unsigned ths_prepare, ths_prepare_ths_zero, ths_zero;
2435 unsigned ths_trail, ths_exit;
2436 unsigned ddr_clk_pre, ddr_clk_post;
2437 unsigned enter_hs_mode_lat, exit_hs_mode_lat;
2438 unsigned ths_eot;
2439 u32 r;
2440
2441 r = dsi_read_reg(DSI_DSIPHY_CFG0);
2442 ths_prepare = FLD_GET(r, 31, 24);
2443 ths_prepare_ths_zero = FLD_GET(r, 23, 16);
2444 ths_zero = ths_prepare_ths_zero - ths_prepare;
2445 ths_trail = FLD_GET(r, 15, 8);
2446 ths_exit = FLD_GET(r, 7, 0);
2447
2448 r = dsi_read_reg(DSI_DSIPHY_CFG1);
2449 tlpx = FLD_GET(r, 22, 16) * 2;
2450 tclk_trail = FLD_GET(r, 15, 8);
2451 tclk_zero = FLD_GET(r, 7, 0);
2452
2453 r = dsi_read_reg(DSI_DSIPHY_CFG2);
2454 tclk_prepare = FLD_GET(r, 7, 0);
2455
2456 /* min 8*UI */
2457 tclk_pre = 20;
2458 /* min 60ns + 52*UI */
2459 tclk_post = ns2ddr(60) + 26;
2460
2461 /* ths_eot is 2 for 2 datalanes and 4 for 1 datalane */
2462 if (dssdev->phy.dsi.data1_lane != 0 &&
2463 dssdev->phy.dsi.data2_lane != 0)
2464 ths_eot = 2;
2465 else
2466 ths_eot = 4;
2467
2468 ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare,
2469 4);
2470 ddr_clk_post = DIV_ROUND_UP(tclk_post + ths_trail, 4) + ths_eot;
2471
2472 BUG_ON(ddr_clk_pre == 0 || ddr_clk_pre > 255);
2473 BUG_ON(ddr_clk_post == 0 || ddr_clk_post > 255);
2474
2475 r = dsi_read_reg(DSI_CLK_TIMING);
2476 r = FLD_MOD(r, ddr_clk_pre, 15, 8);
2477 r = FLD_MOD(r, ddr_clk_post, 7, 0);
2478 dsi_write_reg(DSI_CLK_TIMING, r);
2479
2480 DSSDBG("ddr_clk_pre %u, ddr_clk_post %u\n",
2481 ddr_clk_pre,
2482 ddr_clk_post);
2483
2484 enter_hs_mode_lat = 1 + DIV_ROUND_UP(tlpx, 4) +
2485 DIV_ROUND_UP(ths_prepare, 4) +
2486 DIV_ROUND_UP(ths_zero + 3, 4);
2487
2488 exit_hs_mode_lat = DIV_ROUND_UP(ths_trail + ths_exit, 4) + 1 + ths_eot;
2489
2490 r = FLD_VAL(enter_hs_mode_lat, 31, 16) |
2491 FLD_VAL(exit_hs_mode_lat, 15, 0);
2492 dsi_write_reg(DSI_VM_TIMING7, r);
2493
2494 DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
2495 enter_hs_mode_lat, exit_hs_mode_lat);
2496}
2497
2498
2499#define DSI_DECL_VARS \
2500 int __dsi_cb = 0; u32 __dsi_cv = 0;
2501
2502#define DSI_FLUSH(ch) \
2503 if (__dsi_cb > 0) { \
2504 /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \
2505 dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \
2506 __dsi_cb = __dsi_cv = 0; \
2507 }
2508
2509#define DSI_PUSH(ch, data) \
2510 do { \
2511 __dsi_cv |= (data) << (__dsi_cb * 8); \
2512 /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \
2513 if (++__dsi_cb > 3) \
2514 DSI_FLUSH(ch); \
2515 } while (0)
2516
2517static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
2518 int x, int y, int w, int h)
2519{
2520 /* Note: supports only 24bit colors in 32bit container */
2521 int first = 1;
2522 int fifo_stalls = 0;
2523 int max_dsi_packet_size;
2524 int max_data_per_packet;
2525 int max_pixels_per_packet;
2526 int pixels_left;
2527 int bytespp = dssdev->ctrl.pixel_size / 8;
2528 int scr_width;
2529 u32 __iomem *data;
2530 int start_offset;
2531 int horiz_inc;
2532 int current_x;
2533 struct omap_overlay *ovl;
2534
2535 debug_irq = 0;
2536
2537 DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n",
2538 x, y, w, h);
2539
2540 ovl = dssdev->manager->overlays[0];
2541
2542 if (ovl->info.color_mode != OMAP_DSS_COLOR_RGB24U)
2543 return -EINVAL;
2544
2545 if (dssdev->ctrl.pixel_size != 24)
2546 return -EINVAL;
2547
2548 scr_width = ovl->info.screen_width;
2549 data = ovl->info.vaddr;
2550
2551 start_offset = scr_width * y + x;
2552 horiz_inc = scr_width - w;
2553 current_x = x;
2554
2555 /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes
2556 * in fifo */
2557
2558 /* When using CPU, max long packet size is TX buffer size */
2559 max_dsi_packet_size = dsi.vc[0].fifo_size * 32 * 4;
2560
2561 /* we seem to get better perf if we divide the tx fifo to half,
2562 and while the other half is being sent, we fill the other half
2563 max_dsi_packet_size /= 2; */
2564
2565 max_data_per_packet = max_dsi_packet_size - 4 - 1;
2566
2567 max_pixels_per_packet = max_data_per_packet / bytespp;
2568
2569 DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet);
2570
2571 pixels_left = w * h;
2572
2573 DSSDBG("total pixels %d\n", pixels_left);
2574
2575 data += start_offset;
2576
2577 while (pixels_left > 0) {
2578 /* 0x2c = write_memory_start */
2579 /* 0x3c = write_memory_continue */
2580 u8 dcs_cmd = first ? 0x2c : 0x3c;
2581 int pixels;
2582 DSI_DECL_VARS;
2583 first = 0;
2584
2585#if 1
2586 /* using fifo not empty */
2587 /* TX_FIFO_NOT_EMPTY */
2588 while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) {
2589 udelay(1);
2590 fifo_stalls++;
2591 if (fifo_stalls > 0xfffff) {
2592 DSSERR("fifo stalls overflow, pixels left %d\n",
2593 pixels_left);
2594 dsi_if_enable(0);
2595 return -EIO;
2596 }
2597 }
2598#elif 1
2599 /* using fifo emptiness */
2600 while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 <
2601 max_dsi_packet_size) {
2602 fifo_stalls++;
2603 if (fifo_stalls > 0xfffff) {
2604 DSSERR("fifo stalls overflow, pixels left %d\n",
2605 pixels_left);
2606 dsi_if_enable(0);
2607 return -EIO;
2608 }
2609 }
2610#else
2611 while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 == 0) {
2612 fifo_stalls++;
2613 if (fifo_stalls > 0xfffff) {
2614 DSSERR("fifo stalls overflow, pixels left %d\n",
2615 pixels_left);
2616 dsi_if_enable(0);
2617 return -EIO;
2618 }
2619 }
2620#endif
2621 pixels = min(max_pixels_per_packet, pixels_left);
2622
2623 pixels_left -= pixels;
2624
2625 dsi_vc_write_long_header(0, DSI_DT_DCS_LONG_WRITE,
2626 1 + pixels * bytespp, 0);
2627
2628 DSI_PUSH(0, dcs_cmd);
2629
2630 while (pixels-- > 0) {
2631 u32 pix = __raw_readl(data++);
2632
2633 DSI_PUSH(0, (pix >> 16) & 0xff);
2634 DSI_PUSH(0, (pix >> 8) & 0xff);
2635 DSI_PUSH(0, (pix >> 0) & 0xff);
2636
2637 current_x++;
2638 if (current_x == x+w) {
2639 current_x = x;
2640 data += horiz_inc;
2641 }
2642 }
2643
2644 DSI_FLUSH(0);
2645 }
2646
2647 return 0;
2648}
2649
2650static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
2651 u16 x, u16 y, u16 w, u16 h)
2652{
2653 unsigned bytespp;
2654 unsigned bytespl;
2655 unsigned bytespf;
2656 unsigned total_len;
2657 unsigned packet_payload;
2658 unsigned packet_len;
2659 u32 l;
2660 bool use_te_trigger;
2661 const unsigned channel = 0;
2662 /* line buffer is 1024 x 24bits */
2663 /* XXX: for some reason using full buffer size causes considerable TX
2664 * slowdown with update sizes that fill the whole buffer */
2665 const unsigned line_buf_size = 1023 * 3;
2666
2667 use_te_trigger = dsi.te_enabled && !dsi.use_ext_te;
2668
2669 if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
2670 DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
2671 x, y, w, h);
2672
2673 bytespp = dssdev->ctrl.pixel_size / 8;
2674 bytespl = w * bytespp;
2675 bytespf = bytespl * h;
2676
2677 /* NOTE: packet_payload has to be equal to N * bytespl, where N is
2678 * number of lines in a packet. See errata about VP_CLK_RATIO */
2679
2680 if (bytespf < line_buf_size)
2681 packet_payload = bytespf;
2682 else
2683 packet_payload = (line_buf_size) / bytespl * bytespl;
2684
2685 packet_len = packet_payload + 1; /* 1 byte for DCS cmd */
2686 total_len = (bytespf / packet_payload) * packet_len;
2687
2688 if (bytespf % packet_payload)
2689 total_len += (bytespf % packet_payload) + 1;
2690
2691 if (0)
2692 dsi_vc_print_status(1);
2693
2694 l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
2695 dsi_write_reg(DSI_VC_TE(channel), l);
2696
2697 dsi_vc_write_long_header(channel, DSI_DT_DCS_LONG_WRITE, packet_len, 0);
2698
2699 if (use_te_trigger)
2700 l = FLD_MOD(l, 1, 30, 30); /* TE_EN */
2701 else
2702 l = FLD_MOD(l, 1, 31, 31); /* TE_START */
2703 dsi_write_reg(DSI_VC_TE(channel), l);
2704
2705 /* We put SIDLEMODE to no-idle for the duration of the transfer,
2706 * because DSS interrupts are not capable of waking up the CPU and the
2707 * framedone interrupt could be delayed for quite a long time. I think
2708 * the same goes for any DSS interrupts, but for some reason I have not
2709 * seen the problem anywhere else than here.
2710 */
2711 dispc_disable_sidle();
2712
2713 dss_start_update(dssdev);
2714
2715 if (use_te_trigger) {
2716 /* disable LP_RX_TO, so that we can receive TE. Time to wait
2717 * for TE is longer than the timer allows */
2718 REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
2719
2720 dsi_vc_send_bta(channel);
2721
2722#ifdef DSI_CATCH_MISSING_TE
2723 mod_timer(&dsi.te_timer, jiffies + msecs_to_jiffies(250));
2724#endif
2725 }
2726}
2727
2728#ifdef DSI_CATCH_MISSING_TE
2729static void dsi_te_timeout(unsigned long arg)
2730{
2731 DSSERR("TE not received for 250ms!\n");
2732}
2733#endif
2734
2735static void dsi_framedone_irq_callback(void *data, u32 mask)
2736{
2737 /* Note: We get FRAMEDONE when DISPC has finished sending pixels and
2738 * turns itself off. However, DSI still has the pixels in its buffers,
2739 * and is sending the data.
2740 */
2741
2742 /* SIDLEMODE back to smart-idle */
2743 dispc_enable_sidle();
2744
2745 dsi.framedone_received = true;
2746 wake_up(&dsi.waitqueue);
2747}
2748
2749static void dsi_set_update_region(struct omap_dss_device *dssdev,
2750 u16 x, u16 y, u16 w, u16 h)
2751{
2752 spin_lock(&dsi.update_lock);
2753 if (dsi.update_region.dirty) {
2754 dsi.update_region.x = min(x, dsi.update_region.x);
2755 dsi.update_region.y = min(y, dsi.update_region.y);
2756 dsi.update_region.w = max(w, dsi.update_region.w);
2757 dsi.update_region.h = max(h, dsi.update_region.h);
2758 } else {
2759 dsi.update_region.x = x;
2760 dsi.update_region.y = y;
2761 dsi.update_region.w = w;
2762 dsi.update_region.h = h;
2763 }
2764
2765 dsi.update_region.device = dssdev;
2766 dsi.update_region.dirty = true;
2767
2768 spin_unlock(&dsi.update_lock);
2769
2770}
2771
2772static int dsi_set_update_mode(struct omap_dss_device *dssdev,
2773 enum omap_dss_update_mode mode)
2774{
2775 int r = 0;
2776 int i;
2777
2778 WARN_ON(!mutex_is_locked(&dsi.bus_lock));
2779
2780 if (dsi.update_mode != mode) {
2781 dsi.update_mode = mode;
2782
2783 /* Mark the overlays dirty, and do apply(), so that we get the
2784 * overlays configured properly after update mode change. */
2785 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
2786 struct omap_overlay *ovl;
2787 ovl = omap_dss_get_overlay(i);
2788 if (ovl->manager == dssdev->manager)
2789 ovl->info_dirty = true;
2790 }
2791
2792 r = dssdev->manager->apply(dssdev->manager);
2793
2794 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE &&
2795 mode == OMAP_DSS_UPDATE_AUTO) {
2796 u16 w, h;
2797
2798 DSSDBG("starting auto update\n");
2799
2800 dssdev->get_resolution(dssdev, &w, &h);
2801
2802 dsi_set_update_region(dssdev, 0, 0, w, h);
2803
2804 dsi_perf_mark_start_auto();
2805
2806 wake_up(&dsi.waitqueue);
2807 }
2808 }
2809
2810 return r;
2811}
2812
2813static int dsi_set_te(struct omap_dss_device *dssdev, bool enable)
2814{
2815 int r;
2816 r = dssdev->driver->enable_te(dssdev, enable);
2817 /* XXX for some reason, DSI TE breaks if we don't wait here.
2818 * Panel bug? Needs more studying */
2819 msleep(100);
2820 return r;
2821}
2822
2823static void dsi_handle_framedone(void)
2824{
2825 int r;
2826 const int channel = 0;
2827 bool use_te_trigger;
2828
2829 use_te_trigger = dsi.te_enabled && !dsi.use_ext_te;
2830
2831 if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
2832 DSSDBG("FRAMEDONE\n");
2833
2834 if (use_te_trigger) {
2835 /* enable LP_RX_TO again after the TE */
2836 REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
2837 }
2838
2839 /* Send BTA after the frame. We need this for the TE to work, as TE
2840 * trigger is only sent for BTAs without preceding packet. Thus we need
2841 * to BTA after the pixel packets so that next BTA will cause TE
2842 * trigger.
2843 *
2844 * This is not needed when TE is not in use, but we do it anyway to
2845 * make sure that the transfer has been completed. It would be more
2846 * optimal, but more complex, to wait only just before starting next
2847 * transfer. */
2848 r = dsi_vc_send_bta_sync(channel);
2849 if (r)
2850 DSSERR("BTA after framedone failed\n");
2851
2852 /* RX_FIFO_NOT_EMPTY */
2853 if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
2854 DSSERR("Received error during frame transfer:\n");
2855 dsi_vc_flush_receive_data(0);
2856 }
2857
2858#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
2859 dispc_fake_vsync_irq();
2860#endif
2861}
2862
2863static int dsi_update_thread(void *data)
2864{
2865 unsigned long timeout;
2866 struct omap_dss_device *device;
2867 u16 x, y, w, h;
2868
2869 while (1) {
2870 bool sched;
2871
2872 wait_event_interruptible(dsi.waitqueue,
2873 dsi.update_mode == OMAP_DSS_UPDATE_AUTO ||
2874 (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL &&
2875 dsi.update_region.dirty == true) ||
2876 kthread_should_stop());
2877
2878 if (kthread_should_stop())
2879 break;
2880
2881 dsi_bus_lock();
2882
2883 if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED ||
2884 kthread_should_stop()) {
2885 dsi_bus_unlock();
2886 break;
2887 }
2888
2889 dsi_perf_mark_setup();
2890
2891 if (dsi.update_region.dirty) {
2892 spin_lock(&dsi.update_lock);
2893 dsi.active_update_region = dsi.update_region;
2894 dsi.update_region.dirty = false;
2895 spin_unlock(&dsi.update_lock);
2896 }
2897
2898 device = dsi.active_update_region.device;
2899 x = dsi.active_update_region.x;
2900 y = dsi.active_update_region.y;
2901 w = dsi.active_update_region.w;
2902 h = dsi.active_update_region.h;
2903
2904 if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
2905
2906 if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL)
2907 dss_setup_partial_planes(device,
2908 &x, &y, &w, &h);
2909
2910 dispc_set_lcd_size(w, h);
2911 }
2912
2913 if (dsi.active_update_region.dirty) {
2914 dsi.active_update_region.dirty = false;
2915 /* XXX TODO we don't need to send the coords, if they
2916 * are the same that are already programmed to the
2917 * panel. That should speed up manual update a bit */
2918 device->driver->setup_update(device, x, y, w, h);
2919 }
2920
2921 dsi_perf_mark_start();
2922
2923 if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
2924 dsi_vc_config_vp(0);
2925
2926 if (dsi.te_enabled && dsi.use_ext_te)
2927 device->driver->wait_for_te(device);
2928
2929 dsi.framedone_received = false;
2930
2931 dsi_update_screen_dispc(device, x, y, w, h);
2932
2933 /* wait for framedone */
2934 timeout = msecs_to_jiffies(1000);
2935 wait_event_timeout(dsi.waitqueue,
2936 dsi.framedone_received == true,
2937 timeout);
2938
2939 if (!dsi.framedone_received) {
2940 DSSERR("framedone timeout\n");
2941 DSSERR("failed update %d,%d %dx%d\n",
2942 x, y, w, h);
2943
2944 dispc_enable_sidle();
2945 dispc_enable_lcd_out(0);
2946
2947 dsi_reset_tx_fifo(0);
2948 } else {
2949 dsi_handle_framedone();
2950 dsi_perf_show("DISPC");
2951 }
2952 } else {
2953 dsi_update_screen_l4(device, x, y, w, h);
2954 dsi_perf_show("L4");
2955 }
2956
2957 sched = atomic_read(&dsi.bus_lock.count) < 0;
2958
2959 complete_all(&dsi.update_completion);
2960
2961 dsi_bus_unlock();
2962
2963 /* XXX We need to give others chance to get the bus lock. Is
2964 * there a better way for this? */
2965 if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO && sched)
2966 schedule_timeout_interruptible(1);
2967 }
2968
2969 DSSDBG("update thread exiting\n");
2970
2971 return 0;
2972}
2973
2974
2975
2976/* Display funcs */
2977
2978static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
2979{
2980 int r;
2981
2982 r = omap_dispc_register_isr(dsi_framedone_irq_callback, NULL,
2983 DISPC_IRQ_FRAMEDONE);
2984 if (r) {
2985 DSSERR("can't get FRAMEDONE irq\n");
2986 return r;
2987 }
2988
2989 dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
2990
2991 dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_DSI);
2992 dispc_enable_fifohandcheck(1);
2993
2994 dispc_set_tft_data_lines(dssdev->ctrl.pixel_size);
2995
2996 {
2997 struct omap_video_timings timings = {
2998 .hsw = 1,
2999 .hfp = 1,
3000 .hbp = 1,
3001 .vsw = 1,
3002 .vfp = 0,
3003 .vbp = 0,
3004 };
3005
3006 dispc_set_lcd_timings(&timings);
3007 }
3008
3009 return 0;
3010}
3011
3012static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
3013{
3014 omap_dispc_unregister_isr(dsi_framedone_irq_callback, NULL,
3015 DISPC_IRQ_FRAMEDONE);
3016}
3017
3018static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
3019{
3020 struct dsi_clock_info cinfo;
3021 int r;
3022
3023 /* we always use DSS2_FCK as input clock */
3024 cinfo.use_dss2_fck = true;
3025 cinfo.regn = dssdev->phy.dsi.div.regn;
3026 cinfo.regm = dssdev->phy.dsi.div.regm;
3027 cinfo.regm3 = dssdev->phy.dsi.div.regm3;
3028 cinfo.regm4 = dssdev->phy.dsi.div.regm4;
3029 r = dsi_calc_clock_rates(&cinfo);
3030 if (r)
3031 return r;
3032
3033 r = dsi_pll_set_clock_div(&cinfo);
3034 if (r) {
3035 DSSERR("Failed to set dsi clocks\n");
3036 return r;
3037 }
3038
3039 return 0;
3040}
3041
3042static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)
3043{
3044 struct dispc_clock_info dispc_cinfo;
3045 int r;
3046 unsigned long long fck;
3047
3048 fck = dsi_get_dsi1_pll_rate();
3049
3050 dispc_cinfo.lck_div = dssdev->phy.dsi.div.lck_div;
3051 dispc_cinfo.pck_div = dssdev->phy.dsi.div.pck_div;
3052
3053 r = dispc_calc_clock_rates(fck, &dispc_cinfo);
3054 if (r) {
3055 DSSERR("Failed to calc dispc clocks\n");
3056 return r;
3057 }
3058
3059 r = dispc_set_clock_div(&dispc_cinfo);
3060 if (r) {
3061 DSSERR("Failed to set dispc clocks\n");
3062 return r;
3063 }
3064
3065 return 0;
3066}
3067
3068static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
3069{
3070 int r;
3071
3072 _dsi_print_reset_status();
3073
3074 r = dsi_pll_init(dssdev, true, true);
3075 if (r)
3076 goto err0;
3077
3078 r = dsi_configure_dsi_clocks(dssdev);
3079 if (r)
3080 goto err1;
3081
3082 dss_select_clk_source(true, true);
3083
3084 DSSDBG("PLL OK\n");
3085
3086 r = dsi_configure_dispc_clocks(dssdev);
3087 if (r)
3088 goto err2;
3089
3090 r = dsi_complexio_init(dssdev);
3091 if (r)
3092 goto err2;
3093
3094 _dsi_print_reset_status();
3095
3096 dsi_proto_timings(dssdev);
3097 dsi_set_lp_clk_divisor(dssdev);
3098
3099 if (1)
3100 _dsi_print_reset_status();
3101
3102 r = dsi_proto_config(dssdev);
3103 if (r)
3104 goto err3;
3105
3106 /* enable interface */
3107 dsi_vc_enable(0, 1);
3108 dsi_if_enable(1);
3109 dsi_force_tx_stop_mode_io();
3110
3111 if (dssdev->driver->enable) {
3112 r = dssdev->driver->enable(dssdev);
3113 if (r)
3114 goto err4;
3115 }
3116
3117 /* enable high-speed after initial config */
3118 dsi_vc_enable_hs(0, 1);
3119
3120 return 0;
3121err4:
3122 dsi_if_enable(0);
3123err3:
3124 dsi_complexio_uninit();
3125err2:
3126 dss_select_clk_source(false, false);
3127err1:
3128 dsi_pll_uninit();
3129err0:
3130 return r;
3131}
3132
3133static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev)
3134{
3135 if (dssdev->driver->disable)
3136 dssdev->driver->disable(dssdev);
3137
3138 dss_select_clk_source(false, false);
3139 dsi_complexio_uninit();
3140 dsi_pll_uninit();
3141}
3142
3143static int dsi_core_init(void)
3144{
3145 /* Autoidle */
3146 REG_FLD_MOD(DSI_SYSCONFIG, 1, 0, 0);
3147
3148 /* ENWAKEUP */
3149 REG_FLD_MOD(DSI_SYSCONFIG, 1, 2, 2);
3150
3151 /* SIDLEMODE smart-idle */
3152 REG_FLD_MOD(DSI_SYSCONFIG, 2, 4, 3);
3153
3154 _dsi_initialize_irq();
3155
3156 return 0;
3157}
3158
3159static int dsi_display_enable(struct omap_dss_device *dssdev)
3160{
3161 int r = 0;
3162
3163 DSSDBG("dsi_display_enable\n");
3164
3165 mutex_lock(&dsi.lock);
3166 dsi_bus_lock();
3167
3168 r = omap_dss_start_device(dssdev);
3169 if (r) {
3170 DSSERR("failed to start device\n");
3171 goto err0;
3172 }
3173
3174 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
3175 DSSERR("dssdev already enabled\n");
3176 r = -EINVAL;
3177 goto err1;
3178 }
3179
3180 enable_clocks(1);
3181 dsi_enable_pll_clock(1);
3182
3183 r = _dsi_reset();
3184 if (r)
3185 goto err2;
3186
3187 dsi_core_init();
3188
3189 r = dsi_display_init_dispc(dssdev);
3190 if (r)
3191 goto err2;
3192
3193 r = dsi_display_init_dsi(dssdev);
3194 if (r)
3195 goto err3;
3196
3197 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
3198
3199 dsi.use_ext_te = dssdev->phy.dsi.ext_te;
3200 r = dsi_set_te(dssdev, dsi.te_enabled);
3201 if (r)
3202 goto err4;
3203
3204 dsi_set_update_mode(dssdev, dsi.user_update_mode);
3205
3206 dsi_bus_unlock();
3207 mutex_unlock(&dsi.lock);
3208
3209 return 0;
3210
3211err4:
3212
3213 dsi_display_uninit_dsi(dssdev);
3214err3:
3215 dsi_display_uninit_dispc(dssdev);
3216err2:
3217 enable_clocks(0);
3218 dsi_enable_pll_clock(0);
3219err1:
3220 omap_dss_stop_device(dssdev);
3221err0:
3222 dsi_bus_unlock();
3223 mutex_unlock(&dsi.lock);
3224 DSSDBG("dsi_display_enable FAILED\n");
3225 return r;
3226}
3227
3228static void dsi_display_disable(struct omap_dss_device *dssdev)
3229{
3230 DSSDBG("dsi_display_disable\n");
3231
3232 mutex_lock(&dsi.lock);
3233 dsi_bus_lock();
3234
3235 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
3236 dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
3237 goto end;
3238
3239 dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
3240 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
3241
3242 dsi_display_uninit_dispc(dssdev);
3243
3244 dsi_display_uninit_dsi(dssdev);
3245
3246 enable_clocks(0);
3247 dsi_enable_pll_clock(0);
3248
3249 omap_dss_stop_device(dssdev);
3250end:
3251 dsi_bus_unlock();
3252 mutex_unlock(&dsi.lock);
3253}
3254
3255static int dsi_display_suspend(struct omap_dss_device *dssdev)
3256{
3257 DSSDBG("dsi_display_suspend\n");
3258
3259 mutex_lock(&dsi.lock);
3260 dsi_bus_lock();
3261
3262 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
3263 dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
3264 goto end;
3265
3266 dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
3267 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
3268
3269 dsi_display_uninit_dispc(dssdev);
3270
3271 dsi_display_uninit_dsi(dssdev);
3272
3273 enable_clocks(0);
3274 dsi_enable_pll_clock(0);
3275end:
3276 dsi_bus_unlock();
3277 mutex_unlock(&dsi.lock);
3278
3279 return 0;
3280}
3281
3282static int dsi_display_resume(struct omap_dss_device *dssdev)
3283{
3284 int r;
3285
3286 DSSDBG("dsi_display_resume\n");
3287
3288 mutex_lock(&dsi.lock);
3289 dsi_bus_lock();
3290
3291 if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
3292 DSSERR("dssdev not suspended\n");
3293 r = -EINVAL;
3294 goto err0;
3295 }
3296
3297 enable_clocks(1);
3298 dsi_enable_pll_clock(1);
3299
3300 r = _dsi_reset();
3301 if (r)
3302 goto err1;
3303
3304 dsi_core_init();
3305
3306 r = dsi_display_init_dispc(dssdev);
3307 if (r)
3308 goto err1;
3309
3310 r = dsi_display_init_dsi(dssdev);
3311 if (r)
3312 goto err2;
3313
3314 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
3315
3316 r = dsi_set_te(dssdev, dsi.te_enabled);
3317 if (r)
3318 goto err2;
3319
3320 dsi_set_update_mode(dssdev, dsi.user_update_mode);
3321
3322 dsi_bus_unlock();
3323 mutex_unlock(&dsi.lock);
3324
3325 return 0;
3326
3327err2:
3328 dsi_display_uninit_dispc(dssdev);
3329err1:
3330 enable_clocks(0);
3331 dsi_enable_pll_clock(0);
3332err0:
3333 dsi_bus_unlock();
3334 mutex_unlock(&dsi.lock);
3335 DSSDBG("dsi_display_resume FAILED\n");
3336 return r;
3337}
3338
3339static int dsi_display_update(struct omap_dss_device *dssdev,
3340 u16 x, u16 y, u16 w, u16 h)
3341{
3342 int r = 0;
3343 u16 dw, dh;
3344
3345 DSSDBG("dsi_display_update(%d,%d %dx%d)\n", x, y, w, h);
3346
3347 mutex_lock(&dsi.lock);
3348
3349 if (dsi.update_mode != OMAP_DSS_UPDATE_MANUAL)
3350 goto end;
3351
3352 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
3353 goto end;
3354
3355 dssdev->get_resolution(dssdev, &dw, &dh);
3356
3357 if (x > dw || y > dh)
3358 goto end;
3359
3360 if (x + w > dw)
3361 w = dw - x;
3362
3363 if (y + h > dh)
3364 h = dh - y;
3365
3366 if (w == 0 || h == 0)
3367 goto end;
3368
3369 if (w == 1) {
3370 r = -EINVAL;
3371 goto end;
3372 }
3373
3374 dsi_set_update_region(dssdev, x, y, w, h);
3375
3376 wake_up(&dsi.waitqueue);
3377
3378end:
3379 mutex_unlock(&dsi.lock);
3380
3381 return r;
3382}
3383
3384static int dsi_display_sync(struct omap_dss_device *dssdev)
3385{
3386 bool wait;
3387
3388 DSSDBG("dsi_display_sync()\n");
3389
3390 mutex_lock(&dsi.lock);
3391 dsi_bus_lock();
3392
3393 if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL &&
3394 dsi.update_region.dirty) {
3395 INIT_COMPLETION(dsi.update_completion);
3396 wait = true;
3397 } else {
3398 wait = false;
3399 }
3400
3401 dsi_bus_unlock();
3402 mutex_unlock(&dsi.lock);
3403
3404 if (wait)
3405 wait_for_completion_interruptible(&dsi.update_completion);
3406
3407 DSSDBG("dsi_display_sync() done\n");
3408 return 0;
3409}
3410
3411static int dsi_display_set_update_mode(struct omap_dss_device *dssdev,
3412 enum omap_dss_update_mode mode)
3413{
3414 int r = 0;
3415
3416 DSSDBGF("%d", mode);
3417
3418 mutex_lock(&dsi.lock);
3419 dsi_bus_lock();
3420
3421 dsi.user_update_mode = mode;
3422 r = dsi_set_update_mode(dssdev, mode);
3423
3424 dsi_bus_unlock();
3425 mutex_unlock(&dsi.lock);
3426
3427 return r;
3428}
3429
3430static enum omap_dss_update_mode dsi_display_get_update_mode(
3431 struct omap_dss_device *dssdev)
3432{
3433 return dsi.update_mode;
3434}
3435
3436
3437static int dsi_display_enable_te(struct omap_dss_device *dssdev, bool enable)
3438{
3439 int r = 0;
3440
3441 DSSDBGF("%d", enable);
3442
3443 if (!dssdev->driver->enable_te)
3444 return -ENOENT;
3445
3446 dsi_bus_lock();
3447
3448 dsi.te_enabled = enable;
3449
3450 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
3451 goto end;
3452
3453 r = dsi_set_te(dssdev, enable);
3454end:
3455 dsi_bus_unlock();
3456
3457 return r;
3458}
3459
3460static int dsi_display_get_te(struct omap_dss_device *dssdev)
3461{
3462 return dsi.te_enabled;
3463}
3464
3465static int dsi_display_set_rotate(struct omap_dss_device *dssdev, u8 rotate)
3466{
3467
3468 DSSDBGF("%d", rotate);
3469
3470 if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
3471 return -EINVAL;
3472
3473 dsi_bus_lock();
3474 dssdev->driver->set_rotate(dssdev, rotate);
3475 if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) {
3476 u16 w, h;
3477 /* the display dimensions may have changed, so set a new
3478 * update region */
3479 dssdev->get_resolution(dssdev, &w, &h);
3480 dsi_set_update_region(dssdev, 0, 0, w, h);
3481 }
3482 dsi_bus_unlock();
3483
3484 return 0;
3485}
3486
3487static u8 dsi_display_get_rotate(struct omap_dss_device *dssdev)
3488{
3489 if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
3490 return 0;
3491
3492 return dssdev->driver->get_rotate(dssdev);
3493}
3494
3495static int dsi_display_set_mirror(struct omap_dss_device *dssdev, bool mirror)
3496{
3497 DSSDBGF("%d", mirror);
3498
3499 if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
3500 return -EINVAL;
3501
3502 dsi_bus_lock();
3503 dssdev->driver->set_mirror(dssdev, mirror);
3504 dsi_bus_unlock();
3505
3506 return 0;
3507}
3508
3509static bool dsi_display_get_mirror(struct omap_dss_device *dssdev)
3510{
3511 if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
3512 return 0;
3513
3514 return dssdev->driver->get_mirror(dssdev);
3515}
3516
3517static int dsi_display_run_test(struct omap_dss_device *dssdev, int test_num)
3518{
3519 int r;
3520
3521 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
3522 return -EIO;
3523
3524 DSSDBGF("%d", test_num);
3525
3526 dsi_bus_lock();
3527
3528 /* run test first in low speed mode */
3529 dsi_vc_enable_hs(0, 0);
3530
3531 if (dssdev->driver->run_test) {
3532 r = dssdev->driver->run_test(dssdev, test_num);
3533 if (r)
3534 goto end;
3535 }
3536
3537 /* then in high speed */
3538 dsi_vc_enable_hs(0, 1);
3539
3540 if (dssdev->driver->run_test) {
3541 r = dssdev->driver->run_test(dssdev, test_num);
3542 if (r)
3543 goto end;
3544 }
3545
3546end:
3547 dsi_vc_enable_hs(0, 1);
3548
3549 dsi_bus_unlock();
3550
3551 return r;
3552}
3553
3554static int dsi_display_memory_read(struct omap_dss_device *dssdev,
3555 void *buf, size_t size,
3556 u16 x, u16 y, u16 w, u16 h)
3557{
3558 int r;
3559
3560 DSSDBGF("");
3561
3562 if (!dssdev->driver->memory_read)
3563 return -EINVAL;
3564
3565 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
3566 return -EIO;
3567
3568 dsi_bus_lock();
3569
3570 r = dssdev->driver->memory_read(dssdev, buf, size,
3571 x, y, w, h);
3572
3573 /* Memory read usually changes the update area. This will
3574 * force the next update to re-set the update area */
3575 dsi.active_update_region.dirty = true;
3576
3577 dsi_bus_unlock();
3578
3579 return r;
3580}
3581
3582void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
3583 u32 fifo_size, enum omap_burst_size *burst_size,
3584 u32 *fifo_low, u32 *fifo_high)
3585{
3586 unsigned burst_size_bytes;
3587
3588 *burst_size = OMAP_DSS_BURST_16x32;
3589 burst_size_bytes = 16 * 32 / 8;
3590
3591 *fifo_high = fifo_size - burst_size_bytes;
3592 *fifo_low = fifo_size - burst_size_bytes * 8;
3593}
3594
3595int dsi_init_display(struct omap_dss_device *dssdev)
3596{
3597 DSSDBG("DSI init\n");
3598
3599 dssdev->enable = dsi_display_enable;
3600 dssdev->disable = dsi_display_disable;
3601 dssdev->suspend = dsi_display_suspend;
3602 dssdev->resume = dsi_display_resume;
3603 dssdev->update = dsi_display_update;
3604 dssdev->sync = dsi_display_sync;
3605 dssdev->set_update_mode = dsi_display_set_update_mode;
3606 dssdev->get_update_mode = dsi_display_get_update_mode;
3607 dssdev->enable_te = dsi_display_enable_te;
3608 dssdev->get_te = dsi_display_get_te;
3609
3610 dssdev->get_rotate = dsi_display_get_rotate;
3611 dssdev->set_rotate = dsi_display_set_rotate;
3612
3613 dssdev->get_mirror = dsi_display_get_mirror;
3614 dssdev->set_mirror = dsi_display_set_mirror;
3615
3616 dssdev->run_test = dsi_display_run_test;
3617 dssdev->memory_read = dsi_display_memory_read;
3618
3619 /* XXX these should be figured out dynamically */
3620 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
3621 OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
3622
3623 dsi.vc[0].dssdev = dssdev;
3624 dsi.vc[1].dssdev = dssdev;
3625
3626 return 0;
3627}
3628
3629int dsi_init(struct platform_device *pdev)
3630{
3631 u32 rev;
3632 int r;
3633 struct sched_param param = {
3634 .sched_priority = MAX_USER_RT_PRIO-1
3635 };
3636
3637 spin_lock_init(&dsi.errors_lock);
3638 dsi.errors = 0;
3639
3640 init_completion(&dsi.bta_completion);
3641 init_completion(&dsi.update_completion);
3642
3643 dsi.thread = kthread_create(dsi_update_thread, NULL, "dsi");
3644 if (IS_ERR(dsi.thread)) {
3645 DSSERR("cannot create kthread\n");
3646 r = PTR_ERR(dsi.thread);
3647 goto err0;
3648 }
3649 sched_setscheduler(dsi.thread, SCHED_FIFO, &param);
3650
3651 init_waitqueue_head(&dsi.waitqueue);
3652 spin_lock_init(&dsi.update_lock);
3653
3654 mutex_init(&dsi.lock);
3655 mutex_init(&dsi.bus_lock);
3656
3657#ifdef DSI_CATCH_MISSING_TE
3658 init_timer(&dsi.te_timer);
3659 dsi.te_timer.function = dsi_te_timeout;
3660 dsi.te_timer.data = 0;
3661#endif
3662
3663 dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
3664 dsi.user_update_mode = OMAP_DSS_UPDATE_DISABLED;
3665
3666 dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS);
3667 if (!dsi.base) {
3668 DSSERR("can't ioremap DSI\n");
3669 r = -ENOMEM;
3670 goto err1;
3671 }
3672
3673 dsi.vdds_dsi_reg = regulator_get(&pdev->dev, "vdds_dsi");
3674 if (IS_ERR(dsi.vdds_dsi_reg)) {
3675 iounmap(dsi.base);
3676 DSSERR("can't get VDDS_DSI regulator\n");
3677 r = PTR_ERR(dsi.vdds_dsi_reg);
3678 goto err2;
3679 }
3680
3681 enable_clocks(1);
3682
3683 rev = dsi_read_reg(DSI_REVISION);
3684 printk(KERN_INFO "OMAP DSI rev %d.%d\n",
3685 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
3686
3687 enable_clocks(0);
3688
3689 wake_up_process(dsi.thread);
3690
3691 return 0;
3692err2:
3693 iounmap(dsi.base);
3694err1:
3695 kthread_stop(dsi.thread);
3696err0:
3697 return r;
3698}
3699
3700void dsi_exit(void)
3701{
3702 kthread_stop(dsi.thread);
3703
3704 regulator_put(dsi.vdds_dsi_reg);
3705
3706 iounmap(dsi.base);
3707
3708 DSSDBG("omap_dsi_exit\n");
3709}
3710
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
new file mode 100644
index 000000000000..9b05ee65a15d
--- /dev/null
+++ b/drivers/video/omap2/dss/dss.c
@@ -0,0 +1,596 @@
1/*
2 * linux/drivers/video/omap2/dss/dss.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#define DSS_SUBSYS_NAME "DSS"
24
25#include <linux/kernel.h>
26#include <linux/io.h>
27#include <linux/err.h>
28#include <linux/delay.h>
29#include <linux/interrupt.h>
30#include <linux/seq_file.h>
31#include <linux/clk.h>
32
33#include <plat/display.h>
34#include "dss.h"
35
36#define DSS_BASE 0x48050000
37
38#define DSS_SZ_REGS SZ_512
39
40struct dss_reg {
41 u16 idx;
42};
43
44#define DSS_REG(idx) ((const struct dss_reg) { idx })
45
46#define DSS_REVISION DSS_REG(0x0000)
47#define DSS_SYSCONFIG DSS_REG(0x0010)
48#define DSS_SYSSTATUS DSS_REG(0x0014)
49#define DSS_IRQSTATUS DSS_REG(0x0018)
50#define DSS_CONTROL DSS_REG(0x0040)
51#define DSS_SDI_CONTROL DSS_REG(0x0044)
52#define DSS_PLL_CONTROL DSS_REG(0x0048)
53#define DSS_SDI_STATUS DSS_REG(0x005C)
54
55#define REG_GET(idx, start, end) \
56 FLD_GET(dss_read_reg(idx), start, end)
57
58#define REG_FLD_MOD(idx, val, start, end) \
59 dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
60
61static struct {
62 void __iomem *base;
63
64 struct clk *dpll4_m4_ck;
65
66 unsigned long cache_req_pck;
67 unsigned long cache_prate;
68 struct dss_clock_info cache_dss_cinfo;
69 struct dispc_clock_info cache_dispc_cinfo;
70
71 u32 ctx[DSS_SZ_REGS / sizeof(u32)];
72} dss;
73
74static int _omap_dss_wait_reset(void);
75
76static inline void dss_write_reg(const struct dss_reg idx, u32 val)
77{
78 __raw_writel(val, dss.base + idx.idx);
79}
80
81static inline u32 dss_read_reg(const struct dss_reg idx)
82{
83 return __raw_readl(dss.base + idx.idx);
84}
85
86#define SR(reg) \
87 dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
88#define RR(reg) \
89 dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
90
91void dss_save_context(void)
92{
93 if (cpu_is_omap24xx())
94 return;
95
96 SR(SYSCONFIG);
97 SR(CONTROL);
98
99#ifdef CONFIG_OMAP2_DSS_SDI
100 SR(SDI_CONTROL);
101 SR(PLL_CONTROL);
102#endif
103}
104
105void dss_restore_context(void)
106{
107 if (_omap_dss_wait_reset())
108 DSSERR("DSS not coming out of reset after sleep\n");
109
110 RR(SYSCONFIG);
111 RR(CONTROL);
112
113#ifdef CONFIG_OMAP2_DSS_SDI
114 RR(SDI_CONTROL);
115 RR(PLL_CONTROL);
116#endif
117}
118
119#undef SR
120#undef RR
121
122void dss_sdi_init(u8 datapairs)
123{
124 u32 l;
125
126 BUG_ON(datapairs > 3 || datapairs < 1);
127
128 l = dss_read_reg(DSS_SDI_CONTROL);
129 l = FLD_MOD(l, 0xf, 19, 15); /* SDI_PDIV */
130 l = FLD_MOD(l, datapairs-1, 3, 2); /* SDI_PRSEL */
131 l = FLD_MOD(l, 2, 1, 0); /* SDI_BWSEL */
132 dss_write_reg(DSS_SDI_CONTROL, l);
133
134 l = dss_read_reg(DSS_PLL_CONTROL);
135 l = FLD_MOD(l, 0x7, 25, 22); /* SDI_PLL_FREQSEL */
136 l = FLD_MOD(l, 0xb, 16, 11); /* SDI_PLL_REGN */
137 l = FLD_MOD(l, 0xb4, 10, 1); /* SDI_PLL_REGM */
138 dss_write_reg(DSS_PLL_CONTROL, l);
139}
140
141int dss_sdi_enable(void)
142{
143 unsigned long timeout;
144
145 dispc_pck_free_enable(1);
146
147 /* Reset SDI PLL */
148 REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */
149 udelay(1); /* wait 2x PCLK */
150
151 /* Lock SDI PLL */
152 REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */
153
154 /* Waiting for PLL lock request to complete */
155 timeout = jiffies + msecs_to_jiffies(500);
156 while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6)) {
157 if (time_after_eq(jiffies, timeout)) {
158 DSSERR("PLL lock request timed out\n");
159 goto err1;
160 }
161 }
162
163 /* Clearing PLL_GO bit */
164 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28);
165
166 /* Waiting for PLL to lock */
167 timeout = jiffies + msecs_to_jiffies(500);
168 while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5))) {
169 if (time_after_eq(jiffies, timeout)) {
170 DSSERR("PLL lock timed out\n");
171 goto err1;
172 }
173 }
174
175 dispc_lcd_enable_signal(1);
176
177 /* Waiting for SDI reset to complete */
178 timeout = jiffies + msecs_to_jiffies(500);
179 while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2))) {
180 if (time_after_eq(jiffies, timeout)) {
181 DSSERR("SDI reset timed out\n");
182 goto err2;
183 }
184 }
185
186 return 0;
187
188 err2:
189 dispc_lcd_enable_signal(0);
190 err1:
191 /* Reset SDI PLL */
192 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
193
194 dispc_pck_free_enable(0);
195
196 return -ETIMEDOUT;
197}
198
199void dss_sdi_disable(void)
200{
201 dispc_lcd_enable_signal(0);
202
203 dispc_pck_free_enable(0);
204
205 /* Reset SDI PLL */
206 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
207}
208
209void dss_dump_clocks(struct seq_file *s)
210{
211 unsigned long dpll4_ck_rate;
212 unsigned long dpll4_m4_ck_rate;
213
214 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
215
216 dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
217 dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck);
218
219 seq_printf(s, "- DSS -\n");
220
221 seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
222
223 seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n",
224 dpll4_ck_rate,
225 dpll4_ck_rate / dpll4_m4_ck_rate,
226 dss_clk_get_rate(DSS_CLK_FCK1));
227
228 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
229}
230
231void dss_dump_regs(struct seq_file *s)
232{
233#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
234
235 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
236
237 DUMPREG(DSS_REVISION);
238 DUMPREG(DSS_SYSCONFIG);
239 DUMPREG(DSS_SYSSTATUS);
240 DUMPREG(DSS_IRQSTATUS);
241 DUMPREG(DSS_CONTROL);
242 DUMPREG(DSS_SDI_CONTROL);
243 DUMPREG(DSS_PLL_CONTROL);
244 DUMPREG(DSS_SDI_STATUS);
245
246 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
247#undef DUMPREG
248}
249
250void dss_select_clk_source(bool dsi, bool dispc)
251{
252 u32 r;
253 r = dss_read_reg(DSS_CONTROL);
254 r = FLD_MOD(r, dsi, 1, 1); /* DSI_CLK_SWITCH */
255 r = FLD_MOD(r, dispc, 0, 0); /* DISPC_CLK_SWITCH */
256 dss_write_reg(DSS_CONTROL, r);
257}
258
259int dss_get_dsi_clk_source(void)
260{
261 return FLD_GET(dss_read_reg(DSS_CONTROL), 1, 1);
262}
263
264int dss_get_dispc_clk_source(void)
265{
266 return FLD_GET(dss_read_reg(DSS_CONTROL), 0, 0);
267}
268
269/* calculate clock rates using dividers in cinfo */
270int dss_calc_clock_rates(struct dss_clock_info *cinfo)
271{
272 unsigned long prate;
273
274 if (cinfo->fck_div > 16 || cinfo->fck_div == 0)
275 return -EINVAL;
276
277 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
278
279 cinfo->fck = prate / cinfo->fck_div;
280
281 return 0;
282}
283
284int dss_set_clock_div(struct dss_clock_info *cinfo)
285{
286 unsigned long prate;
287 int r;
288
289 if (cpu_is_omap34xx()) {
290 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
291 DSSDBG("dpll4_m4 = %ld\n", prate);
292
293 r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div);
294 if (r)
295 return r;
296 }
297
298 DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
299
300 return 0;
301}
302
303int dss_get_clock_div(struct dss_clock_info *cinfo)
304{
305 cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1);
306
307 if (cpu_is_omap34xx()) {
308 unsigned long prate;
309 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
310 cinfo->fck_div = prate / (cinfo->fck / 2);
311 } else {
312 cinfo->fck_div = 0;
313 }
314
315 return 0;
316}
317
318unsigned long dss_get_dpll4_rate(void)
319{
320 if (cpu_is_omap34xx())
321 return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
322 else
323 return 0;
324}
325
326int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
327 struct dss_clock_info *dss_cinfo,
328 struct dispc_clock_info *dispc_cinfo)
329{
330 unsigned long prate;
331 struct dss_clock_info best_dss;
332 struct dispc_clock_info best_dispc;
333
334 unsigned long fck;
335
336 u16 fck_div;
337
338 int match = 0;
339 int min_fck_per_pck;
340
341 prate = dss_get_dpll4_rate();
342
343 fck = dss_clk_get_rate(DSS_CLK_FCK1);
344 if (req_pck == dss.cache_req_pck &&
345 ((cpu_is_omap34xx() && prate == dss.cache_prate) ||
346 dss.cache_dss_cinfo.fck == fck)) {
347 DSSDBG("dispc clock info found from cache.\n");
348 *dss_cinfo = dss.cache_dss_cinfo;
349 *dispc_cinfo = dss.cache_dispc_cinfo;
350 return 0;
351 }
352
353 min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
354
355 if (min_fck_per_pck &&
356 req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
357 DSSERR("Requested pixel clock not possible with the current "
358 "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
359 "the constraint off.\n");
360 min_fck_per_pck = 0;
361 }
362
363retry:
364 memset(&best_dss, 0, sizeof(best_dss));
365 memset(&best_dispc, 0, sizeof(best_dispc));
366
367 if (cpu_is_omap24xx()) {
368 struct dispc_clock_info cur_dispc;
369 /* XXX can we change the clock on omap2? */
370 fck = dss_clk_get_rate(DSS_CLK_FCK1);
371 fck_div = 1;
372
373 dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
374 match = 1;
375
376 best_dss.fck = fck;
377 best_dss.fck_div = fck_div;
378
379 best_dispc = cur_dispc;
380
381 goto found;
382 } else if (cpu_is_omap34xx()) {
383 for (fck_div = 16; fck_div > 0; --fck_div) {
384 struct dispc_clock_info cur_dispc;
385
386 fck = prate / fck_div * 2;
387
388 if (fck > DISPC_MAX_FCK)
389 continue;
390
391 if (min_fck_per_pck &&
392 fck < req_pck * min_fck_per_pck)
393 continue;
394
395 match = 1;
396
397 dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
398
399 if (abs(cur_dispc.pck - req_pck) <
400 abs(best_dispc.pck - req_pck)) {
401
402 best_dss.fck = fck;
403 best_dss.fck_div = fck_div;
404
405 best_dispc = cur_dispc;
406
407 if (cur_dispc.pck == req_pck)
408 goto found;
409 }
410 }
411 } else {
412 BUG();
413 }
414
415found:
416 if (!match) {
417 if (min_fck_per_pck) {
418 DSSERR("Could not find suitable clock settings.\n"
419 "Turning FCK/PCK constraint off and"
420 "trying again.\n");
421 min_fck_per_pck = 0;
422 goto retry;
423 }
424
425 DSSERR("Could not find suitable clock settings.\n");
426
427 return -EINVAL;
428 }
429
430 if (dss_cinfo)
431 *dss_cinfo = best_dss;
432 if (dispc_cinfo)
433 *dispc_cinfo = best_dispc;
434
435 dss.cache_req_pck = req_pck;
436 dss.cache_prate = prate;
437 dss.cache_dss_cinfo = best_dss;
438 dss.cache_dispc_cinfo = best_dispc;
439
440 return 0;
441}
442
443
444
445static irqreturn_t dss_irq_handler_omap2(int irq, void *arg)
446{
447 dispc_irq_handler();
448
449 return IRQ_HANDLED;
450}
451
452static irqreturn_t dss_irq_handler_omap3(int irq, void *arg)
453{
454 u32 irqstatus;
455
456 irqstatus = dss_read_reg(DSS_IRQSTATUS);
457
458 if (irqstatus & (1<<0)) /* DISPC_IRQ */
459 dispc_irq_handler();
460#ifdef CONFIG_OMAP2_DSS_DSI
461 if (irqstatus & (1<<1)) /* DSI_IRQ */
462 dsi_irq_handler();
463#endif
464
465 return IRQ_HANDLED;
466}
467
468static int _omap_dss_wait_reset(void)
469{
470 unsigned timeout = 1000;
471
472 while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
473 udelay(1);
474 if (!--timeout) {
475 DSSERR("soft reset failed\n");
476 return -ENODEV;
477 }
478 }
479
480 return 0;
481}
482
483static int _omap_dss_reset(void)
484{
485 /* Soft reset */
486 REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
487 return _omap_dss_wait_reset();
488}
489
490void dss_set_venc_output(enum omap_dss_venc_type type)
491{
492 int l = 0;
493
494 if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
495 l = 0;
496 else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
497 l = 1;
498 else
499 BUG();
500
501 /* venc out selection. 0 = comp, 1 = svideo */
502 REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
503}
504
505void dss_set_dac_pwrdn_bgz(bool enable)
506{
507 REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
508}
509
510int dss_init(bool skip_init)
511{
512 int r;
513 u32 rev;
514
515 dss.base = ioremap(DSS_BASE, DSS_SZ_REGS);
516 if (!dss.base) {
517 DSSERR("can't ioremap DSS\n");
518 r = -ENOMEM;
519 goto fail0;
520 }
521
522 if (!skip_init) {
523 /* disable LCD and DIGIT output. This seems to fix the synclost
524 * problem that we get, if the bootloader starts the DSS and
525 * the kernel resets it */
526 omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
527
528 /* We need to wait here a bit, otherwise we sometimes start to
529 * get synclost errors, and after that only power cycle will
530 * restore DSS functionality. I have no idea why this happens.
531 * And we have to wait _before_ resetting the DSS, but after
532 * enabling clocks.
533 */
534 msleep(50);
535
536 _omap_dss_reset();
537 }
538
539 /* autoidle */
540 REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
541
542 /* Select DPLL */
543 REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
544
545#ifdef CONFIG_OMAP2_DSS_VENC
546 REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
547 REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
548 REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
549#endif
550
551 r = request_irq(INT_24XX_DSS_IRQ,
552 cpu_is_omap24xx()
553 ? dss_irq_handler_omap2
554 : dss_irq_handler_omap3,
555 0, "OMAP DSS", NULL);
556
557 if (r < 0) {
558 DSSERR("omap2 dss: request_irq failed\n");
559 goto fail1;
560 }
561
562 if (cpu_is_omap34xx()) {
563 dss.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
564 if (IS_ERR(dss.dpll4_m4_ck)) {
565 DSSERR("Failed to get dpll4_m4_ck\n");
566 r = PTR_ERR(dss.dpll4_m4_ck);
567 goto fail2;
568 }
569 }
570
571 dss_save_context();
572
573 rev = dss_read_reg(DSS_REVISION);
574 printk(KERN_INFO "OMAP DSS rev %d.%d\n",
575 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
576
577 return 0;
578
579fail2:
580 free_irq(INT_24XX_DSS_IRQ, NULL);
581fail1:
582 iounmap(dss.base);
583fail0:
584 return r;
585}
586
587void dss_exit(void)
588{
589 if (cpu_is_omap34xx())
590 clk_put(dss.dpll4_m4_ck);
591
592 free_irq(INT_24XX_DSS_IRQ, NULL);
593
594 iounmap(dss.base);
595}
596
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
new file mode 100644
index 000000000000..8da5ac42151b
--- /dev/null
+++ b/drivers/video/omap2/dss/dss.h
@@ -0,0 +1,370 @@
1/*
2 * linux/drivers/video/omap2/dss/dss.h
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#ifndef __OMAP2_DSS_H
24#define __OMAP2_DSS_H
25
26#ifdef CONFIG_OMAP2_DSS_DEBUG_SUPPORT
27#define DEBUG
28#endif
29
30#ifdef DEBUG
31extern unsigned int dss_debug;
32#ifdef DSS_SUBSYS_NAME
33#define DSSDBG(format, ...) \
34 if (dss_debug) \
35 printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME ": " format, \
36 ## __VA_ARGS__)
37#else
38#define DSSDBG(format, ...) \
39 if (dss_debug) \
40 printk(KERN_DEBUG "omapdss: " format, ## __VA_ARGS__)
41#endif
42
43#ifdef DSS_SUBSYS_NAME
44#define DSSDBGF(format, ...) \
45 if (dss_debug) \
46 printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME \
47 ": %s(" format ")\n", \
48 __func__, \
49 ## __VA_ARGS__)
50#else
51#define DSSDBGF(format, ...) \
52 if (dss_debug) \
53 printk(KERN_DEBUG "omapdss: " \
54 ": %s(" format ")\n", \
55 __func__, \
56 ## __VA_ARGS__)
57#endif
58
59#else /* DEBUG */
60#define DSSDBG(format, ...)
61#define DSSDBGF(format, ...)
62#endif
63
64
65#ifdef DSS_SUBSYS_NAME
66#define DSSERR(format, ...) \
67 printk(KERN_ERR "omapdss " DSS_SUBSYS_NAME " error: " format, \
68 ## __VA_ARGS__)
69#else
70#define DSSERR(format, ...) \
71 printk(KERN_ERR "omapdss error: " format, ## __VA_ARGS__)
72#endif
73
74#ifdef DSS_SUBSYS_NAME
75#define DSSINFO(format, ...) \
76 printk(KERN_INFO "omapdss " DSS_SUBSYS_NAME ": " format, \
77 ## __VA_ARGS__)
78#else
79#define DSSINFO(format, ...) \
80 printk(KERN_INFO "omapdss: " format, ## __VA_ARGS__)
81#endif
82
83#ifdef DSS_SUBSYS_NAME
84#define DSSWARN(format, ...) \
85 printk(KERN_WARNING "omapdss " DSS_SUBSYS_NAME ": " format, \
86 ## __VA_ARGS__)
87#else
88#define DSSWARN(format, ...) \
89 printk(KERN_WARNING "omapdss: " format, ## __VA_ARGS__)
90#endif
91
92/* OMAP TRM gives bitfields as start:end, where start is the higher bit
93 number. For example 7:0 */
94#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
95#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
96#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end))
97#define FLD_MOD(orig, val, start, end) \
98 (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
99
100#define DISPC_MAX_FCK 173000000
101
102enum omap_burst_size {
103 OMAP_DSS_BURST_4x32 = 0,
104 OMAP_DSS_BURST_8x32 = 1,
105 OMAP_DSS_BURST_16x32 = 2,
106};
107
108enum omap_parallel_interface_mode {
109 OMAP_DSS_PARALLELMODE_BYPASS, /* MIPI DPI */
110 OMAP_DSS_PARALLELMODE_RFBI, /* MIPI DBI */
111 OMAP_DSS_PARALLELMODE_DSI,
112};
113
114enum dss_clock {
115 DSS_CLK_ICK = 1 << 0,
116 DSS_CLK_FCK1 = 1 << 1,
117 DSS_CLK_FCK2 = 1 << 2,
118 DSS_CLK_54M = 1 << 3,
119 DSS_CLK_96M = 1 << 4,
120};
121
122struct dss_clock_info {
123 /* rates that we get with dividers below */
124 unsigned long fck;
125
126 /* dividers */
127 u16 fck_div;
128};
129
130struct dispc_clock_info {
131 /* rates that we get with dividers below */
132 unsigned long lck;
133 unsigned long pck;
134
135 /* dividers */
136 u16 lck_div;
137 u16 pck_div;
138};
139
140struct dsi_clock_info {
141 /* rates that we get with dividers below */
142 unsigned long fint;
143 unsigned long clkin4ddr;
144 unsigned long clkin;
145 unsigned long dsi1_pll_fclk;
146 unsigned long dsi2_pll_fclk;
147
148 unsigned long lp_clk;
149
150 /* dividers */
151 u16 regn;
152 u16 regm;
153 u16 regm3;
154 u16 regm4;
155
156 u16 lp_clk_div;
157
158 u8 highfreq;
159 bool use_dss2_fck;
160};
161
162struct seq_file;
163struct platform_device;
164
165/* core */
166void dss_clk_enable(enum dss_clock clks);
167void dss_clk_disable(enum dss_clock clks);
168unsigned long dss_clk_get_rate(enum dss_clock clk);
169int dss_need_ctx_restore(void);
170void dss_dump_clocks(struct seq_file *s);
171struct bus_type *dss_get_bus(void);
172
173/* display */
174int dss_suspend_all_devices(void);
175int dss_resume_all_devices(void);
176void dss_disable_all_devices(void);
177
178void dss_init_device(struct platform_device *pdev,
179 struct omap_dss_device *dssdev);
180void dss_uninit_device(struct platform_device *pdev,
181 struct omap_dss_device *dssdev);
182bool dss_use_replication(struct omap_dss_device *dssdev,
183 enum omap_color_mode mode);
184void default_get_overlay_fifo_thresholds(enum omap_plane plane,
185 u32 fifo_size, enum omap_burst_size *burst_size,
186 u32 *fifo_low, u32 *fifo_high);
187
188/* manager */
189int dss_init_overlay_managers(struct platform_device *pdev);
190void dss_uninit_overlay_managers(struct platform_device *pdev);
191int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
192void dss_setup_partial_planes(struct omap_dss_device *dssdev,
193 u16 *x, u16 *y, u16 *w, u16 *h);
194void dss_start_update(struct omap_dss_device *dssdev);
195
196/* overlay */
197void dss_init_overlays(struct platform_device *pdev);
198void dss_uninit_overlays(struct platform_device *pdev);
199int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev);
200void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
201#ifdef L4_EXAMPLE
202void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr);
203#endif
204void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
205
206/* DSS */
207int dss_init(bool skip_init);
208void dss_exit(void);
209
210void dss_save_context(void);
211void dss_restore_context(void);
212
213void dss_dump_regs(struct seq_file *s);
214
215void dss_sdi_init(u8 datapairs);
216int dss_sdi_enable(void);
217void dss_sdi_disable(void);
218
219void dss_select_clk_source(bool dsi, bool dispc);
220int dss_get_dsi_clk_source(void);
221int dss_get_dispc_clk_source(void);
222void dss_set_venc_output(enum omap_dss_venc_type type);
223void dss_set_dac_pwrdn_bgz(bool enable);
224
225unsigned long dss_get_dpll4_rate(void);
226int dss_calc_clock_rates(struct dss_clock_info *cinfo);
227int dss_set_clock_div(struct dss_clock_info *cinfo);
228int dss_get_clock_div(struct dss_clock_info *cinfo);
229int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
230 struct dss_clock_info *dss_cinfo,
231 struct dispc_clock_info *dispc_cinfo);
232
233/* SDI */
234int sdi_init(bool skip_init);
235void sdi_exit(void);
236int sdi_init_display(struct omap_dss_device *display);
237
238/* DSI */
239int dsi_init(struct platform_device *pdev);
240void dsi_exit(void);
241
242void dsi_dump_clocks(struct seq_file *s);
243void dsi_dump_regs(struct seq_file *s);
244
245void dsi_save_context(void);
246void dsi_restore_context(void);
247
248int dsi_init_display(struct omap_dss_device *display);
249void dsi_irq_handler(void);
250unsigned long dsi_get_dsi1_pll_rate(void);
251int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo);
252int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck,
253 struct dsi_clock_info *cinfo,
254 struct dispc_clock_info *dispc_cinfo);
255int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk,
256 bool enable_hsdiv);
257void dsi_pll_uninit(void);
258void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
259 u32 fifo_size, enum omap_burst_size *burst_size,
260 u32 *fifo_low, u32 *fifo_high);
261
262/* DPI */
263int dpi_init(void);
264void dpi_exit(void);
265int dpi_init_display(struct omap_dss_device *dssdev);
266
267/* DISPC */
268int dispc_init(void);
269void dispc_exit(void);
270void dispc_dump_clocks(struct seq_file *s);
271void dispc_dump_regs(struct seq_file *s);
272void dispc_irq_handler(void);
273void dispc_fake_vsync_irq(void);
274
275void dispc_save_context(void);
276void dispc_restore_context(void);
277
278void dispc_enable_sidle(void);
279void dispc_disable_sidle(void);
280
281void dispc_lcd_enable_signal_polarity(bool act_high);
282void dispc_lcd_enable_signal(bool enable);
283void dispc_pck_free_enable(bool enable);
284void dispc_enable_fifohandcheck(bool enable);
285
286void dispc_set_lcd_size(u16 width, u16 height);
287void dispc_set_digit_size(u16 width, u16 height);
288u32 dispc_get_plane_fifo_size(enum omap_plane plane);
289void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high);
290void dispc_enable_fifomerge(bool enable);
291void dispc_set_burst_size(enum omap_plane plane,
292 enum omap_burst_size burst_size);
293
294void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
295void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
296void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y);
297void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height);
298void dispc_set_channel_out(enum omap_plane plane,
299 enum omap_channel channel_out);
300
301int dispc_setup_plane(enum omap_plane plane,
302 u32 paddr, u16 screen_width,
303 u16 pos_x, u16 pos_y,
304 u16 width, u16 height,
305 u16 out_width, u16 out_height,
306 enum omap_color_mode color_mode,
307 bool ilace,
308 enum omap_dss_rotation_type rotation_type,
309 u8 rotation, bool mirror,
310 u8 global_alpha);
311
312bool dispc_go_busy(enum omap_channel channel);
313void dispc_go(enum omap_channel channel);
314void dispc_enable_lcd_out(bool enable);
315void dispc_enable_digit_out(bool enable);
316int dispc_enable_plane(enum omap_plane plane, bool enable);
317void dispc_enable_replication(enum omap_plane plane, bool enable);
318
319void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode);
320void dispc_set_tft_data_lines(u8 data_lines);
321void dispc_set_lcd_display_type(enum omap_lcd_display_type type);
322void dispc_set_loadmode(enum omap_dss_load_mode mode);
323
324void dispc_set_default_color(enum omap_channel channel, u32 color);
325u32 dispc_get_default_color(enum omap_channel channel);
326void dispc_set_trans_key(enum omap_channel ch,
327 enum omap_dss_trans_key_type type,
328 u32 trans_key);
329void dispc_get_trans_key(enum omap_channel ch,
330 enum omap_dss_trans_key_type *type,
331 u32 *trans_key);
332void dispc_enable_trans_key(enum omap_channel ch, bool enable);
333void dispc_enable_alpha_blending(enum omap_channel ch, bool enable);
334bool dispc_trans_key_enabled(enum omap_channel ch);
335bool dispc_alpha_blending_enabled(enum omap_channel ch);
336
337bool dispc_lcd_timings_ok(struct omap_video_timings *timings);
338void dispc_set_lcd_timings(struct omap_video_timings *timings);
339unsigned long dispc_fclk_rate(void);
340unsigned long dispc_lclk_rate(void);
341unsigned long dispc_pclk_rate(void);
342void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb);
343void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
344 struct dispc_clock_info *cinfo);
345int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
346 struct dispc_clock_info *cinfo);
347int dispc_set_clock_div(struct dispc_clock_info *cinfo);
348int dispc_get_clock_div(struct dispc_clock_info *cinfo);
349
350
351/* VENC */
352int venc_init(struct platform_device *pdev);
353void venc_exit(void);
354void venc_dump_regs(struct seq_file *s);
355int venc_init_display(struct omap_dss_device *display);
356
357/* RFBI */
358int rfbi_init(void);
359void rfbi_exit(void);
360void rfbi_dump_regs(struct seq_file *s);
361
362int rfbi_configure(int rfbi_module, int bpp, int lines);
363void rfbi_enable_rfbi(bool enable);
364void rfbi_transfer_area(u16 width, u16 height,
365 void (callback)(void *data), void *data);
366void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t);
367unsigned long rfbi_get_max_tx_rate(void);
368int rfbi_init_display(struct omap_dss_device *display);
369
370#endif
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
new file mode 100644
index 000000000000..27d9c465c851
--- /dev/null
+++ b/drivers/video/omap2/dss/manager.c
@@ -0,0 +1,1487 @@
1/*
2 * linux/drivers/video/omap2/dss/manager.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#define DSS_SUBSYS_NAME "MANAGER"
24
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/platform_device.h>
28#include <linux/spinlock.h>
29#include <linux/jiffies.h>
30
31#include <plat/display.h>
32#include <plat/cpu.h>
33
34#include "dss.h"
35
36static int num_managers;
37static struct list_head manager_list;
38
39static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
40{
41 return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
42}
43
44static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
45{
46 return snprintf(buf, PAGE_SIZE, "%s\n",
47 mgr->device ? mgr->device->name : "<none>");
48}
49
50static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
51 const char *buf, size_t size)
52{
53 int r = 0;
54 size_t len = size;
55 struct omap_dss_device *dssdev = NULL;
56
57 int match(struct omap_dss_device *dssdev, void *data)
58 {
59 const char *str = data;
60 return sysfs_streq(dssdev->name, str);
61 }
62
63 if (buf[size-1] == '\n')
64 --len;
65
66 if (len > 0)
67 dssdev = omap_dss_find_device((void *)buf, match);
68
69 if (len > 0 && dssdev == NULL)
70 return -EINVAL;
71
72 if (dssdev)
73 DSSDBG("display %s found\n", dssdev->name);
74
75 if (mgr->device) {
76 r = mgr->unset_device(mgr);
77 if (r) {
78 DSSERR("failed to unset display\n");
79 goto put_device;
80 }
81 }
82
83 if (dssdev) {
84 r = mgr->set_device(mgr, dssdev);
85 if (r) {
86 DSSERR("failed to set manager\n");
87 goto put_device;
88 }
89
90 r = mgr->apply(mgr);
91 if (r) {
92 DSSERR("failed to apply dispc config\n");
93 goto put_device;
94 }
95 }
96
97put_device:
98 if (dssdev)
99 omap_dss_put_device(dssdev);
100
101 return r ? r : size;
102}
103
104static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
105 char *buf)
106{
107 return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.default_color);
108}
109
110static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
111 const char *buf, size_t size)
112{
113 struct omap_overlay_manager_info info;
114 u32 color;
115 int r;
116
117 if (sscanf(buf, "%d", &color) != 1)
118 return -EINVAL;
119
120 mgr->get_manager_info(mgr, &info);
121
122 info.default_color = color;
123
124 r = mgr->set_manager_info(mgr, &info);
125 if (r)
126 return r;
127
128 r = mgr->apply(mgr);
129 if (r)
130 return r;
131
132 return size;
133}
134
135static const char *trans_key_type_str[] = {
136 "gfx-destination",
137 "video-source",
138};
139
140static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
141 char *buf)
142{
143 enum omap_dss_trans_key_type key_type;
144
145 key_type = mgr->info.trans_key_type;
146 BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
147
148 return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
149}
150
151static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
152 const char *buf, size_t size)
153{
154 enum omap_dss_trans_key_type key_type;
155 struct omap_overlay_manager_info info;
156 int r;
157
158 for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
159 key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
160 if (sysfs_streq(buf, trans_key_type_str[key_type]))
161 break;
162 }
163
164 if (key_type == ARRAY_SIZE(trans_key_type_str))
165 return -EINVAL;
166
167 mgr->get_manager_info(mgr, &info);
168
169 info.trans_key_type = key_type;
170
171 r = mgr->set_manager_info(mgr, &info);
172 if (r)
173 return r;
174
175 r = mgr->apply(mgr);
176 if (r)
177 return r;
178
179 return size;
180}
181
182static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
183 char *buf)
184{
185 return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_key);
186}
187
188static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
189 const char *buf, size_t size)
190{
191 struct omap_overlay_manager_info info;
192 u32 key_value;
193 int r;
194
195 if (sscanf(buf, "%d", &key_value) != 1)
196 return -EINVAL;
197
198 mgr->get_manager_info(mgr, &info);
199
200 info.trans_key = key_value;
201
202 r = mgr->set_manager_info(mgr, &info);
203 if (r)
204 return r;
205
206 r = mgr->apply(mgr);
207 if (r)
208 return r;
209
210 return size;
211}
212
213static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
214 char *buf)
215{
216 return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_enabled);
217}
218
219static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
220 const char *buf, size_t size)
221{
222 struct omap_overlay_manager_info info;
223 int enable;
224 int r;
225
226 if (sscanf(buf, "%d", &enable) != 1)
227 return -EINVAL;
228
229 mgr->get_manager_info(mgr, &info);
230
231 info.trans_enabled = enable ? true : false;
232
233 r = mgr->set_manager_info(mgr, &info);
234 if (r)
235 return r;
236
237 r = mgr->apply(mgr);
238 if (r)
239 return r;
240
241 return size;
242}
243
244static ssize_t manager_alpha_blending_enabled_show(
245 struct omap_overlay_manager *mgr, char *buf)
246{
247 return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.alpha_enabled);
248}
249
250static ssize_t manager_alpha_blending_enabled_store(
251 struct omap_overlay_manager *mgr,
252 const char *buf, size_t size)
253{
254 struct omap_overlay_manager_info info;
255 int enable;
256 int r;
257
258 if (sscanf(buf, "%d", &enable) != 1)
259 return -EINVAL;
260
261 mgr->get_manager_info(mgr, &info);
262
263 info.alpha_enabled = enable ? true : false;
264
265 r = mgr->set_manager_info(mgr, &info);
266 if (r)
267 return r;
268
269 r = mgr->apply(mgr);
270 if (r)
271 return r;
272
273 return size;
274}
275
276struct manager_attribute {
277 struct attribute attr;
278 ssize_t (*show)(struct omap_overlay_manager *, char *);
279 ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
280};
281
282#define MANAGER_ATTR(_name, _mode, _show, _store) \
283 struct manager_attribute manager_attr_##_name = \
284 __ATTR(_name, _mode, _show, _store)
285
286static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
287static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
288 manager_display_show, manager_display_store);
289static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
290 manager_default_color_show, manager_default_color_store);
291static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
292 manager_trans_key_type_show, manager_trans_key_type_store);
293static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
294 manager_trans_key_value_show, manager_trans_key_value_store);
295static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
296 manager_trans_key_enabled_show,
297 manager_trans_key_enabled_store);
298static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
299 manager_alpha_blending_enabled_show,
300 manager_alpha_blending_enabled_store);
301
302
303static struct attribute *manager_sysfs_attrs[] = {
304 &manager_attr_name.attr,
305 &manager_attr_display.attr,
306 &manager_attr_default_color.attr,
307 &manager_attr_trans_key_type.attr,
308 &manager_attr_trans_key_value.attr,
309 &manager_attr_trans_key_enabled.attr,
310 &manager_attr_alpha_blending_enabled.attr,
311 NULL
312};
313
314static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
315 char *buf)
316{
317 struct omap_overlay_manager *manager;
318 struct manager_attribute *manager_attr;
319
320 manager = container_of(kobj, struct omap_overlay_manager, kobj);
321 manager_attr = container_of(attr, struct manager_attribute, attr);
322
323 if (!manager_attr->show)
324 return -ENOENT;
325
326 return manager_attr->show(manager, buf);
327}
328
329static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
330 const char *buf, size_t size)
331{
332 struct omap_overlay_manager *manager;
333 struct manager_attribute *manager_attr;
334
335 manager = container_of(kobj, struct omap_overlay_manager, kobj);
336 manager_attr = container_of(attr, struct manager_attribute, attr);
337
338 if (!manager_attr->store)
339 return -ENOENT;
340
341 return manager_attr->store(manager, buf, size);
342}
343
344static struct sysfs_ops manager_sysfs_ops = {
345 .show = manager_attr_show,
346 .store = manager_attr_store,
347};
348
349static struct kobj_type manager_ktype = {
350 .sysfs_ops = &manager_sysfs_ops,
351 .default_attrs = manager_sysfs_attrs,
352};
353
354/*
355 * We have 4 levels of cache for the dispc settings. First two are in SW and
356 * the latter two in HW.
357 *
358 * +--------------------+
359 * |overlay/manager_info|
360 * +--------------------+
361 * v
362 * apply()
363 * v
364 * +--------------------+
365 * | dss_cache |
366 * +--------------------+
367 * v
368 * configure()
369 * v
370 * +--------------------+
371 * | shadow registers |
372 * +--------------------+
373 * v
374 * VFP or lcd/digit_enable
375 * v
376 * +--------------------+
377 * | registers |
378 * +--------------------+
379 */
380
381struct overlay_cache_data {
382 /* If true, cache changed, but not written to shadow registers. Set
383 * in apply(), cleared when registers written. */
384 bool dirty;
385 /* If true, shadow registers contain changed values not yet in real
386 * registers. Set when writing to shadow registers, cleared at
387 * VSYNC/EVSYNC */
388 bool shadow_dirty;
389
390 bool enabled;
391
392 u32 paddr;
393 void __iomem *vaddr;
394 u16 screen_width;
395 u16 width;
396 u16 height;
397 enum omap_color_mode color_mode;
398 u8 rotation;
399 enum omap_dss_rotation_type rotation_type;
400 bool mirror;
401
402 u16 pos_x;
403 u16 pos_y;
404 u16 out_width; /* if 0, out_width == width */
405 u16 out_height; /* if 0, out_height == height */
406 u8 global_alpha;
407
408 enum omap_channel channel;
409 bool replication;
410 bool ilace;
411
412 enum omap_burst_size burst_size;
413 u32 fifo_low;
414 u32 fifo_high;
415
416 bool manual_update;
417};
418
419struct manager_cache_data {
420 /* If true, cache changed, but not written to shadow registers. Set
421 * in apply(), cleared when registers written. */
422 bool dirty;
423 /* If true, shadow registers contain changed values not yet in real
424 * registers. Set when writing to shadow registers, cleared at
425 * VSYNC/EVSYNC */
426 bool shadow_dirty;
427
428 u32 default_color;
429
430 enum omap_dss_trans_key_type trans_key_type;
431 u32 trans_key;
432 bool trans_enabled;
433
434 bool alpha_enabled;
435
436 bool manual_upd_display;
437 bool manual_update;
438 bool do_manual_update;
439
440 /* manual update region */
441 u16 x, y, w, h;
442};
443
444static struct {
445 spinlock_t lock;
446 struct overlay_cache_data overlay_cache[3];
447 struct manager_cache_data manager_cache[2];
448
449 bool irq_enabled;
450} dss_cache;
451
452
453
454static int omap_dss_set_device(struct omap_overlay_manager *mgr,
455 struct omap_dss_device *dssdev)
456{
457 int i;
458 int r;
459
460 if (dssdev->manager) {
461 DSSERR("display '%s' already has a manager '%s'\n",
462 dssdev->name, dssdev->manager->name);
463 return -EINVAL;
464 }
465
466 if ((mgr->supported_displays & dssdev->type) == 0) {
467 DSSERR("display '%s' does not support manager '%s'\n",
468 dssdev->name, mgr->name);
469 return -EINVAL;
470 }
471
472 for (i = 0; i < mgr->num_overlays; i++) {
473 struct omap_overlay *ovl = mgr->overlays[i];
474
475 if (ovl->manager != mgr || !ovl->info.enabled)
476 continue;
477
478 r = dss_check_overlay(ovl, dssdev);
479 if (r)
480 return r;
481 }
482
483 dssdev->manager = mgr;
484 mgr->device = dssdev;
485 mgr->device_changed = true;
486
487 return 0;
488}
489
490static int omap_dss_unset_device(struct omap_overlay_manager *mgr)
491{
492 if (!mgr->device) {
493 DSSERR("failed to unset display, display not set.\n");
494 return -EINVAL;
495 }
496
497 mgr->device->manager = NULL;
498 mgr->device = NULL;
499 mgr->device_changed = true;
500
501 return 0;
502}
503
504static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
505{
506 unsigned long timeout = msecs_to_jiffies(500);
507 struct manager_cache_data *mc;
508 enum omap_channel channel;
509 u32 irq;
510 int r;
511 int i;
512
513 if (!mgr->device)
514 return 0;
515
516 if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) {
517 irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
518 channel = OMAP_DSS_CHANNEL_DIGIT;
519 } else {
520 if (mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
521 enum omap_dss_update_mode mode;
522 mode = mgr->device->get_update_mode(mgr->device);
523 if (mode != OMAP_DSS_UPDATE_AUTO)
524 return 0;
525
526 irq = DISPC_IRQ_FRAMEDONE;
527 } else {
528 irq = DISPC_IRQ_VSYNC;
529 }
530 channel = OMAP_DSS_CHANNEL_LCD;
531 }
532
533 mc = &dss_cache.manager_cache[mgr->id];
534 i = 0;
535 while (1) {
536 unsigned long flags;
537 bool shadow_dirty, dirty;
538
539 spin_lock_irqsave(&dss_cache.lock, flags);
540 dirty = mc->dirty;
541 shadow_dirty = mc->shadow_dirty;
542 spin_unlock_irqrestore(&dss_cache.lock, flags);
543
544 if (!dirty && !shadow_dirty) {
545 r = 0;
546 break;
547 }
548
549 /* 4 iterations is the worst case:
550 * 1 - initial iteration, dirty = true (between VFP and VSYNC)
551 * 2 - first VSYNC, dirty = true
552 * 3 - dirty = false, shadow_dirty = true
553 * 4 - shadow_dirty = false */
554 if (i++ == 3) {
555 DSSERR("mgr(%d)->wait_for_go() not finishing\n",
556 mgr->id);
557 r = 0;
558 break;
559 }
560
561 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
562 if (r == -ERESTARTSYS)
563 break;
564
565 if (r) {
566 DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
567 break;
568 }
569 }
570
571 return r;
572}
573
574int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
575{
576 unsigned long timeout = msecs_to_jiffies(500);
577 enum omap_channel channel;
578 struct overlay_cache_data *oc;
579 struct omap_dss_device *dssdev;
580 u32 irq;
581 int r;
582 int i;
583
584 if (!ovl->manager || !ovl->manager->device)
585 return 0;
586
587 dssdev = ovl->manager->device;
588
589 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
590 irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
591 channel = OMAP_DSS_CHANNEL_DIGIT;
592 } else {
593 if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
594 enum omap_dss_update_mode mode;
595 mode = dssdev->get_update_mode(dssdev);
596 if (mode != OMAP_DSS_UPDATE_AUTO)
597 return 0;
598
599 irq = DISPC_IRQ_FRAMEDONE;
600 } else {
601 irq = DISPC_IRQ_VSYNC;
602 }
603 channel = OMAP_DSS_CHANNEL_LCD;
604 }
605
606 oc = &dss_cache.overlay_cache[ovl->id];
607 i = 0;
608 while (1) {
609 unsigned long flags;
610 bool shadow_dirty, dirty;
611
612 spin_lock_irqsave(&dss_cache.lock, flags);
613 dirty = oc->dirty;
614 shadow_dirty = oc->shadow_dirty;
615 spin_unlock_irqrestore(&dss_cache.lock, flags);
616
617 if (!dirty && !shadow_dirty) {
618 r = 0;
619 break;
620 }
621
622 /* 4 iterations is the worst case:
623 * 1 - initial iteration, dirty = true (between VFP and VSYNC)
624 * 2 - first VSYNC, dirty = true
625 * 3 - dirty = false, shadow_dirty = true
626 * 4 - shadow_dirty = false */
627 if (i++ == 3) {
628 DSSERR("ovl(%d)->wait_for_go() not finishing\n",
629 ovl->id);
630 r = 0;
631 break;
632 }
633
634 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
635 if (r == -ERESTARTSYS)
636 break;
637
638 if (r) {
639 DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
640 break;
641 }
642 }
643
644 return r;
645}
646
647static int overlay_enabled(struct omap_overlay *ovl)
648{
649 return ovl->info.enabled && ovl->manager && ovl->manager->device;
650}
651
652/* Is rect1 a subset of rect2? */
653static bool rectangle_subset(int x1, int y1, int w1, int h1,
654 int x2, int y2, int w2, int h2)
655{
656 if (x1 < x2 || y1 < y2)
657 return false;
658
659 if (x1 + w1 > x2 + w2)
660 return false;
661
662 if (y1 + h1 > y2 + h2)
663 return false;
664
665 return true;
666}
667
668/* Do rect1 and rect2 overlap? */
669static bool rectangle_intersects(int x1, int y1, int w1, int h1,
670 int x2, int y2, int w2, int h2)
671{
672 if (x1 >= x2 + w2)
673 return false;
674
675 if (x2 >= x1 + w1)
676 return false;
677
678 if (y1 >= y2 + h2)
679 return false;
680
681 if (y2 >= y1 + h1)
682 return false;
683
684 return true;
685}
686
687static bool dispc_is_overlay_scaled(struct overlay_cache_data *oc)
688{
689 if (oc->out_width != 0 && oc->width != oc->out_width)
690 return true;
691
692 if (oc->out_height != 0 && oc->height != oc->out_height)
693 return true;
694
695 return false;
696}
697
698static int configure_overlay(enum omap_plane plane)
699{
700 struct overlay_cache_data *c;
701 struct manager_cache_data *mc;
702 u16 outw, outh;
703 u16 x, y, w, h;
704 u32 paddr;
705 int r;
706
707 DSSDBGF("%d", plane);
708
709 c = &dss_cache.overlay_cache[plane];
710
711 if (!c->enabled) {
712 dispc_enable_plane(plane, 0);
713 return 0;
714 }
715
716 mc = &dss_cache.manager_cache[c->channel];
717
718 x = c->pos_x;
719 y = c->pos_y;
720 w = c->width;
721 h = c->height;
722 outw = c->out_width == 0 ? c->width : c->out_width;
723 outh = c->out_height == 0 ? c->height : c->out_height;
724 paddr = c->paddr;
725
726 if (c->manual_update && mc->do_manual_update) {
727 unsigned bpp;
728 /* If the overlay is outside the update region, disable it */
729 if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h,
730 x, y, outw, outh)) {
731 dispc_enable_plane(plane, 0);
732 return 0;
733 }
734
735 switch (c->color_mode) {
736 case OMAP_DSS_COLOR_RGB16:
737 case OMAP_DSS_COLOR_ARGB16:
738 case OMAP_DSS_COLOR_YUV2:
739 case OMAP_DSS_COLOR_UYVY:
740 bpp = 16;
741 break;
742
743 case OMAP_DSS_COLOR_RGB24P:
744 bpp = 24;
745 break;
746
747 case OMAP_DSS_COLOR_RGB24U:
748 case OMAP_DSS_COLOR_ARGB32:
749 case OMAP_DSS_COLOR_RGBA32:
750 case OMAP_DSS_COLOR_RGBX32:
751 bpp = 32;
752 break;
753
754 default:
755 BUG();
756 }
757
758 if (dispc_is_overlay_scaled(c)) {
759 /* If the overlay is scaled, the update area has
760 * already been enlarged to cover the whole overlay. We
761 * only need to adjust x/y here */
762 x = c->pos_x - mc->x;
763 y = c->pos_y - mc->y;
764 } else {
765 if (mc->x > c->pos_x) {
766 x = 0;
767 w -= (mc->x - c->pos_x);
768 paddr += (mc->x - c->pos_x) * bpp / 8;
769 } else {
770 x = c->pos_x - mc->x;
771 }
772
773 if (mc->y > c->pos_y) {
774 y = 0;
775 h -= (mc->y - c->pos_y);
776 paddr += (mc->y - c->pos_y) * c->screen_width *
777 bpp / 8;
778 } else {
779 y = c->pos_y - mc->y;
780 }
781
782 if (mc->w < (x+w))
783 w -= (x+w) - (mc->w);
784
785 if (mc->h < (y+h))
786 h -= (y+h) - (mc->h);
787
788 outw = w;
789 outh = h;
790 }
791 }
792
793 r = dispc_setup_plane(plane,
794 paddr,
795 c->screen_width,
796 x, y,
797 w, h,
798 outw, outh,
799 c->color_mode,
800 c->ilace,
801 c->rotation_type,
802 c->rotation,
803 c->mirror,
804 c->global_alpha);
805
806 if (r) {
807 /* this shouldn't happen */
808 DSSERR("dispc_setup_plane failed for ovl %d\n", plane);
809 dispc_enable_plane(plane, 0);
810 return r;
811 }
812
813 dispc_enable_replication(plane, c->replication);
814
815 dispc_set_burst_size(plane, c->burst_size);
816 dispc_setup_plane_fifo(plane, c->fifo_low, c->fifo_high);
817
818 dispc_enable_plane(plane, 1);
819
820 return 0;
821}
822
823static void configure_manager(enum omap_channel channel)
824{
825 struct manager_cache_data *c;
826
827 DSSDBGF("%d", channel);
828
829 c = &dss_cache.manager_cache[channel];
830
831 dispc_set_trans_key(channel, c->trans_key_type, c->trans_key);
832 dispc_enable_trans_key(channel, c->trans_enabled);
833 dispc_enable_alpha_blending(channel, c->alpha_enabled);
834}
835
836/* configure_dispc() tries to write values from cache to shadow registers.
837 * It writes only to those managers/overlays that are not busy.
838 * returns 0 if everything could be written to shadow registers.
839 * returns 1 if not everything could be written to shadow registers. */
840static int configure_dispc(void)
841{
842 struct overlay_cache_data *oc;
843 struct manager_cache_data *mc;
844 const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
845 const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
846 int i;
847 int r;
848 bool mgr_busy[2];
849 bool mgr_go[2];
850 bool busy;
851
852 r = 0;
853 busy = false;
854
855 mgr_busy[0] = dispc_go_busy(0);
856 mgr_busy[1] = dispc_go_busy(1);
857 mgr_go[0] = false;
858 mgr_go[1] = false;
859
860 /* Commit overlay settings */
861 for (i = 0; i < num_ovls; ++i) {
862 oc = &dss_cache.overlay_cache[i];
863 mc = &dss_cache.manager_cache[oc->channel];
864
865 if (!oc->dirty)
866 continue;
867
868 if (oc->manual_update && !mc->do_manual_update)
869 continue;
870
871 if (mgr_busy[oc->channel]) {
872 busy = true;
873 continue;
874 }
875
876 r = configure_overlay(i);
877 if (r)
878 DSSERR("configure_overlay %d failed\n", i);
879
880 oc->dirty = false;
881 oc->shadow_dirty = true;
882 mgr_go[oc->channel] = true;
883 }
884
885 /* Commit manager settings */
886 for (i = 0; i < num_mgrs; ++i) {
887 mc = &dss_cache.manager_cache[i];
888
889 if (!mc->dirty)
890 continue;
891
892 if (mc->manual_update && !mc->do_manual_update)
893 continue;
894
895 if (mgr_busy[i]) {
896 busy = true;
897 continue;
898 }
899
900 configure_manager(i);
901 mc->dirty = false;
902 mc->shadow_dirty = true;
903 mgr_go[i] = true;
904 }
905
906 /* set GO */
907 for (i = 0; i < num_mgrs; ++i) {
908 mc = &dss_cache.manager_cache[i];
909
910 if (!mgr_go[i])
911 continue;
912
913 /* We don't need GO with manual update display. LCD iface will
914 * always be turned off after frame, and new settings will be
915 * taken in to use at next update */
916 if (!mc->manual_upd_display)
917 dispc_go(i);
918 }
919
920 if (busy)
921 r = 1;
922 else
923 r = 0;
924
925 return r;
926}
927
928/* Configure dispc for partial update. Return possibly modified update
929 * area */
930void dss_setup_partial_planes(struct omap_dss_device *dssdev,
931 u16 *xi, u16 *yi, u16 *wi, u16 *hi)
932{
933 struct overlay_cache_data *oc;
934 struct manager_cache_data *mc;
935 const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
936 struct omap_overlay_manager *mgr;
937 int i;
938 u16 x, y, w, h;
939 unsigned long flags;
940
941 x = *xi;
942 y = *yi;
943 w = *wi;
944 h = *hi;
945
946 DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n",
947 *xi, *yi, *wi, *hi);
948
949 mgr = dssdev->manager;
950
951 if (!mgr) {
952 DSSDBG("no manager\n");
953 return;
954 }
955
956 spin_lock_irqsave(&dss_cache.lock, flags);
957
958 /* We need to show the whole overlay if it is scaled. So look for
959 * those, and make the update area larger if found.
960 * Also mark the overlay cache dirty */
961 for (i = 0; i < num_ovls; ++i) {
962 unsigned x1, y1, x2, y2;
963 unsigned outw, outh;
964
965 oc = &dss_cache.overlay_cache[i];
966
967 if (oc->channel != mgr->id)
968 continue;
969
970 oc->dirty = true;
971
972 if (!oc->enabled)
973 continue;
974
975 if (!dispc_is_overlay_scaled(oc))
976 continue;
977
978 outw = oc->out_width == 0 ? oc->width : oc->out_width;
979 outh = oc->out_height == 0 ? oc->height : oc->out_height;
980
981 /* is the overlay outside the update region? */
982 if (!rectangle_intersects(x, y, w, h,
983 oc->pos_x, oc->pos_y,
984 outw, outh))
985 continue;
986
987 /* if the overlay totally inside the update region? */
988 if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh,
989 x, y, w, h))
990 continue;
991
992 if (x > oc->pos_x)
993 x1 = oc->pos_x;
994 else
995 x1 = x;
996
997 if (y > oc->pos_y)
998 y1 = oc->pos_y;
999 else
1000 y1 = y;
1001
1002 if ((x + w) < (oc->pos_x + outw))
1003 x2 = oc->pos_x + outw;
1004 else
1005 x2 = x + w;
1006
1007 if ((y + h) < (oc->pos_y + outh))
1008 y2 = oc->pos_y + outh;
1009 else
1010 y2 = y + h;
1011
1012 x = x1;
1013 y = y1;
1014 w = x2 - x1;
1015 h = y2 - y1;
1016
1017 DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n",
1018 i, x, y, w, h);
1019 }
1020
1021 mc = &dss_cache.manager_cache[mgr->id];
1022 mc->do_manual_update = true;
1023 mc->x = x;
1024 mc->y = y;
1025 mc->w = w;
1026 mc->h = h;
1027
1028 configure_dispc();
1029
1030 mc->do_manual_update = false;
1031
1032 spin_unlock_irqrestore(&dss_cache.lock, flags);
1033
1034 *xi = x;
1035 *yi = y;
1036 *wi = w;
1037 *hi = h;
1038}
1039
1040void dss_start_update(struct omap_dss_device *dssdev)
1041{
1042 struct manager_cache_data *mc;
1043 struct overlay_cache_data *oc;
1044 const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
1045 const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
1046 struct omap_overlay_manager *mgr;
1047 int i;
1048
1049 mgr = dssdev->manager;
1050
1051 for (i = 0; i < num_ovls; ++i) {
1052 oc = &dss_cache.overlay_cache[i];
1053 if (oc->channel != mgr->id)
1054 continue;
1055
1056 oc->shadow_dirty = false;
1057 }
1058
1059 for (i = 0; i < num_mgrs; ++i) {
1060 mc = &dss_cache.manager_cache[i];
1061 if (mgr->id != i)
1062 continue;
1063
1064 mc->shadow_dirty = false;
1065 }
1066
1067 dispc_enable_lcd_out(1);
1068}
1069
1070static void dss_apply_irq_handler(void *data, u32 mask)
1071{
1072 struct manager_cache_data *mc;
1073 struct overlay_cache_data *oc;
1074 const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
1075 const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
1076 int i, r;
1077 bool mgr_busy[2];
1078
1079 mgr_busy[0] = dispc_go_busy(0);
1080 mgr_busy[1] = dispc_go_busy(1);
1081
1082 spin_lock(&dss_cache.lock);
1083
1084 for (i = 0; i < num_ovls; ++i) {
1085 oc = &dss_cache.overlay_cache[i];
1086 if (!mgr_busy[oc->channel])
1087 oc->shadow_dirty = false;
1088 }
1089
1090 for (i = 0; i < num_mgrs; ++i) {
1091 mc = &dss_cache.manager_cache[i];
1092 if (!mgr_busy[i])
1093 mc->shadow_dirty = false;
1094 }
1095
1096 r = configure_dispc();
1097 if (r == 1)
1098 goto end;
1099
1100 /* re-read busy flags */
1101 mgr_busy[0] = dispc_go_busy(0);
1102 mgr_busy[1] = dispc_go_busy(1);
1103
1104 /* keep running as long as there are busy managers, so that
1105 * we can collect overlay-applied information */
1106 for (i = 0; i < num_mgrs; ++i) {
1107 if (mgr_busy[i])
1108 goto end;
1109 }
1110
1111 omap_dispc_unregister_isr(dss_apply_irq_handler, NULL,
1112 DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
1113 DISPC_IRQ_EVSYNC_EVEN);
1114 dss_cache.irq_enabled = false;
1115
1116end:
1117 spin_unlock(&dss_cache.lock);
1118}
1119
1120static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
1121{
1122 struct overlay_cache_data *oc;
1123 struct manager_cache_data *mc;
1124 int i;
1125 struct omap_overlay *ovl;
1126 int num_planes_enabled = 0;
1127 bool use_fifomerge;
1128 unsigned long flags;
1129 int r;
1130
1131 DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
1132
1133 spin_lock_irqsave(&dss_cache.lock, flags);
1134
1135 /* Configure overlays */
1136 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
1137 struct omap_dss_device *dssdev;
1138
1139 ovl = omap_dss_get_overlay(i);
1140
1141 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
1142 continue;
1143
1144 oc = &dss_cache.overlay_cache[ovl->id];
1145
1146 if (!overlay_enabled(ovl)) {
1147 if (oc->enabled) {
1148 oc->enabled = false;
1149 oc->dirty = true;
1150 }
1151 continue;
1152 }
1153
1154 if (!ovl->info_dirty) {
1155 if (oc->enabled)
1156 ++num_planes_enabled;
1157 continue;
1158 }
1159
1160 dssdev = ovl->manager->device;
1161
1162 if (dss_check_overlay(ovl, dssdev)) {
1163 if (oc->enabled) {
1164 oc->enabled = false;
1165 oc->dirty = true;
1166 }
1167 continue;
1168 }
1169
1170 ovl->info_dirty = false;
1171 oc->dirty = true;
1172
1173 oc->paddr = ovl->info.paddr;
1174 oc->vaddr = ovl->info.vaddr;
1175 oc->screen_width = ovl->info.screen_width;
1176 oc->width = ovl->info.width;
1177 oc->height = ovl->info.height;
1178 oc->color_mode = ovl->info.color_mode;
1179 oc->rotation = ovl->info.rotation;
1180 oc->rotation_type = ovl->info.rotation_type;
1181 oc->mirror = ovl->info.mirror;
1182 oc->pos_x = ovl->info.pos_x;
1183 oc->pos_y = ovl->info.pos_y;
1184 oc->out_width = ovl->info.out_width;
1185 oc->out_height = ovl->info.out_height;
1186 oc->global_alpha = ovl->info.global_alpha;
1187
1188 oc->replication =
1189 dss_use_replication(dssdev, ovl->info.color_mode);
1190
1191 oc->ilace = dssdev->type == OMAP_DISPLAY_TYPE_VENC;
1192
1193 oc->channel = ovl->manager->id;
1194
1195 oc->enabled = true;
1196
1197 oc->manual_update =
1198 dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
1199 dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO;
1200
1201 ++num_planes_enabled;
1202 }
1203
1204 /* Configure managers */
1205 list_for_each_entry(mgr, &manager_list, list) {
1206 struct omap_dss_device *dssdev;
1207
1208 if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC))
1209 continue;
1210
1211 mc = &dss_cache.manager_cache[mgr->id];
1212
1213 if (mgr->device_changed) {
1214 mgr->device_changed = false;
1215 mgr->info_dirty = true;
1216 }
1217
1218 if (!mgr->info_dirty)
1219 continue;
1220
1221 if (!mgr->device)
1222 continue;
1223
1224 dssdev = mgr->device;
1225
1226 mgr->info_dirty = false;
1227 mc->dirty = true;
1228
1229 mc->default_color = mgr->info.default_color;
1230 mc->trans_key_type = mgr->info.trans_key_type;
1231 mc->trans_key = mgr->info.trans_key;
1232 mc->trans_enabled = mgr->info.trans_enabled;
1233 mc->alpha_enabled = mgr->info.alpha_enabled;
1234
1235 mc->manual_upd_display =
1236 dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
1237
1238 mc->manual_update =
1239 dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
1240 dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO;
1241 }
1242
1243 /* XXX TODO: Try to get fifomerge working. The problem is that it
1244 * affects both managers, not individually but at the same time. This
1245 * means the change has to be well synchronized. I guess the proper way
1246 * is to have a two step process for fifo merge:
1247 * fifomerge enable:
1248 * 1. disable other planes, leaving one plane enabled
1249 * 2. wait until the planes are disabled on HW
1250 * 3. config merged fifo thresholds, enable fifomerge
1251 * fifomerge disable:
1252 * 1. config unmerged fifo thresholds, disable fifomerge
1253 * 2. wait until fifo changes are in HW
1254 * 3. enable planes
1255 */
1256 use_fifomerge = false;
1257
1258 /* Configure overlay fifos */
1259 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
1260 struct omap_dss_device *dssdev;
1261 u32 size;
1262
1263 ovl = omap_dss_get_overlay(i);
1264
1265 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
1266 continue;
1267
1268 oc = &dss_cache.overlay_cache[ovl->id];
1269
1270 if (!oc->enabled)
1271 continue;
1272
1273 dssdev = ovl->manager->device;
1274
1275 size = dispc_get_plane_fifo_size(ovl->id);
1276 if (use_fifomerge)
1277 size *= 3;
1278
1279 switch (dssdev->type) {
1280 case OMAP_DISPLAY_TYPE_DPI:
1281 case OMAP_DISPLAY_TYPE_DBI:
1282 case OMAP_DISPLAY_TYPE_SDI:
1283 case OMAP_DISPLAY_TYPE_VENC:
1284 default_get_overlay_fifo_thresholds(ovl->id, size,
1285 &oc->burst_size, &oc->fifo_low,
1286 &oc->fifo_high);
1287 break;
1288#ifdef CONFIG_OMAP2_DSS_DSI
1289 case OMAP_DISPLAY_TYPE_DSI:
1290 dsi_get_overlay_fifo_thresholds(ovl->id, size,
1291 &oc->burst_size, &oc->fifo_low,
1292 &oc->fifo_high);
1293 break;
1294#endif
1295 default:
1296 BUG();
1297 }
1298 }
1299
1300 r = 0;
1301 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
1302 if (!dss_cache.irq_enabled) {
1303 r = omap_dispc_register_isr(dss_apply_irq_handler, NULL,
1304 DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
1305 DISPC_IRQ_EVSYNC_EVEN);
1306 dss_cache.irq_enabled = true;
1307 }
1308 configure_dispc();
1309 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
1310
1311 spin_unlock_irqrestore(&dss_cache.lock, flags);
1312
1313 return r;
1314}
1315
1316static int dss_check_manager(struct omap_overlay_manager *mgr)
1317{
1318 /* OMAP supports only graphics source transparency color key and alpha
1319 * blending simultaneously. See TRM 15.4.2.4.2.2 Alpha Mode */
1320
1321 if (mgr->info.alpha_enabled && mgr->info.trans_enabled &&
1322 mgr->info.trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST)
1323 return -EINVAL;
1324
1325 return 0;
1326}
1327
1328static int omap_dss_mgr_set_info(struct omap_overlay_manager *mgr,
1329 struct omap_overlay_manager_info *info)
1330{
1331 int r;
1332 struct omap_overlay_manager_info old_info;
1333
1334 old_info = mgr->info;
1335 mgr->info = *info;
1336
1337 r = dss_check_manager(mgr);
1338 if (r) {
1339 mgr->info = old_info;
1340 return r;
1341 }
1342
1343 mgr->info_dirty = true;
1344
1345 return 0;
1346}
1347
1348static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr,
1349 struct omap_overlay_manager_info *info)
1350{
1351 *info = mgr->info;
1352}
1353
1354static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager)
1355{
1356 ++num_managers;
1357 list_add_tail(&manager->list, &manager_list);
1358}
1359
1360int dss_init_overlay_managers(struct platform_device *pdev)
1361{
1362 int i, r;
1363
1364 spin_lock_init(&dss_cache.lock);
1365
1366 INIT_LIST_HEAD(&manager_list);
1367
1368 num_managers = 0;
1369
1370 for (i = 0; i < 2; ++i) {
1371 struct omap_overlay_manager *mgr;
1372 mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
1373
1374 BUG_ON(mgr == NULL);
1375
1376 switch (i) {
1377 case 0:
1378 mgr->name = "lcd";
1379 mgr->id = OMAP_DSS_CHANNEL_LCD;
1380 mgr->supported_displays =
1381 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
1382 OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI;
1383 break;
1384 case 1:
1385 mgr->name = "tv";
1386 mgr->id = OMAP_DSS_CHANNEL_DIGIT;
1387 mgr->supported_displays = OMAP_DISPLAY_TYPE_VENC;
1388 break;
1389 }
1390
1391 mgr->set_device = &omap_dss_set_device;
1392 mgr->unset_device = &omap_dss_unset_device;
1393 mgr->apply = &omap_dss_mgr_apply;
1394 mgr->set_manager_info = &omap_dss_mgr_set_info;
1395 mgr->get_manager_info = &omap_dss_mgr_get_info;
1396 mgr->wait_for_go = &dss_mgr_wait_for_go;
1397
1398 mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC;
1399
1400 dss_overlay_setup_dispc_manager(mgr);
1401
1402 omap_dss_add_overlay_manager(mgr);
1403
1404 r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
1405 &pdev->dev.kobj, "manager%d", i);
1406
1407 if (r) {
1408 DSSERR("failed to create sysfs file\n");
1409 continue;
1410 }
1411 }
1412
1413#ifdef L4_EXAMPLE
1414 {
1415 int omap_dss_mgr_apply_l4(struct omap_overlay_manager *mgr)
1416 {
1417 DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name);
1418
1419 return 0;
1420 }
1421
1422 struct omap_overlay_manager *mgr;
1423 mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
1424
1425 BUG_ON(mgr == NULL);
1426
1427 mgr->name = "l4";
1428 mgr->supported_displays =
1429 OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI;
1430
1431 mgr->set_device = &omap_dss_set_device;
1432 mgr->unset_device = &omap_dss_unset_device;
1433 mgr->apply = &omap_dss_mgr_apply_l4;
1434 mgr->set_manager_info = &omap_dss_mgr_set_info;
1435 mgr->get_manager_info = &omap_dss_mgr_get_info;
1436
1437 dss_overlay_setup_l4_manager(mgr);
1438
1439 omap_dss_add_overlay_manager(mgr);
1440
1441 r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
1442 &pdev->dev.kobj, "managerl4");
1443
1444 if (r)
1445 DSSERR("failed to create sysfs file\n");
1446 }
1447#endif
1448
1449 return 0;
1450}
1451
1452void dss_uninit_overlay_managers(struct platform_device *pdev)
1453{
1454 struct omap_overlay_manager *mgr;
1455
1456 while (!list_empty(&manager_list)) {
1457 mgr = list_first_entry(&manager_list,
1458 struct omap_overlay_manager, list);
1459 list_del(&mgr->list);
1460 kobject_del(&mgr->kobj);
1461 kobject_put(&mgr->kobj);
1462 kfree(mgr);
1463 }
1464
1465 num_managers = 0;
1466}
1467
1468int omap_dss_get_num_overlay_managers(void)
1469{
1470 return num_managers;
1471}
1472EXPORT_SYMBOL(omap_dss_get_num_overlay_managers);
1473
1474struct omap_overlay_manager *omap_dss_get_overlay_manager(int num)
1475{
1476 int i = 0;
1477 struct omap_overlay_manager *mgr;
1478
1479 list_for_each_entry(mgr, &manager_list, list) {
1480 if (i++ == num)
1481 return mgr;
1482 }
1483
1484 return NULL;
1485}
1486EXPORT_SYMBOL(omap_dss_get_overlay_manager);
1487
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
new file mode 100644
index 000000000000..b7f9a7339842
--- /dev/null
+++ b/drivers/video/omap2/dss/overlay.c
@@ -0,0 +1,680 @@
1/*
2 * linux/drivers/video/omap2/dss/overlay.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#define DSS_SUBSYS_NAME "OVERLAY"
24
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/err.h>
28#include <linux/sysfs.h>
29#include <linux/kobject.h>
30#include <linux/platform_device.h>
31#include <linux/delay.h>
32
33#include <plat/display.h>
34#include <plat/cpu.h>
35
36#include "dss.h"
37
38static int num_overlays;
39static struct list_head overlay_list;
40
41static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
42{
43 return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
44}
45
46static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
47{
48 return snprintf(buf, PAGE_SIZE, "%s\n",
49 ovl->manager ? ovl->manager->name : "<none>");
50}
51
52static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
53 size_t size)
54{
55 int i, r;
56 struct omap_overlay_manager *mgr = NULL;
57 struct omap_overlay_manager *old_mgr;
58 int len = size;
59
60 if (buf[size-1] == '\n')
61 --len;
62
63 if (len > 0) {
64 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
65 mgr = omap_dss_get_overlay_manager(i);
66
67 if (strncmp(buf, mgr->name, len) == 0)
68 break;
69
70 mgr = NULL;
71 }
72 }
73
74 if (len > 0 && mgr == NULL)
75 return -EINVAL;
76
77 if (mgr)
78 DSSDBG("manager %s found\n", mgr->name);
79
80 if (mgr == ovl->manager)
81 return size;
82
83 old_mgr = ovl->manager;
84
85 /* detach old manager */
86 if (old_mgr) {
87 r = ovl->unset_manager(ovl);
88 if (r) {
89 DSSERR("detach failed\n");
90 return r;
91 }
92
93 r = old_mgr->apply(old_mgr);
94 if (r)
95 return r;
96 }
97
98 if (mgr) {
99 r = ovl->set_manager(ovl, mgr);
100 if (r) {
101 DSSERR("Failed to attach overlay\n");
102 return r;
103 }
104
105 r = mgr->apply(mgr);
106 if (r)
107 return r;
108 }
109
110 return size;
111}
112
113static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
114{
115 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
116 ovl->info.width, ovl->info.height);
117}
118
119static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
120{
121 return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.screen_width);
122}
123
124static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
125{
126 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
127 ovl->info.pos_x, ovl->info.pos_y);
128}
129
130static ssize_t overlay_position_store(struct omap_overlay *ovl,
131 const char *buf, size_t size)
132{
133 int r;
134 char *last;
135 struct omap_overlay_info info;
136
137 ovl->get_overlay_info(ovl, &info);
138
139 info.pos_x = simple_strtoul(buf, &last, 10);
140 ++last;
141 if (last - buf >= size)
142 return -EINVAL;
143
144 info.pos_y = simple_strtoul(last, &last, 10);
145
146 r = ovl->set_overlay_info(ovl, &info);
147 if (r)
148 return r;
149
150 if (ovl->manager) {
151 r = ovl->manager->apply(ovl->manager);
152 if (r)
153 return r;
154 }
155
156 return size;
157}
158
159static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
160{
161 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
162 ovl->info.out_width, ovl->info.out_height);
163}
164
165static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
166 const char *buf, size_t size)
167{
168 int r;
169 char *last;
170 struct omap_overlay_info info;
171
172 ovl->get_overlay_info(ovl, &info);
173
174 info.out_width = simple_strtoul(buf, &last, 10);
175 ++last;
176 if (last - buf >= size)
177 return -EINVAL;
178
179 info.out_height = simple_strtoul(last, &last, 10);
180
181 r = ovl->set_overlay_info(ovl, &info);
182 if (r)
183 return r;
184
185 if (ovl->manager) {
186 r = ovl->manager->apply(ovl->manager);
187 if (r)
188 return r;
189 }
190
191 return size;
192}
193
194static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
195{
196 return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.enabled);
197}
198
199static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
200 size_t size)
201{
202 int r;
203 struct omap_overlay_info info;
204
205 ovl->get_overlay_info(ovl, &info);
206
207 info.enabled = simple_strtoul(buf, NULL, 10);
208
209 r = ovl->set_overlay_info(ovl, &info);
210 if (r)
211 return r;
212
213 if (ovl->manager) {
214 r = ovl->manager->apply(ovl->manager);
215 if (r)
216 return r;
217 }
218
219 return size;
220}
221
222static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
223{
224 return snprintf(buf, PAGE_SIZE, "%d\n",
225 ovl->info.global_alpha);
226}
227
228static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
229 const char *buf, size_t size)
230{
231 int r;
232 struct omap_overlay_info info;
233
234 ovl->get_overlay_info(ovl, &info);
235
236 /* Video1 plane does not support global alpha
237 * to always make it 255 completely opaque
238 */
239 if (ovl->id == OMAP_DSS_VIDEO1)
240 info.global_alpha = 255;
241 else
242 info.global_alpha = simple_strtoul(buf, NULL, 10);
243
244 r = ovl->set_overlay_info(ovl, &info);
245 if (r)
246 return r;
247
248 if (ovl->manager) {
249 r = ovl->manager->apply(ovl->manager);
250 if (r)
251 return r;
252 }
253
254 return size;
255}
256
257struct overlay_attribute {
258 struct attribute attr;
259 ssize_t (*show)(struct omap_overlay *, char *);
260 ssize_t (*store)(struct omap_overlay *, const char *, size_t);
261};
262
263#define OVERLAY_ATTR(_name, _mode, _show, _store) \
264 struct overlay_attribute overlay_attr_##_name = \
265 __ATTR(_name, _mode, _show, _store)
266
267static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
268static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
269 overlay_manager_show, overlay_manager_store);
270static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
271static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
272static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
273 overlay_position_show, overlay_position_store);
274static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
275 overlay_output_size_show, overlay_output_size_store);
276static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
277 overlay_enabled_show, overlay_enabled_store);
278static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
279 overlay_global_alpha_show, overlay_global_alpha_store);
280
281static struct attribute *overlay_sysfs_attrs[] = {
282 &overlay_attr_name.attr,
283 &overlay_attr_manager.attr,
284 &overlay_attr_input_size.attr,
285 &overlay_attr_screen_width.attr,
286 &overlay_attr_position.attr,
287 &overlay_attr_output_size.attr,
288 &overlay_attr_enabled.attr,
289 &overlay_attr_global_alpha.attr,
290 NULL
291};
292
293static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
294 char *buf)
295{
296 struct omap_overlay *overlay;
297 struct overlay_attribute *overlay_attr;
298
299 overlay = container_of(kobj, struct omap_overlay, kobj);
300 overlay_attr = container_of(attr, struct overlay_attribute, attr);
301
302 if (!overlay_attr->show)
303 return -ENOENT;
304
305 return overlay_attr->show(overlay, buf);
306}
307
308static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
309 const char *buf, size_t size)
310{
311 struct omap_overlay *overlay;
312 struct overlay_attribute *overlay_attr;
313
314 overlay = container_of(kobj, struct omap_overlay, kobj);
315 overlay_attr = container_of(attr, struct overlay_attribute, attr);
316
317 if (!overlay_attr->store)
318 return -ENOENT;
319
320 return overlay_attr->store(overlay, buf, size);
321}
322
323static struct sysfs_ops overlay_sysfs_ops = {
324 .show = overlay_attr_show,
325 .store = overlay_attr_store,
326};
327
328static struct kobj_type overlay_ktype = {
329 .sysfs_ops = &overlay_sysfs_ops,
330 .default_attrs = overlay_sysfs_attrs,
331};
332
333/* Check if overlay parameters are compatible with display */
334int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
335{
336 struct omap_overlay_info *info;
337 u16 outw, outh;
338 u16 dw, dh;
339
340 if (!dssdev)
341 return 0;
342
343 if (!ovl->info.enabled)
344 return 0;
345
346 info = &ovl->info;
347
348 if (info->paddr == 0) {
349 DSSDBG("check_overlay failed: paddr 0\n");
350 return -EINVAL;
351 }
352
353 dssdev->get_resolution(dssdev, &dw, &dh);
354
355 DSSDBG("check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)\n",
356 ovl->id,
357 info->pos_x, info->pos_y,
358 info->width, info->height,
359 info->out_width, info->out_height,
360 dw, dh);
361
362 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
363 outw = info->width;
364 outh = info->height;
365 } else {
366 if (info->out_width == 0)
367 outw = info->width;
368 else
369 outw = info->out_width;
370
371 if (info->out_height == 0)
372 outh = info->height;
373 else
374 outh = info->out_height;
375 }
376
377 if (dw < info->pos_x + outw) {
378 DSSDBG("check_overlay failed 1: %d < %d + %d\n",
379 dw, info->pos_x, outw);
380 return -EINVAL;
381 }
382
383 if (dh < info->pos_y + outh) {
384 DSSDBG("check_overlay failed 2: %d < %d + %d\n",
385 dh, info->pos_y, outh);
386 return -EINVAL;
387 }
388
389 if ((ovl->supported_modes & info->color_mode) == 0) {
390 DSSERR("overlay doesn't support mode %d\n", info->color_mode);
391 return -EINVAL;
392 }
393
394 return 0;
395}
396
397static int dss_ovl_set_overlay_info(struct omap_overlay *ovl,
398 struct omap_overlay_info *info)
399{
400 int r;
401 struct omap_overlay_info old_info;
402
403 old_info = ovl->info;
404 ovl->info = *info;
405
406 if (ovl->manager) {
407 r = dss_check_overlay(ovl, ovl->manager->device);
408 if (r) {
409 ovl->info = old_info;
410 return r;
411 }
412 }
413
414 ovl->info_dirty = true;
415
416 return 0;
417}
418
419static void dss_ovl_get_overlay_info(struct omap_overlay *ovl,
420 struct omap_overlay_info *info)
421{
422 *info = ovl->info;
423}
424
425static int dss_ovl_wait_for_go(struct omap_overlay *ovl)
426{
427 return dss_mgr_wait_for_go_ovl(ovl);
428}
429
430static int omap_dss_set_manager(struct omap_overlay *ovl,
431 struct omap_overlay_manager *mgr)
432{
433 if (!mgr)
434 return -EINVAL;
435
436 if (ovl->manager) {
437 DSSERR("overlay '%s' already has a manager '%s'\n",
438 ovl->name, ovl->manager->name);
439 return -EINVAL;
440 }
441
442 if (ovl->info.enabled) {
443 DSSERR("overlay has to be disabled to change the manager\n");
444 return -EINVAL;
445 }
446
447 ovl->manager = mgr;
448
449 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
450 /* XXX: on manual update display, in auto update mode, a bug happens
451 * here. When an overlay is first enabled on LCD, then it's disabled,
452 * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT
453 * errors. Waiting before changing the channel_out fixes it. I'm
454 * guessing that the overlay is still somehow being used for the LCD,
455 * but I don't understand how or why. */
456 msleep(40);
457 dispc_set_channel_out(ovl->id, mgr->id);
458 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
459
460 return 0;
461}
462
463static int omap_dss_unset_manager(struct omap_overlay *ovl)
464{
465 int r;
466
467 if (!ovl->manager) {
468 DSSERR("failed to detach overlay: manager not set\n");
469 return -EINVAL;
470 }
471
472 if (ovl->info.enabled) {
473 DSSERR("overlay has to be disabled to unset the manager\n");
474 return -EINVAL;
475 }
476
477 r = ovl->wait_for_go(ovl);
478 if (r)
479 return r;
480
481 ovl->manager = NULL;
482
483 return 0;
484}
485
486int omap_dss_get_num_overlays(void)
487{
488 return num_overlays;
489}
490EXPORT_SYMBOL(omap_dss_get_num_overlays);
491
492struct omap_overlay *omap_dss_get_overlay(int num)
493{
494 int i = 0;
495 struct omap_overlay *ovl;
496
497 list_for_each_entry(ovl, &overlay_list, list) {
498 if (i++ == num)
499 return ovl;
500 }
501
502 return NULL;
503}
504EXPORT_SYMBOL(omap_dss_get_overlay);
505
506static void omap_dss_add_overlay(struct omap_overlay *overlay)
507{
508 ++num_overlays;
509 list_add_tail(&overlay->list, &overlay_list);
510}
511
512static struct omap_overlay *dispc_overlays[3];
513
514void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr)
515{
516 mgr->num_overlays = 3;
517 mgr->overlays = dispc_overlays;
518}
519
520#ifdef L4_EXAMPLE
521static struct omap_overlay *l4_overlays[1];
522void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr)
523{
524 mgr->num_overlays = 1;
525 mgr->overlays = l4_overlays;
526}
527#endif
528
529void dss_init_overlays(struct platform_device *pdev)
530{
531 int i, r;
532
533 INIT_LIST_HEAD(&overlay_list);
534
535 num_overlays = 0;
536
537 for (i = 0; i < 3; ++i) {
538 struct omap_overlay *ovl;
539 ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
540
541 BUG_ON(ovl == NULL);
542
543 switch (i) {
544 case 0:
545 ovl->name = "gfx";
546 ovl->id = OMAP_DSS_GFX;
547 ovl->supported_modes = cpu_is_omap34xx() ?
548 OMAP_DSS_COLOR_GFX_OMAP3 :
549 OMAP_DSS_COLOR_GFX_OMAP2;
550 ovl->caps = OMAP_DSS_OVL_CAP_DISPC;
551 ovl->info.global_alpha = 255;
552 break;
553 case 1:
554 ovl->name = "vid1";
555 ovl->id = OMAP_DSS_VIDEO1;
556 ovl->supported_modes = cpu_is_omap34xx() ?
557 OMAP_DSS_COLOR_VID1_OMAP3 :
558 OMAP_DSS_COLOR_VID_OMAP2;
559 ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
560 OMAP_DSS_OVL_CAP_DISPC;
561 ovl->info.global_alpha = 255;
562 break;
563 case 2:
564 ovl->name = "vid2";
565 ovl->id = OMAP_DSS_VIDEO2;
566 ovl->supported_modes = cpu_is_omap34xx() ?
567 OMAP_DSS_COLOR_VID2_OMAP3 :
568 OMAP_DSS_COLOR_VID_OMAP2;
569 ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
570 OMAP_DSS_OVL_CAP_DISPC;
571 ovl->info.global_alpha = 255;
572 break;
573 }
574
575 ovl->set_manager = &omap_dss_set_manager;
576 ovl->unset_manager = &omap_dss_unset_manager;
577 ovl->set_overlay_info = &dss_ovl_set_overlay_info;
578 ovl->get_overlay_info = &dss_ovl_get_overlay_info;
579 ovl->wait_for_go = &dss_ovl_wait_for_go;
580
581 omap_dss_add_overlay(ovl);
582
583 r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
584 &pdev->dev.kobj, "overlay%d", i);
585
586 if (r) {
587 DSSERR("failed to create sysfs file\n");
588 continue;
589 }
590
591 dispc_overlays[i] = ovl;
592 }
593
594#ifdef L4_EXAMPLE
595 {
596 struct omap_overlay *ovl;
597 ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
598
599 BUG_ON(ovl == NULL);
600
601 ovl->name = "l4";
602 ovl->supported_modes = OMAP_DSS_COLOR_RGB24U;
603
604 ovl->set_manager = &omap_dss_set_manager;
605 ovl->unset_manager = &omap_dss_unset_manager;
606 ovl->set_overlay_info = &dss_ovl_set_overlay_info;
607 ovl->get_overlay_info = &dss_ovl_get_overlay_info;
608
609 omap_dss_add_overlay(ovl);
610
611 r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
612 &pdev->dev.kobj, "overlayl4");
613
614 if (r)
615 DSSERR("failed to create sysfs file\n");
616
617 l4_overlays[0] = ovl;
618 }
619#endif
620}
621
622/* connect overlays to the new device, if not already connected. if force
623 * selected, connect always. */
624void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
625{
626 int i;
627 struct omap_overlay_manager *lcd_mgr;
628 struct omap_overlay_manager *tv_mgr;
629 struct omap_overlay_manager *mgr = NULL;
630
631 lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD);
632 tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV);
633
634 if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) {
635 if (!lcd_mgr->device || force) {
636 if (lcd_mgr->device)
637 lcd_mgr->unset_device(lcd_mgr);
638 lcd_mgr->set_device(lcd_mgr, dssdev);
639 mgr = lcd_mgr;
640 }
641 }
642
643 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
644 if (!tv_mgr->device || force) {
645 if (tv_mgr->device)
646 tv_mgr->unset_device(tv_mgr);
647 tv_mgr->set_device(tv_mgr, dssdev);
648 mgr = tv_mgr;
649 }
650 }
651
652 if (mgr) {
653 for (i = 0; i < 3; i++) {
654 struct omap_overlay *ovl;
655 ovl = omap_dss_get_overlay(i);
656 if (!ovl->manager || force) {
657 if (ovl->manager)
658 omap_dss_unset_manager(ovl);
659 omap_dss_set_manager(ovl, mgr);
660 }
661 }
662 }
663}
664
665void dss_uninit_overlays(struct platform_device *pdev)
666{
667 struct omap_overlay *ovl;
668
669 while (!list_empty(&overlay_list)) {
670 ovl = list_first_entry(&overlay_list,
671 struct omap_overlay, list);
672 list_del(&ovl->list);
673 kobject_del(&ovl->kobj);
674 kobject_put(&ovl->kobj);
675 kfree(ovl);
676 }
677
678 num_overlays = 0;
679}
680
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
new file mode 100644
index 000000000000..d0b3006ad8a5
--- /dev/null
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -0,0 +1,1309 @@
1/*
2 * linux/drivers/video/omap2/dss/rfbi.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#define DSS_SUBSYS_NAME "RFBI"
24
25#include <linux/kernel.h>
26#include <linux/dma-mapping.h>
27#include <linux/vmalloc.h>
28#include <linux/clk.h>
29#include <linux/io.h>
30#include <linux/delay.h>
31#include <linux/kfifo.h>
32#include <linux/ktime.h>
33#include <linux/hrtimer.h>
34#include <linux/seq_file.h>
35
36#include <plat/display.h>
37#include "dss.h"
38
39/*#define MEASURE_PERF*/
40
41#define RFBI_BASE 0x48050800
42
43struct rfbi_reg { u16 idx; };
44
45#define RFBI_REG(idx) ((const struct rfbi_reg) { idx })
46
47#define RFBI_REVISION RFBI_REG(0x0000)
48#define RFBI_SYSCONFIG RFBI_REG(0x0010)
49#define RFBI_SYSSTATUS RFBI_REG(0x0014)
50#define RFBI_CONTROL RFBI_REG(0x0040)
51#define RFBI_PIXEL_CNT RFBI_REG(0x0044)
52#define RFBI_LINE_NUMBER RFBI_REG(0x0048)
53#define RFBI_CMD RFBI_REG(0x004c)
54#define RFBI_PARAM RFBI_REG(0x0050)
55#define RFBI_DATA RFBI_REG(0x0054)
56#define RFBI_READ RFBI_REG(0x0058)
57#define RFBI_STATUS RFBI_REG(0x005c)
58
59#define RFBI_CONFIG(n) RFBI_REG(0x0060 + (n)*0x18)
60#define RFBI_ONOFF_TIME(n) RFBI_REG(0x0064 + (n)*0x18)
61#define RFBI_CYCLE_TIME(n) RFBI_REG(0x0068 + (n)*0x18)
62#define RFBI_DATA_CYCLE1(n) RFBI_REG(0x006c + (n)*0x18)
63#define RFBI_DATA_CYCLE2(n) RFBI_REG(0x0070 + (n)*0x18)
64#define RFBI_DATA_CYCLE3(n) RFBI_REG(0x0074 + (n)*0x18)
65
66#define RFBI_VSYNC_WIDTH RFBI_REG(0x0090)
67#define RFBI_HSYNC_WIDTH RFBI_REG(0x0094)
68
69#define RFBI_CMD_FIFO_LEN_BYTES (16 * sizeof(struct update_param))
70
71#define REG_FLD_MOD(idx, val, start, end) \
72 rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end))
73
74/* To work around an RFBI transfer rate limitation */
75#define OMAP_RFBI_RATE_LIMIT 1
76
77enum omap_rfbi_cycleformat {
78 OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0,
79 OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1,
80 OMAP_DSS_RFBI_CYCLEFORMAT_3_1 = 2,
81 OMAP_DSS_RFBI_CYCLEFORMAT_3_2 = 3,
82};
83
84enum omap_rfbi_datatype {
85 OMAP_DSS_RFBI_DATATYPE_12 = 0,
86 OMAP_DSS_RFBI_DATATYPE_16 = 1,
87 OMAP_DSS_RFBI_DATATYPE_18 = 2,
88 OMAP_DSS_RFBI_DATATYPE_24 = 3,
89};
90
91enum omap_rfbi_parallelmode {
92 OMAP_DSS_RFBI_PARALLELMODE_8 = 0,
93 OMAP_DSS_RFBI_PARALLELMODE_9 = 1,
94 OMAP_DSS_RFBI_PARALLELMODE_12 = 2,
95 OMAP_DSS_RFBI_PARALLELMODE_16 = 3,
96};
97
98enum update_cmd {
99 RFBI_CMD_UPDATE = 0,
100 RFBI_CMD_SYNC = 1,
101};
102
103static int rfbi_convert_timings(struct rfbi_timings *t);
104static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div);
105static void process_cmd_fifo(void);
106
107static struct {
108 void __iomem *base;
109
110 unsigned long l4_khz;
111
112 enum omap_rfbi_datatype datatype;
113 enum omap_rfbi_parallelmode parallelmode;
114
115 enum omap_rfbi_te_mode te_mode;
116 int te_enabled;
117
118 void (*framedone_callback)(void *data);
119 void *framedone_callback_data;
120
121 struct omap_dss_device *dssdev[2];
122
123 struct kfifo *cmd_fifo;
124 spinlock_t cmd_lock;
125 struct completion cmd_done;
126 atomic_t cmd_fifo_full;
127 atomic_t cmd_pending;
128#ifdef MEASURE_PERF
129 unsigned perf_bytes;
130 ktime_t perf_setup_time;
131 ktime_t perf_start_time;
132#endif
133} rfbi;
134
135struct update_region {
136 u16 x;
137 u16 y;
138 u16 w;
139 u16 h;
140};
141
142struct update_param {
143 u8 rfbi_module;
144 u8 cmd;
145
146 union {
147 struct update_region r;
148 struct completion *sync;
149 } par;
150};
151
152static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
153{
154 __raw_writel(val, rfbi.base + idx.idx);
155}
156
157static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
158{
159 return __raw_readl(rfbi.base + idx.idx);
160}
161
162static void rfbi_enable_clocks(bool enable)
163{
164 if (enable)
165 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
166 else
167 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
168}
169
170void omap_rfbi_write_command(const void *buf, u32 len)
171{
172 rfbi_enable_clocks(1);
173 switch (rfbi.parallelmode) {
174 case OMAP_DSS_RFBI_PARALLELMODE_8:
175 {
176 const u8 *b = buf;
177 for (; len; len--)
178 rfbi_write_reg(RFBI_CMD, *b++);
179 break;
180 }
181
182 case OMAP_DSS_RFBI_PARALLELMODE_16:
183 {
184 const u16 *w = buf;
185 BUG_ON(len & 1);
186 for (; len; len -= 2)
187 rfbi_write_reg(RFBI_CMD, *w++);
188 break;
189 }
190
191 case OMAP_DSS_RFBI_PARALLELMODE_9:
192 case OMAP_DSS_RFBI_PARALLELMODE_12:
193 default:
194 BUG();
195 }
196 rfbi_enable_clocks(0);
197}
198EXPORT_SYMBOL(omap_rfbi_write_command);
199
200void omap_rfbi_read_data(void *buf, u32 len)
201{
202 rfbi_enable_clocks(1);
203 switch (rfbi.parallelmode) {
204 case OMAP_DSS_RFBI_PARALLELMODE_8:
205 {
206 u8 *b = buf;
207 for (; len; len--) {
208 rfbi_write_reg(RFBI_READ, 0);
209 *b++ = rfbi_read_reg(RFBI_READ);
210 }
211 break;
212 }
213
214 case OMAP_DSS_RFBI_PARALLELMODE_16:
215 {
216 u16 *w = buf;
217 BUG_ON(len & ~1);
218 for (; len; len -= 2) {
219 rfbi_write_reg(RFBI_READ, 0);
220 *w++ = rfbi_read_reg(RFBI_READ);
221 }
222 break;
223 }
224
225 case OMAP_DSS_RFBI_PARALLELMODE_9:
226 case OMAP_DSS_RFBI_PARALLELMODE_12:
227 default:
228 BUG();
229 }
230 rfbi_enable_clocks(0);
231}
232EXPORT_SYMBOL(omap_rfbi_read_data);
233
234void omap_rfbi_write_data(const void *buf, u32 len)
235{
236 rfbi_enable_clocks(1);
237 switch (rfbi.parallelmode) {
238 case OMAP_DSS_RFBI_PARALLELMODE_8:
239 {
240 const u8 *b = buf;
241 for (; len; len--)
242 rfbi_write_reg(RFBI_PARAM, *b++);
243 break;
244 }
245
246 case OMAP_DSS_RFBI_PARALLELMODE_16:
247 {
248 const u16 *w = buf;
249 BUG_ON(len & 1);
250 for (; len; len -= 2)
251 rfbi_write_reg(RFBI_PARAM, *w++);
252 break;
253 }
254
255 case OMAP_DSS_RFBI_PARALLELMODE_9:
256 case OMAP_DSS_RFBI_PARALLELMODE_12:
257 default:
258 BUG();
259
260 }
261 rfbi_enable_clocks(0);
262}
263EXPORT_SYMBOL(omap_rfbi_write_data);
264
265void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
266 u16 x, u16 y,
267 u16 w, u16 h)
268{
269 int start_offset = scr_width * y + x;
270 int horiz_offset = scr_width - w;
271 int i;
272
273 rfbi_enable_clocks(1);
274
275 if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
276 rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
277 const u16 __iomem *pd = buf;
278 pd += start_offset;
279
280 for (; h; --h) {
281 for (i = 0; i < w; ++i) {
282 const u8 __iomem *b = (const u8 __iomem *)pd;
283 rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
284 rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
285 ++pd;
286 }
287 pd += horiz_offset;
288 }
289 } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_24 &&
290 rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
291 const u32 __iomem *pd = buf;
292 pd += start_offset;
293
294 for (; h; --h) {
295 for (i = 0; i < w; ++i) {
296 const u8 __iomem *b = (const u8 __iomem *)pd;
297 rfbi_write_reg(RFBI_PARAM, __raw_readb(b+2));
298 rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
299 rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
300 ++pd;
301 }
302 pd += horiz_offset;
303 }
304 } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
305 rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_16) {
306 const u16 __iomem *pd = buf;
307 pd += start_offset;
308
309 for (; h; --h) {
310 for (i = 0; i < w; ++i) {
311 rfbi_write_reg(RFBI_PARAM, __raw_readw(pd));
312 ++pd;
313 }
314 pd += horiz_offset;
315 }
316 } else {
317 BUG();
318 }
319
320 rfbi_enable_clocks(0);
321}
322EXPORT_SYMBOL(omap_rfbi_write_pixels);
323
324#ifdef MEASURE_PERF
325static void perf_mark_setup(void)
326{
327 rfbi.perf_setup_time = ktime_get();
328}
329
330static void perf_mark_start(void)
331{
332 rfbi.perf_start_time = ktime_get();
333}
334
335static void perf_show(const char *name)
336{
337 ktime_t t, setup_time, trans_time;
338 u32 total_bytes;
339 u32 setup_us, trans_us, total_us;
340
341 t = ktime_get();
342
343 setup_time = ktime_sub(rfbi.perf_start_time, rfbi.perf_setup_time);
344 setup_us = (u32)ktime_to_us(setup_time);
345 if (setup_us == 0)
346 setup_us = 1;
347
348 trans_time = ktime_sub(t, rfbi.perf_start_time);
349 trans_us = (u32)ktime_to_us(trans_time);
350 if (trans_us == 0)
351 trans_us = 1;
352
353 total_us = setup_us + trans_us;
354
355 total_bytes = rfbi.perf_bytes;
356
357 DSSINFO("%s update %u us + %u us = %u us (%uHz), %u bytes, "
358 "%u kbytes/sec\n",
359 name,
360 setup_us,
361 trans_us,
362 total_us,
363 1000*1000 / total_us,
364 total_bytes,
365 total_bytes * 1000 / total_us);
366}
367#else
368#define perf_mark_setup()
369#define perf_mark_start()
370#define perf_show(x)
371#endif
372
373void rfbi_transfer_area(u16 width, u16 height,
374 void (callback)(void *data), void *data)
375{
376 u32 l;
377
378 /*BUG_ON(callback == 0);*/
379 BUG_ON(rfbi.framedone_callback != NULL);
380
381 DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
382
383 dispc_set_lcd_size(width, height);
384
385 dispc_enable_lcd_out(1);
386
387 rfbi.framedone_callback = callback;
388 rfbi.framedone_callback_data = data;
389
390 rfbi_enable_clocks(1);
391
392 rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
393
394 l = rfbi_read_reg(RFBI_CONTROL);
395 l = FLD_MOD(l, 1, 0, 0); /* enable */
396 if (!rfbi.te_enabled)
397 l = FLD_MOD(l, 1, 4, 4); /* ITE */
398
399 perf_mark_start();
400
401 rfbi_write_reg(RFBI_CONTROL, l);
402}
403
404static void framedone_callback(void *data, u32 mask)
405{
406 void (*callback)(void *data);
407
408 DSSDBG("FRAMEDONE\n");
409
410 perf_show("DISPC");
411
412 REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0);
413
414 rfbi_enable_clocks(0);
415
416 callback = rfbi.framedone_callback;
417 rfbi.framedone_callback = NULL;
418
419 /*callback(rfbi.framedone_callback_data);*/
420
421 atomic_set(&rfbi.cmd_pending, 0);
422
423 process_cmd_fifo();
424}
425
426#if 1 /* VERBOSE */
427static void rfbi_print_timings(void)
428{
429 u32 l;
430 u32 time;
431
432 l = rfbi_read_reg(RFBI_CONFIG(0));
433 time = 1000000000 / rfbi.l4_khz;
434 if (l & (1 << 4))
435 time *= 2;
436
437 DSSDBG("Tick time %u ps\n", time);
438 l = rfbi_read_reg(RFBI_ONOFF_TIME(0));
439 DSSDBG("CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
440 "REONTIME %d, REOFFTIME %d\n",
441 l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
442 (l >> 20) & 0x0f, (l >> 24) & 0x3f);
443
444 l = rfbi_read_reg(RFBI_CYCLE_TIME(0));
445 DSSDBG("WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
446 "ACCESSTIME %d\n",
447 (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f,
448 (l >> 22) & 0x3f);
449}
450#else
451static void rfbi_print_timings(void) {}
452#endif
453
454
455
456
457static u32 extif_clk_period;
458
459static inline unsigned long round_to_extif_ticks(unsigned long ps, int div)
460{
461 int bus_tick = extif_clk_period * div;
462 return (ps + bus_tick - 1) / bus_tick * bus_tick;
463}
464
465static int calc_reg_timing(struct rfbi_timings *t, int div)
466{
467 t->clk_div = div;
468
469 t->cs_on_time = round_to_extif_ticks(t->cs_on_time, div);
470
471 t->we_on_time = round_to_extif_ticks(t->we_on_time, div);
472 t->we_off_time = round_to_extif_ticks(t->we_off_time, div);
473 t->we_cycle_time = round_to_extif_ticks(t->we_cycle_time, div);
474
475 t->re_on_time = round_to_extif_ticks(t->re_on_time, div);
476 t->re_off_time = round_to_extif_ticks(t->re_off_time, div);
477 t->re_cycle_time = round_to_extif_ticks(t->re_cycle_time, div);
478
479 t->access_time = round_to_extif_ticks(t->access_time, div);
480 t->cs_off_time = round_to_extif_ticks(t->cs_off_time, div);
481 t->cs_pulse_width = round_to_extif_ticks(t->cs_pulse_width, div);
482
483 DSSDBG("[reg]cson %d csoff %d reon %d reoff %d\n",
484 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
485 DSSDBG("[reg]weon %d weoff %d recyc %d wecyc %d\n",
486 t->we_on_time, t->we_off_time, t->re_cycle_time,
487 t->we_cycle_time);
488 DSSDBG("[reg]rdaccess %d cspulse %d\n",
489 t->access_time, t->cs_pulse_width);
490
491 return rfbi_convert_timings(t);
492}
493
494static int calc_extif_timings(struct rfbi_timings *t)
495{
496 u32 max_clk_div;
497 int div;
498
499 rfbi_get_clk_info(&extif_clk_period, &max_clk_div);
500 for (div = 1; div <= max_clk_div; div++) {
501 if (calc_reg_timing(t, div) == 0)
502 break;
503 }
504
505 if (div <= max_clk_div)
506 return 0;
507
508 DSSERR("can't setup timings\n");
509 return -1;
510}
511
512
513void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t)
514{
515 int r;
516
517 if (!t->converted) {
518 r = calc_extif_timings(t);
519 if (r < 0)
520 DSSERR("Failed to calc timings\n");
521 }
522
523 BUG_ON(!t->converted);
524
525 rfbi_enable_clocks(1);
526 rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]);
527 rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]);
528
529 /* TIMEGRANULARITY */
530 REG_FLD_MOD(RFBI_CONFIG(rfbi_module),
531 (t->tim[2] ? 1 : 0), 4, 4);
532
533 rfbi_print_timings();
534 rfbi_enable_clocks(0);
535}
536
537static int ps_to_rfbi_ticks(int time, int div)
538{
539 unsigned long tick_ps;
540 int ret;
541
542 /* Calculate in picosecs to yield more exact results */
543 tick_ps = 1000000000 / (rfbi.l4_khz) * div;
544
545 ret = (time + tick_ps - 1) / tick_ps;
546
547 return ret;
548}
549
550#ifdef OMAP_RFBI_RATE_LIMIT
551unsigned long rfbi_get_max_tx_rate(void)
552{
553 unsigned long l4_rate, dss1_rate;
554 int min_l4_ticks = 0;
555 int i;
556
557 /* According to TI this can't be calculated so make the
558 * adjustments for a couple of known frequencies and warn for
559 * others.
560 */
561 static const struct {
562 unsigned long l4_clk; /* HZ */
563 unsigned long dss1_clk; /* HZ */
564 unsigned long min_l4_ticks;
565 } ftab[] = {
566 { 55, 132, 7, }, /* 7.86 MPix/s */
567 { 110, 110, 12, }, /* 9.16 MPix/s */
568 { 110, 132, 10, }, /* 11 Mpix/s */
569 { 120, 120, 10, }, /* 12 Mpix/s */
570 { 133, 133, 10, }, /* 13.3 Mpix/s */
571 };
572
573 l4_rate = rfbi.l4_khz / 1000;
574 dss1_rate = dss_clk_get_rate(DSS_CLK_FCK1) / 1000000;
575
576 for (i = 0; i < ARRAY_SIZE(ftab); i++) {
577 /* Use a window instead of an exact match, to account
578 * for different DPLL multiplier / divider pairs.
579 */
580 if (abs(ftab[i].l4_clk - l4_rate) < 3 &&
581 abs(ftab[i].dss1_clk - dss1_rate) < 3) {
582 min_l4_ticks = ftab[i].min_l4_ticks;
583 break;
584 }
585 }
586 if (i == ARRAY_SIZE(ftab)) {
587 /* Can't be sure, return anyway the maximum not
588 * rate-limited. This might cause a problem only for the
589 * tearing synchronisation.
590 */
591 DSSERR("can't determine maximum RFBI transfer rate\n");
592 return rfbi.l4_khz * 1000;
593 }
594 return rfbi.l4_khz * 1000 / min_l4_ticks;
595}
596#else
597int rfbi_get_max_tx_rate(void)
598{
599 return rfbi.l4_khz * 1000;
600}
601#endif
602
603static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
604{
605 *clk_period = 1000000000 / rfbi.l4_khz;
606 *max_clk_div = 2;
607}
608
609static int rfbi_convert_timings(struct rfbi_timings *t)
610{
611 u32 l;
612 int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
613 int actim, recyc, wecyc;
614 int div = t->clk_div;
615
616 if (div <= 0 || div > 2)
617 return -1;
618
619 /* Make sure that after conversion it still holds that:
620 * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff,
621 * csoff > cson, csoff >= max(weoff, reoff), actim > reon
622 */
623 weon = ps_to_rfbi_ticks(t->we_on_time, div);
624 weoff = ps_to_rfbi_ticks(t->we_off_time, div);
625 if (weoff <= weon)
626 weoff = weon + 1;
627 if (weon > 0x0f)
628 return -1;
629 if (weoff > 0x3f)
630 return -1;
631
632 reon = ps_to_rfbi_ticks(t->re_on_time, div);
633 reoff = ps_to_rfbi_ticks(t->re_off_time, div);
634 if (reoff <= reon)
635 reoff = reon + 1;
636 if (reon > 0x0f)
637 return -1;
638 if (reoff > 0x3f)
639 return -1;
640
641 cson = ps_to_rfbi_ticks(t->cs_on_time, div);
642 csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
643 if (csoff <= cson)
644 csoff = cson + 1;
645 if (csoff < max(weoff, reoff))
646 csoff = max(weoff, reoff);
647 if (cson > 0x0f)
648 return -1;
649 if (csoff > 0x3f)
650 return -1;
651
652 l = cson;
653 l |= csoff << 4;
654 l |= weon << 10;
655 l |= weoff << 14;
656 l |= reon << 20;
657 l |= reoff << 24;
658
659 t->tim[0] = l;
660
661 actim = ps_to_rfbi_ticks(t->access_time, div);
662 if (actim <= reon)
663 actim = reon + 1;
664 if (actim > 0x3f)
665 return -1;
666
667 wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
668 if (wecyc < weoff)
669 wecyc = weoff;
670 if (wecyc > 0x3f)
671 return -1;
672
673 recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
674 if (recyc < reoff)
675 recyc = reoff;
676 if (recyc > 0x3f)
677 return -1;
678
679 cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
680 if (cs_pulse > 0x3f)
681 return -1;
682
683 l = wecyc;
684 l |= recyc << 6;
685 l |= cs_pulse << 12;
686 l |= actim << 22;
687
688 t->tim[1] = l;
689
690 t->tim[2] = div - 1;
691
692 t->converted = 1;
693
694 return 0;
695}
696
697/* xxx FIX module selection missing */
698int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
699 unsigned hs_pulse_time, unsigned vs_pulse_time,
700 int hs_pol_inv, int vs_pol_inv, int extif_div)
701{
702 int hs, vs;
703 int min;
704 u32 l;
705
706 hs = ps_to_rfbi_ticks(hs_pulse_time, 1);
707 vs = ps_to_rfbi_ticks(vs_pulse_time, 1);
708 if (hs < 2)
709 return -EDOM;
710 if (mode == OMAP_DSS_RFBI_TE_MODE_2)
711 min = 2;
712 else /* OMAP_DSS_RFBI_TE_MODE_1 */
713 min = 4;
714 if (vs < min)
715 return -EDOM;
716 if (vs == hs)
717 return -EINVAL;
718 rfbi.te_mode = mode;
719 DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n",
720 mode, hs, vs, hs_pol_inv, vs_pol_inv);
721
722 rfbi_enable_clocks(1);
723 rfbi_write_reg(RFBI_HSYNC_WIDTH, hs);
724 rfbi_write_reg(RFBI_VSYNC_WIDTH, vs);
725
726 l = rfbi_read_reg(RFBI_CONFIG(0));
727 if (hs_pol_inv)
728 l &= ~(1 << 21);
729 else
730 l |= 1 << 21;
731 if (vs_pol_inv)
732 l &= ~(1 << 20);
733 else
734 l |= 1 << 20;
735 rfbi_enable_clocks(0);
736
737 return 0;
738}
739EXPORT_SYMBOL(omap_rfbi_setup_te);
740
741/* xxx FIX module selection missing */
742int omap_rfbi_enable_te(bool enable, unsigned line)
743{
744 u32 l;
745
746 DSSDBG("te %d line %d mode %d\n", enable, line, rfbi.te_mode);
747 if (line > (1 << 11) - 1)
748 return -EINVAL;
749
750 rfbi_enable_clocks(1);
751 l = rfbi_read_reg(RFBI_CONFIG(0));
752 l &= ~(0x3 << 2);
753 if (enable) {
754 rfbi.te_enabled = 1;
755 l |= rfbi.te_mode << 2;
756 } else
757 rfbi.te_enabled = 0;
758 rfbi_write_reg(RFBI_CONFIG(0), l);
759 rfbi_write_reg(RFBI_LINE_NUMBER, line);
760 rfbi_enable_clocks(0);
761
762 return 0;
763}
764EXPORT_SYMBOL(omap_rfbi_enable_te);
765
766#if 0
767static void rfbi_enable_config(int enable1, int enable2)
768{
769 u32 l;
770 int cs = 0;
771
772 if (enable1)
773 cs |= 1<<0;
774 if (enable2)
775 cs |= 1<<1;
776
777 rfbi_enable_clocks(1);
778
779 l = rfbi_read_reg(RFBI_CONTROL);
780
781 l = FLD_MOD(l, cs, 3, 2);
782 l = FLD_MOD(l, 0, 1, 1);
783
784 rfbi_write_reg(RFBI_CONTROL, l);
785
786
787 l = rfbi_read_reg(RFBI_CONFIG(0));
788 l = FLD_MOD(l, 0, 3, 2); /* TRIGGERMODE: ITE */
789 /*l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */
790 /*l |= FLD_VAL(0, 8, 7); */ /* L4FORMAT, 1pix/L4 */
791
792 l = FLD_MOD(l, 0, 16, 16); /* A0POLARITY */
793 l = FLD_MOD(l, 1, 20, 20); /* TE_VSYNC_POLARITY */
794 l = FLD_MOD(l, 1, 21, 21); /* HSYNCPOLARITY */
795
796 l = FLD_MOD(l, OMAP_DSS_RFBI_PARALLELMODE_8, 1, 0);
797 rfbi_write_reg(RFBI_CONFIG(0), l);
798
799 rfbi_enable_clocks(0);
800}
801#endif
802
803int rfbi_configure(int rfbi_module, int bpp, int lines)
804{
805 u32 l;
806 int cycle1 = 0, cycle2 = 0, cycle3 = 0;
807 enum omap_rfbi_cycleformat cycleformat;
808 enum omap_rfbi_datatype datatype;
809 enum omap_rfbi_parallelmode parallelmode;
810
811 switch (bpp) {
812 case 12:
813 datatype = OMAP_DSS_RFBI_DATATYPE_12;
814 break;
815 case 16:
816 datatype = OMAP_DSS_RFBI_DATATYPE_16;
817 break;
818 case 18:
819 datatype = OMAP_DSS_RFBI_DATATYPE_18;
820 break;
821 case 24:
822 datatype = OMAP_DSS_RFBI_DATATYPE_24;
823 break;
824 default:
825 BUG();
826 return 1;
827 }
828 rfbi.datatype = datatype;
829
830 switch (lines) {
831 case 8:
832 parallelmode = OMAP_DSS_RFBI_PARALLELMODE_8;
833 break;
834 case 9:
835 parallelmode = OMAP_DSS_RFBI_PARALLELMODE_9;
836 break;
837 case 12:
838 parallelmode = OMAP_DSS_RFBI_PARALLELMODE_12;
839 break;
840 case 16:
841 parallelmode = OMAP_DSS_RFBI_PARALLELMODE_16;
842 break;
843 default:
844 BUG();
845 return 1;
846 }
847 rfbi.parallelmode = parallelmode;
848
849 if ((bpp % lines) == 0) {
850 switch (bpp / lines) {
851 case 1:
852 cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_1_1;
853 break;
854 case 2:
855 cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_2_1;
856 break;
857 case 3:
858 cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_1;
859 break;
860 default:
861 BUG();
862 return 1;
863 }
864 } else if ((2 * bpp % lines) == 0) {
865 if ((2 * bpp / lines) == 3)
866 cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_2;
867 else {
868 BUG();
869 return 1;
870 }
871 } else {
872 BUG();
873 return 1;
874 }
875
876 switch (cycleformat) {
877 case OMAP_DSS_RFBI_CYCLEFORMAT_1_1:
878 cycle1 = lines;
879 break;
880
881 case OMAP_DSS_RFBI_CYCLEFORMAT_2_1:
882 cycle1 = lines;
883 cycle2 = lines;
884 break;
885
886 case OMAP_DSS_RFBI_CYCLEFORMAT_3_1:
887 cycle1 = lines;
888 cycle2 = lines;
889 cycle3 = lines;
890 break;
891
892 case OMAP_DSS_RFBI_CYCLEFORMAT_3_2:
893 cycle1 = lines;
894 cycle2 = (lines / 2) | ((lines / 2) << 16);
895 cycle3 = (lines << 16);
896 break;
897 }
898
899 rfbi_enable_clocks(1);
900
901 REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */
902
903 l = 0;
904 l |= FLD_VAL(parallelmode, 1, 0);
905 l |= FLD_VAL(0, 3, 2); /* TRIGGERMODE: ITE */
906 l |= FLD_VAL(0, 4, 4); /* TIMEGRANULARITY */
907 l |= FLD_VAL(datatype, 6, 5);
908 /* l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */
909 l |= FLD_VAL(0, 8, 7); /* L4FORMAT, 1pix/L4 */
910 l |= FLD_VAL(cycleformat, 10, 9);
911 l |= FLD_VAL(0, 12, 11); /* UNUSEDBITS */
912 l |= FLD_VAL(0, 16, 16); /* A0POLARITY */
913 l |= FLD_VAL(0, 17, 17); /* REPOLARITY */
914 l |= FLD_VAL(0, 18, 18); /* WEPOLARITY */
915 l |= FLD_VAL(0, 19, 19); /* CSPOLARITY */
916 l |= FLD_VAL(1, 20, 20); /* TE_VSYNC_POLARITY */
917 l |= FLD_VAL(1, 21, 21); /* HSYNCPOLARITY */
918 rfbi_write_reg(RFBI_CONFIG(rfbi_module), l);
919
920 rfbi_write_reg(RFBI_DATA_CYCLE1(rfbi_module), cycle1);
921 rfbi_write_reg(RFBI_DATA_CYCLE2(rfbi_module), cycle2);
922 rfbi_write_reg(RFBI_DATA_CYCLE3(rfbi_module), cycle3);
923
924
925 l = rfbi_read_reg(RFBI_CONTROL);
926 l = FLD_MOD(l, rfbi_module+1, 3, 2); /* Select CSx */
927 l = FLD_MOD(l, 0, 1, 1); /* clear bypass */
928 rfbi_write_reg(RFBI_CONTROL, l);
929
930
931 DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n",
932 bpp, lines, cycle1, cycle2, cycle3);
933
934 rfbi_enable_clocks(0);
935
936 return 0;
937}
938EXPORT_SYMBOL(rfbi_configure);
939
940static int rfbi_find_display(struct omap_dss_device *dssdev)
941{
942 if (dssdev == rfbi.dssdev[0])
943 return 0;
944
945 if (dssdev == rfbi.dssdev[1])
946 return 1;
947
948 BUG();
949 return -1;
950}
951
952
953static void signal_fifo_waiters(void)
954{
955 if (atomic_read(&rfbi.cmd_fifo_full) > 0) {
956 /* DSSDBG("SIGNALING: Fifo not full for waiter!\n"); */
957 complete(&rfbi.cmd_done);
958 atomic_dec(&rfbi.cmd_fifo_full);
959 }
960}
961
962/* returns 1 for async op, and 0 for sync op */
963static int do_update(struct omap_dss_device *dssdev, struct update_region *upd)
964{
965 u16 x = upd->x;
966 u16 y = upd->y;
967 u16 w = upd->w;
968 u16 h = upd->h;
969
970 perf_mark_setup();
971
972 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
973 /*dssdev->driver->enable_te(dssdev, 1); */
974 dss_setup_partial_planes(dssdev, &x, &y, &w, &h);
975 }
976
977#ifdef MEASURE_PERF
978 rfbi.perf_bytes = w * h * 2; /* XXX always 16bit */
979#endif
980
981 dssdev->driver->setup_update(dssdev, x, y, w, h);
982
983 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
984 rfbi_transfer_area(w, h, NULL, NULL);
985 return 1;
986 } else {
987 struct omap_overlay *ovl;
988 void __iomem *addr;
989 int scr_width;
990
991 ovl = dssdev->manager->overlays[0];
992 scr_width = ovl->info.screen_width;
993 addr = ovl->info.vaddr;
994
995 omap_rfbi_write_pixels(addr, scr_width, x, y, w, h);
996
997 perf_show("L4");
998
999 return 0;
1000 }
1001}
1002
1003static void process_cmd_fifo(void)
1004{
1005 int len;
1006 struct update_param p;
1007 struct omap_dss_device *dssdev;
1008 unsigned long flags;
1009
1010 if (atomic_inc_return(&rfbi.cmd_pending) != 1)
1011 return;
1012
1013 while (true) {
1014 spin_lock_irqsave(rfbi.cmd_fifo->lock, flags);
1015
1016 len = __kfifo_get(rfbi.cmd_fifo, (unsigned char *)&p,
1017 sizeof(struct update_param));
1018 if (len == 0) {
1019 DSSDBG("nothing more in fifo\n");
1020 atomic_set(&rfbi.cmd_pending, 0);
1021 spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
1022 break;
1023 }
1024
1025 /* DSSDBG("fifo full %d\n", rfbi.cmd_fifo_full.counter);*/
1026
1027 spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
1028
1029 BUG_ON(len != sizeof(struct update_param));
1030 BUG_ON(p.rfbi_module > 1);
1031
1032 dssdev = rfbi.dssdev[p.rfbi_module];
1033
1034 if (p.cmd == RFBI_CMD_UPDATE) {
1035 if (do_update(dssdev, &p.par.r))
1036 break; /* async op */
1037 } else if (p.cmd == RFBI_CMD_SYNC) {
1038 DSSDBG("Signaling SYNC done!\n");
1039 complete(p.par.sync);
1040 } else
1041 BUG();
1042 }
1043
1044 signal_fifo_waiters();
1045}
1046
1047static void rfbi_push_cmd(struct update_param *p)
1048{
1049 int ret;
1050
1051 while (1) {
1052 unsigned long flags;
1053 int available;
1054
1055 spin_lock_irqsave(rfbi.cmd_fifo->lock, flags);
1056 available = RFBI_CMD_FIFO_LEN_BYTES -
1057 __kfifo_len(rfbi.cmd_fifo);
1058
1059/* DSSDBG("%d bytes left in fifo\n", available); */
1060 if (available < sizeof(struct update_param)) {
1061 DSSDBG("Going to wait because FIFO FULL..\n");
1062 spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
1063 atomic_inc(&rfbi.cmd_fifo_full);
1064 wait_for_completion(&rfbi.cmd_done);
1065 /*DSSDBG("Woke up because fifo not full anymore\n");*/
1066 continue;
1067 }
1068
1069 ret = __kfifo_put(rfbi.cmd_fifo, (unsigned char *)p,
1070 sizeof(struct update_param));
1071/* DSSDBG("pushed %d bytes\n", ret);*/
1072
1073 spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
1074
1075 BUG_ON(ret != sizeof(struct update_param));
1076
1077 break;
1078 }
1079}
1080
1081static void rfbi_push_update(int rfbi_module, int x, int y, int w, int h)
1082{
1083 struct update_param p;
1084
1085 p.rfbi_module = rfbi_module;
1086 p.cmd = RFBI_CMD_UPDATE;
1087
1088 p.par.r.x = x;
1089 p.par.r.y = y;
1090 p.par.r.w = w;
1091 p.par.r.h = h;
1092
1093 DSSDBG("RFBI pushed %d,%d %dx%d\n", x, y, w, h);
1094
1095 rfbi_push_cmd(&p);
1096
1097 process_cmd_fifo();
1098}
1099
1100static void rfbi_push_sync(int rfbi_module, struct completion *sync_comp)
1101{
1102 struct update_param p;
1103
1104 p.rfbi_module = rfbi_module;
1105 p.cmd = RFBI_CMD_SYNC;
1106 p.par.sync = sync_comp;
1107
1108 rfbi_push_cmd(&p);
1109
1110 DSSDBG("RFBI sync pushed to cmd fifo\n");
1111
1112 process_cmd_fifo();
1113}
1114
1115void rfbi_dump_regs(struct seq_file *s)
1116{
1117#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
1118
1119 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
1120
1121 DUMPREG(RFBI_REVISION);
1122 DUMPREG(RFBI_SYSCONFIG);
1123 DUMPREG(RFBI_SYSSTATUS);
1124 DUMPREG(RFBI_CONTROL);
1125 DUMPREG(RFBI_PIXEL_CNT);
1126 DUMPREG(RFBI_LINE_NUMBER);
1127 DUMPREG(RFBI_CMD);
1128 DUMPREG(RFBI_PARAM);
1129 DUMPREG(RFBI_DATA);
1130 DUMPREG(RFBI_READ);
1131 DUMPREG(RFBI_STATUS);
1132
1133 DUMPREG(RFBI_CONFIG(0));
1134 DUMPREG(RFBI_ONOFF_TIME(0));
1135 DUMPREG(RFBI_CYCLE_TIME(0));
1136 DUMPREG(RFBI_DATA_CYCLE1(0));
1137 DUMPREG(RFBI_DATA_CYCLE2(0));
1138 DUMPREG(RFBI_DATA_CYCLE3(0));
1139
1140 DUMPREG(RFBI_CONFIG(1));
1141 DUMPREG(RFBI_ONOFF_TIME(1));
1142 DUMPREG(RFBI_CYCLE_TIME(1));
1143 DUMPREG(RFBI_DATA_CYCLE1(1));
1144 DUMPREG(RFBI_DATA_CYCLE2(1));
1145 DUMPREG(RFBI_DATA_CYCLE3(1));
1146
1147 DUMPREG(RFBI_VSYNC_WIDTH);
1148 DUMPREG(RFBI_HSYNC_WIDTH);
1149
1150 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
1151#undef DUMPREG
1152}
1153
1154int rfbi_init(void)
1155{
1156 u32 rev;
1157 u32 l;
1158
1159 spin_lock_init(&rfbi.cmd_lock);
1160 rfbi.cmd_fifo = kfifo_alloc(RFBI_CMD_FIFO_LEN_BYTES, GFP_KERNEL,
1161 &rfbi.cmd_lock);
1162 if (IS_ERR(rfbi.cmd_fifo))
1163 return -ENOMEM;
1164
1165 init_completion(&rfbi.cmd_done);
1166 atomic_set(&rfbi.cmd_fifo_full, 0);
1167 atomic_set(&rfbi.cmd_pending, 0);
1168
1169 rfbi.base = ioremap(RFBI_BASE, SZ_256);
1170 if (!rfbi.base) {
1171 DSSERR("can't ioremap RFBI\n");
1172 return -ENOMEM;
1173 }
1174
1175 rfbi_enable_clocks(1);
1176
1177 msleep(10);
1178
1179 rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
1180
1181 /* Enable autoidle and smart-idle */
1182 l = rfbi_read_reg(RFBI_SYSCONFIG);
1183 l |= (1 << 0) | (2 << 3);
1184 rfbi_write_reg(RFBI_SYSCONFIG, l);
1185
1186 rev = rfbi_read_reg(RFBI_REVISION);
1187 printk(KERN_INFO "OMAP RFBI rev %d.%d\n",
1188 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
1189
1190 rfbi_enable_clocks(0);
1191
1192 return 0;
1193}
1194
1195void rfbi_exit(void)
1196{
1197 DSSDBG("rfbi_exit\n");
1198
1199 kfifo_free(rfbi.cmd_fifo);
1200
1201 iounmap(rfbi.base);
1202}
1203
1204/* struct omap_display support */
1205static int rfbi_display_update(struct omap_dss_device *dssdev,
1206 u16 x, u16 y, u16 w, u16 h)
1207{
1208 int rfbi_module;
1209
1210 if (w == 0 || h == 0)
1211 return 0;
1212
1213 rfbi_module = rfbi_find_display(dssdev);
1214
1215 rfbi_push_update(rfbi_module, x, y, w, h);
1216
1217 return 0;
1218}
1219
1220static int rfbi_display_sync(struct omap_dss_device *dssdev)
1221{
1222 struct completion sync_comp;
1223 int rfbi_module;
1224
1225 rfbi_module = rfbi_find_display(dssdev);
1226
1227 init_completion(&sync_comp);
1228 rfbi_push_sync(rfbi_module, &sync_comp);
1229 DSSDBG("Waiting for SYNC to happen...\n");
1230 wait_for_completion(&sync_comp);
1231 DSSDBG("Released from SYNC\n");
1232 return 0;
1233}
1234
1235static int rfbi_display_enable_te(struct omap_dss_device *dssdev, bool enable)
1236{
1237 dssdev->driver->enable_te(dssdev, enable);
1238 return 0;
1239}
1240
1241static int rfbi_display_enable(struct omap_dss_device *dssdev)
1242{
1243 int r;
1244
1245 r = omap_dss_start_device(dssdev);
1246 if (r) {
1247 DSSERR("failed to start device\n");
1248 goto err0;
1249 }
1250
1251 r = omap_dispc_register_isr(framedone_callback, NULL,
1252 DISPC_IRQ_FRAMEDONE);
1253 if (r) {
1254 DSSERR("can't get FRAMEDONE irq\n");
1255 goto err1;
1256 }
1257
1258 dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
1259
1260 dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_RFBI);
1261
1262 dispc_set_tft_data_lines(dssdev->ctrl.pixel_size);
1263
1264 rfbi_configure(dssdev->phy.rfbi.channel,
1265 dssdev->ctrl.pixel_size,
1266 dssdev->phy.rfbi.data_lines);
1267
1268 rfbi_set_timings(dssdev->phy.rfbi.channel,
1269 &dssdev->ctrl.rfbi_timings);
1270
1271
1272 if (dssdev->driver->enable) {
1273 r = dssdev->driver->enable(dssdev);
1274 if (r)
1275 goto err2;
1276 }
1277
1278 return 0;
1279err2:
1280 omap_dispc_unregister_isr(framedone_callback, NULL,
1281 DISPC_IRQ_FRAMEDONE);
1282err1:
1283 omap_dss_stop_device(dssdev);
1284err0:
1285 return r;
1286}
1287
1288static void rfbi_display_disable(struct omap_dss_device *dssdev)
1289{
1290 dssdev->driver->disable(dssdev);
1291 omap_dispc_unregister_isr(framedone_callback, NULL,
1292 DISPC_IRQ_FRAMEDONE);
1293 omap_dss_stop_device(dssdev);
1294}
1295
1296int rfbi_init_display(struct omap_dss_device *dssdev)
1297{
1298 dssdev->enable = rfbi_display_enable;
1299 dssdev->disable = rfbi_display_disable;
1300 dssdev->update = rfbi_display_update;
1301 dssdev->sync = rfbi_display_sync;
1302 dssdev->enable_te = rfbi_display_enable_te;
1303
1304 rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
1305
1306 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
1307
1308 return 0;
1309}
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
new file mode 100644
index 000000000000..c24f307d3da1
--- /dev/null
+++ b/drivers/video/omap2/dss/sdi.c
@@ -0,0 +1,277 @@
1/*
2 * linux/drivers/video/omap2/dss/sdi.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#define DSS_SUBSYS_NAME "SDI"
21
22#include <linux/kernel.h>
23#include <linux/clk.h>
24#include <linux/delay.h>
25#include <linux/err.h>
26
27#include <plat/display.h>
28#include "dss.h"
29
30static struct {
31 bool skip_init;
32 bool update_enabled;
33} sdi;
34
35static void sdi_basic_init(void)
36{
37 dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
38
39 dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
40 dispc_set_tft_data_lines(24);
41 dispc_lcd_enable_signal_polarity(1);
42}
43
44static int sdi_display_enable(struct omap_dss_device *dssdev)
45{
46 struct omap_video_timings *t = &dssdev->panel.timings;
47 struct dss_clock_info dss_cinfo;
48 struct dispc_clock_info dispc_cinfo;
49 u16 lck_div, pck_div;
50 unsigned long fck;
51 unsigned long pck;
52 int r;
53
54 r = omap_dss_start_device(dssdev);
55 if (r) {
56 DSSERR("failed to start device\n");
57 goto err0;
58 }
59
60 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
61 DSSERR("dssdev already enabled\n");
62 r = -EINVAL;
63 goto err1;
64 }
65
66 /* In case of skip_init sdi_init has already enabled the clocks */
67 if (!sdi.skip_init)
68 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
69
70 sdi_basic_init();
71
72 /* 15.5.9.1.2 */
73 dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;
74
75 dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi,
76 dssdev->panel.acb);
77
78 if (!sdi.skip_init) {
79 r = dss_calc_clock_div(1, t->pixel_clock * 1000,
80 &dss_cinfo, &dispc_cinfo);
81 } else {
82 r = dss_get_clock_div(&dss_cinfo);
83 r = dispc_get_clock_div(&dispc_cinfo);
84 }
85
86 if (r)
87 goto err2;
88
89 fck = dss_cinfo.fck;
90 lck_div = dispc_cinfo.lck_div;
91 pck_div = dispc_cinfo.pck_div;
92
93 pck = fck / lck_div / pck_div / 1000;
94
95 if (pck != t->pixel_clock) {
96 DSSWARN("Could not find exact pixel clock. Requested %d kHz, "
97 "got %lu kHz\n",
98 t->pixel_clock, pck);
99
100 t->pixel_clock = pck;
101 }
102
103
104 dispc_set_lcd_timings(t);
105
106 r = dss_set_clock_div(&dss_cinfo);
107 if (r)
108 goto err2;
109
110 r = dispc_set_clock_div(&dispc_cinfo);
111 if (r)
112 goto err2;
113
114 if (!sdi.skip_init) {
115 dss_sdi_init(dssdev->phy.sdi.datapairs);
116 r = dss_sdi_enable();
117 if (r)
118 goto err1;
119 mdelay(2);
120 }
121
122 dispc_enable_lcd_out(1);
123
124 if (dssdev->driver->enable) {
125 r = dssdev->driver->enable(dssdev);
126 if (r)
127 goto err3;
128 }
129
130 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
131
132 sdi.skip_init = 0;
133
134 return 0;
135err3:
136 dispc_enable_lcd_out(0);
137err2:
138 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
139err1:
140 omap_dss_stop_device(dssdev);
141err0:
142 return r;
143}
144
145static int sdi_display_resume(struct omap_dss_device *dssdev);
146
147static void sdi_display_disable(struct omap_dss_device *dssdev)
148{
149 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
150 return;
151
152 if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
153 if (sdi_display_resume(dssdev))
154 return;
155
156 if (dssdev->driver->disable)
157 dssdev->driver->disable(dssdev);
158
159 dispc_enable_lcd_out(0);
160
161 dss_sdi_disable();
162
163 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
164
165 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
166
167 omap_dss_stop_device(dssdev);
168}
169
170static int sdi_display_suspend(struct omap_dss_device *dssdev)
171{
172 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
173 return -EINVAL;
174
175 if (dssdev->driver->suspend)
176 dssdev->driver->suspend(dssdev);
177
178 dispc_enable_lcd_out(0);
179
180 dss_sdi_disable();
181
182 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
183
184 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
185
186 return 0;
187}
188
189static int sdi_display_resume(struct omap_dss_device *dssdev)
190{
191 int r;
192
193 if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
194 return -EINVAL;
195
196 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
197
198 r = dss_sdi_enable();
199 if (r)
200 goto err;
201 mdelay(2);
202
203 dispc_enable_lcd_out(1);
204
205 if (dssdev->driver->resume)
206 dssdev->driver->resume(dssdev);
207
208 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
209
210 return 0;
211err:
212 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
213 return r;
214}
215
216static int sdi_display_set_update_mode(struct omap_dss_device *dssdev,
217 enum omap_dss_update_mode mode)
218{
219 if (mode == OMAP_DSS_UPDATE_MANUAL)
220 return -EINVAL;
221
222 if (mode == OMAP_DSS_UPDATE_DISABLED) {
223 dispc_enable_lcd_out(0);
224 sdi.update_enabled = 0;
225 } else {
226 dispc_enable_lcd_out(1);
227 sdi.update_enabled = 1;
228 }
229
230 return 0;
231}
232
233static enum omap_dss_update_mode sdi_display_get_update_mode(
234 struct omap_dss_device *dssdev)
235{
236 return sdi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
237 OMAP_DSS_UPDATE_DISABLED;
238}
239
240static void sdi_get_timings(struct omap_dss_device *dssdev,
241 struct omap_video_timings *timings)
242{
243 *timings = dssdev->panel.timings;
244}
245
246int sdi_init_display(struct omap_dss_device *dssdev)
247{
248 DSSDBG("SDI init\n");
249
250 dssdev->enable = sdi_display_enable;
251 dssdev->disable = sdi_display_disable;
252 dssdev->suspend = sdi_display_suspend;
253 dssdev->resume = sdi_display_resume;
254 dssdev->set_update_mode = sdi_display_set_update_mode;
255 dssdev->get_update_mode = sdi_display_get_update_mode;
256 dssdev->get_timings = sdi_get_timings;
257
258 return 0;
259}
260
261int sdi_init(bool skip_init)
262{
263 /* we store this for first display enable, then clear it */
264 sdi.skip_init = skip_init;
265
266 /*
267 * Enable clocks already here, otherwise there would be a toggle
268 * of them until sdi_display_enable is called.
269 */
270 if (skip_init)
271 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
272 return 0;
273}
274
275void sdi_exit(void)
276{
277}
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
new file mode 100644
index 000000000000..749a5a0f5be4
--- /dev/null
+++ b/drivers/video/omap2/dss/venc.c
@@ -0,0 +1,797 @@
1/*
2 * linux/drivers/video/omap2/dss/venc.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * VENC settings from TI's DSS driver
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published by
11 * the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#define DSS_SUBSYS_NAME "VENC"
23
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/clk.h>
27#include <linux/err.h>
28#include <linux/io.h>
29#include <linux/mutex.h>
30#include <linux/completion.h>
31#include <linux/delay.h>
32#include <linux/string.h>
33#include <linux/seq_file.h>
34#include <linux/platform_device.h>
35#include <linux/regulator/consumer.h>
36
37#include <plat/display.h>
38#include <plat/cpu.h>
39
40#include "dss.h"
41
42#define VENC_BASE 0x48050C00
43
44/* Venc registers */
45#define VENC_REV_ID 0x00
46#define VENC_STATUS 0x04
47#define VENC_F_CONTROL 0x08
48#define VENC_VIDOUT_CTRL 0x10
49#define VENC_SYNC_CTRL 0x14
50#define VENC_LLEN 0x1C
51#define VENC_FLENS 0x20
52#define VENC_HFLTR_CTRL 0x24
53#define VENC_CC_CARR_WSS_CARR 0x28
54#define VENC_C_PHASE 0x2C
55#define VENC_GAIN_U 0x30
56#define VENC_GAIN_V 0x34
57#define VENC_GAIN_Y 0x38
58#define VENC_BLACK_LEVEL 0x3C
59#define VENC_BLANK_LEVEL 0x40
60#define VENC_X_COLOR 0x44
61#define VENC_M_CONTROL 0x48
62#define VENC_BSTAMP_WSS_DATA 0x4C
63#define VENC_S_CARR 0x50
64#define VENC_LINE21 0x54
65#define VENC_LN_SEL 0x58
66#define VENC_L21__WC_CTL 0x5C
67#define VENC_HTRIGGER_VTRIGGER 0x60
68#define VENC_SAVID__EAVID 0x64
69#define VENC_FLEN__FAL 0x68
70#define VENC_LAL__PHASE_RESET 0x6C
71#define VENC_HS_INT_START_STOP_X 0x70
72#define VENC_HS_EXT_START_STOP_X 0x74
73#define VENC_VS_INT_START_X 0x78
74#define VENC_VS_INT_STOP_X__VS_INT_START_Y 0x7C
75#define VENC_VS_INT_STOP_Y__VS_EXT_START_X 0x80
76#define VENC_VS_EXT_STOP_X__VS_EXT_START_Y 0x84
77#define VENC_VS_EXT_STOP_Y 0x88
78#define VENC_AVID_START_STOP_X 0x90
79#define VENC_AVID_START_STOP_Y 0x94
80#define VENC_FID_INT_START_X__FID_INT_START_Y 0xA0
81#define VENC_FID_INT_OFFSET_Y__FID_EXT_START_X 0xA4
82#define VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y 0xA8
83#define VENC_TVDETGP_INT_START_STOP_X 0xB0
84#define VENC_TVDETGP_INT_START_STOP_Y 0xB4
85#define VENC_GEN_CTRL 0xB8
86#define VENC_OUTPUT_CONTROL 0xC4
87#define VENC_OUTPUT_TEST 0xC8
88#define VENC_DAC_B__DAC_C 0xC8
89
90struct venc_config {
91 u32 f_control;
92 u32 vidout_ctrl;
93 u32 sync_ctrl;
94 u32 llen;
95 u32 flens;
96 u32 hfltr_ctrl;
97 u32 cc_carr_wss_carr;
98 u32 c_phase;
99 u32 gain_u;
100 u32 gain_v;
101 u32 gain_y;
102 u32 black_level;
103 u32 blank_level;
104 u32 x_color;
105 u32 m_control;
106 u32 bstamp_wss_data;
107 u32 s_carr;
108 u32 line21;
109 u32 ln_sel;
110 u32 l21__wc_ctl;
111 u32 htrigger_vtrigger;
112 u32 savid__eavid;
113 u32 flen__fal;
114 u32 lal__phase_reset;
115 u32 hs_int_start_stop_x;
116 u32 hs_ext_start_stop_x;
117 u32 vs_int_start_x;
118 u32 vs_int_stop_x__vs_int_start_y;
119 u32 vs_int_stop_y__vs_ext_start_x;
120 u32 vs_ext_stop_x__vs_ext_start_y;
121 u32 vs_ext_stop_y;
122 u32 avid_start_stop_x;
123 u32 avid_start_stop_y;
124 u32 fid_int_start_x__fid_int_start_y;
125 u32 fid_int_offset_y__fid_ext_start_x;
126 u32 fid_ext_start_y__fid_ext_offset_y;
127 u32 tvdetgp_int_start_stop_x;
128 u32 tvdetgp_int_start_stop_y;
129 u32 gen_ctrl;
130};
131
132/* from TRM */
133static const struct venc_config venc_config_pal_trm = {
134 .f_control = 0,
135 .vidout_ctrl = 1,
136 .sync_ctrl = 0x40,
137 .llen = 0x35F, /* 863 */
138 .flens = 0x270, /* 624 */
139 .hfltr_ctrl = 0,
140 .cc_carr_wss_carr = 0x2F7225ED,
141 .c_phase = 0,
142 .gain_u = 0x111,
143 .gain_v = 0x181,
144 .gain_y = 0x140,
145 .black_level = 0x3B,
146 .blank_level = 0x3B,
147 .x_color = 0x7,
148 .m_control = 0x2,
149 .bstamp_wss_data = 0x3F,
150 .s_carr = 0x2A098ACB,
151 .line21 = 0,
152 .ln_sel = 0x01290015,
153 .l21__wc_ctl = 0x0000F603,
154 .htrigger_vtrigger = 0,
155
156 .savid__eavid = 0x06A70108,
157 .flen__fal = 0x00180270,
158 .lal__phase_reset = 0x00040135,
159 .hs_int_start_stop_x = 0x00880358,
160 .hs_ext_start_stop_x = 0x000F035F,
161 .vs_int_start_x = 0x01A70000,
162 .vs_int_stop_x__vs_int_start_y = 0x000001A7,
163 .vs_int_stop_y__vs_ext_start_x = 0x01AF0000,
164 .vs_ext_stop_x__vs_ext_start_y = 0x000101AF,
165 .vs_ext_stop_y = 0x00000025,
166 .avid_start_stop_x = 0x03530083,
167 .avid_start_stop_y = 0x026C002E,
168 .fid_int_start_x__fid_int_start_y = 0x0001008A,
169 .fid_int_offset_y__fid_ext_start_x = 0x002E0138,
170 .fid_ext_start_y__fid_ext_offset_y = 0x01380001,
171
172 .tvdetgp_int_start_stop_x = 0x00140001,
173 .tvdetgp_int_start_stop_y = 0x00010001,
174 .gen_ctrl = 0x00FF0000,
175};
176
177/* from TRM */
178static const struct venc_config venc_config_ntsc_trm = {
179 .f_control = 0,
180 .vidout_ctrl = 1,
181 .sync_ctrl = 0x8040,
182 .llen = 0x359,
183 .flens = 0x20C,
184 .hfltr_ctrl = 0,
185 .cc_carr_wss_carr = 0x043F2631,
186 .c_phase = 0,
187 .gain_u = 0x102,
188 .gain_v = 0x16C,
189 .gain_y = 0x12F,
190 .black_level = 0x43,
191 .blank_level = 0x38,
192 .x_color = 0x7,
193 .m_control = 0x1,
194 .bstamp_wss_data = 0x38,
195 .s_carr = 0x21F07C1F,
196 .line21 = 0,
197 .ln_sel = 0x01310011,
198 .l21__wc_ctl = 0x0000F003,
199 .htrigger_vtrigger = 0,
200
201 .savid__eavid = 0x069300F4,
202 .flen__fal = 0x0016020C,
203 .lal__phase_reset = 0x00060107,
204 .hs_int_start_stop_x = 0x008E0350,
205 .hs_ext_start_stop_x = 0x000F0359,
206 .vs_int_start_x = 0x01A00000,
207 .vs_int_stop_x__vs_int_start_y = 0x020701A0,
208 .vs_int_stop_y__vs_ext_start_x = 0x01AC0024,
209 .vs_ext_stop_x__vs_ext_start_y = 0x020D01AC,
210 .vs_ext_stop_y = 0x00000006,
211 .avid_start_stop_x = 0x03480078,
212 .avid_start_stop_y = 0x02060024,
213 .fid_int_start_x__fid_int_start_y = 0x0001008A,
214 .fid_int_offset_y__fid_ext_start_x = 0x01AC0106,
215 .fid_ext_start_y__fid_ext_offset_y = 0x01060006,
216
217 .tvdetgp_int_start_stop_x = 0x00140001,
218 .tvdetgp_int_start_stop_y = 0x00010001,
219 .gen_ctrl = 0x00F90000,
220};
221
222static const struct venc_config venc_config_pal_bdghi = {
223 .f_control = 0,
224 .vidout_ctrl = 0,
225 .sync_ctrl = 0,
226 .hfltr_ctrl = 0,
227 .x_color = 0,
228 .line21 = 0,
229 .ln_sel = 21,
230 .htrigger_vtrigger = 0,
231 .tvdetgp_int_start_stop_x = 0x00140001,
232 .tvdetgp_int_start_stop_y = 0x00010001,
233 .gen_ctrl = 0x00FB0000,
234
235 .llen = 864-1,
236 .flens = 625-1,
237 .cc_carr_wss_carr = 0x2F7625ED,
238 .c_phase = 0xDF,
239 .gain_u = 0x111,
240 .gain_v = 0x181,
241 .gain_y = 0x140,
242 .black_level = 0x3e,
243 .blank_level = 0x3e,
244 .m_control = 0<<2 | 1<<1,
245 .bstamp_wss_data = 0x42,
246 .s_carr = 0x2a098acb,
247 .l21__wc_ctl = 0<<13 | 0x16<<8 | 0<<0,
248 .savid__eavid = 0x06A70108,
249 .flen__fal = 23<<16 | 624<<0,
250 .lal__phase_reset = 2<<17 | 310<<0,
251 .hs_int_start_stop_x = 0x00920358,
252 .hs_ext_start_stop_x = 0x000F035F,
253 .vs_int_start_x = 0x1a7<<16,
254 .vs_int_stop_x__vs_int_start_y = 0x000601A7,
255 .vs_int_stop_y__vs_ext_start_x = 0x01AF0036,
256 .vs_ext_stop_x__vs_ext_start_y = 0x27101af,
257 .vs_ext_stop_y = 0x05,
258 .avid_start_stop_x = 0x03530082,
259 .avid_start_stop_y = 0x0270002E,
260 .fid_int_start_x__fid_int_start_y = 0x0005008A,
261 .fid_int_offset_y__fid_ext_start_x = 0x002E0138,
262 .fid_ext_start_y__fid_ext_offset_y = 0x01380005,
263};
264
265const struct omap_video_timings omap_dss_pal_timings = {
266 .x_res = 720,
267 .y_res = 574,
268 .pixel_clock = 13500,
269 .hsw = 64,
270 .hfp = 12,
271 .hbp = 68,
272 .vsw = 5,
273 .vfp = 5,
274 .vbp = 41,
275};
276EXPORT_SYMBOL(omap_dss_pal_timings);
277
278const struct omap_video_timings omap_dss_ntsc_timings = {
279 .x_res = 720,
280 .y_res = 482,
281 .pixel_clock = 13500,
282 .hsw = 64,
283 .hfp = 16,
284 .hbp = 58,
285 .vsw = 6,
286 .vfp = 6,
287 .vbp = 31,
288};
289EXPORT_SYMBOL(omap_dss_ntsc_timings);
290
291static struct {
292 void __iomem *base;
293 struct mutex venc_lock;
294 u32 wss_data;
295 struct regulator *vdda_dac_reg;
296} venc;
297
298static inline void venc_write_reg(int idx, u32 val)
299{
300 __raw_writel(val, venc.base + idx);
301}
302
303static inline u32 venc_read_reg(int idx)
304{
305 u32 l = __raw_readl(venc.base + idx);
306 return l;
307}
308
309static void venc_write_config(const struct venc_config *config)
310{
311 DSSDBG("write venc conf\n");
312
313 venc_write_reg(VENC_LLEN, config->llen);
314 venc_write_reg(VENC_FLENS, config->flens);
315 venc_write_reg(VENC_CC_CARR_WSS_CARR, config->cc_carr_wss_carr);
316 venc_write_reg(VENC_C_PHASE, config->c_phase);
317 venc_write_reg(VENC_GAIN_U, config->gain_u);
318 venc_write_reg(VENC_GAIN_V, config->gain_v);
319 venc_write_reg(VENC_GAIN_Y, config->gain_y);
320 venc_write_reg(VENC_BLACK_LEVEL, config->black_level);
321 venc_write_reg(VENC_BLANK_LEVEL, config->blank_level);
322 venc_write_reg(VENC_M_CONTROL, config->m_control);
323 venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
324 venc.wss_data);
325 venc_write_reg(VENC_S_CARR, config->s_carr);
326 venc_write_reg(VENC_L21__WC_CTL, config->l21__wc_ctl);
327 venc_write_reg(VENC_SAVID__EAVID, config->savid__eavid);
328 venc_write_reg(VENC_FLEN__FAL, config->flen__fal);
329 venc_write_reg(VENC_LAL__PHASE_RESET, config->lal__phase_reset);
330 venc_write_reg(VENC_HS_INT_START_STOP_X, config->hs_int_start_stop_x);
331 venc_write_reg(VENC_HS_EXT_START_STOP_X, config->hs_ext_start_stop_x);
332 venc_write_reg(VENC_VS_INT_START_X, config->vs_int_start_x);
333 venc_write_reg(VENC_VS_INT_STOP_X__VS_INT_START_Y,
334 config->vs_int_stop_x__vs_int_start_y);
335 venc_write_reg(VENC_VS_INT_STOP_Y__VS_EXT_START_X,
336 config->vs_int_stop_y__vs_ext_start_x);
337 venc_write_reg(VENC_VS_EXT_STOP_X__VS_EXT_START_Y,
338 config->vs_ext_stop_x__vs_ext_start_y);
339 venc_write_reg(VENC_VS_EXT_STOP_Y, config->vs_ext_stop_y);
340 venc_write_reg(VENC_AVID_START_STOP_X, config->avid_start_stop_x);
341 venc_write_reg(VENC_AVID_START_STOP_Y, config->avid_start_stop_y);
342 venc_write_reg(VENC_FID_INT_START_X__FID_INT_START_Y,
343 config->fid_int_start_x__fid_int_start_y);
344 venc_write_reg(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X,
345 config->fid_int_offset_y__fid_ext_start_x);
346 venc_write_reg(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y,
347 config->fid_ext_start_y__fid_ext_offset_y);
348
349 venc_write_reg(VENC_DAC_B__DAC_C, venc_read_reg(VENC_DAC_B__DAC_C));
350 venc_write_reg(VENC_VIDOUT_CTRL, config->vidout_ctrl);
351 venc_write_reg(VENC_HFLTR_CTRL, config->hfltr_ctrl);
352 venc_write_reg(VENC_X_COLOR, config->x_color);
353 venc_write_reg(VENC_LINE21, config->line21);
354 venc_write_reg(VENC_LN_SEL, config->ln_sel);
355 venc_write_reg(VENC_HTRIGGER_VTRIGGER, config->htrigger_vtrigger);
356 venc_write_reg(VENC_TVDETGP_INT_START_STOP_X,
357 config->tvdetgp_int_start_stop_x);
358 venc_write_reg(VENC_TVDETGP_INT_START_STOP_Y,
359 config->tvdetgp_int_start_stop_y);
360 venc_write_reg(VENC_GEN_CTRL, config->gen_ctrl);
361 venc_write_reg(VENC_F_CONTROL, config->f_control);
362 venc_write_reg(VENC_SYNC_CTRL, config->sync_ctrl);
363}
364
365static void venc_reset(void)
366{
367 int t = 1000;
368
369 venc_write_reg(VENC_F_CONTROL, 1<<8);
370 while (venc_read_reg(VENC_F_CONTROL) & (1<<8)) {
371 if (--t == 0) {
372 DSSERR("Failed to reset venc\n");
373 return;
374 }
375 }
376
377 /* the magical sleep that makes things work */
378 msleep(20);
379}
380
381static void venc_enable_clocks(int enable)
382{
383 if (enable)
384 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
385 DSS_CLK_96M);
386 else
387 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
388 DSS_CLK_96M);
389}
390
391static const struct venc_config *venc_timings_to_config(
392 struct omap_video_timings *timings)
393{
394 if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
395 return &venc_config_pal_trm;
396
397 if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
398 return &venc_config_ntsc_trm;
399
400 BUG();
401}
402
403
404
405
406
407/* driver */
408static int venc_panel_probe(struct omap_dss_device *dssdev)
409{
410 dssdev->panel.timings = omap_dss_pal_timings;
411
412 return 0;
413}
414
415static void venc_panel_remove(struct omap_dss_device *dssdev)
416{
417}
418
419static int venc_panel_enable(struct omap_dss_device *dssdev)
420{
421 int r = 0;
422
423 /* wait couple of vsyncs until enabling the LCD */
424 msleep(50);
425
426 if (dssdev->platform_enable)
427 r = dssdev->platform_enable(dssdev);
428
429 return r;
430}
431
432static void venc_panel_disable(struct omap_dss_device *dssdev)
433{
434 if (dssdev->platform_disable)
435 dssdev->platform_disable(dssdev);
436
437 /* wait at least 5 vsyncs after disabling the LCD */
438
439 msleep(100);
440}
441
442static int venc_panel_suspend(struct omap_dss_device *dssdev)
443{
444 venc_panel_disable(dssdev);
445 return 0;
446}
447
448static int venc_panel_resume(struct omap_dss_device *dssdev)
449{
450 return venc_panel_enable(dssdev);
451}
452
453static struct omap_dss_driver venc_driver = {
454 .probe = venc_panel_probe,
455 .remove = venc_panel_remove,
456
457 .enable = venc_panel_enable,
458 .disable = venc_panel_disable,
459 .suspend = venc_panel_suspend,
460 .resume = venc_panel_resume,
461
462 .driver = {
463 .name = "venc",
464 .owner = THIS_MODULE,
465 },
466};
467/* driver end */
468
469
470
471int venc_init(struct platform_device *pdev)
472{
473 u8 rev_id;
474
475 mutex_init(&venc.venc_lock);
476
477 venc.wss_data = 0;
478
479 venc.base = ioremap(VENC_BASE, SZ_1K);
480 if (!venc.base) {
481 DSSERR("can't ioremap VENC\n");
482 return -ENOMEM;
483 }
484
485 venc.vdda_dac_reg = regulator_get(&pdev->dev, "vdda_dac");
486 if (IS_ERR(venc.vdda_dac_reg)) {
487 iounmap(venc.base);
488 DSSERR("can't get VDDA_DAC regulator\n");
489 return PTR_ERR(venc.vdda_dac_reg);
490 }
491
492 venc_enable_clocks(1);
493
494 rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
495 printk(KERN_INFO "OMAP VENC rev %d\n", rev_id);
496
497 venc_enable_clocks(0);
498
499 return omap_dss_register_driver(&venc_driver);
500}
501
502void venc_exit(void)
503{
504 omap_dss_unregister_driver(&venc_driver);
505
506 regulator_put(venc.vdda_dac_reg);
507
508 iounmap(venc.base);
509}
510
511static void venc_power_on(struct omap_dss_device *dssdev)
512{
513 u32 l;
514
515 venc_enable_clocks(1);
516
517 venc_reset();
518 venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
519
520 dss_set_venc_output(dssdev->phy.venc.type);
521 dss_set_dac_pwrdn_bgz(1);
522
523 l = 0;
524
525 if (dssdev->phy.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
526 l |= 1 << 1;
527 else /* S-Video */
528 l |= (1 << 0) | (1 << 2);
529
530 if (dssdev->phy.venc.invert_polarity == false)
531 l |= 1 << 3;
532
533 venc_write_reg(VENC_OUTPUT_CONTROL, l);
534
535 dispc_set_digit_size(dssdev->panel.timings.x_res,
536 dssdev->panel.timings.y_res/2);
537
538 regulator_enable(venc.vdda_dac_reg);
539
540 if (dssdev->platform_enable)
541 dssdev->platform_enable(dssdev);
542
543 dispc_enable_digit_out(1);
544}
545
546static void venc_power_off(struct omap_dss_device *dssdev)
547{
548 venc_write_reg(VENC_OUTPUT_CONTROL, 0);
549 dss_set_dac_pwrdn_bgz(0);
550
551 dispc_enable_digit_out(0);
552
553 if (dssdev->platform_disable)
554 dssdev->platform_disable(dssdev);
555
556 regulator_disable(venc.vdda_dac_reg);
557
558 venc_enable_clocks(0);
559}
560
561static int venc_enable_display(struct omap_dss_device *dssdev)
562{
563 int r = 0;
564
565 DSSDBG("venc_enable_display\n");
566
567 mutex_lock(&venc.venc_lock);
568
569 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
570 r = -EINVAL;
571 goto err;
572 }
573
574 venc_power_on(dssdev);
575
576 venc.wss_data = 0;
577
578 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
579err:
580 mutex_unlock(&venc.venc_lock);
581
582 return r;
583}
584
585static void venc_disable_display(struct omap_dss_device *dssdev)
586{
587 DSSDBG("venc_disable_display\n");
588
589 mutex_lock(&venc.venc_lock);
590
591 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
592 goto end;
593
594 if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
595 /* suspended is the same as disabled with venc */
596 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
597 goto end;
598 }
599
600 venc_power_off(dssdev);
601
602 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
603end:
604 mutex_unlock(&venc.venc_lock);
605}
606
607static int venc_display_suspend(struct omap_dss_device *dssdev)
608{
609 int r = 0;
610
611 DSSDBG("venc_display_suspend\n");
612
613 mutex_lock(&venc.venc_lock);
614
615 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
616 r = -EINVAL;
617 goto err;
618 }
619
620 venc_power_off(dssdev);
621
622 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
623err:
624 mutex_unlock(&venc.venc_lock);
625
626 return r;
627}
628
629static int venc_display_resume(struct omap_dss_device *dssdev)
630{
631 int r = 0;
632
633 DSSDBG("venc_display_resume\n");
634
635 mutex_lock(&venc.venc_lock);
636
637 if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
638 r = -EINVAL;
639 goto err;
640 }
641
642 venc_power_on(dssdev);
643
644 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
645err:
646 mutex_unlock(&venc.venc_lock);
647
648 return r;
649}
650
651static void venc_get_timings(struct omap_dss_device *dssdev,
652 struct omap_video_timings *timings)
653{
654 *timings = dssdev->panel.timings;
655}
656
657static void venc_set_timings(struct omap_dss_device *dssdev,
658 struct omap_video_timings *timings)
659{
660 DSSDBG("venc_set_timings\n");
661
662 /* Reset WSS data when the TV standard changes. */
663 if (memcmp(&dssdev->panel.timings, timings, sizeof(*timings)))
664 venc.wss_data = 0;
665
666 dssdev->panel.timings = *timings;
667 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
668 /* turn the venc off and on to get new timings to use */
669 venc_disable_display(dssdev);
670 venc_enable_display(dssdev);
671 }
672}
673
674static int venc_check_timings(struct omap_dss_device *dssdev,
675 struct omap_video_timings *timings)
676{
677 DSSDBG("venc_check_timings\n");
678
679 if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
680 return 0;
681
682 if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
683 return 0;
684
685 return -EINVAL;
686}
687
688static u32 venc_get_wss(struct omap_dss_device *dssdev)
689{
690 /* Invert due to VENC_L21_WC_CTL:INV=1 */
691 return (venc.wss_data >> 8) ^ 0xfffff;
692}
693
694static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
695{
696 const struct venc_config *config;
697
698 DSSDBG("venc_set_wss\n");
699
700 mutex_lock(&venc.venc_lock);
701
702 config = venc_timings_to_config(&dssdev->panel.timings);
703
704 /* Invert due to VENC_L21_WC_CTL:INV=1 */
705 venc.wss_data = (wss ^ 0xfffff) << 8;
706
707 venc_enable_clocks(1);
708
709 venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
710 venc.wss_data);
711
712 venc_enable_clocks(0);
713
714 mutex_unlock(&venc.venc_lock);
715
716 return 0;
717}
718
719static enum omap_dss_update_mode venc_display_get_update_mode(
720 struct omap_dss_device *dssdev)
721{
722 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
723 return OMAP_DSS_UPDATE_AUTO;
724 else
725 return OMAP_DSS_UPDATE_DISABLED;
726}
727
728int venc_init_display(struct omap_dss_device *dssdev)
729{
730 DSSDBG("init_display\n");
731
732 dssdev->enable = venc_enable_display;
733 dssdev->disable = venc_disable_display;
734 dssdev->suspend = venc_display_suspend;
735 dssdev->resume = venc_display_resume;
736 dssdev->get_timings = venc_get_timings;
737 dssdev->set_timings = venc_set_timings;
738 dssdev->check_timings = venc_check_timings;
739 dssdev->get_wss = venc_get_wss;
740 dssdev->set_wss = venc_set_wss;
741 dssdev->get_update_mode = venc_display_get_update_mode;
742
743 return 0;
744}
745
746void venc_dump_regs(struct seq_file *s)
747{
748#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
749
750 venc_enable_clocks(1);
751
752 DUMPREG(VENC_F_CONTROL);
753 DUMPREG(VENC_VIDOUT_CTRL);
754 DUMPREG(VENC_SYNC_CTRL);
755 DUMPREG(VENC_LLEN);
756 DUMPREG(VENC_FLENS);
757 DUMPREG(VENC_HFLTR_CTRL);
758 DUMPREG(VENC_CC_CARR_WSS_CARR);
759 DUMPREG(VENC_C_PHASE);
760 DUMPREG(VENC_GAIN_U);
761 DUMPREG(VENC_GAIN_V);
762 DUMPREG(VENC_GAIN_Y);
763 DUMPREG(VENC_BLACK_LEVEL);
764 DUMPREG(VENC_BLANK_LEVEL);
765 DUMPREG(VENC_X_COLOR);
766 DUMPREG(VENC_M_CONTROL);
767 DUMPREG(VENC_BSTAMP_WSS_DATA);
768 DUMPREG(VENC_S_CARR);
769 DUMPREG(VENC_LINE21);
770 DUMPREG(VENC_LN_SEL);
771 DUMPREG(VENC_L21__WC_CTL);
772 DUMPREG(VENC_HTRIGGER_VTRIGGER);
773 DUMPREG(VENC_SAVID__EAVID);
774 DUMPREG(VENC_FLEN__FAL);
775 DUMPREG(VENC_LAL__PHASE_RESET);
776 DUMPREG(VENC_HS_INT_START_STOP_X);
777 DUMPREG(VENC_HS_EXT_START_STOP_X);
778 DUMPREG(VENC_VS_INT_START_X);
779 DUMPREG(VENC_VS_INT_STOP_X__VS_INT_START_Y);
780 DUMPREG(VENC_VS_INT_STOP_Y__VS_EXT_START_X);
781 DUMPREG(VENC_VS_EXT_STOP_X__VS_EXT_START_Y);
782 DUMPREG(VENC_VS_EXT_STOP_Y);
783 DUMPREG(VENC_AVID_START_STOP_X);
784 DUMPREG(VENC_AVID_START_STOP_Y);
785 DUMPREG(VENC_FID_INT_START_X__FID_INT_START_Y);
786 DUMPREG(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X);
787 DUMPREG(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y);
788 DUMPREG(VENC_TVDETGP_INT_START_STOP_X);
789 DUMPREG(VENC_TVDETGP_INT_START_STOP_Y);
790 DUMPREG(VENC_GEN_CTRL);
791 DUMPREG(VENC_OUTPUT_CONTROL);
792 DUMPREG(VENC_OUTPUT_TEST);
793
794 venc_enable_clocks(0);
795
796#undef DUMPREG
797}