OMAP2, 3: DSS2: DSS: create platform_driver, move init, exit to driver
[deliverable/linux.git] / drivers / video / omap2 / dss / dss.c
CommitLineData
559d6701
TV
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 {
96c401bc 62 struct platform_device *pdev;
559d6701
TV
63 void __iomem *base;
64
65 struct clk *dpll4_m4_ck;
66
67 unsigned long cache_req_pck;
68 unsigned long cache_prate;
69 struct dss_clock_info cache_dss_cinfo;
70 struct dispc_clock_info cache_dispc_cinfo;
71
2f18c4d8
TV
72 enum dss_clk_source dsi_clk_source;
73 enum dss_clk_source dispc_clk_source;
74
559d6701
TV
75 u32 ctx[DSS_SZ_REGS / sizeof(u32)];
76} dss;
77
78static int _omap_dss_wait_reset(void);
79
80static inline void dss_write_reg(const struct dss_reg idx, u32 val)
81{
82 __raw_writel(val, dss.base + idx.idx);
83}
84
85static inline u32 dss_read_reg(const struct dss_reg idx)
86{
87 return __raw_readl(dss.base + idx.idx);
88}
89
90#define SR(reg) \
91 dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
92#define RR(reg) \
93 dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
94
95void dss_save_context(void)
96{
97 if (cpu_is_omap24xx())
98 return;
99
100 SR(SYSCONFIG);
101 SR(CONTROL);
102
103#ifdef CONFIG_OMAP2_DSS_SDI
104 SR(SDI_CONTROL);
105 SR(PLL_CONTROL);
106#endif
107}
108
109void dss_restore_context(void)
110{
111 if (_omap_dss_wait_reset())
112 DSSERR("DSS not coming out of reset after sleep\n");
113
114 RR(SYSCONFIG);
115 RR(CONTROL);
116
117#ifdef CONFIG_OMAP2_DSS_SDI
118 RR(SDI_CONTROL);
119 RR(PLL_CONTROL);
120#endif
121}
122
123#undef SR
124#undef RR
125
126void dss_sdi_init(u8 datapairs)
127{
128 u32 l;
129
130 BUG_ON(datapairs > 3 || datapairs < 1);
131
132 l = dss_read_reg(DSS_SDI_CONTROL);
133 l = FLD_MOD(l, 0xf, 19, 15); /* SDI_PDIV */
134 l = FLD_MOD(l, datapairs-1, 3, 2); /* SDI_PRSEL */
135 l = FLD_MOD(l, 2, 1, 0); /* SDI_BWSEL */
136 dss_write_reg(DSS_SDI_CONTROL, l);
137
138 l = dss_read_reg(DSS_PLL_CONTROL);
139 l = FLD_MOD(l, 0x7, 25, 22); /* SDI_PLL_FREQSEL */
140 l = FLD_MOD(l, 0xb, 16, 11); /* SDI_PLL_REGN */
141 l = FLD_MOD(l, 0xb4, 10, 1); /* SDI_PLL_REGM */
142 dss_write_reg(DSS_PLL_CONTROL, l);
143}
144
145int dss_sdi_enable(void)
146{
147 unsigned long timeout;
148
149 dispc_pck_free_enable(1);
150
151 /* Reset SDI PLL */
152 REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */
153 udelay(1); /* wait 2x PCLK */
154
155 /* Lock SDI PLL */
156 REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */
157
158 /* Waiting for PLL lock request to complete */
159 timeout = jiffies + msecs_to_jiffies(500);
160 while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6)) {
161 if (time_after_eq(jiffies, timeout)) {
162 DSSERR("PLL lock request timed out\n");
163 goto err1;
164 }
165 }
166
167 /* Clearing PLL_GO bit */
168 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28);
169
170 /* Waiting for PLL to lock */
171 timeout = jiffies + msecs_to_jiffies(500);
172 while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5))) {
173 if (time_after_eq(jiffies, timeout)) {
174 DSSERR("PLL lock timed out\n");
175 goto err1;
176 }
177 }
178
179 dispc_lcd_enable_signal(1);
180
181 /* Waiting for SDI reset to complete */
182 timeout = jiffies + msecs_to_jiffies(500);
183 while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2))) {
184 if (time_after_eq(jiffies, timeout)) {
185 DSSERR("SDI reset timed out\n");
186 goto err2;
187 }
188 }
189
190 return 0;
191
192 err2:
193 dispc_lcd_enable_signal(0);
194 err1:
195 /* Reset SDI PLL */
196 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
197
198 dispc_pck_free_enable(0);
199
200 return -ETIMEDOUT;
201}
202
203void dss_sdi_disable(void)
204{
205 dispc_lcd_enable_signal(0);
206
207 dispc_pck_free_enable(0);
208
209 /* Reset SDI PLL */
210 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
211}
212
213void dss_dump_clocks(struct seq_file *s)
214{
215 unsigned long dpll4_ck_rate;
216 unsigned long dpll4_m4_ck_rate;
217
218 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
219
220 dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
221 dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck);
222
223 seq_printf(s, "- DSS -\n");
224
225 seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
226
ac01bb7e
K
227 if (cpu_is_omap3630())
228 seq_printf(s, "dss1_alwon_fclk = %lu / %lu = %lu\n",
229 dpll4_ck_rate,
230 dpll4_ck_rate / dpll4_m4_ck_rate,
231 dss_clk_get_rate(DSS_CLK_FCK1));
232 else
233 seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n",
559d6701
TV
234 dpll4_ck_rate,
235 dpll4_ck_rate / dpll4_m4_ck_rate,
236 dss_clk_get_rate(DSS_CLK_FCK1));
237
238 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
239}
240
241void dss_dump_regs(struct seq_file *s)
242{
243#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
244
245 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
246
247 DUMPREG(DSS_REVISION);
248 DUMPREG(DSS_SYSCONFIG);
249 DUMPREG(DSS_SYSSTATUS);
250 DUMPREG(DSS_IRQSTATUS);
251 DUMPREG(DSS_CONTROL);
252 DUMPREG(DSS_SDI_CONTROL);
253 DUMPREG(DSS_PLL_CONTROL);
254 DUMPREG(DSS_SDI_STATUS);
255
256 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
257#undef DUMPREG
258}
259
2f18c4d8
TV
260void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
261{
262 int b;
263
264 BUG_ON(clk_src != DSS_SRC_DSI1_PLL_FCLK &&
265 clk_src != DSS_SRC_DSS1_ALWON_FCLK);
266
267 b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1;
268
e406f907
TV
269 if (clk_src == DSS_SRC_DSI1_PLL_FCLK)
270 dsi_wait_dsi1_pll_active();
271
2f18c4d8
TV
272 REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */
273
274 dss.dispc_clk_source = clk_src;
275}
276
277void dss_select_dsi_clk_source(enum dss_clk_source clk_src)
559d6701 278{
2f18c4d8
TV
279 int b;
280
281 BUG_ON(clk_src != DSS_SRC_DSI2_PLL_FCLK &&
282 clk_src != DSS_SRC_DSS1_ALWON_FCLK);
283
284 b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1;
285
e406f907
TV
286 if (clk_src == DSS_SRC_DSI2_PLL_FCLK)
287 dsi_wait_dsi2_pll_active();
288
2f18c4d8
TV
289 REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */
290
291 dss.dsi_clk_source = clk_src;
559d6701
TV
292}
293
2f18c4d8 294enum dss_clk_source dss_get_dispc_clk_source(void)
559d6701 295{
2f18c4d8 296 return dss.dispc_clk_source;
559d6701
TV
297}
298
2f18c4d8 299enum dss_clk_source dss_get_dsi_clk_source(void)
559d6701 300{
2f18c4d8 301 return dss.dsi_clk_source;
559d6701
TV
302}
303
304/* calculate clock rates using dividers in cinfo */
305int dss_calc_clock_rates(struct dss_clock_info *cinfo)
306{
307 unsigned long prate;
308
ac01bb7e
K
309 if (cinfo->fck_div > (cpu_is_omap3630() ? 32 : 16) ||
310 cinfo->fck_div == 0)
559d6701
TV
311 return -EINVAL;
312
313 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
314
315 cinfo->fck = prate / cinfo->fck_div;
316
317 return 0;
318}
319
320int dss_set_clock_div(struct dss_clock_info *cinfo)
321{
322 unsigned long prate;
323 int r;
324
325 if (cpu_is_omap34xx()) {
326 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
327 DSSDBG("dpll4_m4 = %ld\n", prate);
328
329 r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div);
330 if (r)
331 return r;
332 }
333
334 DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
335
336 return 0;
337}
338
339int dss_get_clock_div(struct dss_clock_info *cinfo)
340{
341 cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1);
342
343 if (cpu_is_omap34xx()) {
344 unsigned long prate;
345 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
ac01bb7e
K
346 if (cpu_is_omap3630())
347 cinfo->fck_div = prate / (cinfo->fck);
348 else
349 cinfo->fck_div = prate / (cinfo->fck / 2);
559d6701
TV
350 } else {
351 cinfo->fck_div = 0;
352 }
353
354 return 0;
355}
356
357unsigned long dss_get_dpll4_rate(void)
358{
359 if (cpu_is_omap34xx())
360 return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
361 else
362 return 0;
363}
364
365int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
366 struct dss_clock_info *dss_cinfo,
367 struct dispc_clock_info *dispc_cinfo)
368{
369 unsigned long prate;
370 struct dss_clock_info best_dss;
371 struct dispc_clock_info best_dispc;
372
373 unsigned long fck;
374
375 u16 fck_div;
376
377 int match = 0;
378 int min_fck_per_pck;
379
380 prate = dss_get_dpll4_rate();
381
382 fck = dss_clk_get_rate(DSS_CLK_FCK1);
383 if (req_pck == dss.cache_req_pck &&
384 ((cpu_is_omap34xx() && prate == dss.cache_prate) ||
385 dss.cache_dss_cinfo.fck == fck)) {
386 DSSDBG("dispc clock info found from cache.\n");
387 *dss_cinfo = dss.cache_dss_cinfo;
388 *dispc_cinfo = dss.cache_dispc_cinfo;
389 return 0;
390 }
391
392 min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
393
394 if (min_fck_per_pck &&
395 req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
396 DSSERR("Requested pixel clock not possible with the current "
397 "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
398 "the constraint off.\n");
399 min_fck_per_pck = 0;
400 }
401
402retry:
403 memset(&best_dss, 0, sizeof(best_dss));
404 memset(&best_dispc, 0, sizeof(best_dispc));
405
406 if (cpu_is_omap24xx()) {
407 struct dispc_clock_info cur_dispc;
408 /* XXX can we change the clock on omap2? */
409 fck = dss_clk_get_rate(DSS_CLK_FCK1);
410 fck_div = 1;
411
412 dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
413 match = 1;
414
415 best_dss.fck = fck;
416 best_dss.fck_div = fck_div;
417
418 best_dispc = cur_dispc;
419
420 goto found;
421 } else if (cpu_is_omap34xx()) {
ac01bb7e
K
422 for (fck_div = (cpu_is_omap3630() ? 32 : 16);
423 fck_div > 0; --fck_div) {
559d6701
TV
424 struct dispc_clock_info cur_dispc;
425
ac01bb7e
K
426 if (cpu_is_omap3630())
427 fck = prate / fck_div;
428 else
429 fck = prate / fck_div * 2;
559d6701
TV
430
431 if (fck > DISPC_MAX_FCK)
432 continue;
433
434 if (min_fck_per_pck &&
435 fck < req_pck * min_fck_per_pck)
436 continue;
437
438 match = 1;
439
440 dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
441
442 if (abs(cur_dispc.pck - req_pck) <
443 abs(best_dispc.pck - req_pck)) {
444
445 best_dss.fck = fck;
446 best_dss.fck_div = fck_div;
447
448 best_dispc = cur_dispc;
449
450 if (cur_dispc.pck == req_pck)
451 goto found;
452 }
453 }
454 } else {
455 BUG();
456 }
457
458found:
459 if (!match) {
460 if (min_fck_per_pck) {
461 DSSERR("Could not find suitable clock settings.\n"
462 "Turning FCK/PCK constraint off and"
463 "trying again.\n");
464 min_fck_per_pck = 0;
465 goto retry;
466 }
467
468 DSSERR("Could not find suitable clock settings.\n");
469
470 return -EINVAL;
471 }
472
473 if (dss_cinfo)
474 *dss_cinfo = best_dss;
475 if (dispc_cinfo)
476 *dispc_cinfo = best_dispc;
477
478 dss.cache_req_pck = req_pck;
479 dss.cache_prate = prate;
480 dss.cache_dss_cinfo = best_dss;
481 dss.cache_dispc_cinfo = best_dispc;
482
483 return 0;
484}
485
486
487
488static irqreturn_t dss_irq_handler_omap2(int irq, void *arg)
489{
490 dispc_irq_handler();
491
492 return IRQ_HANDLED;
493}
494
495static irqreturn_t dss_irq_handler_omap3(int irq, void *arg)
496{
497 u32 irqstatus;
498
499 irqstatus = dss_read_reg(DSS_IRQSTATUS);
500
501 if (irqstatus & (1<<0)) /* DISPC_IRQ */
502 dispc_irq_handler();
503#ifdef CONFIG_OMAP2_DSS_DSI
504 if (irqstatus & (1<<1)) /* DSI_IRQ */
505 dsi_irq_handler();
506#endif
507
508 return IRQ_HANDLED;
509}
510
511static int _omap_dss_wait_reset(void)
512{
24be78b3 513 int t = 0;
559d6701
TV
514
515 while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
24be78b3 516 if (++t > 1000) {
559d6701
TV
517 DSSERR("soft reset failed\n");
518 return -ENODEV;
519 }
24be78b3 520 udelay(1);
559d6701
TV
521 }
522
523 return 0;
524}
525
526static int _omap_dss_reset(void)
527{
528 /* Soft reset */
529 REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
530 return _omap_dss_wait_reset();
531}
532
533void dss_set_venc_output(enum omap_dss_venc_type type)
534{
535 int l = 0;
536
537 if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
538 l = 0;
539 else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
540 l = 1;
541 else
542 BUG();
543
544 /* venc out selection. 0 = comp, 1 = svideo */
545 REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
546}
547
548void dss_set_dac_pwrdn_bgz(bool enable)
549{
550 REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
551}
552
96c401bc 553static int dss_init(bool skip_init)
559d6701
TV
554{
555 int r;
556 u32 rev;
557
558 dss.base = ioremap(DSS_BASE, DSS_SZ_REGS);
559 if (!dss.base) {
560 DSSERR("can't ioremap DSS\n");
561 r = -ENOMEM;
562 goto fail0;
563 }
564
565 if (!skip_init) {
566 /* disable LCD and DIGIT output. This seems to fix the synclost
567 * problem that we get, if the bootloader starts the DSS and
568 * the kernel resets it */
569 omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
570
571 /* We need to wait here a bit, otherwise we sometimes start to
572 * get synclost errors, and after that only power cycle will
573 * restore DSS functionality. I have no idea why this happens.
574 * And we have to wait _before_ resetting the DSS, but after
575 * enabling clocks.
576 */
577 msleep(50);
578
579 _omap_dss_reset();
580 }
581
582 /* autoidle */
583 REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
584
585 /* Select DPLL */
586 REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
587
588#ifdef CONFIG_OMAP2_DSS_VENC
589 REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
590 REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
591 REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
592#endif
593
594 r = request_irq(INT_24XX_DSS_IRQ,
595 cpu_is_omap24xx()
596 ? dss_irq_handler_omap2
597 : dss_irq_handler_omap3,
598 0, "OMAP DSS", NULL);
599
600 if (r < 0) {
601 DSSERR("omap2 dss: request_irq failed\n");
602 goto fail1;
603 }
604
605 if (cpu_is_omap34xx()) {
606 dss.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
607 if (IS_ERR(dss.dpll4_m4_ck)) {
608 DSSERR("Failed to get dpll4_m4_ck\n");
609 r = PTR_ERR(dss.dpll4_m4_ck);
610 goto fail2;
611 }
612 }
613
ce619e1f
TV
614 dss.dsi_clk_source = DSS_SRC_DSS1_ALWON_FCLK;
615 dss.dispc_clk_source = DSS_SRC_DSS1_ALWON_FCLK;
616
559d6701
TV
617 dss_save_context();
618
619 rev = dss_read_reg(DSS_REVISION);
620 printk(KERN_INFO "OMAP DSS rev %d.%d\n",
621 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
622
623 return 0;
624
625fail2:
626 free_irq(INT_24XX_DSS_IRQ, NULL);
627fail1:
628 iounmap(dss.base);
629fail0:
630 return r;
631}
632
96c401bc 633static void dss_exit(void)
559d6701
TV
634{
635 if (cpu_is_omap34xx())
636 clk_put(dss.dpll4_m4_ck);
637
638 free_irq(INT_24XX_DSS_IRQ, NULL);
639
640 iounmap(dss.base);
641}
642
96c401bc
SG
643/* DSS HW IP initialisation */
644static int omap_dsshw_probe(struct platform_device *pdev)
645{
646 int r;
647 int skip_init = 0;
648
649 dss.pdev = pdev;
650
651#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
652 /* DISPC_CONTROL */
653 if (omap_readl(0x48050440) & 1) /* LCD enabled? */
654 skip_init = 1;
655#endif
656
657 r = dss_init(skip_init);
658 if (r) {
659 DSSERR("Failed to initialize DSS\n");
660 goto err_dss;
661 }
662
663err_dss:
664
665 return r;
666}
667
668static int omap_dsshw_remove(struct platform_device *pdev)
669{
670 dss_exit();
671
672 return 0;
673}
674
675static struct platform_driver omap_dsshw_driver = {
676 .probe = omap_dsshw_probe,
677 .remove = omap_dsshw_remove,
678 .driver = {
679 .name = "omapdss_dss",
680 .owner = THIS_MODULE,
681 },
682};
683
684int dss_init_platform_driver(void)
685{
686 return platform_driver_register(&omap_dsshw_driver);
687}
688
689void dss_uninit_platform_driver(void)
690{
691 return platform_driver_unregister(&omap_dsshw_driver);
692}
This page took 0.171417 seconds and 5 git commands to generate.