diff options
Diffstat (limited to 'drivers/video/omap/rfbi.c')
-rw-r--r-- | drivers/video/omap/rfbi.c | 598 |
1 files changed, 0 insertions, 598 deletions
diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c deleted file mode 100644 index 2c1a3402bef0..000000000000 --- a/drivers/video/omap/rfbi.c +++ /dev/null | |||
@@ -1,598 +0,0 @@ | |||
1 | /* | ||
2 | * OMAP2 Remote Frame Buffer Interface support | ||
3 | * | ||
4 | * Copyright (C) 2005 Nokia Corporation | ||
5 | * Author: Juha Yrjölä <juha.yrjola@nokia.com> | ||
6 | * Imre Deak <imre.deak@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | */ | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/i2c.h> | ||
25 | #include <linux/err.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/clk.h> | ||
28 | #include <linux/io.h> | ||
29 | #include <linux/platform_device.h> | ||
30 | |||
31 | #include "omapfb.h" | ||
32 | #include "dispc.h" | ||
33 | |||
34 | /* To work around an RFBI transfer rate limitation */ | ||
35 | #define OMAP_RFBI_RATE_LIMIT 1 | ||
36 | |||
37 | #define RFBI_BASE 0x48050800 | ||
38 | #define RFBI_REVISION 0x0000 | ||
39 | #define RFBI_SYSCONFIG 0x0010 | ||
40 | #define RFBI_SYSSTATUS 0x0014 | ||
41 | #define RFBI_CONTROL 0x0040 | ||
42 | #define RFBI_PIXEL_CNT 0x0044 | ||
43 | #define RFBI_LINE_NUMBER 0x0048 | ||
44 | #define RFBI_CMD 0x004c | ||
45 | #define RFBI_PARAM 0x0050 | ||
46 | #define RFBI_DATA 0x0054 | ||
47 | #define RFBI_READ 0x0058 | ||
48 | #define RFBI_STATUS 0x005c | ||
49 | #define RFBI_CONFIG0 0x0060 | ||
50 | #define RFBI_ONOFF_TIME0 0x0064 | ||
51 | #define RFBI_CYCLE_TIME0 0x0068 | ||
52 | #define RFBI_DATA_CYCLE1_0 0x006c | ||
53 | #define RFBI_DATA_CYCLE2_0 0x0070 | ||
54 | #define RFBI_DATA_CYCLE3_0 0x0074 | ||
55 | #define RFBI_VSYNC_WIDTH 0x0090 | ||
56 | #define RFBI_HSYNC_WIDTH 0x0094 | ||
57 | |||
58 | #define DISPC_BASE 0x48050400 | ||
59 | #define DISPC_CONTROL 0x0040 | ||
60 | #define DISPC_IRQ_FRAMEMASK 0x0001 | ||
61 | |||
62 | static struct { | ||
63 | void __iomem *base; | ||
64 | void (*lcdc_callback)(void *data); | ||
65 | void *lcdc_callback_data; | ||
66 | unsigned long l4_khz; | ||
67 | int bits_per_cycle; | ||
68 | struct omapfb_device *fbdev; | ||
69 | struct clk *dss_ick; | ||
70 | struct clk *dss1_fck; | ||
71 | unsigned tearsync_pin_cnt; | ||
72 | unsigned tearsync_mode; | ||
73 | } rfbi; | ||
74 | |||
75 | static inline void rfbi_write_reg(int idx, u32 val) | ||
76 | { | ||
77 | __raw_writel(val, rfbi.base + idx); | ||
78 | } | ||
79 | |||
80 | static inline u32 rfbi_read_reg(int idx) | ||
81 | { | ||
82 | return __raw_readl(rfbi.base + idx); | ||
83 | } | ||
84 | |||
85 | static int rfbi_get_clocks(void) | ||
86 | { | ||
87 | rfbi.dss_ick = clk_get(&rfbi.fbdev->dssdev->dev, "ick"); | ||
88 | if (IS_ERR(rfbi.dss_ick)) { | ||
89 | dev_err(rfbi.fbdev->dev, "can't get ick\n"); | ||
90 | return PTR_ERR(rfbi.dss_ick); | ||
91 | } | ||
92 | |||
93 | rfbi.dss1_fck = clk_get(&rfbi.fbdev->dssdev->dev, "fck"); | ||
94 | if (IS_ERR(rfbi.dss1_fck)) { | ||
95 | dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n"); | ||
96 | clk_put(rfbi.dss_ick); | ||
97 | return PTR_ERR(rfbi.dss1_fck); | ||
98 | } | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static void rfbi_put_clocks(void) | ||
104 | { | ||
105 | clk_put(rfbi.dss1_fck); | ||
106 | clk_put(rfbi.dss_ick); | ||
107 | } | ||
108 | |||
109 | static void rfbi_enable_clocks(int enable) | ||
110 | { | ||
111 | if (enable) { | ||
112 | clk_enable(rfbi.dss_ick); | ||
113 | clk_enable(rfbi.dss1_fck); | ||
114 | } else { | ||
115 | clk_disable(rfbi.dss1_fck); | ||
116 | clk_disable(rfbi.dss_ick); | ||
117 | } | ||
118 | } | ||
119 | |||
120 | |||
121 | #ifdef VERBOSE | ||
122 | static void rfbi_print_timings(void) | ||
123 | { | ||
124 | u32 l; | ||
125 | u32 time; | ||
126 | |||
127 | l = rfbi_read_reg(RFBI_CONFIG0); | ||
128 | time = 1000000000 / rfbi.l4_khz; | ||
129 | if (l & (1 << 4)) | ||
130 | time *= 2; | ||
131 | |||
132 | dev_dbg(rfbi.fbdev->dev, "Tick time %u ps\n", time); | ||
133 | l = rfbi_read_reg(RFBI_ONOFF_TIME0); | ||
134 | dev_dbg(rfbi.fbdev->dev, | ||
135 | "CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, " | ||
136 | "REONTIME %d, REOFFTIME %d\n", | ||
137 | l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f, | ||
138 | (l >> 20) & 0x0f, (l >> 24) & 0x3f); | ||
139 | |||
140 | l = rfbi_read_reg(RFBI_CYCLE_TIME0); | ||
141 | dev_dbg(rfbi.fbdev->dev, | ||
142 | "WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, " | ||
143 | "ACCESSTIME %d\n", | ||
144 | (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f, | ||
145 | (l >> 22) & 0x3f); | ||
146 | } | ||
147 | #else | ||
148 | static void rfbi_print_timings(void) {} | ||
149 | #endif | ||
150 | |||
151 | static void rfbi_set_timings(const struct extif_timings *t) | ||
152 | { | ||
153 | u32 l; | ||
154 | |||
155 | BUG_ON(!t->converted); | ||
156 | |||
157 | rfbi_enable_clocks(1); | ||
158 | rfbi_write_reg(RFBI_ONOFF_TIME0, t->tim[0]); | ||
159 | rfbi_write_reg(RFBI_CYCLE_TIME0, t->tim[1]); | ||
160 | |||
161 | l = rfbi_read_reg(RFBI_CONFIG0); | ||
162 | l &= ~(1 << 4); | ||
163 | l |= (t->tim[2] ? 1 : 0) << 4; | ||
164 | rfbi_write_reg(RFBI_CONFIG0, l); | ||
165 | |||
166 | rfbi_print_timings(); | ||
167 | rfbi_enable_clocks(0); | ||
168 | } | ||
169 | |||
170 | static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div) | ||
171 | { | ||
172 | *clk_period = 1000000000 / rfbi.l4_khz; | ||
173 | *max_clk_div = 2; | ||
174 | } | ||
175 | |||
176 | static int ps_to_rfbi_ticks(int time, int div) | ||
177 | { | ||
178 | unsigned long tick_ps; | ||
179 | int ret; | ||
180 | |||
181 | /* Calculate in picosecs to yield more exact results */ | ||
182 | tick_ps = 1000000000 / (rfbi.l4_khz) * div; | ||
183 | |||
184 | ret = (time + tick_ps - 1) / tick_ps; | ||
185 | |||
186 | return ret; | ||
187 | } | ||
188 | |||
189 | #ifdef OMAP_RFBI_RATE_LIMIT | ||
190 | static unsigned long rfbi_get_max_tx_rate(void) | ||
191 | { | ||
192 | unsigned long l4_rate, dss1_rate; | ||
193 | int min_l4_ticks = 0; | ||
194 | int i; | ||
195 | |||
196 | /* According to TI this can't be calculated so make the | ||
197 | * adjustments for a couple of known frequencies and warn for | ||
198 | * others. | ||
199 | */ | ||
200 | static const struct { | ||
201 | unsigned long l4_clk; /* HZ */ | ||
202 | unsigned long dss1_clk; /* HZ */ | ||
203 | unsigned long min_l4_ticks; | ||
204 | } ftab[] = { | ||
205 | { 55, 132, 7, }, /* 7.86 MPix/s */ | ||
206 | { 110, 110, 12, }, /* 9.16 MPix/s */ | ||
207 | { 110, 132, 10, }, /* 11 Mpix/s */ | ||
208 | { 120, 120, 10, }, /* 12 Mpix/s */ | ||
209 | { 133, 133, 10, }, /* 13.3 Mpix/s */ | ||
210 | }; | ||
211 | |||
212 | l4_rate = rfbi.l4_khz / 1000; | ||
213 | dss1_rate = clk_get_rate(rfbi.dss1_fck) / 1000000; | ||
214 | |||
215 | for (i = 0; i < ARRAY_SIZE(ftab); i++) { | ||
216 | /* Use a window instead of an exact match, to account | ||
217 | * for different DPLL multiplier / divider pairs. | ||
218 | */ | ||
219 | if (abs(ftab[i].l4_clk - l4_rate) < 3 && | ||
220 | abs(ftab[i].dss1_clk - dss1_rate) < 3) { | ||
221 | min_l4_ticks = ftab[i].min_l4_ticks; | ||
222 | break; | ||
223 | } | ||
224 | } | ||
225 | if (i == ARRAY_SIZE(ftab)) { | ||
226 | /* Can't be sure, return anyway the maximum not | ||
227 | * rate-limited. This might cause a problem only for the | ||
228 | * tearing synchronisation. | ||
229 | */ | ||
230 | dev_err(rfbi.fbdev->dev, | ||
231 | "can't determine maximum RFBI transfer rate\n"); | ||
232 | return rfbi.l4_khz * 1000; | ||
233 | } | ||
234 | return rfbi.l4_khz * 1000 / min_l4_ticks; | ||
235 | } | ||
236 | #else | ||
237 | static int rfbi_get_max_tx_rate(void) | ||
238 | { | ||
239 | return rfbi.l4_khz * 1000; | ||
240 | } | ||
241 | #endif | ||
242 | |||
243 | |||
244 | static int rfbi_convert_timings(struct extif_timings *t) | ||
245 | { | ||
246 | u32 l; | ||
247 | int reon, reoff, weon, weoff, cson, csoff, cs_pulse; | ||
248 | int actim, recyc, wecyc; | ||
249 | int div = t->clk_div; | ||
250 | |||
251 | if (div <= 0 || div > 2) | ||
252 | return -1; | ||
253 | |||
254 | /* Make sure that after conversion it still holds that: | ||
255 | * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff, | ||
256 | * csoff > cson, csoff >= max(weoff, reoff), actim > reon | ||
257 | */ | ||
258 | weon = ps_to_rfbi_ticks(t->we_on_time, div); | ||
259 | weoff = ps_to_rfbi_ticks(t->we_off_time, div); | ||
260 | if (weoff <= weon) | ||
261 | weoff = weon + 1; | ||
262 | if (weon > 0x0f) | ||
263 | return -1; | ||
264 | if (weoff > 0x3f) | ||
265 | return -1; | ||
266 | |||
267 | reon = ps_to_rfbi_ticks(t->re_on_time, div); | ||
268 | reoff = ps_to_rfbi_ticks(t->re_off_time, div); | ||
269 | if (reoff <= reon) | ||
270 | reoff = reon + 1; | ||
271 | if (reon > 0x0f) | ||
272 | return -1; | ||
273 | if (reoff > 0x3f) | ||
274 | return -1; | ||
275 | |||
276 | cson = ps_to_rfbi_ticks(t->cs_on_time, div); | ||
277 | csoff = ps_to_rfbi_ticks(t->cs_off_time, div); | ||
278 | if (csoff <= cson) | ||
279 | csoff = cson + 1; | ||
280 | if (csoff < max(weoff, reoff)) | ||
281 | csoff = max(weoff, reoff); | ||
282 | if (cson > 0x0f) | ||
283 | return -1; | ||
284 | if (csoff > 0x3f) | ||
285 | return -1; | ||
286 | |||
287 | l = cson; | ||
288 | l |= csoff << 4; | ||
289 | l |= weon << 10; | ||
290 | l |= weoff << 14; | ||
291 | l |= reon << 20; | ||
292 | l |= reoff << 24; | ||
293 | |||
294 | t->tim[0] = l; | ||
295 | |||
296 | actim = ps_to_rfbi_ticks(t->access_time, div); | ||
297 | if (actim <= reon) | ||
298 | actim = reon + 1; | ||
299 | if (actim > 0x3f) | ||
300 | return -1; | ||
301 | |||
302 | wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div); | ||
303 | if (wecyc < weoff) | ||
304 | wecyc = weoff; | ||
305 | if (wecyc > 0x3f) | ||
306 | return -1; | ||
307 | |||
308 | recyc = ps_to_rfbi_ticks(t->re_cycle_time, div); | ||
309 | if (recyc < reoff) | ||
310 | recyc = reoff; | ||
311 | if (recyc > 0x3f) | ||
312 | return -1; | ||
313 | |||
314 | cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div); | ||
315 | if (cs_pulse > 0x3f) | ||
316 | return -1; | ||
317 | |||
318 | l = wecyc; | ||
319 | l |= recyc << 6; | ||
320 | l |= cs_pulse << 12; | ||
321 | l |= actim << 22; | ||
322 | |||
323 | t->tim[1] = l; | ||
324 | |||
325 | t->tim[2] = div - 1; | ||
326 | |||
327 | t->converted = 1; | ||
328 | |||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | static int rfbi_setup_tearsync(unsigned pin_cnt, | ||
333 | unsigned hs_pulse_time, unsigned vs_pulse_time, | ||
334 | int hs_pol_inv, int vs_pol_inv, int extif_div) | ||
335 | { | ||
336 | int hs, vs; | ||
337 | int min; | ||
338 | u32 l; | ||
339 | |||
340 | if (pin_cnt != 1 && pin_cnt != 2) | ||
341 | return -EINVAL; | ||
342 | |||
343 | hs = ps_to_rfbi_ticks(hs_pulse_time, 1); | ||
344 | vs = ps_to_rfbi_ticks(vs_pulse_time, 1); | ||
345 | if (hs < 2) | ||
346 | return -EDOM; | ||
347 | if (pin_cnt == 2) | ||
348 | min = 2; | ||
349 | else | ||
350 | min = 4; | ||
351 | if (vs < min) | ||
352 | return -EDOM; | ||
353 | if (vs == hs) | ||
354 | return -EINVAL; | ||
355 | rfbi.tearsync_pin_cnt = pin_cnt; | ||
356 | dev_dbg(rfbi.fbdev->dev, | ||
357 | "setup_tearsync: pins %d hs %d vs %d hs_inv %d vs_inv %d\n", | ||
358 | pin_cnt, hs, vs, hs_pol_inv, vs_pol_inv); | ||
359 | |||
360 | rfbi_enable_clocks(1); | ||
361 | rfbi_write_reg(RFBI_HSYNC_WIDTH, hs); | ||
362 | rfbi_write_reg(RFBI_VSYNC_WIDTH, vs); | ||
363 | |||
364 | l = rfbi_read_reg(RFBI_CONFIG0); | ||
365 | if (hs_pol_inv) | ||
366 | l &= ~(1 << 21); | ||
367 | else | ||
368 | l |= 1 << 21; | ||
369 | if (vs_pol_inv) | ||
370 | l &= ~(1 << 20); | ||
371 | else | ||
372 | l |= 1 << 20; | ||
373 | rfbi_enable_clocks(0); | ||
374 | |||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | static int rfbi_enable_tearsync(int enable, unsigned line) | ||
379 | { | ||
380 | u32 l; | ||
381 | |||
382 | dev_dbg(rfbi.fbdev->dev, "tearsync %d line %d mode %d\n", | ||
383 | enable, line, rfbi.tearsync_mode); | ||
384 | if (line > (1 << 11) - 1) | ||
385 | return -EINVAL; | ||
386 | |||
387 | rfbi_enable_clocks(1); | ||
388 | l = rfbi_read_reg(RFBI_CONFIG0); | ||
389 | l &= ~(0x3 << 2); | ||
390 | if (enable) { | ||
391 | rfbi.tearsync_mode = rfbi.tearsync_pin_cnt; | ||
392 | l |= rfbi.tearsync_mode << 2; | ||
393 | } else | ||
394 | rfbi.tearsync_mode = 0; | ||
395 | rfbi_write_reg(RFBI_CONFIG0, l); | ||
396 | rfbi_write_reg(RFBI_LINE_NUMBER, line); | ||
397 | rfbi_enable_clocks(0); | ||
398 | |||
399 | return 0; | ||
400 | } | ||
401 | |||
402 | static void rfbi_write_command(const void *buf, unsigned int len) | ||
403 | { | ||
404 | rfbi_enable_clocks(1); | ||
405 | if (rfbi.bits_per_cycle == 16) { | ||
406 | const u16 *w = buf; | ||
407 | BUG_ON(len & 1); | ||
408 | for (; len; len -= 2) | ||
409 | rfbi_write_reg(RFBI_CMD, *w++); | ||
410 | } else { | ||
411 | const u8 *b = buf; | ||
412 | BUG_ON(rfbi.bits_per_cycle != 8); | ||
413 | for (; len; len--) | ||
414 | rfbi_write_reg(RFBI_CMD, *b++); | ||
415 | } | ||
416 | rfbi_enable_clocks(0); | ||
417 | } | ||
418 | |||
419 | static void rfbi_read_data(void *buf, unsigned int len) | ||
420 | { | ||
421 | rfbi_enable_clocks(1); | ||
422 | if (rfbi.bits_per_cycle == 16) { | ||
423 | u16 *w = buf; | ||
424 | BUG_ON(len & ~1); | ||
425 | for (; len; len -= 2) { | ||
426 | rfbi_write_reg(RFBI_READ, 0); | ||
427 | *w++ = rfbi_read_reg(RFBI_READ); | ||
428 | } | ||
429 | } else { | ||
430 | u8 *b = buf; | ||
431 | BUG_ON(rfbi.bits_per_cycle != 8); | ||
432 | for (; len; len--) { | ||
433 | rfbi_write_reg(RFBI_READ, 0); | ||
434 | *b++ = rfbi_read_reg(RFBI_READ); | ||
435 | } | ||
436 | } | ||
437 | rfbi_enable_clocks(0); | ||
438 | } | ||
439 | |||
440 | static void rfbi_write_data(const void *buf, unsigned int len) | ||
441 | { | ||
442 | rfbi_enable_clocks(1); | ||
443 | if (rfbi.bits_per_cycle == 16) { | ||
444 | const u16 *w = buf; | ||
445 | BUG_ON(len & 1); | ||
446 | for (; len; len -= 2) | ||
447 | rfbi_write_reg(RFBI_PARAM, *w++); | ||
448 | } else { | ||
449 | const u8 *b = buf; | ||
450 | BUG_ON(rfbi.bits_per_cycle != 8); | ||
451 | for (; len; len--) | ||
452 | rfbi_write_reg(RFBI_PARAM, *b++); | ||
453 | } | ||
454 | rfbi_enable_clocks(0); | ||
455 | } | ||
456 | |||
457 | static void rfbi_transfer_area(int width, int height, | ||
458 | void (callback)(void * data), void *data) | ||
459 | { | ||
460 | u32 w; | ||
461 | |||
462 | BUG_ON(callback == NULL); | ||
463 | |||
464 | rfbi_enable_clocks(1); | ||
465 | omap_dispc_set_lcd_size(width, height); | ||
466 | |||
467 | rfbi.lcdc_callback = callback; | ||
468 | rfbi.lcdc_callback_data = data; | ||
469 | |||
470 | rfbi_write_reg(RFBI_PIXEL_CNT, width * height); | ||
471 | |||
472 | w = rfbi_read_reg(RFBI_CONTROL); | ||
473 | w |= 1; /* enable */ | ||
474 | if (!rfbi.tearsync_mode) | ||
475 | w |= 1 << 4; /* internal trigger, reset by HW */ | ||
476 | rfbi_write_reg(RFBI_CONTROL, w); | ||
477 | |||
478 | omap_dispc_enable_lcd_out(1); | ||
479 | } | ||
480 | |||
481 | static inline void _stop_transfer(void) | ||
482 | { | ||
483 | u32 w; | ||
484 | |||
485 | w = rfbi_read_reg(RFBI_CONTROL); | ||
486 | rfbi_write_reg(RFBI_CONTROL, w & ~(1 << 0)); | ||
487 | rfbi_enable_clocks(0); | ||
488 | } | ||
489 | |||
490 | static void rfbi_dma_callback(void *data) | ||
491 | { | ||
492 | _stop_transfer(); | ||
493 | rfbi.lcdc_callback(rfbi.lcdc_callback_data); | ||
494 | } | ||
495 | |||
496 | static void rfbi_set_bits_per_cycle(int bpc) | ||
497 | { | ||
498 | u32 l; | ||
499 | |||
500 | rfbi_enable_clocks(1); | ||
501 | l = rfbi_read_reg(RFBI_CONFIG0); | ||
502 | l &= ~(0x03 << 0); | ||
503 | |||
504 | switch (bpc) { | ||
505 | case 8: | ||
506 | break; | ||
507 | case 16: | ||
508 | l |= 3; | ||
509 | break; | ||
510 | default: | ||
511 | BUG(); | ||
512 | } | ||
513 | rfbi_write_reg(RFBI_CONFIG0, l); | ||
514 | rfbi.bits_per_cycle = bpc; | ||
515 | rfbi_enable_clocks(0); | ||
516 | } | ||
517 | |||
518 | static int rfbi_init(struct omapfb_device *fbdev) | ||
519 | { | ||
520 | u32 l; | ||
521 | int r; | ||
522 | |||
523 | rfbi.fbdev = fbdev; | ||
524 | rfbi.base = ioremap(RFBI_BASE, SZ_1K); | ||
525 | if (!rfbi.base) { | ||
526 | dev_err(fbdev->dev, "can't ioremap RFBI\n"); | ||
527 | return -ENOMEM; | ||
528 | } | ||
529 | |||
530 | if ((r = rfbi_get_clocks()) < 0) | ||
531 | return r; | ||
532 | rfbi_enable_clocks(1); | ||
533 | |||
534 | rfbi.l4_khz = clk_get_rate(rfbi.dss_ick) / 1000; | ||
535 | |||
536 | /* Reset */ | ||
537 | rfbi_write_reg(RFBI_SYSCONFIG, 1 << 1); | ||
538 | while (!(rfbi_read_reg(RFBI_SYSSTATUS) & (1 << 0))); | ||
539 | |||
540 | l = rfbi_read_reg(RFBI_SYSCONFIG); | ||
541 | /* Enable autoidle and smart-idle */ | ||
542 | l |= (1 << 0) | (2 << 3); | ||
543 | rfbi_write_reg(RFBI_SYSCONFIG, l); | ||
544 | |||
545 | /* 16-bit interface, ITE trigger mode, 16-bit data */ | ||
546 | l = (0x03 << 0) | (0x00 << 2) | (0x01 << 5) | (0x02 << 7); | ||
547 | l |= (0 << 9) | (1 << 20) | (1 << 21); | ||
548 | rfbi_write_reg(RFBI_CONFIG0, l); | ||
549 | |||
550 | rfbi_write_reg(RFBI_DATA_CYCLE1_0, 0x00000010); | ||
551 | |||
552 | l = rfbi_read_reg(RFBI_CONTROL); | ||
553 | /* Select CS0, clear bypass mode */ | ||
554 | l = (0x01 << 2); | ||
555 | rfbi_write_reg(RFBI_CONTROL, l); | ||
556 | |||
557 | r = omap_dispc_request_irq(DISPC_IRQ_FRAMEMASK, rfbi_dma_callback, | ||
558 | NULL); | ||
559 | if (r < 0) { | ||
560 | dev_err(fbdev->dev, "can't get DISPC irq\n"); | ||
561 | rfbi_enable_clocks(0); | ||
562 | return r; | ||
563 | } | ||
564 | |||
565 | l = rfbi_read_reg(RFBI_REVISION); | ||
566 | pr_info("omapfb: RFBI version %d.%d initialized\n", | ||
567 | (l >> 4) & 0x0f, l & 0x0f); | ||
568 | |||
569 | rfbi_enable_clocks(0); | ||
570 | |||
571 | return 0; | ||
572 | } | ||
573 | |||
574 | static void rfbi_cleanup(void) | ||
575 | { | ||
576 | omap_dispc_free_irq(DISPC_IRQ_FRAMEMASK, rfbi_dma_callback, NULL); | ||
577 | rfbi_put_clocks(); | ||
578 | iounmap(rfbi.base); | ||
579 | } | ||
580 | |||
581 | const struct lcd_ctrl_extif omap2_ext_if = { | ||
582 | .init = rfbi_init, | ||
583 | .cleanup = rfbi_cleanup, | ||
584 | .get_clk_info = rfbi_get_clk_info, | ||
585 | .get_max_tx_rate = rfbi_get_max_tx_rate, | ||
586 | .set_bits_per_cycle = rfbi_set_bits_per_cycle, | ||
587 | .convert_timings = rfbi_convert_timings, | ||
588 | .set_timings = rfbi_set_timings, | ||
589 | .write_command = rfbi_write_command, | ||
590 | .read_data = rfbi_read_data, | ||
591 | .write_data = rfbi_write_data, | ||
592 | .transfer_area = rfbi_transfer_area, | ||
593 | .setup_tearsync = rfbi_setup_tearsync, | ||
594 | .enable_tearsync = rfbi_enable_tearsync, | ||
595 | |||
596 | .max_transmit_size = (u32) ~0, | ||
597 | }; | ||
598 | |||