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