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.
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>
33 #include <asm/arch/omapfb.h>
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
58 #define DISPC_BASE 0x48050400
59 #define DISPC_CONTROL 0x0040
63 void (*lcdc_callback)(void *data);
64 void *lcdc_callback_data;
67 struct omapfb_device *fbdev;
72 static inline void rfbi_write_reg(int idx, u32 val)
74 __raw_writel(val, rfbi.base + idx);
77 static inline u32 rfbi_read_reg(int idx)
79 return __raw_readl(rfbi.base + idx);
82 static int rfbi_get_clocks(void)
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);
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);
98 static void rfbi_put_clocks(void)
100 clk_put(rfbi.dss1_fck);
101 clk_put(rfbi.dss_ick);
104 static void rfbi_enable_clocks(int enable)
107 clk_enable(rfbi.dss_ick);
108 clk_enable(rfbi.dss1_fck);
110 clk_disable(rfbi.dss1_fck);
111 clk_disable(rfbi.dss_ick);
117 static void rfbi_print_timings(void)
122 l = rfbi_read_reg(RFBI_CONFIG0);
123 time = 1000000000 / rfbi.l4_khz;
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);
135 l = rfbi_read_reg(RFBI_CYCLE_TIME0);
136 dev_dbg(rfbi.fbdev->dev,
137 "WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
139 (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f,
143 static void rfbi_print_timings(void) {}
146 static void rfbi_set_timings(const struct extif_timings *t)
150 BUG_ON(!t->converted);
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]);
156 l = rfbi_read_reg(RFBI_CONFIG0);
158 l |= (t->tim[2] ? 1 : 0) << 4;
159 rfbi_write_reg(RFBI_CONFIG0, l);
161 rfbi_print_timings();
162 rfbi_enable_clocks(0);
165 static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
167 *clk_period = 1000000000 / rfbi.l4_khz;
171 static int ps_to_rfbi_ticks(int time, int div)
173 unsigned long tick_ps;
176 /* Calculate in picosecs to yield more exact results */
177 tick_ps = 1000000000 / (rfbi.l4_khz) * div;
179 ret = (time + tick_ps - 1) / tick_ps;
184 static int rfbi_convert_timings(struct extif_timings *t)
187 int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
188 int actim, recyc, wecyc;
189 int div = t->clk_div;
191 if (div <= 0 || div > 2)
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
198 weon = ps_to_rfbi_ticks(t->we_on_time, div);
199 weoff = ps_to_rfbi_ticks(t->we_off_time, div);
207 reon = ps_to_rfbi_ticks(t->re_on_time, div);
208 reoff = ps_to_rfbi_ticks(t->re_off_time, div);
216 cson = ps_to_rfbi_ticks(t->cs_on_time, div);
217 csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
220 if (csoff < max(weoff, reoff))
221 csoff = max(weoff, reoff);
236 actim = ps_to_rfbi_ticks(t->access_time, div);
242 wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
248 recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
254 cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
272 static void rfbi_write_command(const void *buf, unsigned int len)
274 rfbi_enable_clocks(1);
275 if (rfbi.bits_per_cycle == 16) {
278 for (; len; len -= 2)
279 rfbi_write_reg(RFBI_CMD, *w++);
282 BUG_ON(rfbi.bits_per_cycle != 8);
284 rfbi_write_reg(RFBI_CMD, *b++);
286 rfbi_enable_clocks(0);
289 static void rfbi_read_data(void *buf, unsigned int len)
291 rfbi_enable_clocks(1);
292 if (rfbi.bits_per_cycle == 16) {
295 for (; len; len -= 2) {
296 rfbi_write_reg(RFBI_READ, 0);
297 *w++ = rfbi_read_reg(RFBI_READ);
301 BUG_ON(rfbi.bits_per_cycle != 8);
303 rfbi_write_reg(RFBI_READ, 0);
304 *b++ = rfbi_read_reg(RFBI_READ);
307 rfbi_enable_clocks(0);
310 static void rfbi_write_data(const void *buf, unsigned int len)
312 rfbi_enable_clocks(1);
313 if (rfbi.bits_per_cycle == 16) {
316 for (; len; len -= 2)
317 rfbi_write_reg(RFBI_PARAM, *w++);
320 BUG_ON(rfbi.bits_per_cycle != 8);
322 rfbi_write_reg(RFBI_PARAM, *b++);
324 rfbi_enable_clocks(0);
327 static void rfbi_transfer_area(int width, int height,
328 void (callback)(void * data), void *data)
332 BUG_ON(callback == NULL);
334 rfbi_enable_clocks(1);
335 omap_dispc_set_lcd_size(width, height);
337 rfbi.lcdc_callback = callback;
338 rfbi.lcdc_callback_data = data;
340 rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
342 w = rfbi_read_reg(RFBI_CONTROL);
343 /* Enable, Internal trigger */
344 rfbi_write_reg(RFBI_CONTROL, w | (1 << 0) | (1 << 4));
346 omap_dispc_enable_lcd_out(1);
349 static inline void _stop_transfer(void)
353 w = rfbi_read_reg(RFBI_CONTROL);
354 rfbi_write_reg(RFBI_CONTROL, w & ~(1 << 0));
355 rfbi_enable_clocks(0);
358 static void rfbi_dma_callback(void *data)
361 rfbi.lcdc_callback(rfbi.lcdc_callback_data);
364 static void rfbi_set_bits_per_cycle(int bpc)
368 rfbi_enable_clocks(1);
369 l = rfbi_read_reg(RFBI_CONFIG0);
381 rfbi_write_reg(RFBI_CONFIG0, l);
382 rfbi.bits_per_cycle = bpc;
383 rfbi_enable_clocks(0);
386 static int rfbi_init(struct omapfb_device *fbdev)
392 rfbi.base = io_p2v(RFBI_BASE);
394 if ((r = rfbi_get_clocks()) < 0)
396 rfbi_enable_clocks(1);
398 rfbi.l4_khz = clk_get_rate(rfbi.dss_ick) / 1000;
401 rfbi_write_reg(RFBI_SYSCONFIG, 1 << 1);
402 while (!(rfbi_read_reg(RFBI_SYSSTATUS) & (1 << 0)));
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);
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);
414 rfbi_write_reg(RFBI_DATA_CYCLE1_0, 0x00000010);
416 l = rfbi_read_reg(RFBI_CONTROL);
417 /* Select CS0, clear bypass mode */
419 rfbi_write_reg(RFBI_CONTROL, l);
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);
427 l = rfbi_read_reg(RFBI_REVISION);
428 pr_info("omapfb: RFBI version %d.%d initialized\n",
429 (l >> 4) & 0x0f, l & 0x0f);
431 rfbi_enable_clocks(0);
436 static void rfbi_cleanup(void)
438 omap_dispc_free_irq();
442 const struct lcd_ctrl_extif omap2_ext_if = {
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,
454 .max_transmit_size = (u32)~0,