]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/video/omap/rfbi.c
a288b466f3fffde6e1f0950661fcafe26bb41e7c
[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
31 #include <asm/io.h>
32 #include <asm/hardware/clock.h>
33
34 #include <asm/arch/omapfb.h>
35
36 #include "dispc.h"
37
38 #define MODULE_NAME "omapfb-rfbi"
39
40 #define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
41
42 #define RFBI_BASE               0x48050800
43 #define RFBI_REVISION           0x0000
44 #define RFBI_SYSCONFIG          0x0010
45 #define RFBI_SYSSTATUS          0x0014
46 #define RFBI_CONTROL            0x0040
47 #define RFBI_PIXEL_CNT          0x0044
48 #define RFBI_LINE_NUMBER        0x0048
49 #define RFBI_CMD                0x004c
50 #define RFBI_PARAM              0x0050
51 #define RFBI_DATA               0x0054
52 #define RFBI_READ               0x0058
53 #define RFBI_STATUS             0x005c
54 #define RFBI_CONFIG0            0x0060
55 #define RFBI_ONOFF_TIME0        0x0064
56 #define RFBI_CYCLE_TIME0        0x0068
57 #define RFBI_DATA_CYCLE1_0      0x006c
58 #define RFBI_DATA_CYCLE2_0      0x0070
59 #define RFBI_DATA_CYCLE3_0      0x0074
60 #define RFBI_VSYNC_WIDTH        0x0090
61 #define RFBI_HSYNC_WIDTH        0x0094
62
63 #define DISPC_BASE              0x48050400
64 #define DISPC_CONTROL           0x0040
65
66 static struct {
67         u32             base;
68         void            (*lcdc_callback)(void *data);
69         void            *lcdc_callback_data;
70         unsigned long   l4_khz;
71 } rfbi;
72
73 static inline void rfbi_write_reg(int idx, u32 val)
74 {
75         __raw_writel(val, rfbi.base + idx);
76 }
77
78 static inline u32 rfbi_read_reg(int idx)
79 {
80         return __raw_readl(rfbi.base + idx);
81 }
82
83 static int ns_to_l4_ticks(int time)
84 {
85         unsigned long tick_ps;
86         int ret;
87
88         /* Calculate in picosecs to yield more exact results */
89         tick_ps = 1000000000 / (rfbi.l4_khz);
90
91         ret = (time * 1000 + tick_ps - 1) / tick_ps;
92
93         return ret * 2;
94 }
95
96 #ifdef OMAPFB_DBG
97 static void print_timings(void)
98 {
99         u32 l;
100
101         DBGPRINT(1, "Tick time %lu ps\n", 1000000000 / rfbi.l4_khz);
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 #endif
113
114 static void rfbi_set_timings(const struct extif_timings *t)
115 {
116         u32 l;
117         int on, off;
118
119         on = ns_to_l4_ticks(t->cs_on_time) & 0x0f;
120         l = on;
121         off = ns_to_l4_ticks(t->cs_off_time) & 0x3f;
122         if (off <= on)
123                 off = on + 2;
124         l |= off << 4;
125
126         on = ns_to_l4_ticks(t->we_on_time) & 0x0f;
127         l |= on << 10;
128         off = ns_to_l4_ticks(t->we_off_time) & 0x3f;
129         if (off <= on)
130                 off = on + 2;
131         l |= off << 14;
132
133         l |= (ns_to_l4_ticks(t->re_on_time) & 0x0f) << 20;
134         l |= (ns_to_l4_ticks(t->re_off_time) & 0x3f) << 24;
135         rfbi_write_reg(RFBI_ONOFF_TIME0, l);
136
137         l = ns_to_l4_ticks(t->we_cycle_time) & 0x3f;
138         l |= (ns_to_l4_ticks(t->re_cycle_time) & 0x3f) << 6;
139         l |= (ns_to_l4_ticks(t->cs_pulse_width) & 0x3f) << 12;
140         l |= (ns_to_l4_ticks(t->access_time) & 0x3f) << 22;
141         rfbi_write_reg(RFBI_CYCLE_TIME0, l);
142 }
143
144 static void rfbi_write_command(u32 cmd)
145 {
146         rfbi_write_reg(RFBI_CMD, cmd);
147 }
148
149 static u32 rfbi_read_data(void)
150 {
151         u32 val;
152
153         rfbi_write_reg(RFBI_READ, 0);
154         val = rfbi_read_reg(RFBI_READ);
155         return val;
156 }
157
158 static void rfbi_write_data(u32 val)
159 {
160         rfbi_write_reg(RFBI_PARAM, val);
161 }
162
163 static void rfbi_transfer_area(int width, int height,
164                                 void (callback)(void * data), void *data)
165 {
166         u32 w;
167
168         BUG_ON(callback == NULL);
169
170         omap_dispc_set_lcd_size(width, height);
171
172         rfbi.lcdc_callback = callback;
173         rfbi.lcdc_callback_data = data;
174
175         rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
176
177         w = rfbi_read_reg(RFBI_CONTROL);
178         /* Enable, Internal trigger */
179         rfbi_write_reg(RFBI_CONTROL, w | (1 << 0) | (1 << 4));
180
181         omap_dispc_enable_lcd_out(1);
182 }
183
184 static inline void _stop_transfer(void)
185 {
186         u32 w;
187
188         w = rfbi_read_reg(RFBI_CONTROL);
189         rfbi_write_reg(RFBI_CONTROL, w & ~(1 << 0));
190 }
191
192 static void rfbi_dma_callback(void *data)
193 {
194         _stop_transfer();
195         rfbi.lcdc_callback(rfbi.lcdc_callback_data);
196 }
197
198 static int rfbi_init(void)
199 {
200         u32 l;
201         int r;
202         struct clk *dss_ick;
203
204         memset(&rfbi, 0, sizeof(rfbi));
205         rfbi.base = io_p2v(RFBI_BASE);
206
207         l = rfbi_read_reg(RFBI_REVISION);
208         pr_info(MODULE_NAME ": version %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
209
210         dss_ick = clk_get(NULL, "dss_ick");
211         if (IS_ERR(dss_ick)) {
212                 pr_err("can't get dss_ick\n");
213                 return PTR_ERR(dss_ick);
214         }
215         rfbi.l4_khz = clk_get_rate(dss_ick) / 1000;
216         clk_put(dss_ick);
217
218         /* Reset */
219         rfbi_write_reg(RFBI_SYSCONFIG, 1 << 1);
220         while (!(rfbi_read_reg(RFBI_SYSSTATUS) & (1 << 0)));
221
222         l = rfbi_read_reg(RFBI_SYSCONFIG);
223         /* Enable autoidle and smart-idle */
224         l |= (1 << 0) | (2 << 3);
225         rfbi_write_reg(RFBI_SYSCONFIG, l);
226
227         /* 16-bit interface, ITE trigger mode, 16-bit data */
228         l = (0x03 << 0) | (0x00 << 2) | (0x01 << 5) | (0x02 << 7);
229         l |= (0 << 9) | (1 << 20) | (1 << 21);
230         rfbi_write_reg(RFBI_CONFIG0, l);
231
232         l = 0x10;
233         rfbi_write_reg(RFBI_DATA_CYCLE1_0, l);
234         rfbi_write_reg(RFBI_DATA_CYCLE2_0, l);
235         rfbi_write_reg(RFBI_DATA_CYCLE3_0, l);
236
237         l = rfbi_read_reg(RFBI_CONTROL);
238         /* Select CS0 */
239         l = (0x01 << 2);
240         rfbi_write_reg(RFBI_CONTROL, l);
241
242         if ((r = omap_dispc_request_irq(rfbi_dma_callback, NULL)) < 0) {
243                 pr_err("can't get DISPC irq\n");
244                 return r;
245         }
246
247         return 0;
248 }
249
250 static void rfbi_cleanup(void)
251 {
252         omap_dispc_free_irq();
253 }
254
255 struct lcd_ctrl_extif rfbi_extif = {
256         .init                   = rfbi_init,
257         .cleanup                = rfbi_cleanup,
258         .set_timings            = rfbi_set_timings,
259         .write_command          = rfbi_write_command,
260         .read_data              = rfbi_read_data,
261         .write_data             = rfbi_write_data,
262         .transfer_area          = rfbi_transfer_area,
263 };
264