2 * File: drivers/video/omap/omap2/rfbi.c
4 * OMAP2 Remote Frame Buffer Interface support
6 * Copyright (C) 2005 Nokia Corporation
7 * Author: Juha Yrjölä <juha.yrjola@nokia.com>
8 * Imre Deak <imre.deak@nokia.com>
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.
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.
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.
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>
32 #include <asm/hardware/clock.h>
34 #include <asm/arch/omapfb.h>
38 #define MODULE_NAME "omapfb-rfbi"
40 #define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
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
63 #define DISPC_BASE 0x48050400
64 #define DISPC_CONTROL 0x0040
68 void (*lcdc_callback)(void *data);
69 void *lcdc_callback_data;
73 static inline void rfbi_write_reg(int idx, u32 val)
75 __raw_writel(val, rfbi.base + idx);
78 static inline u32 rfbi_read_reg(int idx)
80 return __raw_readl(rfbi.base + idx);
83 static int ns_to_l4_ticks(int time)
85 unsigned long tick_ps;
88 /* Calculate in picosecs to yield more exact results */
89 tick_ps = 1000000000 / (rfbi.l4_khz);
91 ret = (time * 1000 + tick_ps - 1) / tick_ps;
97 static void print_timings(void)
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, "
110 (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f, (l >> 22) & 0x3f);
114 static void rfbi_set_timings(const struct extif_timings *t)
119 on = ns_to_l4_ticks(t->cs_on_time) & 0x0f;
121 off = ns_to_l4_ticks(t->cs_off_time) & 0x3f;
126 on = ns_to_l4_ticks(t->we_on_time) & 0x0f;
128 off = ns_to_l4_ticks(t->we_off_time) & 0x3f;
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);
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);
144 static void rfbi_write_command(u32 cmd)
146 rfbi_write_reg(RFBI_CMD, cmd);
149 static u32 rfbi_read_data(void)
153 rfbi_write_reg(RFBI_READ, 0);
154 val = rfbi_read_reg(RFBI_READ);
158 static void rfbi_write_data(u32 val)
160 rfbi_write_reg(RFBI_PARAM, val);
163 static void rfbi_transfer_area(int width, int height,
164 void (callback)(void * data), void *data)
168 BUG_ON(callback == NULL);
170 omap_dispc_set_lcd_size(width, height);
172 rfbi.lcdc_callback = callback;
173 rfbi.lcdc_callback_data = data;
175 rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
177 w = rfbi_read_reg(RFBI_CONTROL);
178 /* Enable, Internal trigger */
179 rfbi_write_reg(RFBI_CONTROL, w | (1 << 0) | (1 << 4));
181 omap_dispc_enable_lcd_out(1);
184 static inline void _stop_transfer(void)
188 w = rfbi_read_reg(RFBI_CONTROL);
189 rfbi_write_reg(RFBI_CONTROL, w & ~(1 << 0));
192 static void rfbi_dma_callback(void *data)
195 rfbi.lcdc_callback(rfbi.lcdc_callback_data);
198 static int rfbi_init(void)
204 memset(&rfbi, 0, sizeof(rfbi));
205 rfbi.base = io_p2v(RFBI_BASE);
207 l = rfbi_read_reg(RFBI_REVISION);
208 pr_info(MODULE_NAME ": version %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
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);
215 rfbi.l4_khz = clk_get_rate(dss_ick) / 1000;
219 rfbi_write_reg(RFBI_SYSCONFIG, 1 << 1);
220 while (!(rfbi_read_reg(RFBI_SYSSTATUS) & (1 << 0)));
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);
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);
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);
237 l = rfbi_read_reg(RFBI_CONTROL);
240 rfbi_write_reg(RFBI_CONTROL, l);
242 if ((r = omap_dispc_request_irq(rfbi_dma_callback, NULL)) < 0) {
243 pr_err("can't get DISPC irq\n");
250 static void rfbi_cleanup(void)
252 omap_dispc_free_irq();
255 struct lcd_ctrl_extif rfbi_extif = {
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,