OMAP4: DSS2: DSI: Changes for DSI2 on OMAP4
[pandora-kernel.git] / drivers / video / omap2 / dss / dispc.c
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 #include <linux/hardirq.h>
35 #include <linux/interrupt.h>
36
37 #include <plat/sram.h>
38 #include <plat/clock.h>
39
40 #include <video/omapdss.h>
41
42 #include "dss.h"
43 #include "dss_features.h"
44 #include "dispc.h"
45
46 /* DISPC */
47 #define DISPC_SZ_REGS                   SZ_4K
48
49 #define DISPC_IRQ_MASK_ERROR            (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
50                                          DISPC_IRQ_OCP_ERR | \
51                                          DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
52                                          DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
53                                          DISPC_IRQ_SYNC_LOST | \
54                                          DISPC_IRQ_SYNC_LOST_DIGIT)
55
56 #define DISPC_MAX_NR_ISRS               8
57
58 struct omap_dispc_isr_data {
59         omap_dispc_isr_t        isr;
60         void                    *arg;
61         u32                     mask;
62 };
63
64 struct dispc_h_coef {
65         s8 hc4;
66         s8 hc3;
67         u8 hc2;
68         s8 hc1;
69         s8 hc0;
70 };
71
72 struct dispc_v_coef {
73         s8 vc22;
74         s8 vc2;
75         u8 vc1;
76         s8 vc0;
77         s8 vc00;
78 };
79
80 #define REG_GET(idx, start, end) \
81         FLD_GET(dispc_read_reg(idx), start, end)
82
83 #define REG_FLD_MOD(idx, val, start, end)                               \
84         dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
85
86 struct dispc_irq_stats {
87         unsigned long last_reset;
88         unsigned irq_count;
89         unsigned irqs[32];
90 };
91
92 static struct {
93         struct platform_device *pdev;
94         void __iomem    *base;
95         int irq;
96
97         u32     fifo_size[3];
98
99         spinlock_t irq_lock;
100         u32 irq_error_mask;
101         struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
102         u32 error_irqs;
103         struct work_struct error_work;
104
105         u32             ctx[DISPC_SZ_REGS / sizeof(u32)];
106
107 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
108         spinlock_t irq_stats_lock;
109         struct dispc_irq_stats irq_stats;
110 #endif
111 } dispc;
112
113 static void _omap_dispc_set_irqs(void);
114
115 static inline void dispc_write_reg(const u16 idx, u32 val)
116 {
117         __raw_writel(val, dispc.base + idx);
118 }
119
120 static inline u32 dispc_read_reg(const u16 idx)
121 {
122         return __raw_readl(dispc.base + idx);
123 }
124
125 #define SR(reg) \
126         dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
127 #define RR(reg) \
128         dispc_write_reg(DISPC_##reg, dispc.ctx[DISPC_##reg / sizeof(u32)])
129
130 void dispc_save_context(void)
131 {
132         if (cpu_is_omap24xx())
133                 return;
134
135         SR(SYSCONFIG);
136         SR(IRQENABLE);
137         SR(CONTROL);
138         SR(CONFIG);
139         SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD));
140         SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT));
141         SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD));
142         SR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));
143         SR(LINE_NUMBER);
144         SR(TIMING_H(OMAP_DSS_CHANNEL_LCD));
145         SR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
146         SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
147         SR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
148         SR(GLOBAL_ALPHA);
149         SR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
150         SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
151         if (dss_has_feature(FEAT_MGR_LCD2)) {
152                 SR(CONTROL2);
153                 SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2));
154                 SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2));
155                 SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2));
156                 SR(TIMING_H(OMAP_DSS_CHANNEL_LCD2));
157                 SR(TIMING_V(OMAP_DSS_CHANNEL_LCD2));
158                 SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2));
159                 SR(DIVISORo(OMAP_DSS_CHANNEL_LCD2));
160                 SR(CONFIG2);
161         }
162
163         SR(OVL_BA0(OMAP_DSS_GFX));
164         SR(OVL_BA1(OMAP_DSS_GFX));
165         SR(OVL_POSITION(OMAP_DSS_GFX));
166         SR(OVL_SIZE(OMAP_DSS_GFX));
167         SR(OVL_ATTRIBUTES(OMAP_DSS_GFX));
168         SR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX));
169         SR(OVL_ROW_INC(OMAP_DSS_GFX));
170         SR(OVL_PIXEL_INC(OMAP_DSS_GFX));
171         SR(OVL_WINDOW_SKIP(OMAP_DSS_GFX));
172         SR(OVL_TABLE_BA(OMAP_DSS_GFX));
173
174         SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD));
175         SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
176         SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
177
178         SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
179         SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
180         SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
181         if (dss_has_feature(FEAT_MGR_LCD2)) {
182                 SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
183                 SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
184                 SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
185
186                 SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
187                 SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
188                 SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
189         }
190
191         SR(OVL_PRELOAD(OMAP_DSS_GFX));
192
193         /* VID1 */
194         SR(OVL_BA0(OMAP_DSS_VIDEO1));
195         SR(OVL_BA1(OMAP_DSS_VIDEO1));
196         SR(OVL_POSITION(OMAP_DSS_VIDEO1));
197         SR(OVL_SIZE(OMAP_DSS_VIDEO1));
198         SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1));
199         SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1));
200         SR(OVL_ROW_INC(OMAP_DSS_VIDEO1));
201         SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1));
202         SR(OVL_FIR(OMAP_DSS_VIDEO1));
203         SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1));
204         SR(OVL_ACCU0(OMAP_DSS_VIDEO1));
205         SR(OVL_ACCU1(OMAP_DSS_VIDEO1));
206
207         SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 0));
208         SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 1));
209         SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 2));
210         SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 3));
211         SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 4));
212         SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 5));
213         SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 6));
214         SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 7));
215
216         SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 0));
217         SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 1));
218         SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 2));
219         SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 3));
220         SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 4));
221         SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 5));
222         SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 6));
223         SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 7));
224
225         SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0));
226         SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1));
227         SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2));
228         SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3));
229         SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4));
230
231         SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0));
232         SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1));
233         SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2));
234         SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3));
235         SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4));
236         SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5));
237         SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6));
238         SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7));
239
240         SR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
241
242         /* VID2 */
243         SR(OVL_BA0(OMAP_DSS_VIDEO2));
244         SR(OVL_BA1(OMAP_DSS_VIDEO2));
245         SR(OVL_POSITION(OMAP_DSS_VIDEO2));
246         SR(OVL_SIZE(OMAP_DSS_VIDEO2));
247         SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2));
248         SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2));
249         SR(OVL_ROW_INC(OMAP_DSS_VIDEO2));
250         SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2));
251         SR(OVL_FIR(OMAP_DSS_VIDEO2));
252         SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2));
253         SR(OVL_ACCU0(OMAP_DSS_VIDEO2));
254         SR(OVL_ACCU1(OMAP_DSS_VIDEO2));
255
256         SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 0));
257         SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 1));
258         SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 2));
259         SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 3));
260         SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 4));
261         SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 5));
262         SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 6));
263         SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 7));
264
265         SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 0));
266         SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 1));
267         SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 2));
268         SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 3));
269         SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 4));
270         SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 5));
271         SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 6));
272         SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 7));
273
274         SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0));
275         SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1));
276         SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2));
277         SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3));
278         SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4));
279
280         SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0));
281         SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1));
282         SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2));
283         SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3));
284         SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4));
285         SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5));
286         SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6));
287         SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7));
288
289         SR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
290
291         if (dss_has_feature(FEAT_CORE_CLK_DIV))
292                 SR(DIVISOR);
293 }
294
295 void dispc_restore_context(void)
296 {
297         RR(SYSCONFIG);
298         /*RR(IRQENABLE);*/
299         /*RR(CONTROL);*/
300         RR(CONFIG);
301         RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD));
302         RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT));
303         RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD));
304         RR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));
305         RR(LINE_NUMBER);
306         RR(TIMING_H(OMAP_DSS_CHANNEL_LCD));
307         RR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
308         RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
309         RR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
310         RR(GLOBAL_ALPHA);
311         RR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
312         RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
313         if (dss_has_feature(FEAT_MGR_LCD2)) {
314                 RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2));
315                 RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2));
316                 RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2));
317                 RR(TIMING_H(OMAP_DSS_CHANNEL_LCD2));
318                 RR(TIMING_V(OMAP_DSS_CHANNEL_LCD2));
319                 RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2));
320                 RR(DIVISORo(OMAP_DSS_CHANNEL_LCD2));
321                 RR(CONFIG2);
322         }
323
324         RR(OVL_BA0(OMAP_DSS_GFX));
325         RR(OVL_BA1(OMAP_DSS_GFX));
326         RR(OVL_POSITION(OMAP_DSS_GFX));
327         RR(OVL_SIZE(OMAP_DSS_GFX));
328         RR(OVL_ATTRIBUTES(OMAP_DSS_GFX));
329         RR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX));
330         RR(OVL_ROW_INC(OMAP_DSS_GFX));
331         RR(OVL_PIXEL_INC(OMAP_DSS_GFX));
332         RR(OVL_WINDOW_SKIP(OMAP_DSS_GFX));
333         RR(OVL_TABLE_BA(OMAP_DSS_GFX));
334
335
336         RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD));
337         RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
338         RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
339
340         RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
341         RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
342         RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
343         if (dss_has_feature(FEAT_MGR_LCD2)) {
344                 RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
345                 RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
346                 RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
347
348                 RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
349                 RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
350                 RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
351         }
352
353         RR(OVL_PRELOAD(OMAP_DSS_GFX));
354
355         /* VID1 */
356         RR(OVL_BA0(OMAP_DSS_VIDEO1));
357         RR(OVL_BA1(OMAP_DSS_VIDEO1));
358         RR(OVL_POSITION(OMAP_DSS_VIDEO1));
359         RR(OVL_SIZE(OMAP_DSS_VIDEO1));
360         RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1));
361         RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1));
362         RR(OVL_ROW_INC(OMAP_DSS_VIDEO1));
363         RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1));
364         RR(OVL_FIR(OMAP_DSS_VIDEO1));
365         RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1));
366         RR(OVL_ACCU0(OMAP_DSS_VIDEO1));
367         RR(OVL_ACCU1(OMAP_DSS_VIDEO1));
368
369         RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 0));
370         RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 1));
371         RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 2));
372         RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 3));
373         RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 4));
374         RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 5));
375         RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 6));
376         RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 7));
377
378         RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 0));
379         RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 1));
380         RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 2));
381         RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 3));
382         RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 4));
383         RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 5));
384         RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 6));
385         RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 7));
386
387         RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0));
388         RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1));
389         RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2));
390         RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3));
391         RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4));
392
393         RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0));
394         RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1));
395         RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2));
396         RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3));
397         RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4));
398         RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5));
399         RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6));
400         RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7));
401
402         RR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
403
404         /* VID2 */
405         RR(OVL_BA0(OMAP_DSS_VIDEO2));
406         RR(OVL_BA1(OMAP_DSS_VIDEO2));
407         RR(OVL_POSITION(OMAP_DSS_VIDEO2));
408         RR(OVL_SIZE(OMAP_DSS_VIDEO2));
409         RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2));
410         RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2));
411         RR(OVL_ROW_INC(OMAP_DSS_VIDEO2));
412         RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2));
413         RR(OVL_FIR(OMAP_DSS_VIDEO2));
414         RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2));
415         RR(OVL_ACCU0(OMAP_DSS_VIDEO2));
416         RR(OVL_ACCU1(OMAP_DSS_VIDEO2));
417
418         RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 0));
419         RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 1));
420         RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 2));
421         RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 3));
422         RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 4));
423         RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 5));
424         RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 6));
425         RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 7));
426
427         RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 0));
428         RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 1));
429         RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 2));
430         RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 3));
431         RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 4));
432         RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 5));
433         RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 6));
434         RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 7));
435
436         RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0));
437         RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1));
438         RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2));
439         RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3));
440         RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4));
441
442         RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0));
443         RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1));
444         RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2));
445         RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3));
446         RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4));
447         RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5));
448         RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6));
449         RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7));
450
451         RR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
452
453         if (dss_has_feature(FEAT_CORE_CLK_DIV))
454                 RR(DIVISOR);
455
456         /* enable last, because LCD & DIGIT enable are here */
457         RR(CONTROL);
458         if (dss_has_feature(FEAT_MGR_LCD2))
459                 RR(CONTROL2);
460         /* clear spurious SYNC_LOST_DIGIT interrupts */
461         dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
462
463         /*
464          * enable last so IRQs won't trigger before
465          * the context is fully restored
466          */
467         RR(IRQENABLE);
468 }
469
470 #undef SR
471 #undef RR
472
473 static inline void enable_clocks(bool enable)
474 {
475         if (enable)
476                 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
477         else
478                 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
479 }
480
481 bool dispc_go_busy(enum omap_channel channel)
482 {
483         int bit;
484
485         if (channel == OMAP_DSS_CHANNEL_LCD ||
486                         channel == OMAP_DSS_CHANNEL_LCD2)
487                 bit = 5; /* GOLCD */
488         else
489                 bit = 6; /* GODIGIT */
490
491         if (channel == OMAP_DSS_CHANNEL_LCD2)
492                 return REG_GET(DISPC_CONTROL2, bit, bit) == 1;
493         else
494                 return REG_GET(DISPC_CONTROL, bit, bit) == 1;
495 }
496
497 void dispc_go(enum omap_channel channel)
498 {
499         int bit;
500         bool enable_bit, go_bit;
501
502         enable_clocks(1);
503
504         if (channel == OMAP_DSS_CHANNEL_LCD ||
505                         channel == OMAP_DSS_CHANNEL_LCD2)
506                 bit = 0; /* LCDENABLE */
507         else
508                 bit = 1; /* DIGITALENABLE */
509
510         /* if the channel is not enabled, we don't need GO */
511         if (channel == OMAP_DSS_CHANNEL_LCD2)
512                 enable_bit = REG_GET(DISPC_CONTROL2, bit, bit) == 1;
513         else
514                 enable_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1;
515
516         if (!enable_bit)
517                 goto end;
518
519         if (channel == OMAP_DSS_CHANNEL_LCD ||
520                         channel == OMAP_DSS_CHANNEL_LCD2)
521                 bit = 5; /* GOLCD */
522         else
523                 bit = 6; /* GODIGIT */
524
525         if (channel == OMAP_DSS_CHANNEL_LCD2)
526                 go_bit = REG_GET(DISPC_CONTROL2, bit, bit) == 1;
527         else
528                 go_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1;
529
530         if (go_bit) {
531                 DSSERR("GO bit not down for channel %d\n", channel);
532                 goto end;
533         }
534
535         DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" :
536                 (channel == OMAP_DSS_CHANNEL_LCD2 ? "LCD2" : "DIGIT"));
537
538         if (channel == OMAP_DSS_CHANNEL_LCD2)
539                 REG_FLD_MOD(DISPC_CONTROL2, 1, bit, bit);
540         else
541                 REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
542 end:
543         enable_clocks(0);
544 }
545
546 static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
547 {
548         dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value);
549 }
550
551 static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
552 {
553         dispc_write_reg(DISPC_OVL_FIR_COEF_HV(plane, reg), value);
554 }
555
556 static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value)
557 {
558         dispc_write_reg(DISPC_OVL_FIR_COEF_V(plane, reg), value);
559 }
560
561 static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
562                 int vscaleup, int five_taps)
563 {
564         /* Coefficients for horizontal up-sampling */
565         static const struct dispc_h_coef coef_hup[8] = {
566                 {  0,   0, 128,   0,  0 },
567                 { -1,  13, 124,  -8,  0 },
568                 { -2,  30, 112, -11, -1 },
569                 { -5,  51,  95, -11, -2 },
570                 {  0,  -9,  73,  73, -9 },
571                 { -2, -11,  95,  51, -5 },
572                 { -1, -11, 112,  30, -2 },
573                 {  0,  -8, 124,  13, -1 },
574         };
575
576         /* Coefficients for vertical up-sampling */
577         static const struct dispc_v_coef coef_vup_3tap[8] = {
578                 { 0,  0, 128,  0, 0 },
579                 { 0,  3, 123,  2, 0 },
580                 { 0, 12, 111,  5, 0 },
581                 { 0, 32,  89,  7, 0 },
582                 { 0,  0,  64, 64, 0 },
583                 { 0,  7,  89, 32, 0 },
584                 { 0,  5, 111, 12, 0 },
585                 { 0,  2, 123,  3, 0 },
586         };
587
588         static const struct dispc_v_coef coef_vup_5tap[8] = {
589                 {  0,   0, 128,   0,  0 },
590                 { -1,  13, 124,  -8,  0 },
591                 { -2,  30, 112, -11, -1 },
592                 { -5,  51,  95, -11, -2 },
593                 {  0,  -9,  73,  73, -9 },
594                 { -2, -11,  95,  51, -5 },
595                 { -1, -11, 112,  30, -2 },
596                 {  0,  -8, 124,  13, -1 },
597         };
598
599         /* Coefficients for horizontal down-sampling */
600         static const struct dispc_h_coef coef_hdown[8] = {
601                 {   0, 36, 56, 36,  0 },
602                 {   4, 40, 55, 31, -2 },
603                 {   8, 44, 54, 27, -5 },
604                 {  12, 48, 53, 22, -7 },
605                 {  -9, 17, 52, 51, 17 },
606                 {  -7, 22, 53, 48, 12 },
607                 {  -5, 27, 54, 44,  8 },
608                 {  -2, 31, 55, 40,  4 },
609         };
610
611         /* Coefficients for vertical down-sampling */
612         static const struct dispc_v_coef coef_vdown_3tap[8] = {
613                 { 0, 36, 56, 36, 0 },
614                 { 0, 40, 57, 31, 0 },
615                 { 0, 45, 56, 27, 0 },
616                 { 0, 50, 55, 23, 0 },
617                 { 0, 18, 55, 55, 0 },
618                 { 0, 23, 55, 50, 0 },
619                 { 0, 27, 56, 45, 0 },
620                 { 0, 31, 57, 40, 0 },
621         };
622
623         static const struct dispc_v_coef coef_vdown_5tap[8] = {
624                 {   0, 36, 56, 36,  0 },
625                 {   4, 40, 55, 31, -2 },
626                 {   8, 44, 54, 27, -5 },
627                 {  12, 48, 53, 22, -7 },
628                 {  -9, 17, 52, 51, 17 },
629                 {  -7, 22, 53, 48, 12 },
630                 {  -5, 27, 54, 44,  8 },
631                 {  -2, 31, 55, 40,  4 },
632         };
633
634         const struct dispc_h_coef *h_coef;
635         const struct dispc_v_coef *v_coef;
636         int i;
637
638         if (hscaleup)
639                 h_coef = coef_hup;
640         else
641                 h_coef = coef_hdown;
642
643         if (vscaleup)
644                 v_coef = five_taps ? coef_vup_5tap : coef_vup_3tap;
645         else
646                 v_coef = five_taps ? coef_vdown_5tap : coef_vdown_3tap;
647
648         for (i = 0; i < 8; i++) {
649                 u32 h, hv;
650
651                 h = FLD_VAL(h_coef[i].hc0, 7, 0)
652                         | FLD_VAL(h_coef[i].hc1, 15, 8)
653                         | FLD_VAL(h_coef[i].hc2, 23, 16)
654                         | FLD_VAL(h_coef[i].hc3, 31, 24);
655                 hv = FLD_VAL(h_coef[i].hc4, 7, 0)
656                         | FLD_VAL(v_coef[i].vc0, 15, 8)
657                         | FLD_VAL(v_coef[i].vc1, 23, 16)
658                         | FLD_VAL(v_coef[i].vc2, 31, 24);
659
660                 _dispc_write_firh_reg(plane, i, h);
661                 _dispc_write_firhv_reg(plane, i, hv);
662         }
663
664         if (five_taps) {
665                 for (i = 0; i < 8; i++) {
666                         u32 v;
667                         v = FLD_VAL(v_coef[i].vc00, 7, 0)
668                                 | FLD_VAL(v_coef[i].vc22, 15, 8);
669                         _dispc_write_firv_reg(plane, i, v);
670                 }
671         }
672 }
673
674 static void _dispc_setup_color_conv_coef(void)
675 {
676         const struct color_conv_coef {
677                 int  ry,  rcr,  rcb,   gy,  gcr,  gcb,   by,  bcr,  bcb;
678                 int  full_range;
679         }  ctbl_bt601_5 = {
680                 298,  409,    0,  298, -208, -100,  298,    0,  517, 0,
681         };
682
683         const struct color_conv_coef *ct;
684
685 #define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
686
687         ct = &ctbl_bt601_5;
688
689         dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0),
690                 CVAL(ct->rcr, ct->ry));
691         dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1),
692                 CVAL(ct->gy,  ct->rcb));
693         dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2),
694                 CVAL(ct->gcb, ct->gcr));
695         dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3),
696                 CVAL(ct->bcr, ct->by));
697         dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4),
698                 CVAL(0, ct->bcb));
699
700         dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0),
701                 CVAL(ct->rcr, ct->ry));
702         dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1),
703                 CVAL(ct->gy, ct->rcb));
704         dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2),
705                 CVAL(ct->gcb, ct->gcr));
706         dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3),
707                 CVAL(ct->bcr, ct->by));
708         dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4),
709                 CVAL(0, ct->bcb));
710
711 #undef CVAL
712
713         REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1),
714                 ct->full_range, 11, 11);
715         REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2),
716                 ct->full_range, 11, 11);
717 }
718
719
720 static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr)
721 {
722         dispc_write_reg(DISPC_OVL_BA0(plane), paddr);
723 }
724
725 static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr)
726 {
727         dispc_write_reg(DISPC_OVL_BA1(plane), paddr);
728 }
729
730 static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y)
731 {
732         u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
733
734         dispc_write_reg(DISPC_OVL_POSITION(plane), val);
735 }
736
737 static void _dispc_set_pic_size(enum omap_plane plane, int width, int height)
738 {
739         u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
740
741         if (plane == OMAP_DSS_GFX)
742                 dispc_write_reg(DISPC_OVL_SIZE(plane), val);
743         else
744                 dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
745 }
746
747 static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
748 {
749         u32 val;
750
751         BUG_ON(plane == OMAP_DSS_GFX);
752
753         val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
754
755         dispc_write_reg(DISPC_OVL_SIZE(plane), val);
756 }
757
758 static void _dispc_set_pre_mult_alpha(enum omap_plane plane, bool enable)
759 {
760         if (!dss_has_feature(FEAT_PRE_MULT_ALPHA))
761                 return;
762
763         if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
764                 plane == OMAP_DSS_VIDEO1)
765                 return;
766
767         REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);
768 }
769
770 static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
771 {
772         if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
773                 return;
774
775         if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
776                 plane == OMAP_DSS_VIDEO1)
777                 return;
778
779         if (plane == OMAP_DSS_GFX)
780                 REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0);
781         else if (plane == OMAP_DSS_VIDEO2)
782                 REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16);
783 }
784
785 static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc)
786 {
787         dispc_write_reg(DISPC_OVL_PIXEL_INC(plane), inc);
788 }
789
790 static void _dispc_set_row_inc(enum omap_plane plane, s32 inc)
791 {
792         dispc_write_reg(DISPC_OVL_ROW_INC(plane), inc);
793 }
794
795 static void _dispc_set_color_mode(enum omap_plane plane,
796                 enum omap_color_mode color_mode)
797 {
798         u32 m = 0;
799
800         switch (color_mode) {
801         case OMAP_DSS_COLOR_CLUT1:
802                 m = 0x0; break;
803         case OMAP_DSS_COLOR_CLUT2:
804                 m = 0x1; break;
805         case OMAP_DSS_COLOR_CLUT4:
806                 m = 0x2; break;
807         case OMAP_DSS_COLOR_CLUT8:
808                 m = 0x3; break;
809         case OMAP_DSS_COLOR_RGB12U:
810                 m = 0x4; break;
811         case OMAP_DSS_COLOR_ARGB16:
812                 m = 0x5; break;
813         case OMAP_DSS_COLOR_RGB16:
814                 m = 0x6; break;
815         case OMAP_DSS_COLOR_RGB24U:
816                 m = 0x8; break;
817         case OMAP_DSS_COLOR_RGB24P:
818                 m = 0x9; break;
819         case OMAP_DSS_COLOR_YUV2:
820                 m = 0xa; break;
821         case OMAP_DSS_COLOR_UYVY:
822                 m = 0xb; break;
823         case OMAP_DSS_COLOR_ARGB32:
824                 m = 0xc; break;
825         case OMAP_DSS_COLOR_RGBA32:
826                 m = 0xd; break;
827         case OMAP_DSS_COLOR_RGBX32:
828                 m = 0xe; break;
829         default:
830                 BUG(); break;
831         }
832
833         REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
834 }
835
836 static void _dispc_set_channel_out(enum omap_plane plane,
837                 enum omap_channel channel)
838 {
839         int shift;
840         u32 val;
841         int chan = 0, chan2 = 0;
842
843         switch (plane) {
844         case OMAP_DSS_GFX:
845                 shift = 8;
846                 break;
847         case OMAP_DSS_VIDEO1:
848         case OMAP_DSS_VIDEO2:
849                 shift = 16;
850                 break;
851         default:
852                 BUG();
853                 return;
854         }
855
856         val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
857         if (dss_has_feature(FEAT_MGR_LCD2)) {
858                 switch (channel) {
859                 case OMAP_DSS_CHANNEL_LCD:
860                         chan = 0;
861                         chan2 = 0;
862                         break;
863                 case OMAP_DSS_CHANNEL_DIGIT:
864                         chan = 1;
865                         chan2 = 0;
866                         break;
867                 case OMAP_DSS_CHANNEL_LCD2:
868                         chan = 0;
869                         chan2 = 1;
870                         break;
871                 default:
872                         BUG();
873                 }
874
875                 val = FLD_MOD(val, chan, shift, shift);
876                 val = FLD_MOD(val, chan2, 31, 30);
877         } else {
878                 val = FLD_MOD(val, channel, shift, shift);
879         }
880         dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
881 }
882
883 void dispc_set_burst_size(enum omap_plane plane,
884                 enum omap_burst_size burst_size)
885 {
886         int shift;
887         u32 val;
888
889         enable_clocks(1);
890
891         switch (plane) {
892         case OMAP_DSS_GFX:
893                 shift = 6;
894                 break;
895         case OMAP_DSS_VIDEO1:
896         case OMAP_DSS_VIDEO2:
897                 shift = 14;
898                 break;
899         default:
900                 BUG();
901                 return;
902         }
903
904         val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
905         val = FLD_MOD(val, burst_size, shift+1, shift);
906         dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
907
908         enable_clocks(0);
909 }
910
911 void dispc_enable_gamma_table(bool enable)
912 {
913         /*
914          * This is partially implemented to support only disabling of
915          * the gamma table.
916          */
917         if (enable) {
918                 DSSWARN("Gamma table enabling for TV not yet supported");
919                 return;
920         }
921
922         REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);
923 }
924
925 static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
926 {
927         u32 val;
928
929         BUG_ON(plane == OMAP_DSS_GFX);
930
931         val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
932         val = FLD_MOD(val, enable, 9, 9);
933         dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
934 }
935
936 void dispc_enable_replication(enum omap_plane plane, bool enable)
937 {
938         int bit;
939
940         if (plane == OMAP_DSS_GFX)
941                 bit = 5;
942         else
943                 bit = 10;
944
945         enable_clocks(1);
946         REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit);
947         enable_clocks(0);
948 }
949
950 void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
951 {
952         u32 val;
953         BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
954         val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
955         enable_clocks(1);
956         dispc_write_reg(DISPC_SIZE_MGR(channel), val);
957         enable_clocks(0);
958 }
959
960 void dispc_set_digit_size(u16 width, u16 height)
961 {
962         u32 val;
963         BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
964         val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
965         enable_clocks(1);
966         dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val);
967         enable_clocks(0);
968 }
969
970 static void dispc_read_plane_fifo_sizes(void)
971 {
972         u32 size;
973         int plane;
974         u8 start, end;
975
976         enable_clocks(1);
977
978         dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
979
980         for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
981                 size = FLD_GET(dispc_read_reg(DISPC_OVL_FIFO_SIZE_STATUS(plane)),
982                         start, end);
983                 dispc.fifo_size[plane] = size;
984         }
985
986         enable_clocks(0);
987 }
988
989 u32 dispc_get_plane_fifo_size(enum omap_plane plane)
990 {
991         return dispc.fifo_size[plane];
992 }
993
994 void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
995 {
996         u8 hi_start, hi_end, lo_start, lo_end;
997
998         dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
999         dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
1000
1001         enable_clocks(1);
1002
1003         DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
1004                         plane,
1005                         REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
1006                                 lo_start, lo_end),
1007                         REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
1008                                 hi_start, hi_end),
1009                         low, high);
1010
1011         dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane),
1012                         FLD_VAL(high, hi_start, hi_end) |
1013                         FLD_VAL(low, lo_start, lo_end));
1014
1015         enable_clocks(0);
1016 }
1017
1018 void dispc_enable_fifomerge(bool enable)
1019 {
1020         enable_clocks(1);
1021
1022         DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
1023         REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
1024
1025         enable_clocks(0);
1026 }
1027
1028 static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc)
1029 {
1030         u32 val;
1031         u8 hinc_start, hinc_end, vinc_start, vinc_end;
1032
1033         dss_feat_get_reg_field(FEAT_REG_FIRHINC, &hinc_start, &hinc_end);
1034         dss_feat_get_reg_field(FEAT_REG_FIRVINC, &vinc_start, &vinc_end);
1035
1036         val = FLD_VAL(vinc, vinc_start, vinc_end) |
1037                         FLD_VAL(hinc, hinc_start, hinc_end);
1038
1039         dispc_write_reg(DISPC_OVL_FIR(plane), val);
1040 }
1041
1042 static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
1043 {
1044         u32 val;
1045         u8 hor_start, hor_end, vert_start, vert_end;
1046
1047         dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end);
1048         dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end);
1049
1050         val = FLD_VAL(vaccu, vert_start, vert_end) |
1051                         FLD_VAL(haccu, hor_start, hor_end);
1052
1053         dispc_write_reg(DISPC_OVL_ACCU0(plane), val);
1054 }
1055
1056 static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
1057 {
1058         u32 val;
1059         u8 hor_start, hor_end, vert_start, vert_end;
1060
1061         dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end);
1062         dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end);
1063
1064         val = FLD_VAL(vaccu, vert_start, vert_end) |
1065                         FLD_VAL(haccu, hor_start, hor_end);
1066
1067         dispc_write_reg(DISPC_OVL_ACCU1(plane), val);
1068 }
1069
1070
1071 static void _dispc_set_scaling(enum omap_plane plane,
1072                 u16 orig_width, u16 orig_height,
1073                 u16 out_width, u16 out_height,
1074                 bool ilace, bool five_taps,
1075                 bool fieldmode)
1076 {
1077         int fir_hinc;
1078         int fir_vinc;
1079         int hscaleup, vscaleup;
1080         int accu0 = 0;
1081         int accu1 = 0;
1082         u32 l;
1083
1084         BUG_ON(plane == OMAP_DSS_GFX);
1085
1086         hscaleup = orig_width <= out_width;
1087         vscaleup = orig_height <= out_height;
1088
1089         _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps);
1090
1091         if (!orig_width || orig_width == out_width)
1092                 fir_hinc = 0;
1093         else
1094                 fir_hinc = 1024 * orig_width / out_width;
1095
1096         if (!orig_height || orig_height == out_height)
1097                 fir_vinc = 0;
1098         else
1099                 fir_vinc = 1024 * orig_height / out_height;
1100
1101         _dispc_set_fir(plane, fir_hinc, fir_vinc);
1102
1103         l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
1104
1105         /* RESIZEENABLE and VERTICALTAPS */
1106         l &= ~((0x3 << 5) | (0x1 << 21));
1107         l |= fir_hinc ? (1 << 5) : 0;
1108         l |= fir_vinc ? (1 << 6) : 0;
1109         l |= five_taps ? (1 << 21) : 0;
1110
1111         /* VRESIZECONF and HRESIZECONF */
1112         if (dss_has_feature(FEAT_RESIZECONF)) {
1113                 l &= ~(0x3 << 7);
1114                 l |= hscaleup ? 0 : (1 << 7);
1115                 l |= vscaleup ? 0 : (1 << 8);
1116         }
1117
1118         /* LINEBUFFERSPLIT */
1119         if (dss_has_feature(FEAT_LINEBUFFERSPLIT)) {
1120                 l &= ~(0x1 << 22);
1121                 l |= five_taps ? (1 << 22) : 0;
1122         }
1123
1124         dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), l);
1125
1126         /*
1127          * field 0 = even field = bottom field
1128          * field 1 = odd field = top field
1129          */
1130         if (ilace && !fieldmode) {
1131                 accu1 = 0;
1132                 accu0 = (fir_vinc / 2) & 0x3ff;
1133                 if (accu0 >= 1024/2) {
1134                         accu1 = 1024/2;
1135                         accu0 -= accu1;
1136                 }
1137         }
1138
1139         _dispc_set_vid_accu0(plane, 0, accu0);
1140         _dispc_set_vid_accu1(plane, 0, accu1);
1141 }
1142
1143 static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
1144                 bool mirroring, enum omap_color_mode color_mode)
1145 {
1146         bool row_repeat = false;
1147         int vidrot = 0;
1148
1149         if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1150                         color_mode == OMAP_DSS_COLOR_UYVY) {
1151
1152                 if (mirroring) {
1153                         switch (rotation) {
1154                         case OMAP_DSS_ROT_0:
1155                                 vidrot = 2;
1156                                 break;
1157                         case OMAP_DSS_ROT_90:
1158                                 vidrot = 1;
1159                                 break;
1160                         case OMAP_DSS_ROT_180:
1161                                 vidrot = 0;
1162                                 break;
1163                         case OMAP_DSS_ROT_270:
1164                                 vidrot = 3;
1165                                 break;
1166                         }
1167                 } else {
1168                         switch (rotation) {
1169                         case OMAP_DSS_ROT_0:
1170                                 vidrot = 0;
1171                                 break;
1172                         case OMAP_DSS_ROT_90:
1173                                 vidrot = 1;
1174                                 break;
1175                         case OMAP_DSS_ROT_180:
1176                                 vidrot = 2;
1177                                 break;
1178                         case OMAP_DSS_ROT_270:
1179                                 vidrot = 3;
1180                                 break;
1181                         }
1182                 }
1183
1184                 if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270)
1185                         row_repeat = true;
1186                 else
1187                         row_repeat = false;
1188         }
1189
1190         REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12);
1191         if (dss_has_feature(FEAT_ROWREPEATENABLE))
1192                 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane),
1193                         row_repeat ? 1 : 0, 18, 18);
1194 }
1195
1196 static int color_mode_to_bpp(enum omap_color_mode color_mode)
1197 {
1198         switch (color_mode) {
1199         case OMAP_DSS_COLOR_CLUT1:
1200                 return 1;
1201         case OMAP_DSS_COLOR_CLUT2:
1202                 return 2;
1203         case OMAP_DSS_COLOR_CLUT4:
1204                 return 4;
1205         case OMAP_DSS_COLOR_CLUT8:
1206                 return 8;
1207         case OMAP_DSS_COLOR_RGB12U:
1208         case OMAP_DSS_COLOR_RGB16:
1209         case OMAP_DSS_COLOR_ARGB16:
1210         case OMAP_DSS_COLOR_YUV2:
1211         case OMAP_DSS_COLOR_UYVY:
1212                 return 16;
1213         case OMAP_DSS_COLOR_RGB24P:
1214                 return 24;
1215         case OMAP_DSS_COLOR_RGB24U:
1216         case OMAP_DSS_COLOR_ARGB32:
1217         case OMAP_DSS_COLOR_RGBA32:
1218         case OMAP_DSS_COLOR_RGBX32:
1219                 return 32;
1220         default:
1221                 BUG();
1222         }
1223 }
1224
1225 static s32 pixinc(int pixels, u8 ps)
1226 {
1227         if (pixels == 1)
1228                 return 1;
1229         else if (pixels > 1)
1230                 return 1 + (pixels - 1) * ps;
1231         else if (pixels < 0)
1232                 return 1 - (-pixels + 1) * ps;
1233         else
1234                 BUG();
1235 }
1236
1237 static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
1238                 u16 screen_width,
1239                 u16 width, u16 height,
1240                 enum omap_color_mode color_mode, bool fieldmode,
1241                 unsigned int field_offset,
1242                 unsigned *offset0, unsigned *offset1,
1243                 s32 *row_inc, s32 *pix_inc)
1244 {
1245         u8 ps;
1246
1247         /* FIXME CLUT formats */
1248         switch (color_mode) {
1249         case OMAP_DSS_COLOR_CLUT1:
1250         case OMAP_DSS_COLOR_CLUT2:
1251         case OMAP_DSS_COLOR_CLUT4:
1252         case OMAP_DSS_COLOR_CLUT8:
1253                 BUG();
1254                 return;
1255         case OMAP_DSS_COLOR_YUV2:
1256         case OMAP_DSS_COLOR_UYVY:
1257                 ps = 4;
1258                 break;
1259         default:
1260                 ps = color_mode_to_bpp(color_mode) / 8;
1261                 break;
1262         }
1263
1264         DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
1265                         width, height);
1266
1267         /*
1268          * field 0 = even field = bottom field
1269          * field 1 = odd field = top field
1270          */
1271         switch (rotation + mirror * 4) {
1272         case OMAP_DSS_ROT_0:
1273         case OMAP_DSS_ROT_180:
1274                 /*
1275                  * If the pixel format is YUV or UYVY divide the width
1276                  * of the image by 2 for 0 and 180 degree rotation.
1277                  */
1278                 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1279                         color_mode == OMAP_DSS_COLOR_UYVY)
1280                         width = width >> 1;
1281         case OMAP_DSS_ROT_90:
1282         case OMAP_DSS_ROT_270:
1283                 *offset1 = 0;
1284                 if (field_offset)
1285                         *offset0 = field_offset * screen_width * ps;
1286                 else
1287                         *offset0 = 0;
1288
1289                 *row_inc = pixinc(1 + (screen_width - width) +
1290                                 (fieldmode ? screen_width : 0),
1291                                 ps);
1292                 *pix_inc = pixinc(1, ps);
1293                 break;
1294
1295         case OMAP_DSS_ROT_0 + 4:
1296         case OMAP_DSS_ROT_180 + 4:
1297                 /* If the pixel format is YUV or UYVY divide the width
1298                  * of the image by 2  for 0 degree and 180 degree
1299                  */
1300                 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1301                         color_mode == OMAP_DSS_COLOR_UYVY)
1302                         width = width >> 1;
1303         case OMAP_DSS_ROT_90 + 4:
1304         case OMAP_DSS_ROT_270 + 4:
1305                 *offset1 = 0;
1306                 if (field_offset)
1307                         *offset0 = field_offset * screen_width * ps;
1308                 else
1309                         *offset0 = 0;
1310                 *row_inc = pixinc(1 - (screen_width + width) -
1311                                 (fieldmode ? screen_width : 0),
1312                                 ps);
1313                 *pix_inc = pixinc(1, ps);
1314                 break;
1315
1316         default:
1317                 BUG();
1318         }
1319 }
1320
1321 static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1322                 u16 screen_width,
1323                 u16 width, u16 height,
1324                 enum omap_color_mode color_mode, bool fieldmode,
1325                 unsigned int field_offset,
1326                 unsigned *offset0, unsigned *offset1,
1327                 s32 *row_inc, s32 *pix_inc)
1328 {
1329         u8 ps;
1330         u16 fbw, fbh;
1331
1332         /* FIXME CLUT formats */
1333         switch (color_mode) {
1334         case OMAP_DSS_COLOR_CLUT1:
1335         case OMAP_DSS_COLOR_CLUT2:
1336         case OMAP_DSS_COLOR_CLUT4:
1337         case OMAP_DSS_COLOR_CLUT8:
1338                 BUG();
1339                 return;
1340         default:
1341                 ps = color_mode_to_bpp(color_mode) / 8;
1342                 break;
1343         }
1344
1345         DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
1346                         width, height);
1347
1348         /* width & height are overlay sizes, convert to fb sizes */
1349
1350         if (rotation == OMAP_DSS_ROT_0 || rotation == OMAP_DSS_ROT_180) {
1351                 fbw = width;
1352                 fbh = height;
1353         } else {
1354                 fbw = height;
1355                 fbh = width;
1356         }
1357
1358         /*
1359          * field 0 = even field = bottom field
1360          * field 1 = odd field = top field
1361          */
1362         switch (rotation + mirror * 4) {
1363         case OMAP_DSS_ROT_0:
1364                 *offset1 = 0;
1365                 if (field_offset)
1366                         *offset0 = *offset1 + field_offset * screen_width * ps;
1367                 else
1368                         *offset0 = *offset1;
1369                 *row_inc = pixinc(1 + (screen_width - fbw) +
1370                                 (fieldmode ? screen_width : 0),
1371                                 ps);
1372                 *pix_inc = pixinc(1, ps);
1373                 break;
1374         case OMAP_DSS_ROT_90:
1375                 *offset1 = screen_width * (fbh - 1) * ps;
1376                 if (field_offset)
1377                         *offset0 = *offset1 + field_offset * ps;
1378                 else
1379                         *offset0 = *offset1;
1380                 *row_inc = pixinc(screen_width * (fbh - 1) + 1 +
1381                                 (fieldmode ? 1 : 0), ps);
1382                 *pix_inc = pixinc(-screen_width, ps);
1383                 break;
1384         case OMAP_DSS_ROT_180:
1385                 *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
1386                 if (field_offset)
1387                         *offset0 = *offset1 - field_offset * screen_width * ps;
1388                 else
1389                         *offset0 = *offset1;
1390                 *row_inc = pixinc(-1 -
1391                                 (screen_width - fbw) -
1392                                 (fieldmode ? screen_width : 0),
1393                                 ps);
1394                 *pix_inc = pixinc(-1, ps);
1395                 break;
1396         case OMAP_DSS_ROT_270:
1397                 *offset1 = (fbw - 1) * ps;
1398                 if (field_offset)
1399                         *offset0 = *offset1 - field_offset * ps;
1400                 else
1401                         *offset0 = *offset1;
1402                 *row_inc = pixinc(-screen_width * (fbh - 1) - 1 -
1403                                 (fieldmode ? 1 : 0), ps);
1404                 *pix_inc = pixinc(screen_width, ps);
1405                 break;
1406
1407         /* mirroring */
1408         case OMAP_DSS_ROT_0 + 4:
1409                 *offset1 = (fbw - 1) * ps;
1410                 if (field_offset)
1411                         *offset0 = *offset1 + field_offset * screen_width * ps;
1412                 else
1413                         *offset0 = *offset1;
1414                 *row_inc = pixinc(screen_width * 2 - 1 +
1415                                 (fieldmode ? screen_width : 0),
1416                                 ps);
1417                 *pix_inc = pixinc(-1, ps);
1418                 break;
1419
1420         case OMAP_DSS_ROT_90 + 4:
1421                 *offset1 = 0;
1422                 if (field_offset)
1423                         *offset0 = *offset1 + field_offset * ps;
1424                 else
1425                         *offset0 = *offset1;
1426                 *row_inc = pixinc(-screen_width * (fbh - 1) + 1 +
1427                                 (fieldmode ? 1 : 0),
1428                                 ps);
1429                 *pix_inc = pixinc(screen_width, ps);
1430                 break;
1431
1432         case OMAP_DSS_ROT_180 + 4:
1433                 *offset1 = screen_width * (fbh - 1) * ps;
1434                 if (field_offset)
1435                         *offset0 = *offset1 - field_offset * screen_width * ps;
1436                 else
1437                         *offset0 = *offset1;
1438                 *row_inc = pixinc(1 - screen_width * 2 -
1439                                 (fieldmode ? screen_width : 0),
1440                                 ps);
1441                 *pix_inc = pixinc(1, ps);
1442                 break;
1443
1444         case OMAP_DSS_ROT_270 + 4:
1445                 *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
1446                 if (field_offset)
1447                         *offset0 = *offset1 - field_offset * ps;
1448                 else
1449                         *offset0 = *offset1;
1450                 *row_inc = pixinc(screen_width * (fbh - 1) - 1 -
1451                                 (fieldmode ? 1 : 0),
1452                                 ps);
1453                 *pix_inc = pixinc(-screen_width, ps);
1454                 break;
1455
1456         default:
1457                 BUG();
1458         }
1459 }
1460
1461 static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,
1462                 u16 height, u16 out_width, u16 out_height,
1463                 enum omap_color_mode color_mode)
1464 {
1465         u32 fclk = 0;
1466         /* FIXME venc pclk? */
1467         u64 tmp, pclk = dispc_pclk_rate(channel);
1468
1469         if (height > out_height) {
1470                 /* FIXME get real display PPL */
1471                 unsigned int ppl = 800;
1472
1473                 tmp = pclk * height * out_width;
1474                 do_div(tmp, 2 * out_height * ppl);
1475                 fclk = tmp;
1476
1477                 if (height > 2 * out_height) {
1478                         if (ppl == out_width)
1479                                 return 0;
1480
1481                         tmp = pclk * (height - 2 * out_height) * out_width;
1482                         do_div(tmp, 2 * out_height * (ppl - out_width));
1483                         fclk = max(fclk, (u32) tmp);
1484                 }
1485         }
1486
1487         if (width > out_width) {
1488                 tmp = pclk * width;
1489                 do_div(tmp, out_width);
1490                 fclk = max(fclk, (u32) tmp);
1491
1492                 if (color_mode == OMAP_DSS_COLOR_RGB24U)
1493                         fclk <<= 1;
1494         }
1495
1496         return fclk;
1497 }
1498
1499 static unsigned long calc_fclk(enum omap_channel channel, u16 width,
1500                 u16 height, u16 out_width, u16 out_height)
1501 {
1502         unsigned int hf, vf;
1503
1504         /*
1505          * FIXME how to determine the 'A' factor
1506          * for the no downscaling case ?
1507          */
1508
1509         if (width > 3 * out_width)
1510                 hf = 4;
1511         else if (width > 2 * out_width)
1512                 hf = 3;
1513         else if (width > out_width)
1514                 hf = 2;
1515         else
1516                 hf = 1;
1517
1518         if (height > out_height)
1519                 vf = 2;
1520         else
1521                 vf = 1;
1522
1523         /* FIXME venc pclk? */
1524         return dispc_pclk_rate(channel) * vf * hf;
1525 }
1526
1527 void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out)
1528 {
1529         enable_clocks(1);
1530         _dispc_set_channel_out(plane, channel_out);
1531         enable_clocks(0);
1532 }
1533
1534 static int _dispc_setup_plane(enum omap_plane plane,
1535                 u32 paddr, u16 screen_width,
1536                 u16 pos_x, u16 pos_y,
1537                 u16 width, u16 height,
1538                 u16 out_width, u16 out_height,
1539                 enum omap_color_mode color_mode,
1540                 bool ilace,
1541                 enum omap_dss_rotation_type rotation_type,
1542                 u8 rotation, int mirror,
1543                 u8 global_alpha, u8 pre_mult_alpha,
1544                 enum omap_channel channel)
1545 {
1546         const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
1547         bool five_taps = 0;
1548         bool fieldmode = 0;
1549         int cconv = 0;
1550         unsigned offset0, offset1;
1551         s32 row_inc;
1552         s32 pix_inc;
1553         u16 frame_height = height;
1554         unsigned int field_offset = 0;
1555
1556         if (paddr == 0)
1557                 return -EINVAL;
1558
1559         if (ilace && height == out_height)
1560                 fieldmode = 1;
1561
1562         if (ilace) {
1563                 if (fieldmode)
1564                         height /= 2;
1565                 pos_y /= 2;
1566                 out_height /= 2;
1567
1568                 DSSDBG("adjusting for ilace: height %d, pos_y %d, "
1569                                 "out_height %d\n",
1570                                 height, pos_y, out_height);
1571         }
1572
1573         if (!dss_feat_color_mode_supported(plane, color_mode))
1574                 return -EINVAL;
1575
1576         if (plane == OMAP_DSS_GFX) {
1577                 if (width != out_width || height != out_height)
1578                         return -EINVAL;
1579         } else {
1580                 /* video plane */
1581
1582                 unsigned long fclk = 0;
1583
1584                 if (out_width < width / maxdownscale ||
1585                    out_width > width * 8)
1586                         return -EINVAL;
1587
1588                 if (out_height < height / maxdownscale ||
1589                    out_height > height * 8)
1590                         return -EINVAL;
1591
1592                 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1593                         color_mode == OMAP_DSS_COLOR_UYVY)
1594                         cconv = 1;
1595
1596                 /* Must use 5-tap filter? */
1597                 five_taps = height > out_height * 2;
1598
1599                 if (!five_taps) {
1600                         fclk = calc_fclk(channel, width, height, out_width,
1601                                         out_height);
1602
1603                         /* Try 5-tap filter if 3-tap fclk is too high */
1604                         if (cpu_is_omap34xx() && height > out_height &&
1605                                         fclk > dispc_fclk_rate())
1606                                 five_taps = true;
1607                 }
1608
1609                 if (width > (2048 >> five_taps)) {
1610                         DSSERR("failed to set up scaling, fclk too low\n");
1611                         return -EINVAL;
1612                 }
1613
1614                 if (five_taps)
1615                         fclk = calc_fclk_five_taps(channel, width, height,
1616                                         out_width, out_height, color_mode);
1617
1618                 DSSDBG("required fclk rate = %lu Hz\n", fclk);
1619                 DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
1620
1621                 if (!fclk || fclk > dispc_fclk_rate()) {
1622                         DSSERR("failed to set up scaling, "
1623                                         "required fclk rate = %lu Hz, "
1624                                         "current fclk rate = %lu Hz\n",
1625                                         fclk, dispc_fclk_rate());
1626                         return -EINVAL;
1627                 }
1628         }
1629
1630         if (ilace && !fieldmode) {
1631                 /*
1632                  * when downscaling the bottom field may have to start several
1633                  * source lines below the top field. Unfortunately ACCUI
1634                  * registers will only hold the fractional part of the offset
1635                  * so the integer part must be added to the base address of the
1636                  * bottom field.
1637                  */
1638                 if (!height || height == out_height)
1639                         field_offset = 0;
1640                 else
1641                         field_offset = height / out_height / 2;
1642         }
1643
1644         /* Fields are independent but interleaved in memory. */
1645         if (fieldmode)
1646                 field_offset = 1;
1647
1648         if (rotation_type == OMAP_DSS_ROT_DMA)
1649                 calc_dma_rotation_offset(rotation, mirror,
1650                                 screen_width, width, frame_height, color_mode,
1651                                 fieldmode, field_offset,
1652                                 &offset0, &offset1, &row_inc, &pix_inc);
1653         else
1654                 calc_vrfb_rotation_offset(rotation, mirror,
1655                                 screen_width, width, frame_height, color_mode,
1656                                 fieldmode, field_offset,
1657                                 &offset0, &offset1, &row_inc, &pix_inc);
1658
1659         DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
1660                         offset0, offset1, row_inc, pix_inc);
1661
1662         _dispc_set_color_mode(plane, color_mode);
1663
1664         _dispc_set_plane_ba0(plane, paddr + offset0);
1665         _dispc_set_plane_ba1(plane, paddr + offset1);
1666
1667         _dispc_set_row_inc(plane, row_inc);
1668         _dispc_set_pix_inc(plane, pix_inc);
1669
1670         DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height,
1671                         out_width, out_height);
1672
1673         _dispc_set_plane_pos(plane, pos_x, pos_y);
1674
1675         _dispc_set_pic_size(plane, width, height);
1676
1677         if (plane != OMAP_DSS_GFX) {
1678                 _dispc_set_scaling(plane, width, height,
1679                                    out_width, out_height,
1680                                    ilace, five_taps, fieldmode);
1681                 _dispc_set_vid_size(plane, out_width, out_height);
1682                 _dispc_set_vid_color_conv(plane, cconv);
1683         }
1684
1685         _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode);
1686
1687         _dispc_set_pre_mult_alpha(plane, pre_mult_alpha);
1688         _dispc_setup_global_alpha(plane, global_alpha);
1689
1690         return 0;
1691 }
1692
1693 static void _dispc_enable_plane(enum omap_plane plane, bool enable)
1694 {
1695         REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
1696 }
1697
1698 static void dispc_disable_isr(void *data, u32 mask)
1699 {
1700         struct completion *compl = data;
1701         complete(compl);
1702 }
1703
1704 static void _enable_lcd_out(enum omap_channel channel, bool enable)
1705 {
1706         if (channel == OMAP_DSS_CHANNEL_LCD2)
1707                 REG_FLD_MOD(DISPC_CONTROL2, enable ? 1 : 0, 0, 0);
1708         else
1709                 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
1710 }
1711
1712 static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
1713 {
1714         struct completion frame_done_completion;
1715         bool is_on;
1716         int r;
1717         u32 irq;
1718
1719         enable_clocks(1);
1720
1721         /* When we disable LCD output, we need to wait until frame is done.
1722          * Otherwise the DSS is still working, and turning off the clocks
1723          * prevents DSS from going to OFF mode */
1724         is_on = channel == OMAP_DSS_CHANNEL_LCD2 ?
1725                         REG_GET(DISPC_CONTROL2, 0, 0) :
1726                         REG_GET(DISPC_CONTROL, 0, 0);
1727
1728         irq = channel == OMAP_DSS_CHANNEL_LCD2 ? DISPC_IRQ_FRAMEDONE2 :
1729                         DISPC_IRQ_FRAMEDONE;
1730
1731         if (!enable && is_on) {
1732                 init_completion(&frame_done_completion);
1733
1734                 r = omap_dispc_register_isr(dispc_disable_isr,
1735                                 &frame_done_completion, irq);
1736
1737                 if (r)
1738                         DSSERR("failed to register FRAMEDONE isr\n");
1739         }
1740
1741         _enable_lcd_out(channel, enable);
1742
1743         if (!enable && is_on) {
1744                 if (!wait_for_completion_timeout(&frame_done_completion,
1745                                         msecs_to_jiffies(100)))
1746                         DSSERR("timeout waiting for FRAME DONE\n");
1747
1748                 r = omap_dispc_unregister_isr(dispc_disable_isr,
1749                                 &frame_done_completion, irq);
1750
1751                 if (r)
1752                         DSSERR("failed to unregister FRAMEDONE isr\n");
1753         }
1754
1755         enable_clocks(0);
1756 }
1757
1758 static void _enable_digit_out(bool enable)
1759 {
1760         REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
1761 }
1762
1763 static void dispc_enable_digit_out(bool enable)
1764 {
1765         struct completion frame_done_completion;
1766         int r;
1767
1768         enable_clocks(1);
1769
1770         if (REG_GET(DISPC_CONTROL, 1, 1) == enable) {
1771                 enable_clocks(0);
1772                 return;
1773         }
1774
1775         if (enable) {
1776                 unsigned long flags;
1777                 /* When we enable digit output, we'll get an extra digit
1778                  * sync lost interrupt, that we need to ignore */
1779                 spin_lock_irqsave(&dispc.irq_lock, flags);
1780                 dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
1781                 _omap_dispc_set_irqs();
1782                 spin_unlock_irqrestore(&dispc.irq_lock, flags);
1783         }
1784
1785         /* When we disable digit output, we need to wait until fields are done.
1786          * Otherwise the DSS is still working, and turning off the clocks
1787          * prevents DSS from going to OFF mode. And when enabling, we need to
1788          * wait for the extra sync losts */
1789         init_completion(&frame_done_completion);
1790
1791         r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion,
1792                         DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
1793         if (r)
1794                 DSSERR("failed to register EVSYNC isr\n");
1795
1796         _enable_digit_out(enable);
1797
1798         /* XXX I understand from TRM that we should only wait for the
1799          * current field to complete. But it seems we have to wait
1800          * for both fields */
1801         if (!wait_for_completion_timeout(&frame_done_completion,
1802                                 msecs_to_jiffies(100)))
1803                 DSSERR("timeout waiting for EVSYNC\n");
1804
1805         if (!wait_for_completion_timeout(&frame_done_completion,
1806                                 msecs_to_jiffies(100)))
1807                 DSSERR("timeout waiting for EVSYNC\n");
1808
1809         r = omap_dispc_unregister_isr(dispc_disable_isr,
1810                         &frame_done_completion,
1811                         DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
1812         if (r)
1813                 DSSERR("failed to unregister EVSYNC isr\n");
1814
1815         if (enable) {
1816                 unsigned long flags;
1817                 spin_lock_irqsave(&dispc.irq_lock, flags);
1818                 dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
1819                 if (dss_has_feature(FEAT_MGR_LCD2))
1820                         dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
1821                 dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
1822                 _omap_dispc_set_irqs();
1823                 spin_unlock_irqrestore(&dispc.irq_lock, flags);
1824         }
1825
1826         enable_clocks(0);
1827 }
1828
1829 bool dispc_is_channel_enabled(enum omap_channel channel)
1830 {
1831         if (channel == OMAP_DSS_CHANNEL_LCD)
1832                 return !!REG_GET(DISPC_CONTROL, 0, 0);
1833         else if (channel == OMAP_DSS_CHANNEL_DIGIT)
1834                 return !!REG_GET(DISPC_CONTROL, 1, 1);
1835         else if (channel == OMAP_DSS_CHANNEL_LCD2)
1836                 return !!REG_GET(DISPC_CONTROL2, 0, 0);
1837         else
1838                 BUG();
1839 }
1840
1841 void dispc_enable_channel(enum omap_channel channel, bool enable)
1842 {
1843         if (channel == OMAP_DSS_CHANNEL_LCD ||
1844                         channel == OMAP_DSS_CHANNEL_LCD2)
1845                 dispc_enable_lcd_out(channel, enable);
1846         else if (channel == OMAP_DSS_CHANNEL_DIGIT)
1847                 dispc_enable_digit_out(enable);
1848         else
1849                 BUG();
1850 }
1851
1852 void dispc_lcd_enable_signal_polarity(bool act_high)
1853 {
1854         if (!dss_has_feature(FEAT_LCDENABLEPOL))
1855                 return;
1856
1857         enable_clocks(1);
1858         REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
1859         enable_clocks(0);
1860 }
1861
1862 void dispc_lcd_enable_signal(bool enable)
1863 {
1864         if (!dss_has_feature(FEAT_LCDENABLESIGNAL))
1865                 return;
1866
1867         enable_clocks(1);
1868         REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
1869         enable_clocks(0);
1870 }
1871
1872 void dispc_pck_free_enable(bool enable)
1873 {
1874         if (!dss_has_feature(FEAT_PCKFREEENABLE))
1875                 return;
1876
1877         enable_clocks(1);
1878         REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
1879         enable_clocks(0);
1880 }
1881
1882 void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable)
1883 {
1884         enable_clocks(1);
1885         if (channel == OMAP_DSS_CHANNEL_LCD2)
1886                 REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16);
1887         else
1888                 REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
1889         enable_clocks(0);
1890 }
1891
1892
1893 void dispc_set_lcd_display_type(enum omap_channel channel,
1894                 enum omap_lcd_display_type type)
1895 {
1896         int mode;
1897
1898         switch (type) {
1899         case OMAP_DSS_LCD_DISPLAY_STN:
1900                 mode = 0;
1901                 break;
1902
1903         case OMAP_DSS_LCD_DISPLAY_TFT:
1904                 mode = 1;
1905                 break;
1906
1907         default:
1908                 BUG();
1909                 return;
1910         }
1911
1912         enable_clocks(1);
1913         if (channel == OMAP_DSS_CHANNEL_LCD2)
1914                 REG_FLD_MOD(DISPC_CONTROL2, mode, 3, 3);
1915         else
1916                 REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
1917         enable_clocks(0);
1918 }
1919
1920 void dispc_set_loadmode(enum omap_dss_load_mode mode)
1921 {
1922         enable_clocks(1);
1923         REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
1924         enable_clocks(0);
1925 }
1926
1927
1928 void dispc_set_default_color(enum omap_channel channel, u32 color)
1929 {
1930         enable_clocks(1);
1931         dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
1932         enable_clocks(0);
1933 }
1934
1935 u32 dispc_get_default_color(enum omap_channel channel)
1936 {
1937         u32 l;
1938
1939         BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT &&
1940                 channel != OMAP_DSS_CHANNEL_LCD &&
1941                 channel != OMAP_DSS_CHANNEL_LCD2);
1942
1943         enable_clocks(1);
1944         l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel));
1945         enable_clocks(0);
1946
1947         return l;
1948 }
1949
1950 void dispc_set_trans_key(enum omap_channel ch,
1951                 enum omap_dss_trans_key_type type,
1952                 u32 trans_key)
1953 {
1954         enable_clocks(1);
1955         if (ch == OMAP_DSS_CHANNEL_LCD)
1956                 REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
1957         else if (ch == OMAP_DSS_CHANNEL_DIGIT)
1958                 REG_FLD_MOD(DISPC_CONFIG, type, 13, 13);
1959         else /* OMAP_DSS_CHANNEL_LCD2 */
1960                 REG_FLD_MOD(DISPC_CONFIG2, type, 11, 11);
1961
1962         dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
1963         enable_clocks(0);
1964 }
1965
1966 void dispc_get_trans_key(enum omap_channel ch,
1967                 enum omap_dss_trans_key_type *type,
1968                 u32 *trans_key)
1969 {
1970         enable_clocks(1);
1971         if (type) {
1972                 if (ch == OMAP_DSS_CHANNEL_LCD)
1973                         *type = REG_GET(DISPC_CONFIG, 11, 11);
1974                 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
1975                         *type = REG_GET(DISPC_CONFIG, 13, 13);
1976                 else if (ch == OMAP_DSS_CHANNEL_LCD2)
1977                         *type = REG_GET(DISPC_CONFIG2, 11, 11);
1978                 else
1979                         BUG();
1980         }
1981
1982         if (trans_key)
1983                 *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch));
1984         enable_clocks(0);
1985 }
1986
1987 void dispc_enable_trans_key(enum omap_channel ch, bool enable)
1988 {
1989         enable_clocks(1);
1990         if (ch == OMAP_DSS_CHANNEL_LCD)
1991                 REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
1992         else if (ch == OMAP_DSS_CHANNEL_DIGIT)
1993                 REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
1994         else /* OMAP_DSS_CHANNEL_LCD2 */
1995                 REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10);
1996         enable_clocks(0);
1997 }
1998 void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
1999 {
2000         if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
2001                 return;
2002
2003         enable_clocks(1);
2004         if (ch == OMAP_DSS_CHANNEL_LCD)
2005                 REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
2006         else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2007                 REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
2008         else /* OMAP_DSS_CHANNEL_LCD2 */
2009                 REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18);
2010         enable_clocks(0);
2011 }
2012 bool dispc_alpha_blending_enabled(enum omap_channel ch)
2013 {
2014         bool enabled;
2015
2016         if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
2017                 return false;
2018
2019         enable_clocks(1);
2020         if (ch == OMAP_DSS_CHANNEL_LCD)
2021                 enabled = REG_GET(DISPC_CONFIG, 18, 18);
2022         else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2023                 enabled = REG_GET(DISPC_CONFIG, 19, 19);
2024         else if (ch == OMAP_DSS_CHANNEL_LCD2)
2025                 enabled = REG_GET(DISPC_CONFIG2, 18, 18);
2026         else
2027                 BUG();
2028         enable_clocks(0);
2029
2030         return enabled;
2031 }
2032
2033
2034 bool dispc_trans_key_enabled(enum omap_channel ch)
2035 {
2036         bool enabled;
2037
2038         enable_clocks(1);
2039         if (ch == OMAP_DSS_CHANNEL_LCD)
2040                 enabled = REG_GET(DISPC_CONFIG, 10, 10);
2041         else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2042                 enabled = REG_GET(DISPC_CONFIG, 12, 12);
2043         else if (ch == OMAP_DSS_CHANNEL_LCD2)
2044                 enabled = REG_GET(DISPC_CONFIG2, 10, 10);
2045         else
2046                 BUG();
2047         enable_clocks(0);
2048
2049         return enabled;
2050 }
2051
2052
2053 void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
2054 {
2055         int code;
2056
2057         switch (data_lines) {
2058         case 12:
2059                 code = 0;
2060                 break;
2061         case 16:
2062                 code = 1;
2063                 break;
2064         case 18:
2065                 code = 2;
2066                 break;
2067         case 24:
2068                 code = 3;
2069                 break;
2070         default:
2071                 BUG();
2072                 return;
2073         }
2074
2075         enable_clocks(1);
2076         if (channel == OMAP_DSS_CHANNEL_LCD2)
2077                 REG_FLD_MOD(DISPC_CONTROL2, code, 9, 8);
2078         else
2079                 REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
2080         enable_clocks(0);
2081 }
2082
2083 void dispc_set_parallel_interface_mode(enum omap_channel channel,
2084                 enum omap_parallel_interface_mode mode)
2085 {
2086         u32 l;
2087         int stallmode;
2088         int gpout0 = 1;
2089         int gpout1;
2090
2091         switch (mode) {
2092         case OMAP_DSS_PARALLELMODE_BYPASS:
2093                 stallmode = 0;
2094                 gpout1 = 1;
2095                 break;
2096
2097         case OMAP_DSS_PARALLELMODE_RFBI:
2098                 stallmode = 1;
2099                 gpout1 = 0;
2100                 break;
2101
2102         case OMAP_DSS_PARALLELMODE_DSI:
2103                 stallmode = 1;
2104                 gpout1 = 1;
2105                 break;
2106
2107         default:
2108                 BUG();
2109                 return;
2110         }
2111
2112         enable_clocks(1);
2113
2114         if (channel == OMAP_DSS_CHANNEL_LCD2) {
2115                 l = dispc_read_reg(DISPC_CONTROL2);
2116                 l = FLD_MOD(l, stallmode, 11, 11);
2117                 dispc_write_reg(DISPC_CONTROL2, l);
2118         } else {
2119                 l = dispc_read_reg(DISPC_CONTROL);
2120                 l = FLD_MOD(l, stallmode, 11, 11);
2121                 l = FLD_MOD(l, gpout0, 15, 15);
2122                 l = FLD_MOD(l, gpout1, 16, 16);
2123                 dispc_write_reg(DISPC_CONTROL, l);
2124         }
2125
2126         enable_clocks(0);
2127 }
2128
2129 static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
2130                 int vsw, int vfp, int vbp)
2131 {
2132         if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
2133                 if (hsw < 1 || hsw > 64 ||
2134                                 hfp < 1 || hfp > 256 ||
2135                                 hbp < 1 || hbp > 256 ||
2136                                 vsw < 1 || vsw > 64 ||
2137                                 vfp < 0 || vfp > 255 ||
2138                                 vbp < 0 || vbp > 255)
2139                         return false;
2140         } else {
2141                 if (hsw < 1 || hsw > 256 ||
2142                                 hfp < 1 || hfp > 4096 ||
2143                                 hbp < 1 || hbp > 4096 ||
2144                                 vsw < 1 || vsw > 256 ||
2145                                 vfp < 0 || vfp > 4095 ||
2146                                 vbp < 0 || vbp > 4095)
2147                         return false;
2148         }
2149
2150         return true;
2151 }
2152
2153 bool dispc_lcd_timings_ok(struct omap_video_timings *timings)
2154 {
2155         return _dispc_lcd_timings_ok(timings->hsw, timings->hfp,
2156                         timings->hbp, timings->vsw,
2157                         timings->vfp, timings->vbp);
2158 }
2159
2160 static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw,
2161                 int hfp, int hbp, int vsw, int vfp, int vbp)
2162 {
2163         u32 timing_h, timing_v;
2164
2165         if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
2166                 timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) |
2167                         FLD_VAL(hbp-1, 27, 20);
2168
2169                 timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) |
2170                         FLD_VAL(vbp, 27, 20);
2171         } else {
2172                 timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) |
2173                         FLD_VAL(hbp-1, 31, 20);
2174
2175                 timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) |
2176                         FLD_VAL(vbp, 31, 20);
2177         }
2178
2179         enable_clocks(1);
2180         dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
2181         dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
2182         enable_clocks(0);
2183 }
2184
2185 /* change name to mode? */
2186 void dispc_set_lcd_timings(enum omap_channel channel,
2187                 struct omap_video_timings *timings)
2188 {
2189         unsigned xtot, ytot;
2190         unsigned long ht, vt;
2191
2192         if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp,
2193                                 timings->hbp, timings->vsw,
2194                                 timings->vfp, timings->vbp))
2195                 BUG();
2196
2197         _dispc_set_lcd_timings(channel, timings->hsw, timings->hfp,
2198                         timings->hbp, timings->vsw, timings->vfp,
2199                         timings->vbp);
2200
2201         dispc_set_lcd_size(channel, timings->x_res, timings->y_res);
2202
2203         xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp;
2204         ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp;
2205
2206         ht = (timings->pixel_clock * 1000) / xtot;
2207         vt = (timings->pixel_clock * 1000) / xtot / ytot;
2208
2209         DSSDBG("channel %d xres %u yres %u\n", channel, timings->x_res,
2210                         timings->y_res);
2211         DSSDBG("pck %u\n", timings->pixel_clock);
2212         DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
2213                         timings->hsw, timings->hfp, timings->hbp,
2214                         timings->vsw, timings->vfp, timings->vbp);
2215
2216         DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
2217 }
2218
2219 static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
2220                 u16 pck_div)
2221 {
2222         BUG_ON(lck_div < 1);
2223         BUG_ON(pck_div < 2);
2224
2225         enable_clocks(1);
2226         dispc_write_reg(DISPC_DIVISORo(channel),
2227                         FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
2228         enable_clocks(0);
2229 }
2230
2231 static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div,
2232                 int *pck_div)
2233 {
2234         u32 l;
2235         l = dispc_read_reg(DISPC_DIVISORo(channel));
2236         *lck_div = FLD_GET(l, 23, 16);
2237         *pck_div = FLD_GET(l, 7, 0);
2238 }
2239
2240 unsigned long dispc_fclk_rate(void)
2241 {
2242         struct platform_device *dsidev;
2243         unsigned long r = 0;
2244
2245         switch (dss_get_dispc_clk_source()) {
2246         case OMAP_DSS_CLK_SRC_FCK:
2247                 r = dss_clk_get_rate(DSS_CLK_FCK);
2248                 break;
2249         case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
2250                 dsidev = dsi_get_dsidev_from_id(0);
2251                 r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
2252                 break;
2253         case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
2254                 dsidev = dsi_get_dsidev_from_id(1);
2255                 r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
2256                 break;
2257         default:
2258                 BUG();
2259         }
2260
2261         return r;
2262 }
2263
2264 unsigned long dispc_lclk_rate(enum omap_channel channel)
2265 {
2266         struct platform_device *dsidev;
2267         int lcd;
2268         unsigned long r;
2269         u32 l;
2270
2271         l = dispc_read_reg(DISPC_DIVISORo(channel));
2272
2273         lcd = FLD_GET(l, 23, 16);
2274
2275         switch (dss_get_lcd_clk_source(channel)) {
2276         case OMAP_DSS_CLK_SRC_FCK:
2277                 r = dss_clk_get_rate(DSS_CLK_FCK);
2278                 break;
2279         case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
2280                 dsidev = dsi_get_dsidev_from_id(0);
2281                 r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
2282                 break;
2283         case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
2284                 dsidev = dsi_get_dsidev_from_id(1);
2285                 r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
2286                 break;
2287         default:
2288                 BUG();
2289         }
2290
2291         return r / lcd;
2292 }
2293
2294 unsigned long dispc_pclk_rate(enum omap_channel channel)
2295 {
2296         int pcd;
2297         unsigned long r;
2298         u32 l;
2299
2300         l = dispc_read_reg(DISPC_DIVISORo(channel));
2301
2302         pcd = FLD_GET(l, 7, 0);
2303
2304         r = dispc_lclk_rate(channel);
2305
2306         return r / pcd;
2307 }
2308
2309 void dispc_dump_clocks(struct seq_file *s)
2310 {
2311         int lcd, pcd;
2312         u32 l;
2313         enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source();
2314         enum omap_dss_clk_source lcd_clk_src;
2315
2316         enable_clocks(1);
2317
2318         seq_printf(s, "- DISPC -\n");
2319
2320         seq_printf(s, "dispc fclk source = %s (%s)\n",
2321                         dss_get_generic_clk_source_name(dispc_clk_src),
2322                         dss_feat_get_clk_source_name(dispc_clk_src));
2323
2324         seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate());
2325
2326         if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
2327                 seq_printf(s, "- DISPC-CORE-CLK -\n");
2328                 l = dispc_read_reg(DISPC_DIVISOR);
2329                 lcd = FLD_GET(l, 23, 16);
2330
2331                 seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
2332                                 (dispc_fclk_rate()/lcd), lcd);
2333         }
2334         seq_printf(s, "- LCD1 -\n");
2335
2336         lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD);
2337
2338         seq_printf(s, "lcd1_clk source = %s (%s)\n",
2339                 dss_get_generic_clk_source_name(lcd_clk_src),
2340                 dss_feat_get_clk_source_name(lcd_clk_src));
2341
2342         dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd);
2343
2344         seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
2345                         dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD), lcd);
2346         seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
2347                         dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD), pcd);
2348         if (dss_has_feature(FEAT_MGR_LCD2)) {
2349                 seq_printf(s, "- LCD2 -\n");
2350
2351                 lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD2);
2352
2353                 seq_printf(s, "lcd2_clk source = %s (%s)\n",
2354                         dss_get_generic_clk_source_name(lcd_clk_src),
2355                         dss_feat_get_clk_source_name(lcd_clk_src));
2356
2357                 dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd);
2358
2359                 seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
2360                                 dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD2), lcd);
2361                 seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
2362                                 dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd);
2363         }
2364         enable_clocks(0);
2365 }
2366
2367 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
2368 void dispc_dump_irqs(struct seq_file *s)
2369 {
2370         unsigned long flags;
2371         struct dispc_irq_stats stats;
2372
2373         spin_lock_irqsave(&dispc.irq_stats_lock, flags);
2374
2375         stats = dispc.irq_stats;
2376         memset(&dispc.irq_stats, 0, sizeof(dispc.irq_stats));
2377         dispc.irq_stats.last_reset = jiffies;
2378
2379         spin_unlock_irqrestore(&dispc.irq_stats_lock, flags);
2380
2381         seq_printf(s, "period %u ms\n",
2382                         jiffies_to_msecs(jiffies - stats.last_reset));
2383
2384         seq_printf(s, "irqs %d\n", stats.irq_count);
2385 #define PIS(x) \
2386         seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
2387
2388         PIS(FRAMEDONE);
2389         PIS(VSYNC);
2390         PIS(EVSYNC_EVEN);
2391         PIS(EVSYNC_ODD);
2392         PIS(ACBIAS_COUNT_STAT);
2393         PIS(PROG_LINE_NUM);
2394         PIS(GFX_FIFO_UNDERFLOW);
2395         PIS(GFX_END_WIN);
2396         PIS(PAL_GAMMA_MASK);
2397         PIS(OCP_ERR);
2398         PIS(VID1_FIFO_UNDERFLOW);
2399         PIS(VID1_END_WIN);
2400         PIS(VID2_FIFO_UNDERFLOW);
2401         PIS(VID2_END_WIN);
2402         PIS(SYNC_LOST);
2403         PIS(SYNC_LOST_DIGIT);
2404         PIS(WAKEUP);
2405         if (dss_has_feature(FEAT_MGR_LCD2)) {
2406                 PIS(FRAMEDONE2);
2407                 PIS(VSYNC2);
2408                 PIS(ACBIAS_COUNT_STAT2);
2409                 PIS(SYNC_LOST2);
2410         }
2411 #undef PIS
2412 }
2413 #endif
2414
2415 void dispc_dump_regs(struct seq_file *s)
2416 {
2417 #define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r))
2418
2419         dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
2420
2421         DUMPREG(DISPC_REVISION);
2422         DUMPREG(DISPC_SYSCONFIG);
2423         DUMPREG(DISPC_SYSSTATUS);
2424         DUMPREG(DISPC_IRQSTATUS);
2425         DUMPREG(DISPC_IRQENABLE);
2426         DUMPREG(DISPC_CONTROL);
2427         DUMPREG(DISPC_CONFIG);
2428         DUMPREG(DISPC_CAPABLE);
2429         DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD));
2430         DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT));
2431         DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD));
2432         DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));
2433         DUMPREG(DISPC_LINE_STATUS);
2434         DUMPREG(DISPC_LINE_NUMBER);
2435         DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD));
2436         DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD));
2437         DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD));
2438         DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD));
2439         DUMPREG(DISPC_GLOBAL_ALPHA);
2440         DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
2441         DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
2442         if (dss_has_feature(FEAT_MGR_LCD2)) {
2443                 DUMPREG(DISPC_CONTROL2);
2444                 DUMPREG(DISPC_CONFIG2);
2445                 DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2));
2446                 DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2));
2447                 DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD2));
2448                 DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD2));
2449                 DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD2));
2450                 DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD2));
2451                 DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD2));
2452         }
2453
2454         DUMPREG(DISPC_OVL_BA0(OMAP_DSS_GFX));
2455         DUMPREG(DISPC_OVL_BA1(OMAP_DSS_GFX));
2456         DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_GFX));
2457         DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_GFX));
2458         DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_GFX));
2459         DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_GFX));
2460         DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_GFX));
2461         DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_GFX));
2462         DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_GFX));
2463         DUMPREG(DISPC_OVL_WINDOW_SKIP(OMAP_DSS_GFX));
2464         DUMPREG(DISPC_OVL_TABLE_BA(OMAP_DSS_GFX));
2465
2466         DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD));
2467         DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
2468         DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
2469
2470         DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
2471         DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
2472         DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
2473         if (dss_has_feature(FEAT_MGR_LCD2)) {
2474                 DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
2475                 DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
2476                 DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
2477
2478                 DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
2479                 DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
2480                 DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
2481         }
2482
2483         DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX));
2484
2485         DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO1));
2486         DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO1));
2487         DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO1));
2488         DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO1));
2489         DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1));
2490         DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1));
2491         DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO1));
2492         DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO1));
2493         DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO1));
2494         DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO1));
2495         DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1));
2496         DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO1));
2497         DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO1));
2498
2499         DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO2));
2500         DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO2));
2501         DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO2));
2502         DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO2));
2503         DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2));
2504         DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2));
2505         DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO2));
2506         DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO2));
2507         DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO2));
2508         DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO2));
2509         DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2));
2510         DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO2));
2511         DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO2));
2512
2513         DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 0));
2514         DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 1));
2515         DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 2));
2516         DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 3));
2517         DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 4));
2518         DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 5));
2519         DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 6));
2520         DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 7));
2521         DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 0));
2522         DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 1));
2523         DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 2));
2524         DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 3));
2525         DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 4));
2526         DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 5));
2527         DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 6));
2528         DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 7));
2529         DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0));
2530         DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1));
2531         DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2));
2532         DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3));
2533         DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4));
2534         DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0));
2535         DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1));
2536         DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2));
2537         DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3));
2538         DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4));
2539         DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5));
2540         DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6));
2541         DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7));
2542
2543         DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 0));
2544         DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 1));
2545         DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 2));
2546         DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 3));
2547         DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 4));
2548         DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 5));
2549         DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 6));
2550         DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 7));
2551         DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 0));
2552         DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 1));
2553         DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 2));
2554         DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 3));
2555         DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 4));
2556         DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 5));
2557         DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 6));
2558         DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 7));
2559         DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0));
2560         DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1));
2561         DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2));
2562         DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3));
2563         DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4));
2564         DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0));
2565         DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1));
2566         DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2));
2567         DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3));
2568         DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4));
2569         DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5));
2570         DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6));
2571         DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7));
2572
2573         DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1));
2574         DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2));
2575
2576         dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
2577 #undef DUMPREG
2578 }
2579
2580 static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf,
2581                 bool ieo, bool ipc, bool ihs, bool ivs, u8 acbi, u8 acb)
2582 {
2583         u32 l = 0;
2584
2585         DSSDBG("onoff %d rf %d ieo %d ipc %d ihs %d ivs %d acbi %d acb %d\n",
2586                         onoff, rf, ieo, ipc, ihs, ivs, acbi, acb);
2587
2588         l |= FLD_VAL(onoff, 17, 17);
2589         l |= FLD_VAL(rf, 16, 16);
2590         l |= FLD_VAL(ieo, 15, 15);
2591         l |= FLD_VAL(ipc, 14, 14);
2592         l |= FLD_VAL(ihs, 13, 13);
2593         l |= FLD_VAL(ivs, 12, 12);
2594         l |= FLD_VAL(acbi, 11, 8);
2595         l |= FLD_VAL(acb, 7, 0);
2596
2597         enable_clocks(1);
2598         dispc_write_reg(DISPC_POL_FREQ(channel), l);
2599         enable_clocks(0);
2600 }
2601
2602 void dispc_set_pol_freq(enum omap_channel channel,
2603                 enum omap_panel_config config, u8 acbi, u8 acb)
2604 {
2605         _dispc_set_pol_freq(channel, (config & OMAP_DSS_LCD_ONOFF) != 0,
2606                         (config & OMAP_DSS_LCD_RF) != 0,
2607                         (config & OMAP_DSS_LCD_IEO) != 0,
2608                         (config & OMAP_DSS_LCD_IPC) != 0,
2609                         (config & OMAP_DSS_LCD_IHS) != 0,
2610                         (config & OMAP_DSS_LCD_IVS) != 0,
2611                         acbi, acb);
2612 }
2613
2614 /* with fck as input clock rate, find dispc dividers that produce req_pck */
2615 void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
2616                 struct dispc_clock_info *cinfo)
2617 {
2618         u16 pcd_min = is_tft ? 2 : 3;
2619         unsigned long best_pck;
2620         u16 best_ld, cur_ld;
2621         u16 best_pd, cur_pd;
2622
2623         best_pck = 0;
2624         best_ld = 0;
2625         best_pd = 0;
2626
2627         for (cur_ld = 1; cur_ld <= 255; ++cur_ld) {
2628                 unsigned long lck = fck / cur_ld;
2629
2630                 for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) {
2631                         unsigned long pck = lck / cur_pd;
2632                         long old_delta = abs(best_pck - req_pck);
2633                         long new_delta = abs(pck - req_pck);
2634
2635                         if (best_pck == 0 || new_delta < old_delta) {
2636                                 best_pck = pck;
2637                                 best_ld = cur_ld;
2638                                 best_pd = cur_pd;
2639
2640                                 if (pck == req_pck)
2641                                         goto found;
2642                         }
2643
2644                         if (pck < req_pck)
2645                                 break;
2646                 }
2647
2648                 if (lck / pcd_min < req_pck)
2649                         break;
2650         }
2651
2652 found:
2653         cinfo->lck_div = best_ld;
2654         cinfo->pck_div = best_pd;
2655         cinfo->lck = fck / cinfo->lck_div;
2656         cinfo->pck = cinfo->lck / cinfo->pck_div;
2657 }
2658
2659 /* calculate clock rates using dividers in cinfo */
2660 int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
2661                 struct dispc_clock_info *cinfo)
2662 {
2663         if (cinfo->lck_div > 255 || cinfo->lck_div == 0)
2664                 return -EINVAL;
2665         if (cinfo->pck_div < 2 || cinfo->pck_div > 255)
2666                 return -EINVAL;
2667
2668         cinfo->lck = dispc_fclk_rate / cinfo->lck_div;
2669         cinfo->pck = cinfo->lck / cinfo->pck_div;
2670
2671         return 0;
2672 }
2673
2674 int dispc_set_clock_div(enum omap_channel channel,
2675                 struct dispc_clock_info *cinfo)
2676 {
2677         DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);
2678         DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div);
2679
2680         dispc_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div);
2681
2682         return 0;
2683 }
2684
2685 int dispc_get_clock_div(enum omap_channel channel,
2686                 struct dispc_clock_info *cinfo)
2687 {
2688         unsigned long fck;
2689
2690         fck = dispc_fclk_rate();
2691
2692         cinfo->lck_div = REG_GET(DISPC_DIVISORo(channel), 23, 16);
2693         cinfo->pck_div = REG_GET(DISPC_DIVISORo(channel), 7, 0);
2694
2695         cinfo->lck = fck / cinfo->lck_div;
2696         cinfo->pck = cinfo->lck / cinfo->pck_div;
2697
2698         return 0;
2699 }
2700
2701 /* dispc.irq_lock has to be locked by the caller */
2702 static void _omap_dispc_set_irqs(void)
2703 {
2704         u32 mask;
2705         u32 old_mask;
2706         int i;
2707         struct omap_dispc_isr_data *isr_data;
2708
2709         mask = dispc.irq_error_mask;
2710
2711         for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
2712                 isr_data = &dispc.registered_isr[i];
2713
2714                 if (isr_data->isr == NULL)
2715                         continue;
2716
2717                 mask |= isr_data->mask;
2718         }
2719
2720         enable_clocks(1);
2721
2722         old_mask = dispc_read_reg(DISPC_IRQENABLE);
2723         /* clear the irqstatus for newly enabled irqs */
2724         dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
2725
2726         dispc_write_reg(DISPC_IRQENABLE, mask);
2727
2728         enable_clocks(0);
2729 }
2730
2731 int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
2732 {
2733         int i;
2734         int ret;
2735         unsigned long flags;
2736         struct omap_dispc_isr_data *isr_data;
2737
2738         if (isr == NULL)
2739                 return -EINVAL;
2740
2741         spin_lock_irqsave(&dispc.irq_lock, flags);
2742
2743         /* check for duplicate entry */
2744         for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
2745                 isr_data = &dispc.registered_isr[i];
2746                 if (isr_data->isr == isr && isr_data->arg == arg &&
2747                                 isr_data->mask == mask) {
2748                         ret = -EINVAL;
2749                         goto err;
2750                 }
2751         }
2752
2753         isr_data = NULL;
2754         ret = -EBUSY;
2755
2756         for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
2757                 isr_data = &dispc.registered_isr[i];
2758
2759                 if (isr_data->isr != NULL)
2760                         continue;
2761
2762                 isr_data->isr = isr;
2763                 isr_data->arg = arg;
2764                 isr_data->mask = mask;
2765                 ret = 0;
2766
2767                 break;
2768         }
2769
2770         if (ret)
2771                 goto err;
2772
2773         _omap_dispc_set_irqs();
2774
2775         spin_unlock_irqrestore(&dispc.irq_lock, flags);
2776
2777         return 0;
2778 err:
2779         spin_unlock_irqrestore(&dispc.irq_lock, flags);
2780
2781         return ret;
2782 }
2783 EXPORT_SYMBOL(omap_dispc_register_isr);
2784
2785 int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
2786 {
2787         int i;
2788         unsigned long flags;
2789         int ret = -EINVAL;
2790         struct omap_dispc_isr_data *isr_data;
2791
2792         spin_lock_irqsave(&dispc.irq_lock, flags);
2793
2794         for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
2795                 isr_data = &dispc.registered_isr[i];
2796                 if (isr_data->isr != isr || isr_data->arg != arg ||
2797                                 isr_data->mask != mask)
2798                         continue;
2799
2800                 /* found the correct isr */
2801
2802                 isr_data->isr = NULL;
2803                 isr_data->arg = NULL;
2804                 isr_data->mask = 0;
2805
2806                 ret = 0;
2807                 break;
2808         }
2809
2810         if (ret == 0)
2811                 _omap_dispc_set_irqs();
2812
2813         spin_unlock_irqrestore(&dispc.irq_lock, flags);
2814
2815         return ret;
2816 }
2817 EXPORT_SYMBOL(omap_dispc_unregister_isr);
2818
2819 #ifdef DEBUG
2820 static void print_irq_status(u32 status)
2821 {
2822         if ((status & dispc.irq_error_mask) == 0)
2823                 return;
2824
2825         printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status);
2826
2827 #define PIS(x) \
2828         if (status & DISPC_IRQ_##x) \
2829                 printk(#x " ");
2830         PIS(GFX_FIFO_UNDERFLOW);
2831         PIS(OCP_ERR);
2832         PIS(VID1_FIFO_UNDERFLOW);
2833         PIS(VID2_FIFO_UNDERFLOW);
2834         PIS(SYNC_LOST);
2835         PIS(SYNC_LOST_DIGIT);
2836         if (dss_has_feature(FEAT_MGR_LCD2))
2837                 PIS(SYNC_LOST2);
2838 #undef PIS
2839
2840         printk("\n");
2841 }
2842 #endif
2843
2844 /* Called from dss.c. Note that we don't touch clocks here,
2845  * but we presume they are on because we got an IRQ. However,
2846  * an irq handler may turn the clocks off, so we may not have
2847  * clock later in the function. */
2848 static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
2849 {
2850         int i;
2851         u32 irqstatus, irqenable;
2852         u32 handledirqs = 0;
2853         u32 unhandled_errors;
2854         struct omap_dispc_isr_data *isr_data;
2855         struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
2856
2857         spin_lock(&dispc.irq_lock);
2858
2859         irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
2860         irqenable = dispc_read_reg(DISPC_IRQENABLE);
2861
2862         /* IRQ is not for us */
2863         if (!(irqstatus & irqenable)) {
2864                 spin_unlock(&dispc.irq_lock);
2865                 return IRQ_NONE;
2866         }
2867
2868 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
2869         spin_lock(&dispc.irq_stats_lock);
2870         dispc.irq_stats.irq_count++;
2871         dss_collect_irq_stats(irqstatus, dispc.irq_stats.irqs);
2872         spin_unlock(&dispc.irq_stats_lock);
2873 #endif
2874
2875 #ifdef DEBUG
2876         if (dss_debug)
2877                 print_irq_status(irqstatus);
2878 #endif
2879         /* Ack the interrupt. Do it here before clocks are possibly turned
2880          * off */
2881         dispc_write_reg(DISPC_IRQSTATUS, irqstatus);
2882         /* flush posted write */
2883         dispc_read_reg(DISPC_IRQSTATUS);
2884
2885         /* make a copy and unlock, so that isrs can unregister
2886          * themselves */
2887         memcpy(registered_isr, dispc.registered_isr,
2888                         sizeof(registered_isr));
2889
2890         spin_unlock(&dispc.irq_lock);
2891
2892         for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
2893                 isr_data = &registered_isr[i];
2894
2895                 if (!isr_data->isr)
2896                         continue;
2897
2898                 if (isr_data->mask & irqstatus) {
2899                         isr_data->isr(isr_data->arg, irqstatus);
2900                         handledirqs |= isr_data->mask;
2901                 }
2902         }
2903
2904         spin_lock(&dispc.irq_lock);
2905
2906         unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask;
2907
2908         if (unhandled_errors) {
2909                 dispc.error_irqs |= unhandled_errors;
2910
2911                 dispc.irq_error_mask &= ~unhandled_errors;
2912                 _omap_dispc_set_irqs();
2913
2914                 schedule_work(&dispc.error_work);
2915         }
2916
2917         spin_unlock(&dispc.irq_lock);
2918
2919         return IRQ_HANDLED;
2920 }
2921
2922 static void dispc_error_worker(struct work_struct *work)
2923 {
2924         int i;
2925         u32 errors;
2926         unsigned long flags;
2927
2928         spin_lock_irqsave(&dispc.irq_lock, flags);
2929         errors = dispc.error_irqs;
2930         dispc.error_irqs = 0;
2931         spin_unlock_irqrestore(&dispc.irq_lock, flags);
2932
2933         if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) {
2934                 DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n");
2935                 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
2936                         struct omap_overlay *ovl;
2937                         ovl = omap_dss_get_overlay(i);
2938
2939                         if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
2940                                 continue;
2941
2942                         if (ovl->id == 0) {
2943                                 dispc_enable_plane(ovl->id, 0);
2944                                 dispc_go(ovl->manager->id);
2945                                 mdelay(50);
2946                                 break;
2947                         }
2948                 }
2949         }
2950
2951         if (errors & DISPC_IRQ_VID1_FIFO_UNDERFLOW) {
2952                 DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n");
2953                 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
2954                         struct omap_overlay *ovl;
2955                         ovl = omap_dss_get_overlay(i);
2956
2957                         if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
2958                                 continue;
2959
2960                         if (ovl->id == 1) {
2961                                 dispc_enable_plane(ovl->id, 0);
2962                                 dispc_go(ovl->manager->id);
2963                                 mdelay(50);
2964                                 break;
2965                         }
2966                 }
2967         }
2968
2969         if (errors & DISPC_IRQ_VID2_FIFO_UNDERFLOW) {
2970                 DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n");
2971                 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
2972                         struct omap_overlay *ovl;
2973                         ovl = omap_dss_get_overlay(i);
2974
2975                         if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
2976                                 continue;
2977
2978                         if (ovl->id == 2) {
2979                                 dispc_enable_plane(ovl->id, 0);
2980                                 dispc_go(ovl->manager->id);
2981                                 mdelay(50);
2982                                 break;
2983                         }
2984                 }
2985         }
2986
2987         if (errors & DISPC_IRQ_SYNC_LOST) {
2988                 struct omap_overlay_manager *manager = NULL;
2989                 bool enable = false;
2990
2991                 DSSERR("SYNC_LOST, disabling LCD\n");
2992
2993                 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
2994                         struct omap_overlay_manager *mgr;
2995                         mgr = omap_dss_get_overlay_manager(i);
2996
2997                         if (mgr->id == OMAP_DSS_CHANNEL_LCD) {
2998                                 manager = mgr;
2999                                 enable = mgr->device->state ==
3000                                                 OMAP_DSS_DISPLAY_ACTIVE;
3001                                 mgr->device->driver->disable(mgr->device);
3002                                 break;
3003                         }
3004                 }
3005
3006                 if (manager) {
3007                         struct omap_dss_device *dssdev = manager->device;
3008                         for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
3009                                 struct omap_overlay *ovl;
3010                                 ovl = omap_dss_get_overlay(i);
3011
3012                                 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
3013                                         continue;
3014
3015                                 if (ovl->id != 0 && ovl->manager == manager)
3016                                         dispc_enable_plane(ovl->id, 0);
3017                         }
3018
3019                         dispc_go(manager->id);
3020                         mdelay(50);
3021                         if (enable)
3022                                 dssdev->driver->enable(dssdev);
3023                 }
3024         }
3025
3026         if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) {
3027                 struct omap_overlay_manager *manager = NULL;
3028                 bool enable = false;
3029
3030                 DSSERR("SYNC_LOST_DIGIT, disabling TV\n");
3031
3032                 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
3033                         struct omap_overlay_manager *mgr;
3034                         mgr = omap_dss_get_overlay_manager(i);
3035
3036                         if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) {
3037                                 manager = mgr;
3038                                 enable = mgr->device->state ==
3039                                                 OMAP_DSS_DISPLAY_ACTIVE;
3040                                 mgr->device->driver->disable(mgr->device);
3041                                 break;
3042                         }
3043                 }
3044
3045                 if (manager) {
3046                         struct omap_dss_device *dssdev = manager->device;
3047                         for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
3048                                 struct omap_overlay *ovl;
3049                                 ovl = omap_dss_get_overlay(i);
3050
3051                                 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
3052                                         continue;
3053
3054                                 if (ovl->id != 0 && ovl->manager == manager)
3055                                         dispc_enable_plane(ovl->id, 0);
3056                         }
3057
3058                         dispc_go(manager->id);
3059                         mdelay(50);
3060                         if (enable)
3061                                 dssdev->driver->enable(dssdev);
3062                 }
3063         }
3064
3065         if (errors & DISPC_IRQ_SYNC_LOST2) {
3066                 struct omap_overlay_manager *manager = NULL;
3067                 bool enable = false;
3068
3069                 DSSERR("SYNC_LOST for LCD2, disabling LCD2\n");
3070
3071                 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
3072                         struct omap_overlay_manager *mgr;
3073                         mgr = omap_dss_get_overlay_manager(i);
3074
3075                         if (mgr->id == OMAP_DSS_CHANNEL_LCD2) {
3076                                 manager = mgr;
3077                                 enable = mgr->device->state ==
3078                                                 OMAP_DSS_DISPLAY_ACTIVE;
3079                                 mgr->device->driver->disable(mgr->device);
3080                                 break;
3081                         }
3082                 }
3083
3084                 if (manager) {
3085                         struct omap_dss_device *dssdev = manager->device;
3086                         for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
3087                                 struct omap_overlay *ovl;
3088                                 ovl = omap_dss_get_overlay(i);
3089
3090                                 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
3091                                         continue;
3092
3093                                 if (ovl->id != 0 && ovl->manager == manager)
3094                                         dispc_enable_plane(ovl->id, 0);
3095                         }
3096
3097                         dispc_go(manager->id);
3098                         mdelay(50);
3099                         if (enable)
3100                                 dssdev->driver->enable(dssdev);
3101                 }
3102         }
3103
3104         if (errors & DISPC_IRQ_OCP_ERR) {
3105                 DSSERR("OCP_ERR\n");
3106                 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
3107                         struct omap_overlay_manager *mgr;
3108                         mgr = omap_dss_get_overlay_manager(i);
3109
3110                         if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC)
3111                                 mgr->device->driver->disable(mgr->device);
3112                 }
3113         }
3114
3115         spin_lock_irqsave(&dispc.irq_lock, flags);
3116         dispc.irq_error_mask |= errors;
3117         _omap_dispc_set_irqs();
3118         spin_unlock_irqrestore(&dispc.irq_lock, flags);
3119 }
3120
3121 int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
3122 {
3123         void dispc_irq_wait_handler(void *data, u32 mask)
3124         {
3125                 complete((struct completion *)data);
3126         }
3127
3128         int r;
3129         DECLARE_COMPLETION_ONSTACK(completion);
3130
3131         r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
3132                         irqmask);
3133
3134         if (r)
3135                 return r;
3136
3137         timeout = wait_for_completion_timeout(&completion, timeout);
3138
3139         omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
3140
3141         if (timeout == 0)
3142                 return -ETIMEDOUT;
3143
3144         if (timeout == -ERESTARTSYS)
3145                 return -ERESTARTSYS;
3146
3147         return 0;
3148 }
3149
3150 int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
3151                 unsigned long timeout)
3152 {
3153         void dispc_irq_wait_handler(void *data, u32 mask)
3154         {
3155                 complete((struct completion *)data);
3156         }
3157
3158         int r;
3159         DECLARE_COMPLETION_ONSTACK(completion);
3160
3161         r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
3162                         irqmask);
3163
3164         if (r)
3165                 return r;
3166
3167         timeout = wait_for_completion_interruptible_timeout(&completion,
3168                         timeout);
3169
3170         omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
3171
3172         if (timeout == 0)
3173                 return -ETIMEDOUT;
3174
3175         if (timeout == -ERESTARTSYS)
3176                 return -ERESTARTSYS;
3177
3178         return 0;
3179 }
3180
3181 #ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
3182 void dispc_fake_vsync_irq(void)
3183 {
3184         u32 irqstatus = DISPC_IRQ_VSYNC;
3185         int i;
3186
3187         WARN_ON(!in_interrupt());
3188
3189         for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
3190                 struct omap_dispc_isr_data *isr_data;
3191                 isr_data = &dispc.registered_isr[i];
3192
3193                 if (!isr_data->isr)
3194                         continue;
3195
3196                 if (isr_data->mask & irqstatus)
3197                         isr_data->isr(isr_data->arg, irqstatus);
3198         }
3199 }
3200 #endif
3201
3202 static void _omap_dispc_initialize_irq(void)
3203 {
3204         unsigned long flags;
3205
3206         spin_lock_irqsave(&dispc.irq_lock, flags);
3207
3208         memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr));
3209
3210         dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
3211         if (dss_has_feature(FEAT_MGR_LCD2))
3212                 dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
3213
3214         /* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
3215          * so clear it */
3216         dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS));
3217
3218         _omap_dispc_set_irqs();
3219
3220         spin_unlock_irqrestore(&dispc.irq_lock, flags);
3221 }
3222
3223 void dispc_enable_sidle(void)
3224 {
3225         REG_FLD_MOD(DISPC_SYSCONFIG, 2, 4, 3);  /* SIDLEMODE: smart idle */
3226 }
3227
3228 void dispc_disable_sidle(void)
3229 {
3230         REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3);  /* SIDLEMODE: no idle */
3231 }
3232
3233 static void _omap_dispc_initial_config(void)
3234 {
3235         u32 l;
3236
3237         l = dispc_read_reg(DISPC_SYSCONFIG);
3238         l = FLD_MOD(l, 2, 13, 12);      /* MIDLEMODE: smart standby */
3239         l = FLD_MOD(l, 2, 4, 3);        /* SIDLEMODE: smart idle */
3240         l = FLD_MOD(l, 1, 2, 2);        /* ENWAKEUP */
3241         l = FLD_MOD(l, 1, 0, 0);        /* AUTOIDLE */
3242         dispc_write_reg(DISPC_SYSCONFIG, l);
3243
3244         /* Exclusively enable DISPC_CORE_CLK and set divider to 1 */
3245         if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
3246                 l = dispc_read_reg(DISPC_DIVISOR);
3247                 /* Use DISPC_DIVISOR.LCD, instead of DISPC_DIVISOR1.LCD */
3248                 l = FLD_MOD(l, 1, 0, 0);
3249                 l = FLD_MOD(l, 1, 23, 16);
3250                 dispc_write_reg(DISPC_DIVISOR, l);
3251         }
3252
3253         /* FUNCGATED */
3254         if (dss_has_feature(FEAT_FUNCGATED))
3255                 REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
3256
3257         /* L3 firewall setting: enable access to OCM RAM */
3258         /* XXX this should be somewhere in plat-omap */
3259         if (cpu_is_omap24xx())
3260                 __raw_writel(0x402000b0, OMAP2_L3_IO_ADDRESS(0x680050a0));
3261
3262         _dispc_setup_color_conv_coef();
3263
3264         dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
3265
3266         dispc_read_plane_fifo_sizes();
3267 }
3268
3269 int dispc_enable_plane(enum omap_plane plane, bool enable)
3270 {
3271         DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
3272
3273         enable_clocks(1);
3274         _dispc_enable_plane(plane, enable);
3275         enable_clocks(0);
3276
3277         return 0;
3278 }
3279
3280 int dispc_setup_plane(enum omap_plane plane,
3281                        u32 paddr, u16 screen_width,
3282                        u16 pos_x, u16 pos_y,
3283                        u16 width, u16 height,
3284                        u16 out_width, u16 out_height,
3285                        enum omap_color_mode color_mode,
3286                        bool ilace,
3287                        enum omap_dss_rotation_type rotation_type,
3288                        u8 rotation, bool mirror, u8 global_alpha,
3289                        u8 pre_mult_alpha, enum omap_channel channel)
3290 {
3291         int r = 0;
3292
3293         DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> "
3294                "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n",
3295                plane, paddr, screen_width, pos_x, pos_y,
3296                width, height,
3297                out_width, out_height,
3298                ilace, color_mode,
3299                rotation, mirror, channel);
3300
3301         enable_clocks(1);
3302
3303         r = _dispc_setup_plane(plane,
3304                            paddr, screen_width,
3305                            pos_x, pos_y,
3306                            width, height,
3307                            out_width, out_height,
3308                            color_mode, ilace,
3309                            rotation_type,
3310                            rotation, mirror,
3311                            global_alpha,
3312                            pre_mult_alpha, channel);
3313
3314         enable_clocks(0);
3315
3316         return r;
3317 }
3318
3319 /* DISPC HW IP initialisation */
3320 static int omap_dispchw_probe(struct platform_device *pdev)
3321 {
3322         u32 rev;
3323         int r = 0;
3324         struct resource *dispc_mem;
3325
3326         dispc.pdev = pdev;
3327
3328         spin_lock_init(&dispc.irq_lock);
3329
3330 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
3331         spin_lock_init(&dispc.irq_stats_lock);
3332         dispc.irq_stats.last_reset = jiffies;
3333 #endif
3334
3335         INIT_WORK(&dispc.error_work, dispc_error_worker);
3336
3337         dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
3338         if (!dispc_mem) {
3339                 DSSERR("can't get IORESOURCE_MEM DISPC\n");
3340                 r = -EINVAL;
3341                 goto fail0;
3342         }
3343         dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem));
3344         if (!dispc.base) {
3345                 DSSERR("can't ioremap DISPC\n");
3346                 r = -ENOMEM;
3347                 goto fail0;
3348         }
3349         dispc.irq = platform_get_irq(dispc.pdev, 0);
3350         if (dispc.irq < 0) {
3351                 DSSERR("platform_get_irq failed\n");
3352                 r = -ENODEV;
3353                 goto fail1;
3354         }
3355
3356         r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED,
3357                 "OMAP DISPC", dispc.pdev);
3358         if (r < 0) {
3359                 DSSERR("request_irq failed\n");
3360                 goto fail1;
3361         }
3362
3363         enable_clocks(1);
3364
3365         _omap_dispc_initial_config();
3366
3367         _omap_dispc_initialize_irq();
3368
3369         dispc_save_context();
3370
3371         rev = dispc_read_reg(DISPC_REVISION);
3372         dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
3373                FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
3374
3375         enable_clocks(0);
3376
3377         return 0;
3378 fail1:
3379         iounmap(dispc.base);
3380 fail0:
3381         return r;
3382 }
3383
3384 static int omap_dispchw_remove(struct platform_device *pdev)
3385 {
3386         free_irq(dispc.irq, dispc.pdev);
3387         iounmap(dispc.base);
3388         return 0;
3389 }
3390
3391 static struct platform_driver omap_dispchw_driver = {
3392         .probe          = omap_dispchw_probe,
3393         .remove         = omap_dispchw_remove,
3394         .driver         = {
3395                 .name   = "omapdss_dispc",
3396                 .owner  = THIS_MODULE,
3397         },
3398 };
3399
3400 int dispc_init_platform_driver(void)
3401 {
3402         return platform_driver_register(&omap_dispchw_driver);
3403 }
3404
3405 void dispc_uninit_platform_driver(void)
3406 {
3407         return platform_driver_unregister(&omap_dispchw_driver);
3408 }