DSS2: OMAP2/3 Display Subsystem driver
[pandora-kernel.git] / drivers / video / omap2 / dss / dss.c
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
32 #include <mach/display.h>
33 #include "dss.h"
34
35 #define DSS_BASE                        0x48050000
36
37 #define DSS_SZ_REGS                     SZ_512
38
39 struct dss_reg {
40         u16 idx;
41 };
42
43 #define DSS_REG(idx)                    ((const struct dss_reg) { idx })
44
45 #define DSS_REVISION                    DSS_REG(0x0000)
46 #define DSS_SYSCONFIG                   DSS_REG(0x0010)
47 #define DSS_SYSSTATUS                   DSS_REG(0x0014)
48 #define DSS_IRQSTATUS                   DSS_REG(0x0018)
49 #define DSS_CONTROL                     DSS_REG(0x0040)
50 #define DSS_SDI_CONTROL                 DSS_REG(0x0044)
51 #define DSS_PLL_CONTROL                 DSS_REG(0x0048)
52 #define DSS_SDI_STATUS                  DSS_REG(0x005C)
53
54 #define REG_GET(idx, start, end) \
55         FLD_GET(dss_read_reg(idx), start, end)
56
57 #define REG_FLD_MOD(idx, val, start, end) \
58         dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
59
60 static struct {
61         void __iomem    *base;
62
63         u32             ctx[DSS_SZ_REGS / sizeof(u32)];
64 } dss;
65
66 static int _omap_dss_wait_reset(void);
67
68 static inline void dss_write_reg(const struct dss_reg idx, u32 val)
69 {
70         __raw_writel(val, dss.base + idx.idx);
71 }
72
73 static inline u32 dss_read_reg(const struct dss_reg idx)
74 {
75         return __raw_readl(dss.base + idx.idx);
76 }
77
78 #define SR(reg) \
79         dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
80 #define RR(reg) \
81         dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
82
83 void dss_save_context(void)
84 {
85         if (cpu_is_omap24xx())
86                 return;
87
88         SR(SYSCONFIG);
89         SR(CONTROL);
90
91 #ifdef CONFIG_OMAP2_DSS_SDI
92         SR(SDI_CONTROL);
93         SR(PLL_CONTROL);
94 #endif
95 }
96
97 void dss_restore_context(void)
98 {
99         if (_omap_dss_wait_reset())
100                 DSSERR("DSS not coming out of reset after sleep\n");
101
102         RR(SYSCONFIG);
103         RR(CONTROL);
104
105 #ifdef CONFIG_OMAP2_DSS_SDI
106         RR(SDI_CONTROL);
107         RR(PLL_CONTROL);
108 #endif
109 }
110
111 #undef SR
112 #undef RR
113
114 void dss_sdi_init(u8 datapairs)
115 {
116         u32 l;
117
118         BUG_ON(datapairs > 3 || datapairs < 1);
119
120         l = dss_read_reg(DSS_SDI_CONTROL);
121         l = FLD_MOD(l, 0xf, 19, 15);            /* SDI_PDIV */
122         l = FLD_MOD(l, datapairs-1, 3, 2);      /* SDI_PRSEL */
123         l = FLD_MOD(l, 2, 1, 0);                /* SDI_BWSEL */
124         dss_write_reg(DSS_SDI_CONTROL, l);
125
126         l = dss_read_reg(DSS_PLL_CONTROL);
127         l = FLD_MOD(l, 0x7, 25, 22);    /* SDI_PLL_FREQSEL */
128         l = FLD_MOD(l, 0xb, 16, 11);    /* SDI_PLL_REGN */
129         l = FLD_MOD(l, 0xb4, 10, 1);    /* SDI_PLL_REGM */
130         dss_write_reg(DSS_PLL_CONTROL, l);
131 }
132
133 void dss_sdi_enable(void)
134 {
135         dispc_pck_free_enable(1);
136
137         /* Reset SDI PLL */
138         REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */
139         udelay(1);      /* wait 2x PCLK */
140
141         /* Lock SDI PLL */
142         REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */
143
144         /* Waiting for PLL lock request to complete */
145         while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6))
146                 ;
147
148         /* Clearing PLL_GO bit */
149         REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28);
150
151         /* Waiting for PLL to lock */
152         while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5)))
153                 ;
154
155         dispc_lcd_enable_signal(1);
156
157         /* Waiting for SDI reset to complete */
158         while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2)))
159                 ;
160 }
161
162 void dss_sdi_disable(void)
163 {
164         dispc_lcd_enable_signal(0);
165
166         dispc_pck_free_enable(0);
167
168         /* Reset SDI PLL */
169         REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
170 }
171
172 void dss_dump_regs(struct seq_file *s)
173 {
174 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
175
176         dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
177
178         DUMPREG(DSS_REVISION);
179         DUMPREG(DSS_SYSCONFIG);
180         DUMPREG(DSS_SYSSTATUS);
181         DUMPREG(DSS_IRQSTATUS);
182         DUMPREG(DSS_CONTROL);
183         DUMPREG(DSS_SDI_CONTROL);
184         DUMPREG(DSS_PLL_CONTROL);
185         DUMPREG(DSS_SDI_STATUS);
186
187         dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
188 #undef DUMPREG
189 }
190
191 void dss_select_clk_source(bool dsi, bool dispc)
192 {
193         u32 r;
194         r = dss_read_reg(DSS_CONTROL);
195         r = FLD_MOD(r, dsi, 1, 1);      /* DSI_CLK_SWITCH */
196         r = FLD_MOD(r, dispc, 0, 0);    /* DISPC_CLK_SWITCH */
197         dss_write_reg(DSS_CONTROL, r);
198 }
199
200 int dss_get_dsi_clk_source(void)
201 {
202         return FLD_GET(dss_read_reg(DSS_CONTROL), 1, 1);
203 }
204
205 int dss_get_dispc_clk_source(void)
206 {
207         return FLD_GET(dss_read_reg(DSS_CONTROL), 0, 0);
208 }
209
210 static irqreturn_t dss_irq_handler_omap2(int irq, void *arg)
211 {
212         dispc_irq_handler();
213
214         return IRQ_HANDLED;
215 }
216
217 static irqreturn_t dss_irq_handler_omap3(int irq, void *arg)
218 {
219         u32 irqstatus;
220
221         irqstatus = dss_read_reg(DSS_IRQSTATUS);
222
223         if (irqstatus & (1<<0)) /* DISPC_IRQ */
224                 dispc_irq_handler();
225 #ifdef CONFIG_OMAP2_DSS_DSI
226         if (irqstatus & (1<<1)) /* DSI_IRQ */
227                 dsi_irq_handler();
228 #endif
229
230         return IRQ_HANDLED;
231 }
232
233 static int _omap_dss_wait_reset(void)
234 {
235         unsigned timeout = 1000;
236
237         while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
238                 udelay(1);
239                 if (!--timeout) {
240                         DSSERR("soft reset failed\n");
241                         return -ENODEV;
242                 }
243         }
244
245         return 0;
246 }
247
248 static int _omap_dss_reset(void)
249 {
250         /* Soft reset */
251         REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
252         return _omap_dss_wait_reset();
253 }
254
255 void dss_set_venc_output(enum omap_dss_venc_type type)
256 {
257         int l = 0;
258
259         if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
260                 l = 0;
261         else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
262                 l = 1;
263         else
264                 BUG();
265
266         /* venc out selection. 0 = comp, 1 = svideo */
267         REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
268 }
269
270 void dss_set_dac_pwrdn_bgz(bool enable)
271 {
272         REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
273 }
274
275 int dss_init(bool skip_init)
276 {
277         int r;
278         u32 rev;
279
280         dss.base = ioremap(DSS_BASE, DSS_SZ_REGS);
281         if (!dss.base) {
282                 DSSERR("can't ioremap DSS\n");
283                 r = -ENOMEM;
284                 goto fail0;
285         }
286
287         if (!skip_init) {
288                 /* We need to wait here a bit, otherwise we sometimes start to
289                  * get synclost errors, and after that only power cycle will
290                  * restore DSS functionality. I have no idea why this happens.
291                  * And we have to wait _before_ resetting the DSS, but after
292                  * enabling clocks.
293                  */
294                 msleep(50);
295
296                 _omap_dss_reset();
297
298         }
299         else
300                 printk("DSS SKIP RESET\n");
301
302         /* autoidle */
303         REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
304
305         /* Select DPLL */
306         REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
307
308 #ifdef CONFIG_OMAP2_DSS_VENC
309         REG_FLD_MOD(DSS_CONTROL, 1, 4, 4);      /* venc dac demen */
310         REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);      /* venc clock 4x enable */
311         REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);      /* venc clock mode = normal */
312 #endif
313
314         r = request_irq(INT_24XX_DSS_IRQ,
315                         cpu_is_omap24xx()
316                         ? dss_irq_handler_omap2
317                         : dss_irq_handler_omap3,
318                         0, "OMAP DSS", NULL);
319
320         if (r < 0) {
321                 DSSERR("omap2 dss: request_irq failed\n");
322                 goto fail1;
323         }
324
325         dss_save_context();
326
327         rev = dss_read_reg(DSS_REVISION);
328         printk(KERN_INFO "OMAP DSS rev %d.%d\n",
329                         FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
330
331         return 0;
332
333 fail1:
334         iounmap(dss.base);
335 fail0:
336         return r;
337 }
338
339 void dss_exit(void)
340 {
341         free_irq(INT_24XX_DSS_IRQ, NULL);
342
343         iounmap(dss.base);
344 }
345