]> 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
25 #include <linux/module.h>
26 #include <linux/delay.h>
27 #include <linux/i2c.h>
28 #include <linux/err.h>
29 #include <linux/interrupt.h>
30 #include <linux/clk.h>
31
32 #include <asm/io.h>
33
34 #include <asm/arch/omapfb.h>
35
36 #include "dispc.h"
37
38 /* #define OMAPFB_DBG 1 */
39
40 #include "debug.h"
41
42 #define MODULE_NAME "omapfb-rfbi"
43
44 #define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
45
46 #define RFBI_BASE               0x48050800
47 #define RFBI_REVISION           0x0000
48 #define RFBI_SYSCONFIG          0x0010
49 #define RFBI_SYSSTATUS          0x0014
50 #define RFBI_CONTROL            0x0040
51 #define RFBI_PIXEL_CNT          0x0044
52 #define RFBI_LINE_NUMBER        0x0048
53 #define RFBI_CMD                0x004c
54 #define RFBI_PARAM              0x0050
55 #define RFBI_DATA               0x0054
56 #define RFBI_READ               0x0058
57 #define RFBI_STATUS             0x005c
58 #define RFBI_CONFIG0            0x0060
59 #define RFBI_ONOFF_TIME0        0x0064
60 #define RFBI_CYCLE_TIME0        0x0068
61 #define RFBI_DATA_CYCLE1_0      0x006c
62 #define RFBI_DATA_CYCLE2_0      0x0070
63 #define RFBI_DATA_CYCLE3_0      0x0074
64 #define RFBI_VSYNC_WIDTH        0x0090
65 #define RFBI_HSYNC_WIDTH        0x0094
66
67 #define DISPC_BASE              0x48050400
68 #define DISPC_CONTROL           0x0040
69
70 static struct {
71         u32             base;
72         void            (*lcdc_callback)(void *data);
73         void            *lcdc_callback_data;
74         unsigned long   l4_khz;
75         int             bits_per_cycle;
76 } rfbi;
77
78 struct lcd_ctrl_extif rfbi_extif;
79
80 static inline void rfbi_write_reg(int idx, u32 val)
81 {
82         __raw_writel(val, rfbi.base + idx);
83 }
84
85 static inline u32 rfbi_read_reg(int idx)
86 {
87         return __raw_readl(rfbi.base + idx);
88 }
89
90 #ifdef OMAPFB_DBG
91 static void rfbi_print_timings(void)
92 {
93         u32 l;
94         u32 time;
95
96         l = rfbi_read_reg(RFBI_CONFIG0);
97         time = 1000000000 / rfbi.l4_khz;
98         if (l & (1 << 4))
99                 time *= 2;
100
101         DBGPRINT(1, "Tick time %u ps\n", time);
102         l = rfbi_read_reg(RFBI_ONOFF_TIME0);
103         DBGPRINT(1, "CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
104                "REONTIME %d, REOFFTIME %d\n",
105                l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
106                (l >> 20) & 0x0f, (l >> 24) & 0x3f);
107         l = rfbi_read_reg(RFBI_CYCLE_TIME0);
108         DBGPRINT(1, "WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
109                "ACCESSTIME %d\n",
110                (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f, (l >> 22) & 0x3f);
111 }
112 #else
113 static void rfbi_print_timings(void) {}
114 #endif
115
116 static void rfbi_set_timings(const struct extif_timings *t)
117 {
118         u32 l;
119
120         BUG_ON(!t->converted);
121
122         rfbi_write_reg(RFBI_ONOFF_TIME0, t->tim[0]);
123         rfbi_write_reg(RFBI_CYCLE_TIME0, t->tim[1]);
124
125         l = rfbi_read_reg(RFBI_CONFIG0);
126         l &= ~(1 << 4);
127         l |= (t->tim[2] ? 1 : 0) << 4;
128         rfbi_write_reg(RFBI_CONFIG0, l);
129
130         rfbi_print_timings();
131 }
132
133 static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
134 {
135         *clk_period = 1000000000 / rfbi.l4_khz;
136         *max_clk_div = 2;
137 }
138
139 static int ps_to_rfbi_ticks(int time, int div)
140 {
141         unsigned long tick_ps;
142         int ret;
143
144         /* Calculate in picosecs to yield more exact results */
145         tick_ps = 1000000000 / (rfbi.l4_khz) * div;
146
147         ret = (time + tick_ps - 1) / tick_ps;
148
149         return ret;
150 }
151
152 static int rfbi_convert_timings(struct extif_timings *t)
153 {
154         u32 l;
155         int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
156         int actim, recyc, wecyc;
157         int div = t->clk_div;
158
159         if (div <= 0 || div > 2)
160                 return -1;
161
162         /* Make sure that after conversion it still holds that:
163          * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff,
164          * csoff > cson, csoff >= max(weoff, reoff), actim > reon
165          */
166         weon = ps_to_rfbi_ticks(t->we_on_time, div);
167         weoff = ps_to_rfbi_ticks(t->we_off_time, div);
168         if (weoff <= weon)
169                 weoff = weon + 1;
170         if (weon > 0x0f)
171                 return -1;
172         if (weoff > 0x3f)
173                 return -1;
174
175         reon = ps_to_rfbi_ticks(t->re_on_time, div);
176         reoff = ps_to_rfbi_ticks(t->re_off_time, div);
177         if (reoff <= reon)
178                 reoff = reon + 1;
179         if (reon > 0x0f)
180                 return -1;
181         if (reoff > 0x3f)
182                 return -1;
183
184         cson = ps_to_rfbi_ticks(t->cs_on_time, div);
185         csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
186         if (csoff <= cson)
187                 csoff = cson + 1;
188         if (csoff < max(weoff, reoff))
189                 csoff = max(weoff, reoff);
190         if (cson > 0x0f)
191                 return -1;
192         if (csoff > 0x3f)
193                 return -1;
194
195         l =  cson;
196         l |= csoff << 4;
197         l |= weon  << 10;
198         l |= weoff << 14;
199         l |= reon  << 20;
200         l |= reoff << 24;
201
202         t->tim[0] = l;
203
204         actim = ps_to_rfbi_ticks(t->access_time, div);
205         if (actim <= reon)
206                 actim = reon + 1;
207         if (actim > 0x3f)
208                 return -1;
209
210         wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
211         if (wecyc < weoff)
212                 wecyc = weoff;
213         if (wecyc > 0x3f)
214                 return -1;
215
216         recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
217         if (recyc < reoff)
218                 recyc = reoff;
219         if (recyc > 0x3f)
220                 return -1;
221
222         cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
223         if (cs_pulse > 0x3f)
224                 return -1;
225
226         l =  wecyc;
227         l |= recyc    << 6;
228         l |= cs_pulse << 12;
229         l |= actim    << 22;
230
231         t->tim[1] = l;
232
233         t->tim[2] = div - 1;
234
235         t->converted = 1;
236
237         return 0;
238 }
239
240 static void rfbi_write_command(const void *buf, unsigned int len)
241 {
242         if (rfbi.bits_per_cycle == 16) {
243                 const u16 *w = buf;
244                 BUG_ON(len & 1);
245                 for (; len; len -= 2)
246                         rfbi_write_reg(RFBI_CMD, *w++);
247         } else {
248                 const u8 *b = buf;
249                 BUG_ON(rfbi.bits_per_cycle != 8);
250                 for (; len; len--)
251                         rfbi_write_reg(RFBI_CMD, *b++);
252         }
253 }
254
255 static void rfbi_read_data(void *buf, unsigned int len)
256 {
257         if (rfbi.bits_per_cycle == 16) {
258                 u16 *w = buf;
259                 BUG_ON(len & ~1);
260                 for (; len; len -= 2) {
261                         rfbi_write_reg(RFBI_READ, 0);
262                         *w++ = rfbi_read_reg(RFBI_READ);
263                 }
264         } else {
265                 u8 *b = buf;
266                 BUG_ON(rfbi.bits_per_cycle != 8);
267                 for (; len; len--) {
268                         rfbi_write_reg(RFBI_READ, 0);
269                         *b++ = rfbi_read_reg(RFBI_READ);
270                 }
271         }
272 }
273
274 static void rfbi_write_data(const void *buf, unsigned int len)
275 {
276         if (rfbi.bits_per_cycle == 16) {
277                 const u16 *w = buf;
278                 BUG_ON(len & 1);
279                 for (; len; len -= 2)
280                         rfbi_write_reg(RFBI_PARAM, *w++);
281         } else {
282                 const u8 *b = buf;
283                 BUG_ON(rfbi.bits_per_cycle != 8);
284                 for (; len; len--)
285                         rfbi_write_reg(RFBI_PARAM, *b++);
286         }
287 }
288
289 static void rfbi_transfer_area(int width, int height,
290                                 void (callback)(void * data), void *data)
291 {
292         u32 w;
293
294         BUG_ON(callback == NULL);
295
296         omap_dispc_set_lcd_size(width, height);
297
298         rfbi.lcdc_callback = callback;
299         rfbi.lcdc_callback_data = data;
300
301         rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
302
303         w = rfbi_read_reg(RFBI_CONTROL);
304         /* Enable, Internal trigger */
305         rfbi_write_reg(RFBI_CONTROL, w | (1 << 0) | (1 << 4));
306
307         omap_dispc_enable_lcd_out(1);
308 }
309
310 static inline void _stop_transfer(void)
311 {
312         u32 w;
313
314         w = rfbi_read_reg(RFBI_CONTROL);
315         rfbi_write_reg(RFBI_CONTROL, w & ~(1 << 0));
316 }
317
318 static void rfbi_dma_callback(void *data)
319 {
320         _stop_transfer();
321         rfbi.lcdc_callback(rfbi.lcdc_callback_data);
322 }
323
324 static void rfbi_set_bits_per_cycle(int bpc)
325 {
326         u32 l;
327
328         l = rfbi_read_reg(RFBI_CONFIG0);
329         l &= ~(0x03 << 0);
330         switch (bpc)
331         {
332         case 8:
333                 break;
334         case 16:
335                 l |= 3;
336                 break;
337         default:
338                 BUG();
339         }
340         rfbi_write_reg(RFBI_CONFIG0, l);
341         rfbi.bits_per_cycle = bpc;
342 }
343
344 static int rfbi_init(void)
345 {
346         u32 l;
347         int r;
348         struct clk *dss_ick;
349
350         rfbi.base = io_p2v(RFBI_BASE);
351
352         l = rfbi_read_reg(RFBI_REVISION);
353         pr_info(MODULE_NAME ": version %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
354
355         dss_ick = clk_get(NULL, "dss_ick");
356         if (IS_ERR(dss_ick)) {
357                 pr_err("can't get dss_ick\n");
358                 return PTR_ERR(dss_ick);
359         }
360
361         rfbi.l4_khz = clk_get_rate(dss_ick) / 1000;
362         clk_put(dss_ick);
363
364         /* Reset */
365         rfbi_write_reg(RFBI_SYSCONFIG, 1 << 1);
366         while (!(rfbi_read_reg(RFBI_SYSSTATUS) & (1 << 0)));
367
368         l = rfbi_read_reg(RFBI_SYSCONFIG);
369         /* Enable autoidle and smart-idle */
370         l |= (1 << 0) | (2 << 3);
371         rfbi_write_reg(RFBI_SYSCONFIG, l);
372
373         /* 16-bit interface, ITE trigger mode, 16-bit data */
374         l = (0x03 << 0) | (0x00 << 2) | (0x01 << 5) | (0x02 << 7);
375         l |= (0 << 9) | (1 << 20) | (1 << 21);
376         rfbi_write_reg(RFBI_CONFIG0, l);
377
378         rfbi_write_reg(RFBI_DATA_CYCLE1_0, 0x00000010);
379
380         l = rfbi_read_reg(RFBI_CONTROL);
381         /* Select CS0, clear bypass mode */
382         l = (0x01 << 2);
383         rfbi_write_reg(RFBI_CONTROL, l);
384
385         if ((r = omap_dispc_request_irq(rfbi_dma_callback, NULL)) < 0) {
386                 pr_err("can't get DISPC irq\n");
387                 return r;
388         }
389
390         return 0;
391 }
392
393 static void rfbi_cleanup(void)
394 {
395         omap_dispc_free_irq();
396 }
397
398 struct lcd_ctrl_extif rfbi_extif = {
399         .init                   = rfbi_init,
400         .cleanup                = rfbi_cleanup,
401         .get_clk_info           = rfbi_get_clk_info,
402         .set_bits_per_cycle     = rfbi_set_bits_per_cycle,
403         .convert_timings        = rfbi_convert_timings,
404         .set_timings            = rfbi_set_timings,
405         .write_command          = rfbi_write_command,
406         .read_data              = rfbi_read_data,
407         .write_data             = rfbi_write_data,
408         .transfer_area          = rfbi_transfer_area,
409         .max_transmit_size      = (u32)~0,
410 };
411