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