]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/video/omap/rfbi.c
Merge with /home/tmlind/src/kernel/linux-2.6
[linux-2.6-omap-h63xx.git] / drivers / video / omap / rfbi.c
1 /*
2  * File: drivers/video/omap/omap2/rfbi.c
3  *
4  * OMAP2 Remote Frame Buffer Interface support
5  *
6  * Copyright (C) 2005 Nokia Corporation
7  * Author: Juha Yrjölä <juha.yrjola@nokia.com>
8  *         Imre Deak <imre.deak@nokia.com>
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 as published by the
12  * Free Software Foundation; either version 2 of the License, or (at your
13  * option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with this program; if not, write to the Free Software Foundation, Inc.,
22  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24 #include <linux/module.h>
25 #include <linux/delay.h>
26 #include <linux/i2c.h>
27 #include <linux/err.h>
28 #include <linux/interrupt.h>
29 #include <linux/clk.h>
30
31 #include <asm/io.h>
32
33 #include <asm/arch/omapfb.h>
34
35 #include "dispc.h"
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
61 static struct {
62         u32             base;
63         void            (*lcdc_callback)(void *data);
64         void            *lcdc_callback_data;
65         unsigned long   l4_khz;
66         int             bits_per_cycle;
67         struct omapfb_device *fbdev;
68         struct clk      *dss_ick;
69         struct clk      *dss1_fck;
70 } rfbi;
71
72 static inline void rfbi_write_reg(int idx, u32 val)
73 {
74         __raw_writel(val, rfbi.base + idx);
75 }
76
77 static inline u32 rfbi_read_reg(int idx)
78 {
79         return __raw_readl(rfbi.base + idx);
80 }
81
82 static int rfbi_get_clocks(void)
83 {
84         if (IS_ERR((rfbi.dss_ick = clk_get(rfbi.fbdev->dev, "dss_ick")))) {
85                 dev_err(rfbi.fbdev->dev, "can't get dss_ick");
86                 return PTR_ERR(rfbi.dss_ick);
87         }
88
89         if (IS_ERR((rfbi.dss1_fck = clk_get(rfbi.fbdev->dev, "dss1_fck")))) {
90                 dev_err(rfbi.fbdev->dev, "can't get dss1_fck");
91                 clk_put(rfbi.dss_ick);
92                 return PTR_ERR(rfbi.dss1_fck);
93         }
94
95         return 0;
96 }
97
98 static void rfbi_put_clocks(void)
99 {
100         clk_put(rfbi.dss1_fck);
101         clk_put(rfbi.dss_ick);
102 }
103
104 static void rfbi_enable_clocks(int enable)
105 {
106         if (enable) {
107                 clk_enable(rfbi.dss_ick);
108                 clk_enable(rfbi.dss1_fck);
109         } else {
110                 clk_disable(rfbi.dss1_fck);
111                 clk_disable(rfbi.dss_ick);
112         }
113 }
114
115
116 #ifdef VERBOSE
117 static void rfbi_print_timings(void)
118 {
119         u32 l;
120         u32 time;
121
122         l = rfbi_read_reg(RFBI_CONFIG0);
123         time = 1000000000 / rfbi.l4_khz;
124         if (l & (1 << 4))
125                 time *= 2;
126
127         dev_dbg(rfbi.fbdev->dev, "Tick time %u ps\n", time);
128         l = rfbi_read_reg(RFBI_ONOFF_TIME0);
129         dev_dbg(rfbi.fbdev->dev,
130                 "CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
131                 "REONTIME %d, REOFFTIME %d\n",
132                 l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
133                 (l >> 20) & 0x0f, (l >> 24) & 0x3f);
134
135         l = rfbi_read_reg(RFBI_CYCLE_TIME0);
136         dev_dbg(rfbi.fbdev->dev,
137                 "WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
138                 "ACCESSTIME %d\n",
139                 (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f,
140                 (l >> 22) & 0x3f);
141 }
142 #else
143 static void rfbi_print_timings(void) {}
144 #endif
145
146 static void rfbi_set_timings(const struct extif_timings *t)
147 {
148         u32 l;
149
150         BUG_ON(!t->converted);
151
152         rfbi_enable_clocks(1);
153         rfbi_write_reg(RFBI_ONOFF_TIME0, t->tim[0]);
154         rfbi_write_reg(RFBI_CYCLE_TIME0, t->tim[1]);
155
156         l = rfbi_read_reg(RFBI_CONFIG0);
157         l &= ~(1 << 4);
158         l |= (t->tim[2] ? 1 : 0) << 4;
159         rfbi_write_reg(RFBI_CONFIG0, l);
160
161         rfbi_print_timings();
162         rfbi_enable_clocks(0);
163 }
164
165 static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
166 {
167         *clk_period = 1000000000 / rfbi.l4_khz;
168         *max_clk_div = 2;
169 }
170
171 static int ps_to_rfbi_ticks(int time, int div)
172 {
173         unsigned long tick_ps;
174         int ret;
175
176         /* Calculate in picosecs to yield more exact results */
177         tick_ps = 1000000000 / (rfbi.l4_khz) * div;
178
179         ret = (time + tick_ps - 1) / tick_ps;
180
181         return ret;
182 }
183
184 static int rfbi_convert_timings(struct extif_timings *t)
185 {
186         u32 l;
187         int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
188         int actim, recyc, wecyc;
189         int div = t->clk_div;
190
191         if (div <= 0 || div > 2)
192                 return -1;
193
194         /* Make sure that after conversion it still holds that:
195          * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff,
196          * csoff > cson, csoff >= max(weoff, reoff), actim > reon
197          */
198         weon = ps_to_rfbi_ticks(t->we_on_time, div);
199         weoff = ps_to_rfbi_ticks(t->we_off_time, div);
200         if (weoff <= weon)
201                 weoff = weon + 1;
202         if (weon > 0x0f)
203                 return -1;
204         if (weoff > 0x3f)
205                 return -1;
206
207         reon = ps_to_rfbi_ticks(t->re_on_time, div);
208         reoff = ps_to_rfbi_ticks(t->re_off_time, div);
209         if (reoff <= reon)
210                 reoff = reon + 1;
211         if (reon > 0x0f)
212                 return -1;
213         if (reoff > 0x3f)
214                 return -1;
215
216         cson = ps_to_rfbi_ticks(t->cs_on_time, div);
217         csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
218         if (csoff <= cson)
219                 csoff = cson + 1;
220         if (csoff < max(weoff, reoff))
221                 csoff = max(weoff, reoff);
222         if (cson > 0x0f)
223                 return -1;
224         if (csoff > 0x3f)
225                 return -1;
226
227         l =  cson;
228         l |= csoff << 4;
229         l |= weon  << 10;
230         l |= weoff << 14;
231         l |= reon  << 20;
232         l |= reoff << 24;
233
234         t->tim[0] = l;
235
236         actim = ps_to_rfbi_ticks(t->access_time, div);
237         if (actim <= reon)
238                 actim = reon + 1;
239         if (actim > 0x3f)
240                 return -1;
241
242         wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
243         if (wecyc < weoff)
244                 wecyc = weoff;
245         if (wecyc > 0x3f)
246                 return -1;
247
248         recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
249         if (recyc < reoff)
250                 recyc = reoff;
251         if (recyc > 0x3f)
252                 return -1;
253
254         cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
255         if (cs_pulse > 0x3f)
256                 return -1;
257
258         l =  wecyc;
259         l |= recyc    << 6;
260         l |= cs_pulse << 12;
261         l |= actim    << 22;
262
263         t->tim[1] = l;
264
265         t->tim[2] = div - 1;
266
267         t->converted = 1;
268
269         return 0;
270 }
271
272 static void rfbi_write_command(const void *buf, unsigned int len)
273 {
274         rfbi_enable_clocks(1);
275         if (rfbi.bits_per_cycle == 16) {
276                 const u16 *w = buf;
277                 BUG_ON(len & 1);
278                 for (; len; len -= 2)
279                         rfbi_write_reg(RFBI_CMD, *w++);
280         } else {
281                 const u8 *b = buf;
282                 BUG_ON(rfbi.bits_per_cycle != 8);
283                 for (; len; len--)
284                         rfbi_write_reg(RFBI_CMD, *b++);
285         }
286         rfbi_enable_clocks(0);
287 }
288
289 static void rfbi_read_data(void *buf, unsigned int len)
290 {
291         rfbi_enable_clocks(1);
292         if (rfbi.bits_per_cycle == 16) {
293                 u16 *w = buf;
294                 BUG_ON(len & ~1);
295                 for (; len; len -= 2) {
296                         rfbi_write_reg(RFBI_READ, 0);
297                         *w++ = rfbi_read_reg(RFBI_READ);
298                 }
299         } else {
300                 u8 *b = buf;
301                 BUG_ON(rfbi.bits_per_cycle != 8);
302                 for (; len; len--) {
303                         rfbi_write_reg(RFBI_READ, 0);
304                         *b++ = rfbi_read_reg(RFBI_READ);
305                 }
306         }
307         rfbi_enable_clocks(0);
308 }
309
310 static void rfbi_write_data(const void *buf, unsigned int len)
311 {
312         rfbi_enable_clocks(1);
313         if (rfbi.bits_per_cycle == 16) {
314                 const u16 *w = buf;
315                 BUG_ON(len & 1);
316                 for (; len; len -= 2)
317                         rfbi_write_reg(RFBI_PARAM, *w++);
318         } else {
319                 const u8 *b = buf;
320                 BUG_ON(rfbi.bits_per_cycle != 8);
321                 for (; len; len--)
322                         rfbi_write_reg(RFBI_PARAM, *b++);
323         }
324         rfbi_enable_clocks(0);
325 }
326
327 static void rfbi_transfer_area(int width, int height,
328                                 void (callback)(void * data), void *data)
329 {
330         u32 w;
331
332         BUG_ON(callback == NULL);
333
334         rfbi_enable_clocks(1);
335         omap_dispc_set_lcd_size(width, height);
336
337         rfbi.lcdc_callback = callback;
338         rfbi.lcdc_callback_data = data;
339
340         rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
341
342         w = rfbi_read_reg(RFBI_CONTROL);
343         /* Enable, Internal trigger */
344         rfbi_write_reg(RFBI_CONTROL, w | (1 << 0) | (1 << 4));
345
346         omap_dispc_enable_lcd_out(1);
347 }
348
349 static inline void _stop_transfer(void)
350 {
351         u32 w;
352
353         w = rfbi_read_reg(RFBI_CONTROL);
354         rfbi_write_reg(RFBI_CONTROL, w & ~(1 << 0));
355         rfbi_enable_clocks(0);
356 }
357
358 static void rfbi_dma_callback(void *data)
359 {
360         _stop_transfer();
361         rfbi.lcdc_callback(rfbi.lcdc_callback_data);
362 }
363
364 static void rfbi_set_bits_per_cycle(int bpc)
365 {
366         u32 l;
367
368         rfbi_enable_clocks(1);
369         l = rfbi_read_reg(RFBI_CONFIG0);
370         l &= ~(0x03 << 0);
371         switch (bpc)
372         {
373         case 8:
374                 break;
375         case 16:
376                 l |= 3;
377                 break;
378         default:
379                 BUG();
380         }
381         rfbi_write_reg(RFBI_CONFIG0, l);
382         rfbi.bits_per_cycle = bpc;
383         rfbi_enable_clocks(0);
384 }
385
386 static int rfbi_init(struct omapfb_device *fbdev)
387 {
388         u32 l;
389         int r;
390
391         rfbi.fbdev = fbdev;
392         rfbi.base = io_p2v(RFBI_BASE);
393
394         if ((r = rfbi_get_clocks()) < 0)
395                 return r;
396         rfbi_enable_clocks(1);
397
398         rfbi.l4_khz = clk_get_rate(rfbi.dss_ick) / 1000;
399
400         /* Reset */
401         rfbi_write_reg(RFBI_SYSCONFIG, 1 << 1);
402         while (!(rfbi_read_reg(RFBI_SYSSTATUS) & (1 << 0)));
403
404         l = rfbi_read_reg(RFBI_SYSCONFIG);
405         /* Enable autoidle and smart-idle */
406         l |= (1 << 0) | (2 << 3);
407         rfbi_write_reg(RFBI_SYSCONFIG, l);
408
409         /* 16-bit interface, ITE trigger mode, 16-bit data */
410         l = (0x03 << 0) | (0x00 << 2) | (0x01 << 5) | (0x02 << 7);
411         l |= (0 << 9) | (1 << 20) | (1 << 21);
412         rfbi_write_reg(RFBI_CONFIG0, l);
413
414         rfbi_write_reg(RFBI_DATA_CYCLE1_0, 0x00000010);
415
416         l = rfbi_read_reg(RFBI_CONTROL);
417         /* Select CS0, clear bypass mode */
418         l = (0x01 << 2);
419         rfbi_write_reg(RFBI_CONTROL, l);
420
421         if ((r = omap_dispc_request_irq(rfbi_dma_callback, NULL)) < 0) {
422                 dev_err(fbdev->dev, "can't get DISPC irq\n");
423                 rfbi_enable_clocks(0);
424                 return r;
425         }
426
427         l = rfbi_read_reg(RFBI_REVISION);
428         pr_info("omapfb: RFBI version %d.%d initialized\n",
429                 (l >> 4) & 0x0f, l & 0x0f);
430
431         rfbi_enable_clocks(0);
432
433         return 0;
434 }
435
436 static void rfbi_cleanup(void)
437 {
438         omap_dispc_free_irq();
439         rfbi_put_clocks();
440 }
441
442 const struct lcd_ctrl_extif omap2_ext_if = {
443         .init                   = rfbi_init,
444         .cleanup                = rfbi_cleanup,
445         .get_clk_info           = rfbi_get_clk_info,
446         .set_bits_per_cycle     = rfbi_set_bits_per_cycle,
447         .convert_timings        = rfbi_convert_timings,
448         .set_timings            = rfbi_set_timings,
449         .write_command          = rfbi_write_command,
450         .read_data              = rfbi_read_data,
451         .write_data             = rfbi_write_data,
452         .transfer_area          = rfbi_transfer_area,
453
454         .max_transmit_size      = (u32)~0,
455 };
456