aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap
diff options
context:
space:
mode:
authorFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2012-03-20 04:49:51 -0400
committerFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2012-03-20 04:49:51 -0400
commite9fe8a714e450b26f76eaf8832f5b9fe24d00e79 (patch)
tree78d0045cfdede7ad7e42181bde96978fdc792e06 /drivers/video/omap
parentf413070e3f0bccb40ca939b90699347daf815607 (diff)
parentdf01d53068bdf31609aafd9a857901a1f16dfa52 (diff)
Merge branch 'for-3.4' of git://gitorious.org/linux-omap-dss2/linux into fbdev-next
Diffstat (limited to 'drivers/video/omap')
-rw-r--r--drivers/video/omap/Kconfig16
-rw-r--r--drivers/video/omap/Makefile12
-rw-r--r--drivers/video/omap/blizzard.c1648
-rw-r--r--drivers/video/omap/dispc.c1547
-rw-r--r--drivers/video/omap/dispc.h46
-rw-r--r--drivers/video/omap/hwa742.c21
-rw-r--r--drivers/video/omap/omapfb.h25
-rw-r--r--drivers/video/omap/omapfb_main.c30
-rw-r--r--drivers/video/omap/rfbi.c598
9 files changed, 35 insertions, 3908 deletions
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
index 84ff23208c25..1e7536d9a8fc 100644
--- a/drivers/video/omap/Kconfig
+++ b/drivers/video/omap/Kconfig
@@ -1,11 +1,10 @@
1config FB_OMAP 1config FB_OMAP
2 tristate "OMAP frame buffer support (EXPERIMENTAL)" 2 tristate "OMAP frame buffer support (EXPERIMENTAL)"
3 depends on FB && (OMAP2_DSS = "n") 3 depends on FB
4 depends on ARCH_OMAP1 || ARCH_OMAP2 || ARCH_OMAP3 4 depends on ARCH_OMAP1
5 select FB_CFB_FILLRECT 5 select FB_CFB_FILLRECT
6 select FB_CFB_COPYAREA 6 select FB_CFB_COPYAREA
7 select FB_CFB_IMAGEBLIT 7 select FB_CFB_IMAGEBLIT
8 select TWL4030_CORE if MACH_OMAP_2430SDP
9 help 8 help
10 Frame buffer driver for OMAP based boards. 9 Frame buffer driver for OMAP based boards.
11 10
@@ -23,13 +22,6 @@ config FB_OMAP_LCDC_HWA742
23 Say Y here if you want to have support for the external 22 Say Y here if you want to have support for the external
24 Epson HWA742 LCD controller. 23 Epson HWA742 LCD controller.
25 24
26config FB_OMAP_LCDC_BLIZZARD
27 bool "Epson Blizzard LCD controller support"
28 depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL
29 help
30 Say Y here if you want to have support for the external
31 Epson Blizzard LCD controller.
32
33config FB_OMAP_MANUAL_UPDATE 25config FB_OMAP_MANUAL_UPDATE
34 bool "Default to manual update mode" 26 bool "Default to manual update mode"
35 depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL 27 depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL
@@ -49,7 +41,7 @@ config FB_OMAP_LCD_MIPID
49 41
50config FB_OMAP_BOOTLOADER_INIT 42config FB_OMAP_BOOTLOADER_INIT
51 bool "Check bootloader initialization" 43 bool "Check bootloader initialization"
52 depends on FB_OMAP || FB_OMAP2 44 depends on FB_OMAP
53 help 45 help
54 Say Y here if you want to enable checking if the bootloader has 46 Say Y here if you want to enable checking if the bootloader has
55 already initialized the display controller. In this case the 47 already initialized the display controller. In this case the
@@ -68,7 +60,7 @@ config FB_OMAP_CONSISTENT_DMA_SIZE
68 60
69config FB_OMAP_DMA_TUNE 61config FB_OMAP_DMA_TUNE
70 bool "Set DMA SDRAM access priority high" 62 bool "Set DMA SDRAM access priority high"
71 depends on FB_OMAP && ARCH_OMAP1 63 depends on FB_OMAP
72 help 64 help
73 On systems in which video memory is in system memory 65 On systems in which video memory is in system memory
74 (SDRAM) this will speed up graphics DMA operations. 66 (SDRAM) this will speed up graphics DMA operations.
diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile
index ef78550917ff..1927faffb5bc 100644
--- a/drivers/video/omap/Makefile
+++ b/drivers/video/omap/Makefile
@@ -1,20 +1,14 @@
1# 1#
2# Makefile for the new OMAP framebuffer device driver 2# Makefile for the OMAP1 framebuffer device driver
3# 3#
4 4
5obj-$(CONFIG_FB_OMAP) += omapfb.o 5obj-$(CONFIG_FB_OMAP) += omapfb.o
6 6
7objs-yy := omapfb_main.o 7objs-yy := omapfb_main.o lcdc.o
8 8
9objs-y$(CONFIG_ARCH_OMAP1) += lcdc.o 9objs-y$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += sossi.o
10objs-y$(CONFIG_ARCH_OMAP2) += dispc.o
11objs-y$(CONFIG_ARCH_OMAP3) += dispc.o
12
13objs-$(CONFIG_ARCH_OMAP1)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += sossi.o
14objs-$(CONFIG_ARCH_OMAP2)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += rfbi.o
15 10
16objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o 11objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o
17objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o
18 12
19objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o 13objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o
20objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o 14objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o
diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c
deleted file mode 100644
index c0504a8a5079..000000000000
--- a/drivers/video/omap/blizzard.c
+++ /dev/null
@@ -1,1648 +0,0 @@
1/*
2 * Epson Blizzard LCD controller driver
3 *
4 * Copyright (C) 2004-2005 Nokia Corporation
5 * Authors: Juha Yrjola <juha.yrjola@nokia.com>
6 * Imre Deak <imre.deak@nokia.com>
7 * YUV support: Jussi Laako <jussi.laako@nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23#include <linux/module.h>
24#include <linux/mm.h>
25#include <linux/fb.h>
26#include <linux/delay.h>
27#include <linux/clk.h>
28
29#include <plat/dma.h>
30#include <plat/blizzard.h>
31
32#include "omapfb.h"
33#include "dispc.h"
34
35#define MODULE_NAME "blizzard"
36
37#define BLIZZARD_REV_CODE 0x00
38#define BLIZZARD_CONFIG 0x02
39#define BLIZZARD_PLL_DIV 0x04
40#define BLIZZARD_PLL_LOCK_RANGE 0x06
41#define BLIZZARD_PLL_CLOCK_SYNTH_0 0x08
42#define BLIZZARD_PLL_CLOCK_SYNTH_1 0x0a
43#define BLIZZARD_PLL_MODE 0x0c
44#define BLIZZARD_CLK_SRC 0x0e
45#define BLIZZARD_MEM_BANK0_ACTIVATE 0x10
46#define BLIZZARD_MEM_BANK0_STATUS 0x14
47#define BLIZZARD_PANEL_CONFIGURATION 0x28
48#define BLIZZARD_HDISP 0x2a
49#define BLIZZARD_HNDP 0x2c
50#define BLIZZARD_VDISP0 0x2e
51#define BLIZZARD_VDISP1 0x30
52#define BLIZZARD_VNDP 0x32
53#define BLIZZARD_HSW 0x34
54#define BLIZZARD_VSW 0x38
55#define BLIZZARD_DISPLAY_MODE 0x68
56#define BLIZZARD_INPUT_WIN_X_START_0 0x6c
57#define BLIZZARD_DATA_SOURCE_SELECT 0x8e
58#define BLIZZARD_DISP_MEM_DATA_PORT 0x90
59#define BLIZZARD_DISP_MEM_READ_ADDR0 0x92
60#define BLIZZARD_POWER_SAVE 0xE6
61#define BLIZZARD_NDISP_CTRL_STATUS 0xE8
62
63/* Data source select */
64/* For S1D13745 */
65#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND 0x00
66#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE 0x01
67#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE 0x04
68#define BLIZZARD_SRC_DISABLE_OVERLAY 0x05
69/* For S1D13744 */
70#define BLIZZARD_SRC_WRITE_LCD 0x00
71#define BLIZZARD_SRC_BLT_LCD 0x06
72
73#define BLIZZARD_COLOR_RGB565 0x01
74#define BLIZZARD_COLOR_YUV420 0x09
75
76#define BLIZZARD_VERSION_S1D13745 0x01 /* Hailstorm */
77#define BLIZZARD_VERSION_S1D13744 0x02 /* Blizzard */
78
79#define BLIZZARD_AUTO_UPDATE_TIME (HZ / 20)
80
81/* Reserve 4 request slots for requests in irq context */
82#define REQ_POOL_SIZE 24
83#define IRQ_REQ_POOL_SIZE 4
84
85#define REQ_FROM_IRQ_POOL 0x01
86
87#define REQ_COMPLETE 0
88#define REQ_PENDING 1
89
90struct blizzard_reg_list {
91 int start;
92 int end;
93};
94
95/* These need to be saved / restored separately from the rest. */
96static const struct blizzard_reg_list blizzard_pll_regs[] = {
97 {
98 .start = 0x04, /* Don't save PLL ctrl (0x0C) */
99 .end = 0x0a,
100 },
101 {
102 .start = 0x0e, /* Clock configuration */
103 .end = 0x0e,
104 },
105};
106
107static const struct blizzard_reg_list blizzard_gen_regs[] = {
108 {
109 .start = 0x18, /* SDRAM control */
110 .end = 0x20,
111 },
112 {
113 .start = 0x28, /* LCD Panel configuration */
114 .end = 0x5a, /* HSSI interface, TV configuration */
115 },
116};
117
118static u8 blizzard_reg_cache[0x5a / 2];
119
120struct update_param {
121 int plane;
122 int x, y, width, height;
123 int out_x, out_y;
124 int out_width, out_height;
125 int color_mode;
126 int bpp;
127 int flags;
128};
129
130struct blizzard_request {
131 struct list_head entry;
132 unsigned int flags;
133
134 int (*handler)(struct blizzard_request *req);
135 void (*complete)(void *data);
136 void *complete_data;
137
138 union {
139 struct update_param update;
140 struct completion *sync;
141 } par;
142};
143
144struct plane_info {
145 unsigned long offset;
146 int pos_x, pos_y;
147 int width, height;
148 int out_width, out_height;
149 int scr_width;
150 int color_mode;
151 int bpp;
152};
153
154struct blizzard_struct {
155 enum omapfb_update_mode update_mode;
156 enum omapfb_update_mode update_mode_before_suspend;
157
158 struct timer_list auto_update_timer;
159 int stop_auto_update;
160 struct omapfb_update_window auto_update_window;
161 int enabled_planes;
162 int vid_nonstd_color;
163 int vid_scaled;
164 int last_color_mode;
165 int zoom_on;
166 int zoom_area_gx1;
167 int zoom_area_gx2;
168 int zoom_area_gy1;
169 int zoom_area_gy2;
170 int screen_width;
171 int screen_height;
172 unsigned te_connected:1;
173 unsigned vsync_only:1;
174
175 struct plane_info plane[OMAPFB_PLANE_NUM];
176
177 struct blizzard_request req_pool[REQ_POOL_SIZE];
178 struct list_head pending_req_list;
179 struct list_head free_req_list;
180 struct semaphore req_sema;
181 spinlock_t req_lock;
182
183 unsigned long sys_ck_rate;
184 struct extif_timings reg_timings, lut_timings;
185
186 u32 max_transmit_size;
187 u32 extif_clk_period;
188 int extif_clk_div;
189 unsigned long pix_tx_time;
190 unsigned long line_upd_time;
191
192 struct omapfb_device *fbdev;
193 struct lcd_ctrl_extif *extif;
194 const struct lcd_ctrl *int_ctrl;
195
196 void (*power_up)(struct device *dev);
197 void (*power_down)(struct device *dev);
198
199 int version;
200} blizzard;
201
202struct lcd_ctrl blizzard_ctrl;
203
204static u8 blizzard_read_reg(u8 reg)
205{
206 u8 data;
207
208 blizzard.extif->set_bits_per_cycle(8);
209 blizzard.extif->write_command(&reg, 1);
210 blizzard.extif->read_data(&data, 1);
211
212 return data;
213}
214
215static void blizzard_write_reg(u8 reg, u8 val)
216{
217 blizzard.extif->set_bits_per_cycle(8);
218 blizzard.extif->write_command(&reg, 1);
219 blizzard.extif->write_data(&val, 1);
220}
221
222static void blizzard_restart_sdram(void)
223{
224 unsigned long tmo;
225
226 blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 0);
227 udelay(50);
228 blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 1);
229 tmo = jiffies + msecs_to_jiffies(200);
230 while (!(blizzard_read_reg(BLIZZARD_MEM_BANK0_STATUS) & 0x01)) {
231 if (time_after(jiffies, tmo)) {
232 dev_err(blizzard.fbdev->dev,
233 "s1d1374x: SDRAM not ready\n");
234 break;
235 }
236 msleep(1);
237 }
238}
239
240static void blizzard_stop_sdram(void)
241{
242 blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 0);
243}
244
245/* Wait until the last window was completely written into the controllers
246 * SDRAM and we can start transferring the next window.
247 */
248static void blizzard_wait_line_buffer(void)
249{
250 unsigned long tmo = jiffies + msecs_to_jiffies(30);
251
252 while (blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS) & (1 << 7)) {
253 if (time_after(jiffies, tmo)) {
254 if (printk_ratelimit())
255 dev_err(blizzard.fbdev->dev,
256 "s1d1374x: line buffer not ready\n");
257 break;
258 }
259 }
260}
261
262/* Wait until the YYC color space converter is idle. */
263static void blizzard_wait_yyc(void)
264{
265 unsigned long tmo = jiffies + msecs_to_jiffies(30);
266
267 while (blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS) & (1 << 4)) {
268 if (time_after(jiffies, tmo)) {
269 if (printk_ratelimit())
270 dev_err(blizzard.fbdev->dev,
271 "s1d1374x: YYC not ready\n");
272 break;
273 }
274 }
275}
276
277static void disable_overlay(void)
278{
279 blizzard_write_reg(BLIZZARD_DATA_SOURCE_SELECT,
280 BLIZZARD_SRC_DISABLE_OVERLAY);
281}
282
283static void set_window_regs(int x_start, int y_start, int x_end, int y_end,
284 int x_out_start, int y_out_start,
285 int x_out_end, int y_out_end, int color_mode,
286 int zoom_off, int flags)
287{
288 u8 tmp[18];
289 u8 cmd;
290
291 x_end--;
292 y_end--;
293 tmp[0] = x_start;
294 tmp[1] = x_start >> 8;
295 tmp[2] = y_start;
296 tmp[3] = y_start >> 8;
297 tmp[4] = x_end;
298 tmp[5] = x_end >> 8;
299 tmp[6] = y_end;
300 tmp[7] = y_end >> 8;
301
302 x_out_end--;
303 y_out_end--;
304 tmp[8] = x_out_start;
305 tmp[9] = x_out_start >> 8;
306 tmp[10] = y_out_start;
307 tmp[11] = y_out_start >> 8;
308 tmp[12] = x_out_end;
309 tmp[13] = x_out_end >> 8;
310 tmp[14] = y_out_end;
311 tmp[15] = y_out_end >> 8;
312
313 tmp[16] = color_mode;
314 if (zoom_off && blizzard.version == BLIZZARD_VERSION_S1D13745)
315 tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;
316 else if (flags & OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY)
317 tmp[17] = BLIZZARD_SRC_WRITE_OVERLAY_ENABLE;
318 else
319 tmp[17] = blizzard.version == BLIZZARD_VERSION_S1D13744 ?
320 BLIZZARD_SRC_WRITE_LCD :
321 BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
322
323 blizzard.extif->set_bits_per_cycle(8);
324 cmd = BLIZZARD_INPUT_WIN_X_START_0;
325 blizzard.extif->write_command(&cmd, 1);
326 blizzard.extif->write_data(tmp, 18);
327}
328
329static void enable_tearsync(int y, int width, int height, int screen_height,
330 int out_height, int force_vsync)
331{
332 u8 b;
333
334 b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
335 b |= 1 << 3;
336 blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b);
337
338 if (likely(blizzard.vsync_only || force_vsync)) {
339 blizzard.extif->enable_tearsync(1, 0);
340 return;
341 }
342
343 if (width * blizzard.pix_tx_time < blizzard.line_upd_time) {
344 blizzard.extif->enable_tearsync(1, 0);
345 return;
346 }
347
348 if ((width * blizzard.pix_tx_time / 1000) * height <
349 (y + out_height) * (blizzard.line_upd_time / 1000)) {
350 blizzard.extif->enable_tearsync(1, 0);
351 return;
352 }
353
354 blizzard.extif->enable_tearsync(1, y + 1);
355}
356
357static void disable_tearsync(void)
358{
359 u8 b;
360
361 blizzard.extif->enable_tearsync(0, 0);
362 b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
363 b &= ~(1 << 3);
364 blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b);
365 b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
366}
367
368static inline void set_extif_timings(const struct extif_timings *t);
369
370static inline struct blizzard_request *alloc_req(void)
371{
372 unsigned long flags;
373 struct blizzard_request *req;
374 int req_flags = 0;
375
376 if (!in_interrupt())
377 down(&blizzard.req_sema);
378 else
379 req_flags = REQ_FROM_IRQ_POOL;
380
381 spin_lock_irqsave(&blizzard.req_lock, flags);
382 BUG_ON(list_empty(&blizzard.free_req_list));
383 req = list_entry(blizzard.free_req_list.next,
384 struct blizzard_request, entry);
385 list_del(&req->entry);
386 spin_unlock_irqrestore(&blizzard.req_lock, flags);
387
388 INIT_LIST_HEAD(&req->entry);
389 req->flags = req_flags;
390
391 return req;
392}
393
394static inline void free_req(struct blizzard_request *req)
395{
396 unsigned long flags;
397
398 spin_lock_irqsave(&blizzard.req_lock, flags);
399
400 list_move(&req->entry, &blizzard.free_req_list);
401 if (!(req->flags & REQ_FROM_IRQ_POOL))
402 up(&blizzard.req_sema);
403
404 spin_unlock_irqrestore(&blizzard.req_lock, flags);
405}
406
407static void process_pending_requests(void)
408{
409 unsigned long flags;
410
411 spin_lock_irqsave(&blizzard.req_lock, flags);
412
413 while (!list_empty(&blizzard.pending_req_list)) {
414 struct blizzard_request *req;
415 void (*complete)(void *);
416 void *complete_data;
417
418 req = list_entry(blizzard.pending_req_list.next,
419 struct blizzard_request, entry);
420 spin_unlock_irqrestore(&blizzard.req_lock, flags);
421
422 if (req->handler(req) == REQ_PENDING)
423 return;
424
425 complete = req->complete;
426 complete_data = req->complete_data;
427 free_req(req);
428
429 if (complete)
430 complete(complete_data);
431
432 spin_lock_irqsave(&blizzard.req_lock, flags);
433 }
434
435 spin_unlock_irqrestore(&blizzard.req_lock, flags);
436}
437
438static void submit_req_list(struct list_head *head)
439{
440 unsigned long flags;
441 int process = 1;
442
443 spin_lock_irqsave(&blizzard.req_lock, flags);
444 if (likely(!list_empty(&blizzard.pending_req_list)))
445 process = 0;
446 list_splice_init(head, blizzard.pending_req_list.prev);
447 spin_unlock_irqrestore(&blizzard.req_lock, flags);
448
449 if (process)
450 process_pending_requests();
451}
452
453static void request_complete(void *data)
454{
455 struct blizzard_request *req = (struct blizzard_request *)data;
456 void (*complete)(void *);
457 void *complete_data;
458
459 complete = req->complete;
460 complete_data = req->complete_data;
461
462 free_req(req);
463
464 if (complete)
465 complete(complete_data);
466
467 process_pending_requests();
468}
469
470
471static int do_full_screen_update(struct blizzard_request *req)
472{
473 int i;
474 int flags;
475
476 for (i = 0; i < 3; i++) {
477 struct plane_info *p = &blizzard.plane[i];
478 if (!(blizzard.enabled_planes & (1 << i))) {
479 blizzard.int_ctrl->enable_plane(i, 0);
480 continue;
481 }
482 dev_dbg(blizzard.fbdev->dev, "pw %d ph %d\n",
483 p->width, p->height);
484 blizzard.int_ctrl->setup_plane(i,
485 OMAPFB_CHANNEL_OUT_LCD, p->offset,
486 p->scr_width, p->pos_x, p->pos_y,
487 p->width, p->height,
488 p->color_mode);
489 blizzard.int_ctrl->enable_plane(i, 1);
490 }
491
492 dev_dbg(blizzard.fbdev->dev, "sw %d sh %d\n",
493 blizzard.screen_width, blizzard.screen_height);
494 blizzard_wait_line_buffer();
495 flags = req->par.update.flags;
496 if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC)
497 enable_tearsync(0, blizzard.screen_width,
498 blizzard.screen_height,
499 blizzard.screen_height,
500 blizzard.screen_height,
501 flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC);
502 else
503 disable_tearsync();
504
505 set_window_regs(0, 0, blizzard.screen_width, blizzard.screen_height,
506 0, 0, blizzard.screen_width, blizzard.screen_height,
507 BLIZZARD_COLOR_RGB565, blizzard.zoom_on, flags);
508 blizzard.zoom_on = 0;
509
510 blizzard.extif->set_bits_per_cycle(16);
511 /* set_window_regs has left the register index at the right
512 * place, so no need to set it here.
513 */
514 blizzard.extif->transfer_area(blizzard.screen_width,
515 blizzard.screen_height,
516 request_complete, req);
517 return REQ_PENDING;
518}
519
520static int check_1d_intersect(int a1, int a2, int b1, int b2)
521{
522 if (a2 <= b1 || b2 <= a1)
523 return 0;
524 return 1;
525}
526
527/* Setup all planes with an overlapping area with the update window. */
528static int do_partial_update(struct blizzard_request *req, int plane,
529 int x, int y, int w, int h,
530 int x_out, int y_out, int w_out, int h_out,
531 int wnd_color_mode, int bpp)
532{
533 int i;
534 int gx1, gy1, gx2, gy2;
535 int gx1_out, gy1_out, gx2_out, gy2_out;
536 int color_mode;
537 int flags;
538 int zoom_off;
539 int have_zoom_for_this_update = 0;
540
541 /* Global coordinates, relative to pixel 0,0 of the LCD */
542 gx1 = x + blizzard.plane[plane].pos_x;
543 gy1 = y + blizzard.plane[plane].pos_y;
544 gx2 = gx1 + w;
545 gy2 = gy1 + h;
546
547 flags = req->par.update.flags;
548 if (flags & OMAPFB_FORMAT_FLAG_DOUBLE) {
549 gx1_out = gx1;
550 gy1_out = gy1;
551 gx2_out = gx1 + w * 2;
552 gy2_out = gy1 + h * 2;
553 } else {
554 gx1_out = x_out + blizzard.plane[plane].pos_x;
555 gy1_out = y_out + blizzard.plane[plane].pos_y;
556 gx2_out = gx1_out + w_out;
557 gy2_out = gy1_out + h_out;
558 }
559
560 for (i = 0; i < OMAPFB_PLANE_NUM; i++) {
561 struct plane_info *p = &blizzard.plane[i];
562 int px1, py1;
563 int px2, py2;
564 int pw, ph;
565 int pposx, pposy;
566 unsigned long offset;
567
568 if (!(blizzard.enabled_planes & (1 << i)) ||
569 (wnd_color_mode && i != plane)) {
570 blizzard.int_ctrl->enable_plane(i, 0);
571 continue;
572 }
573 /* Plane coordinates */
574 if (i == plane) {
575 /* Plane in which we are doing the update.
576 * Local coordinates are the one in the update
577 * request.
578 */
579 px1 = x;
580 py1 = y;
581 px2 = x + w;
582 py2 = y + h;
583 pposx = 0;
584 pposy = 0;
585 } else {
586 /* Check if this plane has an overlapping part */
587 px1 = gx1 - p->pos_x;
588 py1 = gy1 - p->pos_y;
589 px2 = gx2 - p->pos_x;
590 py2 = gy2 - p->pos_y;
591 if (px1 >= p->width || py1 >= p->height ||
592 px2 <= 0 || py2 <= 0) {
593 blizzard.int_ctrl->enable_plane(i, 0);
594 continue;
595 }
596 /* Calculate the coordinates for the overlapping
597 * part in the plane's local coordinates.
598 */
599 pposx = -px1;
600 pposy = -py1;
601 if (px1 < 0)
602 px1 = 0;
603 if (py1 < 0)
604 py1 = 0;
605 if (px2 > p->width)
606 px2 = p->width;
607 if (py2 > p->height)
608 py2 = p->height;
609 if (pposx < 0)
610 pposx = 0;
611 if (pposy < 0)
612 pposy = 0;
613 }
614 pw = px2 - px1;
615 ph = py2 - py1;
616 offset = p->offset + (p->scr_width * py1 + px1) * p->bpp / 8;
617 if (wnd_color_mode)
618 /* Window embedded in the plane with a differing
619 * color mode / bpp. Calculate the number of DMA
620 * transfer elements in terms of the plane's bpp.
621 */
622 pw = (pw + 1) * bpp / p->bpp;
623#ifdef VERBOSE
624 dev_dbg(blizzard.fbdev->dev,
625 "plane %d offset %#08lx pposx %d pposy %d "
626 "px1 %d py1 %d pw %d ph %d\n",
627 i, offset, pposx, pposy, px1, py1, pw, ph);
628#endif
629 blizzard.int_ctrl->setup_plane(i,
630 OMAPFB_CHANNEL_OUT_LCD, offset,
631 p->scr_width,
632 pposx, pposy, pw, ph,
633 p->color_mode);
634
635 blizzard.int_ctrl->enable_plane(i, 1);
636 }
637
638 switch (wnd_color_mode) {
639 case OMAPFB_COLOR_YUV420:
640 color_mode = BLIZZARD_COLOR_YUV420;
641 /* Currently only the 16 bits/pixel cycle format is
642 * supported on the external interface. Adjust the number
643 * of transfer elements per line for 12bpp format.
644 */
645 w = (w + 1) * 3 / 4;
646 break;
647 default:
648 color_mode = BLIZZARD_COLOR_RGB565;
649 break;
650 }
651
652 blizzard_wait_line_buffer();
653 if (blizzard.last_color_mode == BLIZZARD_COLOR_YUV420)
654 blizzard_wait_yyc();
655 blizzard.last_color_mode = color_mode;
656 if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC)
657 enable_tearsync(gy1, w, h,
658 blizzard.screen_height,
659 h_out,
660 flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC);
661 else
662 disable_tearsync();
663
664 if ((gx2_out - gx1_out) != (gx2 - gx1) ||
665 (gy2_out - gy1_out) != (gy2 - gy1))
666 have_zoom_for_this_update = 1;
667
668 /* 'background' type of screen update (as opposed to 'destructive')
669 can be used to disable scaling if scaling is active */
670 zoom_off = blizzard.zoom_on && !have_zoom_for_this_update &&
671 (gx1_out == 0) && (gx2_out == blizzard.screen_width) &&
672 (gy1_out == 0) && (gy2_out == blizzard.screen_height) &&
673 (gx1 == 0) && (gy1 == 0);
674
675 if (blizzard.zoom_on && !have_zoom_for_this_update && !zoom_off &&
676 check_1d_intersect(blizzard.zoom_area_gx1, blizzard.zoom_area_gx2,
677 gx1_out, gx2_out) &&
678 check_1d_intersect(blizzard.zoom_area_gy1, blizzard.zoom_area_gy2,
679 gy1_out, gy2_out)) {
680 /* Previous screen update was using scaling, current update
681 * is not using it. Additionally, current screen update is
682 * going to overlap with the scaled area. Scaling needs to be
683 * disabled in order to avoid 'magnifying glass' effect.
684 * Dummy setup of background window can be used for this.
685 */
686 set_window_regs(0, 0, blizzard.screen_width,
687 blizzard.screen_height,
688 0, 0, blizzard.screen_width,
689 blizzard.screen_height,
690 BLIZZARD_COLOR_RGB565, 1, flags);
691 blizzard.zoom_on = 0;
692 }
693
694 /* remember scaling settings if we have scaled update */
695 if (have_zoom_for_this_update) {
696 blizzard.zoom_on = 1;
697 blizzard.zoom_area_gx1 = gx1_out;
698 blizzard.zoom_area_gx2 = gx2_out;
699 blizzard.zoom_area_gy1 = gy1_out;
700 blizzard.zoom_area_gy2 = gy2_out;
701 }
702
703 set_window_regs(gx1, gy1, gx2, gy2, gx1_out, gy1_out, gx2_out, gy2_out,
704 color_mode, zoom_off, flags);
705 if (zoom_off)
706 blizzard.zoom_on = 0;
707
708 blizzard.extif->set_bits_per_cycle(16);
709 /* set_window_regs has left the register index at the right
710 * place, so no need to set it here.
711 */
712 blizzard.extif->transfer_area(w, h, request_complete, req);
713
714 return REQ_PENDING;
715}
716
717static int send_frame_handler(struct blizzard_request *req)
718{
719 struct update_param *par = &req->par.update;
720 int plane = par->plane;
721
722#ifdef VERBOSE
723 dev_dbg(blizzard.fbdev->dev,
724 "send_frame: x %d y %d w %d h %d "
725 "x_out %d y_out %d w_out %d h_out %d "
726 "color_mode %04x flags %04x planes %01x\n",
727 par->x, par->y, par->width, par->height,
728 par->out_x, par->out_y, par->out_width, par->out_height,
729 par->color_mode, par->flags, blizzard.enabled_planes);
730#endif
731 if (par->flags & OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY)
732 disable_overlay();
733
734 if ((blizzard.enabled_planes & blizzard.vid_nonstd_color) ||
735 (blizzard.enabled_planes & blizzard.vid_scaled))
736 return do_full_screen_update(req);
737
738 return do_partial_update(req, plane, par->x, par->y,
739 par->width, par->height,
740 par->out_x, par->out_y,
741 par->out_width, par->out_height,
742 par->color_mode, par->bpp);
743}
744
745static void send_frame_complete(void *data)
746{
747}
748
749#define ADD_PREQ(_x, _y, _w, _h, _x_out, _y_out, _w_out, _h_out) do { \
750 req = alloc_req(); \
751 req->handler = send_frame_handler; \
752 req->complete = send_frame_complete; \
753 req->par.update.plane = plane_idx; \
754 req->par.update.x = _x; \
755 req->par.update.y = _y; \
756 req->par.update.width = _w; \
757 req->par.update.height = _h; \
758 req->par.update.out_x = _x_out; \
759 req->par.update.out_y = _y_out; \
760 req->par.update.out_width = _w_out; \
761 req->par.update.out_height = _h_out; \
762 req->par.update.bpp = bpp; \
763 req->par.update.color_mode = color_mode;\
764 req->par.update.flags = flags; \
765 list_add_tail(&req->entry, req_head); \
766} while(0)
767
768static void create_req_list(int plane_idx,
769 struct omapfb_update_window *win,
770 struct list_head *req_head)
771{
772 struct blizzard_request *req;
773 int x = win->x;
774 int y = win->y;
775 int width = win->width;
776 int height = win->height;
777 int x_out = win->out_x;
778 int y_out = win->out_y;
779 int width_out = win->out_width;
780 int height_out = win->out_height;
781 int color_mode;
782 int bpp;
783 int flags;
784 unsigned int ystart = y;
785 unsigned int yspan = height;
786 unsigned int ystart_out = y_out;
787 unsigned int yspan_out = height_out;
788
789 flags = win->format & ~OMAPFB_FORMAT_MASK;
790 color_mode = win->format & OMAPFB_FORMAT_MASK;
791 switch (color_mode) {
792 case OMAPFB_COLOR_YUV420:
793 /* Embedded window with different color mode */
794 bpp = 12;
795 /* X, Y, height must be aligned at 2, width at 4 pixels */
796 x &= ~1;
797 y &= ~1;
798 height = yspan = height & ~1;
799 width = width & ~3;
800 break;
801 default:
802 /* Same as the plane color mode */
803 bpp = blizzard.plane[plane_idx].bpp;
804 break;
805 }
806 if (width * height * bpp / 8 > blizzard.max_transmit_size) {
807 yspan = blizzard.max_transmit_size / (width * bpp / 8);
808 yspan_out = yspan * height_out / height;
809 ADD_PREQ(x, ystart, width, yspan, x_out, ystart_out,
810 width_out, yspan_out);
811 ystart += yspan;
812 ystart_out += yspan_out;
813 yspan = height - yspan;
814 yspan_out = height_out - yspan_out;
815 flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
816 }
817
818 ADD_PREQ(x, ystart, width, yspan, x_out, ystart_out,
819 width_out, yspan_out);
820}
821
822static void auto_update_complete(void *data)
823{
824 if (!blizzard.stop_auto_update)
825 mod_timer(&blizzard.auto_update_timer,
826 jiffies + BLIZZARD_AUTO_UPDATE_TIME);
827}
828
829static void blizzard_update_window_auto(unsigned long arg)
830{
831 LIST_HEAD(req_list);
832 struct blizzard_request *last;
833 struct omapfb_plane_struct *plane;
834
835 plane = blizzard.fbdev->fb_info[0]->par;
836 create_req_list(plane->idx,
837 &blizzard.auto_update_window, &req_list);
838 last = list_entry(req_list.prev, struct blizzard_request, entry);
839
840 last->complete = auto_update_complete;
841 last->complete_data = NULL;
842
843 submit_req_list(&req_list);
844}
845
846int blizzard_update_window_async(struct fb_info *fbi,
847 struct omapfb_update_window *win,
848 void (*complete_callback)(void *arg),
849 void *complete_callback_data)
850{
851 LIST_HEAD(req_list);
852 struct blizzard_request *last;
853 struct omapfb_plane_struct *plane = fbi->par;
854
855 if (unlikely(blizzard.update_mode != OMAPFB_MANUAL_UPDATE))
856 return -EINVAL;
857 if (unlikely(!blizzard.te_connected &&
858 (win->format & OMAPFB_FORMAT_FLAG_TEARSYNC)))
859 return -EINVAL;
860
861 create_req_list(plane->idx, win, &req_list);
862 last = list_entry(req_list.prev, struct blizzard_request, entry);
863
864 last->complete = complete_callback;
865 last->complete_data = (void *)complete_callback_data;
866
867 submit_req_list(&req_list);
868
869 return 0;
870}
871EXPORT_SYMBOL(blizzard_update_window_async);
872
873static int update_full_screen(void)
874{
875 return blizzard_update_window_async(blizzard.fbdev->fb_info[0],
876 &blizzard.auto_update_window, NULL, NULL);
877
878}
879
880static int blizzard_setup_plane(int plane, int channel_out,
881 unsigned long offset, int screen_width,
882 int pos_x, int pos_y, int width, int height,
883 int color_mode)
884{
885 struct plane_info *p;
886
887#ifdef VERBOSE
888 dev_dbg(blizzard.fbdev->dev,
889 "plane %d ch_out %d offset %#08lx scr_width %d "
890 "pos_x %d pos_y %d width %d height %d color_mode %d\n",
891 plane, channel_out, offset, screen_width,
892 pos_x, pos_y, width, height, color_mode);
893#endif
894 if ((unsigned)plane > OMAPFB_PLANE_NUM)
895 return -EINVAL;
896 p = &blizzard.plane[plane];
897
898 switch (color_mode) {
899 case OMAPFB_COLOR_YUV422:
900 case OMAPFB_COLOR_YUY422:
901 p->bpp = 16;
902 blizzard.vid_nonstd_color &= ~(1 << plane);
903 break;
904 case OMAPFB_COLOR_YUV420:
905 p->bpp = 12;
906 blizzard.vid_nonstd_color |= 1 << plane;
907 break;
908 case OMAPFB_COLOR_RGB565:
909 p->bpp = 16;
910 blizzard.vid_nonstd_color &= ~(1 << plane);
911 break;
912 default:
913 return -EINVAL;
914 }
915
916 p->offset = offset;
917 p->pos_x = pos_x;
918 p->pos_y = pos_y;
919 p->width = width;
920 p->height = height;
921 p->scr_width = screen_width;
922 if (!p->out_width)
923 p->out_width = width;
924 if (!p->out_height)
925 p->out_height = height;
926
927 p->color_mode = color_mode;
928
929 return 0;
930}
931
932static int blizzard_set_scale(int plane, int orig_w, int orig_h,
933 int out_w, int out_h)
934{
935 struct plane_info *p = &blizzard.plane[plane];
936 int r;
937
938 dev_dbg(blizzard.fbdev->dev,
939 "plane %d orig_w %d orig_h %d out_w %d out_h %d\n",
940 plane, orig_w, orig_h, out_w, out_h);
941 if ((unsigned)plane > OMAPFB_PLANE_NUM)
942 return -ENODEV;
943
944 r = blizzard.int_ctrl->set_scale(plane, orig_w, orig_h, out_w, out_h);
945 if (r < 0)
946 return r;
947
948 p->width = orig_w;
949 p->height = orig_h;
950 p->out_width = out_w;
951 p->out_height = out_h;
952 if (orig_w == out_w && orig_h == out_h)
953 blizzard.vid_scaled &= ~(1 << plane);
954 else
955 blizzard.vid_scaled |= 1 << plane;
956
957 return 0;
958}
959
960static int blizzard_set_rotate(int angle)
961{
962 u32 l;
963
964 l = blizzard_read_reg(BLIZZARD_PANEL_CONFIGURATION);
965 l &= ~0x03;
966
967 switch (angle) {
968 case 0:
969 l = l | 0x00;
970 break;
971 case 90:
972 l = l | 0x03;
973 break;
974 case 180:
975 l = l | 0x02;
976 break;
977 case 270:
978 l = l | 0x01;
979 break;
980 default:
981 return -EINVAL;
982 }
983
984 blizzard_write_reg(BLIZZARD_PANEL_CONFIGURATION, l);
985
986 return 0;
987}
988
989static int blizzard_enable_plane(int plane, int enable)
990{
991 if (enable)
992 blizzard.enabled_planes |= 1 << plane;
993 else
994 blizzard.enabled_planes &= ~(1 << plane);
995
996 return 0;
997}
998
999static int sync_handler(struct blizzard_request *req)
1000{
1001 complete(req->par.sync);
1002 return REQ_COMPLETE;
1003}
1004
1005static void blizzard_sync(void)
1006{
1007 LIST_HEAD(req_list);
1008 struct blizzard_request *req;
1009 struct completion comp;
1010
1011 req = alloc_req();
1012
1013 req->handler = sync_handler;
1014 req->complete = NULL;
1015 init_completion(&comp);
1016 req->par.sync = &comp;
1017
1018 list_add(&req->entry, &req_list);
1019 submit_req_list(&req_list);
1020
1021 wait_for_completion(&comp);
1022}
1023
1024
1025static void blizzard_bind_client(struct omapfb_notifier_block *nb)
1026{
1027 if (blizzard.update_mode == OMAPFB_MANUAL_UPDATE) {
1028 omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_READY);
1029 }
1030}
1031
1032static int blizzard_set_update_mode(enum omapfb_update_mode mode)
1033{
1034 if (unlikely(mode != OMAPFB_MANUAL_UPDATE &&
1035 mode != OMAPFB_AUTO_UPDATE &&
1036 mode != OMAPFB_UPDATE_DISABLED))
1037 return -EINVAL;
1038
1039 if (mode == blizzard.update_mode)
1040 return 0;
1041
1042 dev_info(blizzard.fbdev->dev, "s1d1374x: setting update mode to %s\n",
1043 mode == OMAPFB_UPDATE_DISABLED ? "disabled" :
1044 (mode == OMAPFB_AUTO_UPDATE ? "auto" : "manual"));
1045
1046 switch (blizzard.update_mode) {
1047 case OMAPFB_MANUAL_UPDATE:
1048 omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_DISABLED);
1049 break;
1050 case OMAPFB_AUTO_UPDATE:
1051 blizzard.stop_auto_update = 1;
1052 del_timer_sync(&blizzard.auto_update_timer);
1053 break;
1054 case OMAPFB_UPDATE_DISABLED:
1055 break;
1056 }
1057
1058 blizzard.update_mode = mode;
1059 blizzard_sync();
1060 blizzard.stop_auto_update = 0;
1061
1062 switch (mode) {
1063 case OMAPFB_MANUAL_UPDATE:
1064 omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_READY);
1065 break;
1066 case OMAPFB_AUTO_UPDATE:
1067 blizzard_update_window_auto(0);
1068 break;
1069 case OMAPFB_UPDATE_DISABLED:
1070 break;
1071 }
1072
1073 return 0;
1074}
1075
1076static enum omapfb_update_mode blizzard_get_update_mode(void)
1077{
1078 return blizzard.update_mode;
1079}
1080
1081static inline void set_extif_timings(const struct extif_timings *t)
1082{
1083 blizzard.extif->set_timings(t);
1084}
1085
1086static inline unsigned long round_to_extif_ticks(unsigned long ps, int div)
1087{
1088 int bus_tick = blizzard.extif_clk_period * div;
1089 return (ps + bus_tick - 1) / bus_tick * bus_tick;
1090}
1091
1092static int calc_reg_timing(unsigned long sysclk, int div)
1093{
1094 struct extif_timings *t;
1095 unsigned long systim;
1096
1097 /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
1098 * AccessTime 2 ns + 12.2 ns (regs),
1099 * WEOffTime = WEOnTime + 1 ns,
1100 * REOffTime = REOnTime + 12 ns (regs),
1101 * CSOffTime = REOffTime + 1 ns
1102 * ReadCycle = 2ns + 2*SYSCLK (regs),
1103 * WriteCycle = 2*SYSCLK + 2 ns,
1104 * CSPulseWidth = 10 ns */
1105
1106 systim = 1000000000 / (sysclk / 1000);
1107 dev_dbg(blizzard.fbdev->dev,
1108 "Blizzard systim %lu ps extif_clk_period %u div %d\n",
1109 systim, blizzard.extif_clk_period, div);
1110
1111 t = &blizzard.reg_timings;
1112 memset(t, 0, sizeof(*t));
1113
1114 t->clk_div = div;
1115
1116 t->cs_on_time = 0;
1117 t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
1118 t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
1119 t->access_time = round_to_extif_ticks(t->re_on_time + 12200, div);
1120 t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
1121 t->re_off_time = round_to_extif_ticks(t->re_on_time + 13000, div);
1122 t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
1123 t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
1124 if (t->we_cycle_time < t->we_off_time)
1125 t->we_cycle_time = t->we_off_time;
1126 t->re_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
1127 if (t->re_cycle_time < t->re_off_time)
1128 t->re_cycle_time = t->re_off_time;
1129 t->cs_pulse_width = 0;
1130
1131 dev_dbg(blizzard.fbdev->dev, "[reg]cson %d csoff %d reon %d reoff %d\n",
1132 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
1133 dev_dbg(blizzard.fbdev->dev, "[reg]weon %d weoff %d recyc %d wecyc %d\n",
1134 t->we_on_time, t->we_off_time, t->re_cycle_time,
1135 t->we_cycle_time);
1136 dev_dbg(blizzard.fbdev->dev, "[reg]rdaccess %d cspulse %d\n",
1137 t->access_time, t->cs_pulse_width);
1138
1139 return blizzard.extif->convert_timings(t);
1140}
1141
1142static int calc_lut_timing(unsigned long sysclk, int div)
1143{
1144 struct extif_timings *t;
1145 unsigned long systim;
1146
1147 /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
1148 * AccessTime 2 ns + 4 * SYSCLK + 26 (lut),
1149 * WEOffTime = WEOnTime + 1 ns,
1150 * REOffTime = REOnTime + 4*SYSCLK + 26 ns (lut),
1151 * CSOffTime = REOffTime + 1 ns
1152 * ReadCycle = 2ns + 4*SYSCLK + 26 ns (lut),
1153 * WriteCycle = 2*SYSCLK + 2 ns,
1154 * CSPulseWidth = 10 ns */
1155
1156 systim = 1000000000 / (sysclk / 1000);
1157 dev_dbg(blizzard.fbdev->dev,
1158 "Blizzard systim %lu ps extif_clk_period %u div %d\n",
1159 systim, blizzard.extif_clk_period, div);
1160
1161 t = &blizzard.lut_timings;
1162 memset(t, 0, sizeof(*t));
1163
1164 t->clk_div = div;
1165
1166 t->cs_on_time = 0;
1167 t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
1168 t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
1169 t->access_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
1170 26000, div);
1171 t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
1172 t->re_off_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
1173 26000, div);
1174 t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
1175 t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
1176 if (t->we_cycle_time < t->we_off_time)
1177 t->we_cycle_time = t->we_off_time;
1178 t->re_cycle_time = round_to_extif_ticks(2000 + 4 * systim + 26000, div);
1179 if (t->re_cycle_time < t->re_off_time)
1180 t->re_cycle_time = t->re_off_time;
1181 t->cs_pulse_width = 0;
1182
1183 dev_dbg(blizzard.fbdev->dev,
1184 "[lut]cson %d csoff %d reon %d reoff %d\n",
1185 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
1186 dev_dbg(blizzard.fbdev->dev,
1187 "[lut]weon %d weoff %d recyc %d wecyc %d\n",
1188 t->we_on_time, t->we_off_time, t->re_cycle_time,
1189 t->we_cycle_time);
1190 dev_dbg(blizzard.fbdev->dev, "[lut]rdaccess %d cspulse %d\n",
1191 t->access_time, t->cs_pulse_width);
1192
1193 return blizzard.extif->convert_timings(t);
1194}
1195
1196static int calc_extif_timings(unsigned long sysclk, int *extif_mem_div)
1197{
1198 int max_clk_div;
1199 int div;
1200
1201 blizzard.extif->get_clk_info(&blizzard.extif_clk_period, &max_clk_div);
1202 for (div = 1; div <= max_clk_div; div++) {
1203 if (calc_reg_timing(sysclk, div) == 0)
1204 break;
1205 }
1206 if (div > max_clk_div) {
1207 dev_dbg(blizzard.fbdev->dev, "reg timing failed\n");
1208 goto err;
1209 }
1210 *extif_mem_div = div;
1211
1212 for (div = 1; div <= max_clk_div; div++) {
1213 if (calc_lut_timing(sysclk, div) == 0)
1214 break;
1215 }
1216
1217 if (div > max_clk_div)
1218 goto err;
1219
1220 blizzard.extif_clk_div = div;
1221
1222 return 0;
1223err:
1224 dev_err(blizzard.fbdev->dev, "can't setup timings\n");
1225 return -1;
1226}
1227
1228static void calc_blizzard_clk_rates(unsigned long ext_clk,
1229 unsigned long *sys_clk, unsigned long *pix_clk)
1230{
1231 int pix_clk_src;
1232 int sys_div = 0, sys_mul = 0;
1233 int pix_div;
1234
1235 pix_clk_src = blizzard_read_reg(BLIZZARD_CLK_SRC);
1236 pix_div = ((pix_clk_src >> 3) & 0x1f) + 1;
1237 if ((pix_clk_src & (0x3 << 1)) == 0) {
1238 /* Source is the PLL */
1239 sys_div = (blizzard_read_reg(BLIZZARD_PLL_DIV) & 0x3f) + 1;
1240 sys_mul = blizzard_read_reg(BLIZZARD_PLL_CLOCK_SYNTH_0);
1241 sys_mul |= ((blizzard_read_reg(BLIZZARD_PLL_CLOCK_SYNTH_1)
1242 & 0x0f) << 11);
1243 *sys_clk = ext_clk * sys_mul / sys_div;
1244 } else /* else source is ext clk, or oscillator */
1245 *sys_clk = ext_clk;
1246
1247 *pix_clk = *sys_clk / pix_div; /* HZ */
1248 dev_dbg(blizzard.fbdev->dev,
1249 "ext_clk %ld pix_src %d pix_div %d sys_div %d sys_mul %d\n",
1250 ext_clk, pix_clk_src & (0x3 << 1), pix_div, sys_div, sys_mul);
1251 dev_dbg(blizzard.fbdev->dev, "sys_clk %ld pix_clk %ld\n",
1252 *sys_clk, *pix_clk);
1253}
1254
1255static int setup_tearsync(unsigned long pix_clk, int extif_div)
1256{
1257 int hdisp, vdisp;
1258 int hndp, vndp;
1259 int hsw, vsw;
1260 int hs, vs;
1261 int hs_pol_inv, vs_pol_inv;
1262 int use_hsvs, use_ndp;
1263 u8 b;
1264
1265 hsw = blizzard_read_reg(BLIZZARD_HSW);
1266 vsw = blizzard_read_reg(BLIZZARD_VSW);
1267 hs_pol_inv = !(hsw & 0x80);
1268 vs_pol_inv = !(vsw & 0x80);
1269 hsw = hsw & 0x7f;
1270 vsw = vsw & 0x3f;
1271
1272 hdisp = blizzard_read_reg(BLIZZARD_HDISP) * 8;
1273 vdisp = blizzard_read_reg(BLIZZARD_VDISP0) +
1274 ((blizzard_read_reg(BLIZZARD_VDISP1) & 0x3) << 8);
1275
1276 hndp = blizzard_read_reg(BLIZZARD_HNDP) & 0x3f;
1277 vndp = blizzard_read_reg(BLIZZARD_VNDP);
1278
1279 /* time to transfer one pixel (16bpp) in ps */
1280 blizzard.pix_tx_time = blizzard.reg_timings.we_cycle_time;
1281 if (blizzard.extif->get_max_tx_rate != NULL) {
1282 /* The external interface might have a rate limitation,
1283 * if so, we have to maximize our transfer rate.
1284 */
1285 unsigned long min_tx_time;
1286 unsigned long max_tx_rate = blizzard.extif->get_max_tx_rate();
1287
1288 dev_dbg(blizzard.fbdev->dev, "max_tx_rate %ld HZ\n",
1289 max_tx_rate);
1290 min_tx_time = 1000000000 / (max_tx_rate / 1000); /* ps */
1291 if (blizzard.pix_tx_time < min_tx_time)
1292 blizzard.pix_tx_time = min_tx_time;
1293 }
1294
1295 /* time to update one line in ps */
1296 blizzard.line_upd_time = (hdisp + hndp) * 1000000 / (pix_clk / 1000);
1297 blizzard.line_upd_time *= 1000;
1298 if (hdisp * blizzard.pix_tx_time > blizzard.line_upd_time)
1299 /* transfer speed too low, we might have to use both
1300 * HS and VS */
1301 use_hsvs = 1;
1302 else
1303 /* decent transfer speed, we'll always use only VS */
1304 use_hsvs = 0;
1305
1306 if (use_hsvs && (hs_pol_inv || vs_pol_inv)) {
1307 /* HS or'ed with VS doesn't work, use the active high
1308 * TE signal based on HNDP / VNDP */
1309 use_ndp = 1;
1310 hs_pol_inv = 0;
1311 vs_pol_inv = 0;
1312 hs = hndp;
1313 vs = vndp;
1314 } else {
1315 /* Use HS or'ed with VS as a TE signal if both are needed
1316 * or VNDP if only vsync is needed. */
1317 use_ndp = 0;
1318 hs = hsw;
1319 vs = vsw;
1320 if (!use_hsvs) {
1321 hs_pol_inv = 0;
1322 vs_pol_inv = 0;
1323 }
1324 }
1325
1326 hs = hs * 1000000 / (pix_clk / 1000); /* ps */
1327 hs *= 1000;
1328
1329 vs = vs * (hdisp + hndp) * 1000000 / (pix_clk / 1000); /* ps */
1330 vs *= 1000;
1331
1332 if (vs <= hs)
1333 return -EDOM;
1334 /* set VS to 120% of HS to minimize VS detection time */
1335 vs = hs * 12 / 10;
1336 /* minimize HS too */
1337 if (hs > 10000)
1338 hs = 10000;
1339
1340 b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
1341 b &= ~0x3;
1342 b |= use_hsvs ? 1 : 0;
1343 b |= (use_ndp && use_hsvs) ? 0 : 2;
1344 blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b);
1345
1346 blizzard.vsync_only = !use_hsvs;
1347
1348 dev_dbg(blizzard.fbdev->dev,
1349 "pix_clk %ld HZ pix_tx_time %ld ps line_upd_time %ld ps\n",
1350 pix_clk, blizzard.pix_tx_time, blizzard.line_upd_time);
1351 dev_dbg(blizzard.fbdev->dev,
1352 "hs %d ps vs %d ps mode %d vsync_only %d\n",
1353 hs, vs, b & 0x3, !use_hsvs);
1354
1355 return blizzard.extif->setup_tearsync(1, hs, vs,
1356 hs_pol_inv, vs_pol_inv,
1357 extif_div);
1358}
1359
1360static void blizzard_get_caps(int plane, struct omapfb_caps *caps)
1361{
1362 blizzard.int_ctrl->get_caps(plane, caps);
1363 caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE |
1364 OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE |
1365 OMAPFB_CAPS_WINDOW_SCALE |
1366 OMAPFB_CAPS_WINDOW_OVERLAY |
1367 OMAPFB_CAPS_WINDOW_ROTATE;
1368 if (blizzard.te_connected)
1369 caps->ctrl |= OMAPFB_CAPS_TEARSYNC;
1370 caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) |
1371 (1 << OMAPFB_COLOR_YUV420);
1372}
1373
1374static void _save_regs(const struct blizzard_reg_list *list, int cnt)
1375{
1376 int i;
1377
1378 for (i = 0; i < cnt; i++, list++) {
1379 int reg;
1380 for (reg = list->start; reg <= list->end; reg += 2)
1381 blizzard_reg_cache[reg / 2] = blizzard_read_reg(reg);
1382 }
1383}
1384
1385static void _restore_regs(const struct blizzard_reg_list *list, int cnt)
1386{
1387 int i;
1388
1389 for (i = 0; i < cnt; i++, list++) {
1390 int reg;
1391 for (reg = list->start; reg <= list->end; reg += 2)
1392 blizzard_write_reg(reg, blizzard_reg_cache[reg / 2]);
1393 }
1394}
1395
1396static void blizzard_save_all_regs(void)
1397{
1398 _save_regs(blizzard_pll_regs, ARRAY_SIZE(blizzard_pll_regs));
1399 _save_regs(blizzard_gen_regs, ARRAY_SIZE(blizzard_gen_regs));
1400}
1401
1402static void blizzard_restore_pll_regs(void)
1403{
1404 _restore_regs(blizzard_pll_regs, ARRAY_SIZE(blizzard_pll_regs));
1405}
1406
1407static void blizzard_restore_gen_regs(void)
1408{
1409 _restore_regs(blizzard_gen_regs, ARRAY_SIZE(blizzard_gen_regs));
1410}
1411
1412static void blizzard_suspend(void)
1413{
1414 u32 l;
1415 unsigned long tmo;
1416
1417 if (blizzard.last_color_mode) {
1418 update_full_screen();
1419 blizzard_sync();
1420 }
1421 blizzard.update_mode_before_suspend = blizzard.update_mode;
1422 /* the following will disable clocks as well */
1423 blizzard_set_update_mode(OMAPFB_UPDATE_DISABLED);
1424
1425 blizzard_save_all_regs();
1426
1427 blizzard_stop_sdram();
1428
1429 l = blizzard_read_reg(BLIZZARD_POWER_SAVE);
1430 /* Standby, Sleep. We assume we use an external clock. */
1431 l |= 0x03;
1432 blizzard_write_reg(BLIZZARD_POWER_SAVE, l);
1433
1434 tmo = jiffies + msecs_to_jiffies(100);
1435 while (!(blizzard_read_reg(BLIZZARD_PLL_MODE) & (1 << 1))) {
1436 if (time_after(jiffies, tmo)) {
1437 dev_err(blizzard.fbdev->dev,
1438 "s1d1374x: sleep timeout, stopping PLL manually\n");
1439 l = blizzard_read_reg(BLIZZARD_PLL_MODE);
1440 l &= ~0x03;
1441 /* Disable PLL, counter function */
1442 l |= 0x2;
1443 blizzard_write_reg(BLIZZARD_PLL_MODE, l);
1444 break;
1445 }
1446 msleep(1);
1447 }
1448
1449 if (blizzard.power_down != NULL)
1450 blizzard.power_down(blizzard.fbdev->dev);
1451}
1452
1453static void blizzard_resume(void)
1454{
1455 u32 l;
1456
1457 if (blizzard.power_up != NULL)
1458 blizzard.power_up(blizzard.fbdev->dev);
1459
1460 l = blizzard_read_reg(BLIZZARD_POWER_SAVE);
1461 /* Standby, Sleep */
1462 l &= ~0x03;
1463 blizzard_write_reg(BLIZZARD_POWER_SAVE, l);
1464
1465 blizzard_restore_pll_regs();
1466 l = blizzard_read_reg(BLIZZARD_PLL_MODE);
1467 l &= ~0x03;
1468 /* Enable PLL, counter function */
1469 l |= 0x1;
1470 blizzard_write_reg(BLIZZARD_PLL_MODE, l);
1471
1472 while (!(blizzard_read_reg(BLIZZARD_PLL_DIV) & (1 << 7)))
1473 msleep(1);
1474
1475 blizzard_restart_sdram();
1476
1477 blizzard_restore_gen_regs();
1478
1479 /* Enable display */
1480 blizzard_write_reg(BLIZZARD_DISPLAY_MODE, 0x01);
1481
1482 /* the following will enable clocks as necessary */
1483 blizzard_set_update_mode(blizzard.update_mode_before_suspend);
1484
1485 /* Force a background update */
1486 blizzard.zoom_on = 1;
1487 update_full_screen();
1488 blizzard_sync();
1489}
1490
1491static int blizzard_init(struct omapfb_device *fbdev, int ext_mode,
1492 struct omapfb_mem_desc *req_vram)
1493{
1494 int r = 0, i;
1495 u8 rev, conf;
1496 unsigned long ext_clk;
1497 int extif_div;
1498 unsigned long sys_clk, pix_clk;
1499 struct omapfb_platform_data *omapfb_conf;
1500 struct blizzard_platform_data *ctrl_conf;
1501
1502 blizzard.fbdev = fbdev;
1503
1504 BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl);
1505
1506 blizzard.fbdev = fbdev;
1507 blizzard.extif = fbdev->ext_if;
1508 blizzard.int_ctrl = fbdev->int_ctrl;
1509
1510 omapfb_conf = fbdev->dev->platform_data;
1511 ctrl_conf = omapfb_conf->ctrl_platform_data;
1512 if (ctrl_conf == NULL || ctrl_conf->get_clock_rate == NULL) {
1513 dev_err(fbdev->dev, "s1d1374x: missing platform data\n");
1514 r = -ENOENT;
1515 goto err1;
1516 }
1517
1518 blizzard.power_down = ctrl_conf->power_down;
1519 blizzard.power_up = ctrl_conf->power_up;
1520
1521 spin_lock_init(&blizzard.req_lock);
1522
1523 if ((r = blizzard.int_ctrl->init(fbdev, 1, req_vram)) < 0)
1524 goto err1;
1525
1526 if ((r = blizzard.extif->init(fbdev)) < 0)
1527 goto err2;
1528
1529 blizzard_ctrl.set_color_key = blizzard.int_ctrl->set_color_key;
1530 blizzard_ctrl.get_color_key = blizzard.int_ctrl->get_color_key;
1531 blizzard_ctrl.setup_mem = blizzard.int_ctrl->setup_mem;
1532 blizzard_ctrl.mmap = blizzard.int_ctrl->mmap;
1533
1534 ext_clk = ctrl_conf->get_clock_rate(fbdev->dev);
1535 if ((r = calc_extif_timings(ext_clk, &extif_div)) < 0)
1536 goto err3;
1537
1538 set_extif_timings(&blizzard.reg_timings);
1539
1540 if (blizzard.power_up != NULL)
1541 blizzard.power_up(fbdev->dev);
1542
1543 calc_blizzard_clk_rates(ext_clk, &sys_clk, &pix_clk);
1544
1545 if ((r = calc_extif_timings(sys_clk, &extif_div)) < 0)
1546 goto err3;
1547 set_extif_timings(&blizzard.reg_timings);
1548
1549 if (!(blizzard_read_reg(BLIZZARD_PLL_DIV) & 0x80)) {
1550 dev_err(fbdev->dev,
1551 "controller not initialized by the bootloader\n");
1552 r = -ENODEV;
1553 goto err3;
1554 }
1555
1556 if (ctrl_conf->te_connected) {
1557 if ((r = setup_tearsync(pix_clk, extif_div)) < 0)
1558 goto err3;
1559 blizzard.te_connected = 1;
1560 }
1561
1562 rev = blizzard_read_reg(BLIZZARD_REV_CODE);
1563 conf = blizzard_read_reg(BLIZZARD_CONFIG);
1564
1565 switch (rev & 0xfc) {
1566 case 0x9c:
1567 blizzard.version = BLIZZARD_VERSION_S1D13744;
1568 pr_info("omapfb: s1d13744 LCD controller rev %d "
1569 "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
1570 break;
1571 case 0xa4:
1572 blizzard.version = BLIZZARD_VERSION_S1D13745;
1573 pr_info("omapfb: s1d13745 LCD controller rev %d "
1574 "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
1575 break;
1576 default:
1577 dev_err(fbdev->dev, "invalid s1d1374x revision %02x\n",
1578 rev);
1579 r = -ENODEV;
1580 goto err3;
1581 }
1582
1583 blizzard.max_transmit_size = blizzard.extif->max_transmit_size;
1584
1585 blizzard.update_mode = OMAPFB_UPDATE_DISABLED;
1586
1587 blizzard.auto_update_window.x = 0;
1588 blizzard.auto_update_window.y = 0;
1589 blizzard.auto_update_window.width = fbdev->panel->x_res;
1590 blizzard.auto_update_window.height = fbdev->panel->y_res;
1591 blizzard.auto_update_window.out_x = 0;
1592 blizzard.auto_update_window.out_y = 0;
1593 blizzard.auto_update_window.out_width = fbdev->panel->x_res;
1594 blizzard.auto_update_window.out_height = fbdev->panel->y_res;
1595 blizzard.auto_update_window.format = 0;
1596
1597 blizzard.screen_width = fbdev->panel->x_res;
1598 blizzard.screen_height = fbdev->panel->y_res;
1599
1600 init_timer(&blizzard.auto_update_timer);
1601 blizzard.auto_update_timer.function = blizzard_update_window_auto;
1602 blizzard.auto_update_timer.data = 0;
1603
1604 INIT_LIST_HEAD(&blizzard.free_req_list);
1605 INIT_LIST_HEAD(&blizzard.pending_req_list);
1606 for (i = 0; i < ARRAY_SIZE(blizzard.req_pool); i++)
1607 list_add(&blizzard.req_pool[i].entry, &blizzard.free_req_list);
1608 BUG_ON(i <= IRQ_REQ_POOL_SIZE);
1609 sema_init(&blizzard.req_sema, i - IRQ_REQ_POOL_SIZE);
1610
1611 return 0;
1612err3:
1613 if (blizzard.power_down != NULL)
1614 blizzard.power_down(fbdev->dev);
1615 blizzard.extif->cleanup();
1616err2:
1617 blizzard.int_ctrl->cleanup();
1618err1:
1619 return r;
1620}
1621
1622static void blizzard_cleanup(void)
1623{
1624 blizzard_set_update_mode(OMAPFB_UPDATE_DISABLED);
1625 blizzard.extif->cleanup();
1626 blizzard.int_ctrl->cleanup();
1627 if (blizzard.power_down != NULL)
1628 blizzard.power_down(blizzard.fbdev->dev);
1629}
1630
1631struct lcd_ctrl blizzard_ctrl = {
1632 .name = "blizzard",
1633 .init = blizzard_init,
1634 .cleanup = blizzard_cleanup,
1635 .bind_client = blizzard_bind_client,
1636 .get_caps = blizzard_get_caps,
1637 .set_update_mode = blizzard_set_update_mode,
1638 .get_update_mode = blizzard_get_update_mode,
1639 .setup_plane = blizzard_setup_plane,
1640 .set_scale = blizzard_set_scale,
1641 .enable_plane = blizzard_enable_plane,
1642 .set_rotate = blizzard_set_rotate,
1643 .update_window = blizzard_update_window_async,
1644 .sync = blizzard_sync,
1645 .suspend = blizzard_suspend,
1646 .resume = blizzard_resume,
1647};
1648
diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
deleted file mode 100644
index 6f61e781f15a..000000000000
--- a/drivers/video/omap/dispc.c
+++ /dev/null
@@ -1,1547 +0,0 @@
1/*
2 * OMAP2 display controller support
3 *
4 * Copyright (C) 2005 Nokia Corporation
5 * Author: Imre Deak <imre.deak@nokia.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/dma-mapping.h>
24#include <linux/mm.h>
25#include <linux/vmalloc.h>
26#include <linux/clk.h>
27#include <linux/io.h>
28#include <linux/platform_device.h>
29#include <linux/slab.h>
30
31#include <plat/sram.h>
32#include <plat/board.h>
33
34#include "omapfb.h"
35#include "dispc.h"
36
37#define MODULE_NAME "dispc"
38
39#define DSS_BASE 0x48050000
40#define DSS_SYSCONFIG 0x0010
41
42#define DISPC_BASE 0x48050400
43
44/* DISPC common */
45#define DISPC_REVISION 0x0000
46#define DISPC_SYSCONFIG 0x0010
47#define DISPC_SYSSTATUS 0x0014
48#define DISPC_IRQSTATUS 0x0018
49#define DISPC_IRQENABLE 0x001C
50#define DISPC_CONTROL 0x0040
51#define DISPC_CONFIG 0x0044
52#define DISPC_CAPABLE 0x0048
53#define DISPC_DEFAULT_COLOR0 0x004C
54#define DISPC_DEFAULT_COLOR1 0x0050
55#define DISPC_TRANS_COLOR0 0x0054
56#define DISPC_TRANS_COLOR1 0x0058
57#define DISPC_LINE_STATUS 0x005C
58#define DISPC_LINE_NUMBER 0x0060
59#define DISPC_TIMING_H 0x0064
60#define DISPC_TIMING_V 0x0068
61#define DISPC_POL_FREQ 0x006C
62#define DISPC_DIVISOR 0x0070
63#define DISPC_SIZE_DIG 0x0078
64#define DISPC_SIZE_LCD 0x007C
65
66#define DISPC_DATA_CYCLE1 0x01D4
67#define DISPC_DATA_CYCLE2 0x01D8
68#define DISPC_DATA_CYCLE3 0x01DC
69
70/* DISPC GFX plane */
71#define DISPC_GFX_BA0 0x0080
72#define DISPC_GFX_BA1 0x0084
73#define DISPC_GFX_POSITION 0x0088
74#define DISPC_GFX_SIZE 0x008C
75#define DISPC_GFX_ATTRIBUTES 0x00A0
76#define DISPC_GFX_FIFO_THRESHOLD 0x00A4
77#define DISPC_GFX_FIFO_SIZE_STATUS 0x00A8
78#define DISPC_GFX_ROW_INC 0x00AC
79#define DISPC_GFX_PIXEL_INC 0x00B0
80#define DISPC_GFX_WINDOW_SKIP 0x00B4
81#define DISPC_GFX_TABLE_BA 0x00B8
82
83/* DISPC Video plane 1/2 */
84#define DISPC_VID1_BASE 0x00BC
85#define DISPC_VID2_BASE 0x014C
86
87/* Offsets into DISPC_VID1/2_BASE */
88#define DISPC_VID_BA0 0x0000
89#define DISPC_VID_BA1 0x0004
90#define DISPC_VID_POSITION 0x0008
91#define DISPC_VID_SIZE 0x000C
92#define DISPC_VID_ATTRIBUTES 0x0010
93#define DISPC_VID_FIFO_THRESHOLD 0x0014
94#define DISPC_VID_FIFO_SIZE_STATUS 0x0018
95#define DISPC_VID_ROW_INC 0x001C
96#define DISPC_VID_PIXEL_INC 0x0020
97#define DISPC_VID_FIR 0x0024
98#define DISPC_VID_PICTURE_SIZE 0x0028
99#define DISPC_VID_ACCU0 0x002C
100#define DISPC_VID_ACCU1 0x0030
101
102/* 8 elements in 8 byte increments */
103#define DISPC_VID_FIR_COEF_H0 0x0034
104/* 8 elements in 8 byte increments */
105#define DISPC_VID_FIR_COEF_HV0 0x0038
106/* 5 elements in 4 byte increments */
107#define DISPC_VID_CONV_COEF0 0x0074
108
109#define DISPC_IRQ_FRAMEMASK 0x0001
110#define DISPC_IRQ_VSYNC 0x0002
111#define DISPC_IRQ_EVSYNC_EVEN 0x0004
112#define DISPC_IRQ_EVSYNC_ODD 0x0008
113#define DISPC_IRQ_ACBIAS_COUNT_STAT 0x0010
114#define DISPC_IRQ_PROG_LINE_NUM 0x0020
115#define DISPC_IRQ_GFX_FIFO_UNDERFLOW 0x0040
116#define DISPC_IRQ_GFX_END_WIN 0x0080
117#define DISPC_IRQ_PAL_GAMMA_MASK 0x0100
118#define DISPC_IRQ_OCP_ERR 0x0200
119#define DISPC_IRQ_VID1_FIFO_UNDERFLOW 0x0400
120#define DISPC_IRQ_VID1_END_WIN 0x0800
121#define DISPC_IRQ_VID2_FIFO_UNDERFLOW 0x1000
122#define DISPC_IRQ_VID2_END_WIN 0x2000
123#define DISPC_IRQ_SYNC_LOST 0x4000
124
125#define DISPC_IRQ_MASK_ALL 0x7fff
126
127#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
128 DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
129 DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
130 DISPC_IRQ_SYNC_LOST)
131
132#define RFBI_CONTROL 0x48050040
133
134#define MAX_PALETTE_SIZE (256 * 16)
135
136#define FLD_MASK(pos, len) (((1 << len) - 1) << pos)
137
138#define MOD_REG_FLD(reg, mask, val) \
139 dispc_write_reg((reg), (dispc_read_reg(reg) & ~(mask)) | (val));
140
141#define OMAP2_SRAM_START 0x40200000
142/* Maximum size, in reality this is smaller if SRAM is partially locked. */
143#define OMAP2_SRAM_SIZE 0xa0000 /* 640k */
144
145/* We support the SDRAM / SRAM types. See OMAPFB_PLANE_MEMTYPE_* in omapfb.h */
146#define DISPC_MEMTYPE_NUM 2
147
148#define RESMAP_SIZE(_page_cnt) \
149 ((_page_cnt + (sizeof(unsigned long) * 8) - 1) / 8)
150#define RESMAP_PTR(_res_map, _page_nr) \
151 (((_res_map)->map) + (_page_nr) / (sizeof(unsigned long) * 8))
152#define RESMAP_MASK(_page_nr) \
153 (1 << ((_page_nr) & (sizeof(unsigned long) * 8 - 1)))
154
155struct resmap {
156 unsigned long start;
157 unsigned page_cnt;
158 unsigned long *map;
159};
160
161#define MAX_IRQ_HANDLERS 4
162
163static struct {
164 void __iomem *base;
165
166 struct omapfb_mem_desc mem_desc;
167 struct resmap *res_map[DISPC_MEMTYPE_NUM];
168 atomic_t map_count[OMAPFB_PLANE_NUM];
169
170 dma_addr_t palette_paddr;
171 void *palette_vaddr;
172
173 int ext_mode;
174
175 struct {
176 u32 irq_mask;
177 void (*callback)(void *);
178 void *data;
179 } irq_handlers[MAX_IRQ_HANDLERS];
180 struct completion frame_done;
181
182 int fir_hinc[OMAPFB_PLANE_NUM];
183 int fir_vinc[OMAPFB_PLANE_NUM];
184
185 struct clk *dss_ick, *dss1_fck;
186 struct clk *dss_54m_fck;
187
188 enum omapfb_update_mode update_mode;
189 struct omapfb_device *fbdev;
190
191 struct omapfb_color_key color_key;
192} dispc;
193
194static void enable_lcd_clocks(int enable);
195
196static void inline dispc_write_reg(int idx, u32 val)
197{
198 __raw_writel(val, dispc.base + idx);
199}
200
201static u32 inline dispc_read_reg(int idx)
202{
203 u32 l = __raw_readl(dispc.base + idx);
204 return l;
205}
206
207/* Select RFBI or bypass mode */
208static void enable_rfbi_mode(int enable)
209{
210 void __iomem *rfbi_control;
211 u32 l;
212
213 l = dispc_read_reg(DISPC_CONTROL);
214 /* Enable RFBI, GPIO0/1 */
215 l &= ~((1 << 11) | (1 << 15) | (1 << 16));
216 l |= enable ? (1 << 11) : 0;
217 /* RFBI En: GPIO0/1=10 RFBI Dis: GPIO0/1=11 */
218 l |= 1 << 15;
219 l |= enable ? 0 : (1 << 16);
220 dispc_write_reg(DISPC_CONTROL, l);
221
222 /* Set bypass mode in RFBI module */
223 rfbi_control = ioremap(RFBI_CONTROL, SZ_1K);
224 if (!rfbi_control) {
225 pr_err("Unable to ioremap rfbi_control\n");
226 return;
227 }
228 l = __raw_readl(rfbi_control);
229 l |= enable ? 0 : (1 << 1);
230 __raw_writel(l, rfbi_control);
231 iounmap(rfbi_control);
232}
233
234static void set_lcd_data_lines(int data_lines)
235{
236 u32 l;
237 int code = 0;
238
239 switch (data_lines) {
240 case 12:
241 code = 0;
242 break;
243 case 16:
244 code = 1;
245 break;
246 case 18:
247 code = 2;
248 break;
249 case 24:
250 code = 3;
251 break;
252 default:
253 BUG();
254 }
255
256 l = dispc_read_reg(DISPC_CONTROL);
257 l &= ~(0x03 << 8);
258 l |= code << 8;
259 dispc_write_reg(DISPC_CONTROL, l);
260}
261
262static void set_load_mode(int mode)
263{
264 BUG_ON(mode & ~(DISPC_LOAD_CLUT_ONLY | DISPC_LOAD_FRAME_ONLY |
265 DISPC_LOAD_CLUT_ONCE_FRAME));
266 MOD_REG_FLD(DISPC_CONFIG, 0x03 << 1, mode << 1);
267}
268
269void omap_dispc_set_lcd_size(int x, int y)
270{
271 BUG_ON((x > (1 << 11)) || (y > (1 << 11)));
272 enable_lcd_clocks(1);
273 MOD_REG_FLD(DISPC_SIZE_LCD, FLD_MASK(16, 11) | FLD_MASK(0, 11),
274 ((y - 1) << 16) | (x - 1));
275 enable_lcd_clocks(0);
276}
277EXPORT_SYMBOL(omap_dispc_set_lcd_size);
278
279void omap_dispc_set_digit_size(int x, int y)
280{
281 BUG_ON((x > (1 << 11)) || (y > (1 << 11)));
282 enable_lcd_clocks(1);
283 MOD_REG_FLD(DISPC_SIZE_DIG, FLD_MASK(16, 11) | FLD_MASK(0, 11),
284 ((y - 1) << 16) | (x - 1));
285 enable_lcd_clocks(0);
286}
287EXPORT_SYMBOL(omap_dispc_set_digit_size);
288
289static void setup_plane_fifo(int plane, int ext_mode)
290{
291 const u32 ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
292 DISPC_VID1_BASE + DISPC_VID_FIFO_THRESHOLD,
293 DISPC_VID2_BASE + DISPC_VID_FIFO_THRESHOLD };
294 const u32 fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,
295 DISPC_VID1_BASE + DISPC_VID_FIFO_SIZE_STATUS,
296 DISPC_VID2_BASE + DISPC_VID_FIFO_SIZE_STATUS };
297 int low, high;
298 u32 l;
299
300 BUG_ON(plane > 2);
301
302 l = dispc_read_reg(fsz_reg[plane]);
303 l &= FLD_MASK(0, 11);
304 if (ext_mode) {
305 low = l * 3 / 4;
306 high = l;
307 } else {
308 low = l / 4;
309 high = l * 3 / 4;
310 }
311 MOD_REG_FLD(ftrs_reg[plane], FLD_MASK(16, 12) | FLD_MASK(0, 12),
312 (high << 16) | low);
313}
314
315void omap_dispc_enable_lcd_out(int enable)
316{
317 enable_lcd_clocks(1);
318 MOD_REG_FLD(DISPC_CONTROL, 1, enable ? 1 : 0);
319 enable_lcd_clocks(0);
320}
321EXPORT_SYMBOL(omap_dispc_enable_lcd_out);
322
323void omap_dispc_enable_digit_out(int enable)
324{
325 enable_lcd_clocks(1);
326 MOD_REG_FLD(DISPC_CONTROL, 1 << 1, enable ? 1 << 1 : 0);
327 enable_lcd_clocks(0);
328}
329EXPORT_SYMBOL(omap_dispc_enable_digit_out);
330
331static inline int _setup_plane(int plane, int channel_out,
332 u32 paddr, int screen_width,
333 int pos_x, int pos_y, int width, int height,
334 int color_mode)
335{
336 const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES,
337 DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
338 DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
339 const u32 ba_reg[] = { DISPC_GFX_BA0, DISPC_VID1_BASE + DISPC_VID_BA0,
340 DISPC_VID2_BASE + DISPC_VID_BA0 };
341 const u32 ps_reg[] = { DISPC_GFX_POSITION,
342 DISPC_VID1_BASE + DISPC_VID_POSITION,
343 DISPC_VID2_BASE + DISPC_VID_POSITION };
344 const u32 sz_reg[] = { DISPC_GFX_SIZE,
345 DISPC_VID1_BASE + DISPC_VID_PICTURE_SIZE,
346 DISPC_VID2_BASE + DISPC_VID_PICTURE_SIZE };
347 const u32 ri_reg[] = { DISPC_GFX_ROW_INC,
348 DISPC_VID1_BASE + DISPC_VID_ROW_INC,
349 DISPC_VID2_BASE + DISPC_VID_ROW_INC };
350 const u32 vs_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_SIZE,
351 DISPC_VID2_BASE + DISPC_VID_SIZE };
352
353 int chout_shift, burst_shift;
354 int chout_val;
355 int color_code;
356 int bpp;
357 int cconv_en;
358 int set_vsize;
359 u32 l;
360
361#ifdef VERBOSE
362 dev_dbg(dispc.fbdev->dev, "plane %d channel %d paddr %#08x scr_width %d"
363 " pos_x %d pos_y %d width %d height %d color_mode %d\n",
364 plane, channel_out, paddr, screen_width, pos_x, pos_y,
365 width, height, color_mode);
366#endif
367
368 set_vsize = 0;
369 switch (plane) {
370 case OMAPFB_PLANE_GFX:
371 burst_shift = 6;
372 chout_shift = 8;
373 break;
374 case OMAPFB_PLANE_VID1:
375 case OMAPFB_PLANE_VID2:
376 burst_shift = 14;
377 chout_shift = 16;
378 set_vsize = 1;
379 break;
380 default:
381 return -EINVAL;
382 }
383
384 switch (channel_out) {
385 case OMAPFB_CHANNEL_OUT_LCD:
386 chout_val = 0;
387 break;
388 case OMAPFB_CHANNEL_OUT_DIGIT:
389 chout_val = 1;
390 break;
391 default:
392 return -EINVAL;
393 }
394
395 cconv_en = 0;
396 switch (color_mode) {
397 case OMAPFB_COLOR_RGB565:
398 color_code = DISPC_RGB_16_BPP;
399 bpp = 16;
400 break;
401 case OMAPFB_COLOR_YUV422:
402 if (plane == 0)
403 return -EINVAL;
404 color_code = DISPC_UYVY_422;
405 cconv_en = 1;
406 bpp = 16;
407 break;
408 case OMAPFB_COLOR_YUY422:
409 if (plane == 0)
410 return -EINVAL;
411 color_code = DISPC_YUV2_422;
412 cconv_en = 1;
413 bpp = 16;
414 break;
415 default:
416 return -EINVAL;
417 }
418
419 l = dispc_read_reg(at_reg[plane]);
420
421 l &= ~(0x0f << 1);
422 l |= color_code << 1;
423 l &= ~(1 << 9);
424 l |= cconv_en << 9;
425
426 l &= ~(0x03 << burst_shift);
427 l |= DISPC_BURST_8x32 << burst_shift;
428
429 l &= ~(1 << chout_shift);
430 l |= chout_val << chout_shift;
431
432 dispc_write_reg(at_reg[plane], l);
433
434 dispc_write_reg(ba_reg[plane], paddr);
435 MOD_REG_FLD(ps_reg[plane],
436 FLD_MASK(16, 11) | FLD_MASK(0, 11), (pos_y << 16) | pos_x);
437
438 MOD_REG_FLD(sz_reg[plane], FLD_MASK(16, 11) | FLD_MASK(0, 11),
439 ((height - 1) << 16) | (width - 1));
440
441 if (set_vsize) {
442 /* Set video size if set_scale hasn't set it */
443 if (!dispc.fir_vinc[plane])
444 MOD_REG_FLD(vs_reg[plane],
445 FLD_MASK(16, 11), (height - 1) << 16);
446 if (!dispc.fir_hinc[plane])
447 MOD_REG_FLD(vs_reg[plane],
448 FLD_MASK(0, 11), width - 1);
449 }
450
451 dispc_write_reg(ri_reg[plane], (screen_width - width) * bpp / 8 + 1);
452
453 return height * screen_width * bpp / 8;
454}
455
456static int omap_dispc_setup_plane(int plane, int channel_out,
457 unsigned long offset,
458 int screen_width,
459 int pos_x, int pos_y, int width, int height,
460 int color_mode)
461{
462 u32 paddr;
463 int r;
464
465 if ((unsigned)plane > dispc.mem_desc.region_cnt)
466 return -EINVAL;
467 paddr = dispc.mem_desc.region[plane].paddr + offset;
468 enable_lcd_clocks(1);
469 r = _setup_plane(plane, channel_out, paddr,
470 screen_width,
471 pos_x, pos_y, width, height, color_mode);
472 enable_lcd_clocks(0);
473 return r;
474}
475
476static void write_firh_reg(int plane, int reg, u32 value)
477{
478 u32 base;
479
480 if (plane == 1)
481 base = DISPC_VID1_BASE + DISPC_VID_FIR_COEF_H0;
482 else
483 base = DISPC_VID2_BASE + DISPC_VID_FIR_COEF_H0;
484 dispc_write_reg(base + reg * 8, value);
485}
486
487static void write_firhv_reg(int plane, int reg, u32 value)
488{
489 u32 base;
490
491 if (plane == 1)
492 base = DISPC_VID1_BASE + DISPC_VID_FIR_COEF_HV0;
493 else
494 base = DISPC_VID2_BASE + DISPC_VID_FIR_COEF_HV0;
495 dispc_write_reg(base + reg * 8, value);
496}
497
498static void set_upsampling_coef_table(int plane)
499{
500 const u32 coef[][2] = {
501 { 0x00800000, 0x00800000 },
502 { 0x0D7CF800, 0x037B02FF },
503 { 0x1E70F5FF, 0x0C6F05FE },
504 { 0x335FF5FE, 0x205907FB },
505 { 0xF74949F7, 0x00404000 },
506 { 0xF55F33FB, 0x075920FE },
507 { 0xF5701EFE, 0x056F0CFF },
508 { 0xF87C0DFF, 0x027B0300 },
509 };
510 int i;
511
512 for (i = 0; i < 8; i++) {
513 write_firh_reg(plane, i, coef[i][0]);
514 write_firhv_reg(plane, i, coef[i][1]);
515 }
516}
517
518static int omap_dispc_set_scale(int plane,
519 int orig_width, int orig_height,
520 int out_width, int out_height)
521{
522 const u32 at_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
523 DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
524 const u32 vs_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_SIZE,
525 DISPC_VID2_BASE + DISPC_VID_SIZE };
526 const u32 fir_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_FIR,
527 DISPC_VID2_BASE + DISPC_VID_FIR };
528
529 u32 l;
530 int fir_hinc;
531 int fir_vinc;
532
533 if ((unsigned)plane > OMAPFB_PLANE_NUM)
534 return -ENODEV;
535
536 if (plane == OMAPFB_PLANE_GFX &&
537 (out_width != orig_width || out_height != orig_height))
538 return -EINVAL;
539
540 enable_lcd_clocks(1);
541 if (orig_width < out_width) {
542 /*
543 * Upsampling.
544 * Currently you can only scale both dimensions in one way.
545 */
546 if (orig_height > out_height ||
547 orig_width * 8 < out_width ||
548 orig_height * 8 < out_height) {
549 enable_lcd_clocks(0);
550 return -EINVAL;
551 }
552 set_upsampling_coef_table(plane);
553 } else if (orig_width > out_width) {
554 /* Downsampling not yet supported
555 */
556
557 enable_lcd_clocks(0);
558 return -EINVAL;
559 }
560 if (!orig_width || orig_width == out_width)
561 fir_hinc = 0;
562 else
563 fir_hinc = 1024 * orig_width / out_width;
564 if (!orig_height || orig_height == out_height)
565 fir_vinc = 0;
566 else
567 fir_vinc = 1024 * orig_height / out_height;
568 dispc.fir_hinc[plane] = fir_hinc;
569 dispc.fir_vinc[plane] = fir_vinc;
570
571 MOD_REG_FLD(fir_reg[plane],
572 FLD_MASK(16, 12) | FLD_MASK(0, 12),
573 ((fir_vinc & 4095) << 16) |
574 (fir_hinc & 4095));
575
576 dev_dbg(dispc.fbdev->dev, "out_width %d out_height %d orig_width %d "
577 "orig_height %d fir_hinc %d fir_vinc %d\n",
578 out_width, out_height, orig_width, orig_height,
579 fir_hinc, fir_vinc);
580
581 MOD_REG_FLD(vs_reg[plane],
582 FLD_MASK(16, 11) | FLD_MASK(0, 11),
583 ((out_height - 1) << 16) | (out_width - 1));
584
585 l = dispc_read_reg(at_reg[plane]);
586 l &= ~(0x03 << 5);
587 l |= fir_hinc ? (1 << 5) : 0;
588 l |= fir_vinc ? (1 << 6) : 0;
589 dispc_write_reg(at_reg[plane], l);
590
591 enable_lcd_clocks(0);
592 return 0;
593}
594
595static int omap_dispc_enable_plane(int plane, int enable)
596{
597 const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES,
598 DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
599 DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
600 if ((unsigned int)plane > dispc.mem_desc.region_cnt)
601 return -EINVAL;
602
603 enable_lcd_clocks(1);
604 MOD_REG_FLD(at_reg[plane], 1, enable ? 1 : 0);
605 enable_lcd_clocks(0);
606
607 return 0;
608}
609
610static int omap_dispc_set_color_key(struct omapfb_color_key *ck)
611{
612 u32 df_reg, tr_reg;
613 int shift, val;
614
615 switch (ck->channel_out) {
616 case OMAPFB_CHANNEL_OUT_LCD:
617 df_reg = DISPC_DEFAULT_COLOR0;
618 tr_reg = DISPC_TRANS_COLOR0;
619 shift = 10;
620 break;
621 case OMAPFB_CHANNEL_OUT_DIGIT:
622 df_reg = DISPC_DEFAULT_COLOR1;
623 tr_reg = DISPC_TRANS_COLOR1;
624 shift = 12;
625 break;
626 default:
627 return -EINVAL;
628 }
629 switch (ck->key_type) {
630 case OMAPFB_COLOR_KEY_DISABLED:
631 val = 0;
632 break;
633 case OMAPFB_COLOR_KEY_GFX_DST:
634 val = 1;
635 break;
636 case OMAPFB_COLOR_KEY_VID_SRC:
637 val = 3;
638 break;
639 default:
640 return -EINVAL;
641 }
642 enable_lcd_clocks(1);
643 MOD_REG_FLD(DISPC_CONFIG, FLD_MASK(shift, 2), val << shift);
644
645 if (val != 0)
646 dispc_write_reg(tr_reg, ck->trans_key);
647 dispc_write_reg(df_reg, ck->background);
648 enable_lcd_clocks(0);
649
650 dispc.color_key = *ck;
651
652 return 0;
653}
654
655static int omap_dispc_get_color_key(struct omapfb_color_key *ck)
656{
657 *ck = dispc.color_key;
658 return 0;
659}
660
661static void load_palette(void)
662{
663}
664
665static int omap_dispc_set_update_mode(enum omapfb_update_mode mode)
666{
667 int r = 0;
668
669 if (mode != dispc.update_mode) {
670 switch (mode) {
671 case OMAPFB_AUTO_UPDATE:
672 case OMAPFB_MANUAL_UPDATE:
673 enable_lcd_clocks(1);
674 omap_dispc_enable_lcd_out(1);
675 dispc.update_mode = mode;
676 break;
677 case OMAPFB_UPDATE_DISABLED:
678 init_completion(&dispc.frame_done);
679 omap_dispc_enable_lcd_out(0);
680 if (!wait_for_completion_timeout(&dispc.frame_done,
681 msecs_to_jiffies(500))) {
682 dev_err(dispc.fbdev->dev,
683 "timeout waiting for FRAME DONE\n");
684 }
685 dispc.update_mode = mode;
686 enable_lcd_clocks(0);
687 break;
688 default:
689 r = -EINVAL;
690 }
691 }
692
693 return r;
694}
695
696static void omap_dispc_get_caps(int plane, struct omapfb_caps *caps)
697{
698 caps->ctrl |= OMAPFB_CAPS_PLANE_RELOCATE_MEM;
699 if (plane > 0)
700 caps->ctrl |= OMAPFB_CAPS_PLANE_SCALE;
701 caps->plane_color |= (1 << OMAPFB_COLOR_RGB565) |
702 (1 << OMAPFB_COLOR_YUV422) |
703 (1 << OMAPFB_COLOR_YUY422);
704 if (plane == 0)
705 caps->plane_color |= (1 << OMAPFB_COLOR_CLUT_8BPP) |
706 (1 << OMAPFB_COLOR_CLUT_4BPP) |
707 (1 << OMAPFB_COLOR_CLUT_2BPP) |
708 (1 << OMAPFB_COLOR_CLUT_1BPP) |
709 (1 << OMAPFB_COLOR_RGB444);
710}
711
712static enum omapfb_update_mode omap_dispc_get_update_mode(void)
713{
714 return dispc.update_mode;
715}
716
717static void setup_color_conv_coef(void)
718{
719 u32 mask = FLD_MASK(16, 11) | FLD_MASK(0, 11);
720 int cf1_reg = DISPC_VID1_BASE + DISPC_VID_CONV_COEF0;
721 int cf2_reg = DISPC_VID2_BASE + DISPC_VID_CONV_COEF0;
722 int at1_reg = DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES;
723 int at2_reg = DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES;
724 const struct color_conv_coef {
725 int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
726 int full_range;
727 } ctbl_bt601_5 = {
728 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
729 };
730 const struct color_conv_coef *ct;
731#define CVAL(x, y) (((x & 2047) << 16) | (y & 2047))
732
733 ct = &ctbl_bt601_5;
734
735 MOD_REG_FLD(cf1_reg, mask, CVAL(ct->rcr, ct->ry));
736 MOD_REG_FLD(cf1_reg + 4, mask, CVAL(ct->gy, ct->rcb));
737 MOD_REG_FLD(cf1_reg + 8, mask, CVAL(ct->gcb, ct->gcr));
738 MOD_REG_FLD(cf1_reg + 12, mask, CVAL(ct->bcr, ct->by));
739 MOD_REG_FLD(cf1_reg + 16, mask, CVAL(0, ct->bcb));
740
741 MOD_REG_FLD(cf2_reg, mask, CVAL(ct->rcr, ct->ry));
742 MOD_REG_FLD(cf2_reg + 4, mask, CVAL(ct->gy, ct->rcb));
743 MOD_REG_FLD(cf2_reg + 8, mask, CVAL(ct->gcb, ct->gcr));
744 MOD_REG_FLD(cf2_reg + 12, mask, CVAL(ct->bcr, ct->by));
745 MOD_REG_FLD(cf2_reg + 16, mask, CVAL(0, ct->bcb));
746#undef CVAL
747
748 MOD_REG_FLD(at1_reg, (1 << 11), ct->full_range);
749 MOD_REG_FLD(at2_reg, (1 << 11), ct->full_range);
750}
751
752static void calc_ck_div(int is_tft, int pck, int *lck_div, int *pck_div)
753{
754 unsigned long fck, lck;
755
756 *lck_div = 1;
757 pck = max(1, pck);
758 fck = clk_get_rate(dispc.dss1_fck);
759 lck = fck;
760 *pck_div = (lck + pck - 1) / pck;
761 if (is_tft)
762 *pck_div = max(2, *pck_div);
763 else
764 *pck_div = max(3, *pck_div);
765 if (*pck_div > 255) {
766 *pck_div = 255;
767 lck = pck * *pck_div;
768 *lck_div = fck / lck;
769 BUG_ON(*lck_div < 1);
770 if (*lck_div > 255) {
771 *lck_div = 255;
772 dev_warn(dispc.fbdev->dev, "pixclock %d kHz too low.\n",
773 pck / 1000);
774 }
775 }
776}
777
778static void set_lcd_tft_mode(int enable)
779{
780 u32 mask;
781
782 mask = 1 << 3;
783 MOD_REG_FLD(DISPC_CONTROL, mask, enable ? mask : 0);
784}
785
786static void set_lcd_timings(void)
787{
788 u32 l;
789 int lck_div, pck_div;
790 struct lcd_panel *panel = dispc.fbdev->panel;
791 int is_tft = panel->config & OMAP_LCDC_PANEL_TFT;
792 unsigned long fck;
793
794 l = dispc_read_reg(DISPC_TIMING_H);
795 l &= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8));
796 l |= ( max(1, (min(64, panel->hsw))) - 1 ) << 0;
797 l |= ( max(1, (min(256, panel->hfp))) - 1 ) << 8;
798 l |= ( max(1, (min(256, panel->hbp))) - 1 ) << 20;
799 dispc_write_reg(DISPC_TIMING_H, l);
800
801 l = dispc_read_reg(DISPC_TIMING_V);
802 l &= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8));
803 l |= ( max(1, (min(64, panel->vsw))) - 1 ) << 0;
804 l |= ( max(0, (min(255, panel->vfp))) - 0 ) << 8;
805 l |= ( max(0, (min(255, panel->vbp))) - 0 ) << 20;
806 dispc_write_reg(DISPC_TIMING_V, l);
807
808 l = dispc_read_reg(DISPC_POL_FREQ);
809 l &= ~FLD_MASK(12, 6);
810 l |= (panel->config & OMAP_LCDC_SIGNAL_MASK) << 12;
811 l |= panel->acb & 0xff;
812 dispc_write_reg(DISPC_POL_FREQ, l);
813
814 calc_ck_div(is_tft, panel->pixel_clock * 1000, &lck_div, &pck_div);
815
816 l = dispc_read_reg(DISPC_DIVISOR);
817 l &= ~(FLD_MASK(16, 8) | FLD_MASK(0, 8));
818 l |= (lck_div << 16) | (pck_div << 0);
819 dispc_write_reg(DISPC_DIVISOR, l);
820
821 /* update panel info with the exact clock */
822 fck = clk_get_rate(dispc.dss1_fck);
823 panel->pixel_clock = fck / lck_div / pck_div / 1000;
824}
825
826static void recalc_irq_mask(void)
827{
828 int i;
829 unsigned long irq_mask = DISPC_IRQ_MASK_ERROR;
830
831 for (i = 0; i < MAX_IRQ_HANDLERS; i++) {
832 if (!dispc.irq_handlers[i].callback)
833 continue;
834
835 irq_mask |= dispc.irq_handlers[i].irq_mask;
836 }
837
838 enable_lcd_clocks(1);
839 MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask);
840 enable_lcd_clocks(0);
841}
842
843int omap_dispc_request_irq(unsigned long irq_mask, void (*callback)(void *data),
844 void *data)
845{
846 int i;
847
848 BUG_ON(callback == NULL);
849
850 for (i = 0; i < MAX_IRQ_HANDLERS; i++) {
851 if (dispc.irq_handlers[i].callback)
852 continue;
853
854 dispc.irq_handlers[i].irq_mask = irq_mask;
855 dispc.irq_handlers[i].callback = callback;
856 dispc.irq_handlers[i].data = data;
857 recalc_irq_mask();
858
859 return 0;
860 }
861
862 return -EBUSY;
863}
864EXPORT_SYMBOL(omap_dispc_request_irq);
865
866void omap_dispc_free_irq(unsigned long irq_mask, void (*callback)(void *data),
867 void *data)
868{
869 int i;
870
871 for (i = 0; i < MAX_IRQ_HANDLERS; i++) {
872 if (dispc.irq_handlers[i].callback == callback &&
873 dispc.irq_handlers[i].data == data) {
874 dispc.irq_handlers[i].irq_mask = 0;
875 dispc.irq_handlers[i].callback = NULL;
876 dispc.irq_handlers[i].data = NULL;
877 recalc_irq_mask();
878 return;
879 }
880 }
881
882 BUG();
883}
884EXPORT_SYMBOL(omap_dispc_free_irq);
885
886static irqreturn_t omap_dispc_irq_handler(int irq, void *dev)
887{
888 u32 stat;
889 int i = 0;
890
891 enable_lcd_clocks(1);
892
893 stat = dispc_read_reg(DISPC_IRQSTATUS);
894 if (stat & DISPC_IRQ_FRAMEMASK)
895 complete(&dispc.frame_done);
896
897 if (stat & DISPC_IRQ_MASK_ERROR) {
898 if (printk_ratelimit()) {
899 dev_err(dispc.fbdev->dev, "irq error status %04x\n",
900 stat & 0x7fff);
901 }
902 }
903
904 for (i = 0; i < MAX_IRQ_HANDLERS; i++) {
905 if (unlikely(dispc.irq_handlers[i].callback &&
906 (stat & dispc.irq_handlers[i].irq_mask)))
907 dispc.irq_handlers[i].callback(
908 dispc.irq_handlers[i].data);
909 }
910
911 dispc_write_reg(DISPC_IRQSTATUS, stat);
912
913 enable_lcd_clocks(0);
914
915 return IRQ_HANDLED;
916}
917
918static int get_dss_clocks(void)
919{
920 dispc.dss_ick = clk_get(&dispc.fbdev->dssdev->dev, "ick");
921 if (IS_ERR(dispc.dss_ick)) {
922 dev_err(dispc.fbdev->dev, "can't get ick\n");
923 return PTR_ERR(dispc.dss_ick);
924 }
925
926 dispc.dss1_fck = clk_get(&dispc.fbdev->dssdev->dev, "fck");
927 if (IS_ERR(dispc.dss1_fck)) {
928 dev_err(dispc.fbdev->dev, "can't get dss1_fck\n");
929 clk_put(dispc.dss_ick);
930 return PTR_ERR(dispc.dss1_fck);
931 }
932
933 dispc.dss_54m_fck = clk_get(&dispc.fbdev->dssdev->dev, "tv_clk");
934 if (IS_ERR(dispc.dss_54m_fck)) {
935 dev_err(dispc.fbdev->dev, "can't get tv_fck\n");
936 clk_put(dispc.dss_ick);
937 clk_put(dispc.dss1_fck);
938 return PTR_ERR(dispc.dss_54m_fck);
939 }
940
941 return 0;
942}
943
944static void put_dss_clocks(void)
945{
946 clk_put(dispc.dss_54m_fck);
947 clk_put(dispc.dss1_fck);
948 clk_put(dispc.dss_ick);
949}
950
951static void enable_lcd_clocks(int enable)
952{
953 if (enable) {
954 clk_enable(dispc.dss_ick);
955 clk_enable(dispc.dss1_fck);
956 } else {
957 clk_disable(dispc.dss1_fck);
958 clk_disable(dispc.dss_ick);
959 }
960}
961
962static void enable_digit_clocks(int enable)
963{
964 if (enable)
965 clk_enable(dispc.dss_54m_fck);
966 else
967 clk_disable(dispc.dss_54m_fck);
968}
969
970static void omap_dispc_suspend(void)
971{
972 if (dispc.update_mode == OMAPFB_AUTO_UPDATE) {
973 init_completion(&dispc.frame_done);
974 omap_dispc_enable_lcd_out(0);
975 if (!wait_for_completion_timeout(&dispc.frame_done,
976 msecs_to_jiffies(500))) {
977 dev_err(dispc.fbdev->dev,
978 "timeout waiting for FRAME DONE\n");
979 }
980 enable_lcd_clocks(0);
981 }
982}
983
984static void omap_dispc_resume(void)
985{
986 if (dispc.update_mode == OMAPFB_AUTO_UPDATE) {
987 enable_lcd_clocks(1);
988 if (!dispc.ext_mode) {
989 set_lcd_timings();
990 load_palette();
991 }
992 omap_dispc_enable_lcd_out(1);
993 }
994}
995
996
997static int omap_dispc_update_window(struct fb_info *fbi,
998 struct omapfb_update_window *win,
999 void (*complete_callback)(void *arg),
1000 void *complete_callback_data)
1001{
1002 return dispc.update_mode == OMAPFB_UPDATE_DISABLED ? -ENODEV : 0;
1003}
1004
1005static int mmap_kern(struct omapfb_mem_region *region)
1006{
1007 struct vm_struct *kvma;
1008 struct vm_area_struct vma;
1009 pgprot_t pgprot;
1010 unsigned long vaddr;
1011
1012 kvma = get_vm_area(region->size, VM_IOREMAP);
1013 if (kvma == NULL) {
1014 dev_err(dispc.fbdev->dev, "can't get kernel vm area\n");
1015 return -ENOMEM;
1016 }
1017 vma.vm_mm = &init_mm;
1018
1019 vaddr = (unsigned long)kvma->addr;
1020
1021 pgprot = pgprot_writecombine(pgprot_kernel);
1022 vma.vm_start = vaddr;
1023 vma.vm_end = vaddr + region->size;
1024 if (io_remap_pfn_range(&vma, vaddr, region->paddr >> PAGE_SHIFT,
1025 region->size, pgprot) < 0) {
1026 dev_err(dispc.fbdev->dev, "kernel mmap for FBMEM failed\n");
1027 return -EAGAIN;
1028 }
1029 region->vaddr = (void *)vaddr;
1030
1031 return 0;
1032}
1033
1034static void mmap_user_open(struct vm_area_struct *vma)
1035{
1036 int plane = (int)vma->vm_private_data;
1037
1038 atomic_inc(&dispc.map_count[plane]);
1039}
1040
1041static void mmap_user_close(struct vm_area_struct *vma)
1042{
1043 int plane = (int)vma->vm_private_data;
1044
1045 atomic_dec(&dispc.map_count[plane]);
1046}
1047
1048static const struct vm_operations_struct mmap_user_ops = {
1049 .open = mmap_user_open,
1050 .close = mmap_user_close,
1051};
1052
1053static int omap_dispc_mmap_user(struct fb_info *info,
1054 struct vm_area_struct *vma)
1055{
1056 struct omapfb_plane_struct *plane = info->par;
1057 unsigned long off;
1058 unsigned long start;
1059 u32 len;
1060
1061 if (vma->vm_end - vma->vm_start == 0)
1062 return 0;
1063 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
1064 return -EINVAL;
1065 off = vma->vm_pgoff << PAGE_SHIFT;
1066
1067 start = info->fix.smem_start;
1068 len = info->fix.smem_len;
1069 if (off >= len)
1070 return -EINVAL;
1071 if ((vma->vm_end - vma->vm_start + off) > len)
1072 return -EINVAL;
1073 off += start;
1074 vma->vm_pgoff = off >> PAGE_SHIFT;
1075 vma->vm_flags |= VM_IO | VM_RESERVED;
1076 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
1077 vma->vm_ops = &mmap_user_ops;
1078 vma->vm_private_data = (void *)plane->idx;
1079 if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
1080 vma->vm_end - vma->vm_start, vma->vm_page_prot))
1081 return -EAGAIN;
1082 /* vm_ops.open won't be called for mmap itself. */
1083 atomic_inc(&dispc.map_count[plane->idx]);
1084 return 0;
1085}
1086
1087static void unmap_kern(struct omapfb_mem_region *region)
1088{
1089 vunmap(region->vaddr);
1090}
1091
1092static int alloc_palette_ram(void)
1093{
1094 dispc.palette_vaddr = dma_alloc_writecombine(dispc.fbdev->dev,
1095 MAX_PALETTE_SIZE, &dispc.palette_paddr, GFP_KERNEL);
1096 if (dispc.palette_vaddr == NULL) {
1097 dev_err(dispc.fbdev->dev, "failed to alloc palette memory\n");
1098 return -ENOMEM;
1099 }
1100
1101 return 0;
1102}
1103
1104static void free_palette_ram(void)
1105{
1106 dma_free_writecombine(dispc.fbdev->dev, MAX_PALETTE_SIZE,
1107 dispc.palette_vaddr, dispc.palette_paddr);
1108}
1109
1110static int alloc_fbmem(struct omapfb_mem_region *region)
1111{
1112 region->vaddr = dma_alloc_writecombine(dispc.fbdev->dev,
1113 region->size, &region->paddr, GFP_KERNEL);
1114
1115 if (region->vaddr == NULL) {
1116 dev_err(dispc.fbdev->dev, "unable to allocate FB DMA memory\n");
1117 return -ENOMEM;
1118 }
1119
1120 return 0;
1121}
1122
1123static void free_fbmem(struct omapfb_mem_region *region)
1124{
1125 dma_free_writecombine(dispc.fbdev->dev, region->size,
1126 region->vaddr, region->paddr);
1127}
1128
1129static struct resmap *init_resmap(unsigned long start, size_t size)
1130{
1131 unsigned page_cnt;
1132 struct resmap *res_map;
1133
1134 page_cnt = PAGE_ALIGN(size) / PAGE_SIZE;
1135 res_map =
1136 kzalloc(sizeof(struct resmap) + RESMAP_SIZE(page_cnt), GFP_KERNEL);
1137 if (res_map == NULL)
1138 return NULL;
1139 res_map->start = start;
1140 res_map->page_cnt = page_cnt;
1141 res_map->map = (unsigned long *)(res_map + 1);
1142 return res_map;
1143}
1144
1145static void cleanup_resmap(struct resmap *res_map)
1146{
1147 kfree(res_map);
1148}
1149
1150static inline int resmap_mem_type(unsigned long start)
1151{
1152 if (start >= OMAP2_SRAM_START &&
1153 start < OMAP2_SRAM_START + OMAP2_SRAM_SIZE)
1154 return OMAPFB_MEMTYPE_SRAM;
1155 else
1156 return OMAPFB_MEMTYPE_SDRAM;
1157}
1158
1159static inline int resmap_page_reserved(struct resmap *res_map, unsigned page_nr)
1160{
1161 return *RESMAP_PTR(res_map, page_nr) & RESMAP_MASK(page_nr) ? 1 : 0;
1162}
1163
1164static inline void resmap_reserve_page(struct resmap *res_map, unsigned page_nr)
1165{
1166 BUG_ON(resmap_page_reserved(res_map, page_nr));
1167 *RESMAP_PTR(res_map, page_nr) |= RESMAP_MASK(page_nr);
1168}
1169
1170static inline void resmap_free_page(struct resmap *res_map, unsigned page_nr)
1171{
1172 BUG_ON(!resmap_page_reserved(res_map, page_nr));
1173 *RESMAP_PTR(res_map, page_nr) &= ~RESMAP_MASK(page_nr);
1174}
1175
1176static void resmap_reserve_region(unsigned long start, size_t size)
1177{
1178
1179 struct resmap *res_map;
1180 unsigned start_page;
1181 unsigned end_page;
1182 int mtype;
1183 unsigned i;
1184
1185 mtype = resmap_mem_type(start);
1186 res_map = dispc.res_map[mtype];
1187 dev_dbg(dispc.fbdev->dev, "reserve mem type %d start %08lx size %d\n",
1188 mtype, start, size);
1189 start_page = (start - res_map->start) / PAGE_SIZE;
1190 end_page = start_page + PAGE_ALIGN(size) / PAGE_SIZE;
1191 for (i = start_page; i < end_page; i++)
1192 resmap_reserve_page(res_map, i);
1193}
1194
1195static void resmap_free_region(unsigned long start, size_t size)
1196{
1197 struct resmap *res_map;
1198 unsigned start_page;
1199 unsigned end_page;
1200 unsigned i;
1201 int mtype;
1202
1203 mtype = resmap_mem_type(start);
1204 res_map = dispc.res_map[mtype];
1205 dev_dbg(dispc.fbdev->dev, "free mem type %d start %08lx size %d\n",
1206 mtype, start, size);
1207 start_page = (start - res_map->start) / PAGE_SIZE;
1208 end_page = start_page + PAGE_ALIGN(size) / PAGE_SIZE;
1209 for (i = start_page; i < end_page; i++)
1210 resmap_free_page(res_map, i);
1211}
1212
1213static unsigned long resmap_alloc_region(int mtype, size_t size)
1214{
1215 unsigned i;
1216 unsigned total;
1217 unsigned start_page;
1218 unsigned long start;
1219 struct resmap *res_map = dispc.res_map[mtype];
1220
1221 BUG_ON(mtype >= DISPC_MEMTYPE_NUM || res_map == NULL || !size);
1222
1223 size = PAGE_ALIGN(size) / PAGE_SIZE;
1224 start_page = 0;
1225 total = 0;
1226 for (i = 0; i < res_map->page_cnt; i++) {
1227 if (resmap_page_reserved(res_map, i)) {
1228 start_page = i + 1;
1229 total = 0;
1230 } else if (++total == size)
1231 break;
1232 }
1233 if (total < size)
1234 return 0;
1235
1236 start = res_map->start + start_page * PAGE_SIZE;
1237 resmap_reserve_region(start, size * PAGE_SIZE);
1238
1239 return start;
1240}
1241
1242/* Note that this will only work for user mappings, we don't deal with
1243 * kernel mappings here, so fbcon will keep using the old region.
1244 */
1245static int omap_dispc_setup_mem(int plane, size_t size, int mem_type,
1246 unsigned long *paddr)
1247{
1248 struct omapfb_mem_region *rg;
1249 unsigned long new_addr = 0;
1250
1251 if ((unsigned)plane > dispc.mem_desc.region_cnt)
1252 return -EINVAL;
1253 if (mem_type >= DISPC_MEMTYPE_NUM)
1254 return -EINVAL;
1255 if (dispc.res_map[mem_type] == NULL)
1256 return -ENOMEM;
1257 rg = &dispc.mem_desc.region[plane];
1258 if (size == rg->size && mem_type == rg->type)
1259 return 0;
1260 if (atomic_read(&dispc.map_count[plane]))
1261 return -EBUSY;
1262 if (rg->size != 0)
1263 resmap_free_region(rg->paddr, rg->size);
1264 if (size != 0) {
1265 new_addr = resmap_alloc_region(mem_type, size);
1266 if (!new_addr) {
1267 /* Reallocate old region. */
1268 resmap_reserve_region(rg->paddr, rg->size);
1269 return -ENOMEM;
1270 }
1271 }
1272 rg->paddr = new_addr;
1273 rg->size = size;
1274 rg->type = mem_type;
1275
1276 *paddr = new_addr;
1277
1278 return 0;
1279}
1280
1281static int setup_fbmem(struct omapfb_mem_desc *req_md)
1282{
1283 struct omapfb_mem_region *rg;
1284 int i;
1285 int r;
1286 unsigned long mem_start[DISPC_MEMTYPE_NUM];
1287 unsigned long mem_end[DISPC_MEMTYPE_NUM];
1288
1289 if (!req_md->region_cnt) {
1290 dev_err(dispc.fbdev->dev, "no memory regions defined\n");
1291 return -ENOENT;
1292 }
1293
1294 rg = &req_md->region[0];
1295 memset(mem_start, 0xff, sizeof(mem_start));
1296 memset(mem_end, 0, sizeof(mem_end));
1297
1298 for (i = 0; i < req_md->region_cnt; i++, rg++) {
1299 int mtype;
1300 if (rg->paddr) {
1301 rg->alloc = 0;
1302 if (rg->vaddr == NULL) {
1303 rg->map = 1;
1304 if ((r = mmap_kern(rg)) < 0)
1305 return r;
1306 }
1307 } else {
1308 if (rg->type != OMAPFB_MEMTYPE_SDRAM) {
1309 dev_err(dispc.fbdev->dev,
1310 "unsupported memory type\n");
1311 return -EINVAL;
1312 }
1313 rg->alloc = rg->map = 1;
1314 if ((r = alloc_fbmem(rg)) < 0)
1315 return r;
1316 }
1317 mtype = rg->type;
1318
1319 if (rg->paddr < mem_start[mtype])
1320 mem_start[mtype] = rg->paddr;
1321 if (rg->paddr + rg->size > mem_end[mtype])
1322 mem_end[mtype] = rg->paddr + rg->size;
1323 }
1324
1325 for (i = 0; i < DISPC_MEMTYPE_NUM; i++) {
1326 unsigned long start;
1327 size_t size;
1328 if (mem_end[i] == 0)
1329 continue;
1330 start = mem_start[i];
1331 size = mem_end[i] - start;
1332 dispc.res_map[i] = init_resmap(start, size);
1333 r = -ENOMEM;
1334 if (dispc.res_map[i] == NULL)
1335 goto fail;
1336 /* Initial state is that everything is reserved. This
1337 * includes possible holes as well, which will never be
1338 * freed.
1339 */
1340 resmap_reserve_region(start, size);
1341 }
1342
1343 dispc.mem_desc = *req_md;
1344
1345 return 0;
1346fail:
1347 for (i = 0; i < DISPC_MEMTYPE_NUM; i++) {
1348 if (dispc.res_map[i] != NULL)
1349 cleanup_resmap(dispc.res_map[i]);
1350 }
1351 return r;
1352}
1353
1354static void cleanup_fbmem(void)
1355{
1356 struct omapfb_mem_region *rg;
1357 int i;
1358
1359 for (i = 0; i < DISPC_MEMTYPE_NUM; i++) {
1360 if (dispc.res_map[i] != NULL)
1361 cleanup_resmap(dispc.res_map[i]);
1362 }
1363 rg = &dispc.mem_desc.region[0];
1364 for (i = 0; i < dispc.mem_desc.region_cnt; i++, rg++) {
1365 if (rg->alloc)
1366 free_fbmem(rg);
1367 else {
1368 if (rg->map)
1369 unmap_kern(rg);
1370 }
1371 }
1372}
1373
1374static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
1375 struct omapfb_mem_desc *req_vram)
1376{
1377 int r;
1378 u32 l;
1379 struct lcd_panel *panel = fbdev->panel;
1380 void __iomem *ram_fw_base;
1381 int tmo = 10000;
1382 int skip_init = 0;
1383 int i;
1384
1385 memset(&dispc, 0, sizeof(dispc));
1386
1387 dispc.base = ioremap(DISPC_BASE, SZ_1K);
1388 if (!dispc.base) {
1389 dev_err(fbdev->dev, "can't ioremap DISPC\n");
1390 return -ENOMEM;
1391 }
1392
1393 dispc.fbdev = fbdev;
1394 dispc.ext_mode = ext_mode;
1395
1396 init_completion(&dispc.frame_done);
1397
1398 if ((r = get_dss_clocks()) < 0)
1399 goto fail0;
1400
1401 enable_lcd_clocks(1);
1402
1403#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
1404 l = dispc_read_reg(DISPC_CONTROL);
1405 /* LCD enabled ? */
1406 if (l & 1) {
1407 pr_info("omapfb: skipping hardware initialization\n");
1408 skip_init = 1;
1409 }
1410#endif
1411
1412 if (!skip_init) {
1413 /* Reset monitoring works only w/ the 54M clk */
1414 enable_digit_clocks(1);
1415
1416 /* Soft reset */
1417 MOD_REG_FLD(DISPC_SYSCONFIG, 1 << 1, 1 << 1);
1418
1419 while (!(dispc_read_reg(DISPC_SYSSTATUS) & 1)) {
1420 if (!--tmo) {
1421 dev_err(dispc.fbdev->dev, "soft reset failed\n");
1422 r = -ENODEV;
1423 enable_digit_clocks(0);
1424 goto fail1;
1425 }
1426 }
1427
1428 enable_digit_clocks(0);
1429 }
1430
1431 /* Enable smart standby/idle, autoidle and wakeup */
1432 l = dispc_read_reg(DISPC_SYSCONFIG);
1433 l &= ~((3 << 12) | (3 << 3));
1434 l |= (2 << 12) | (2 << 3) | (1 << 2) | (1 << 0);
1435 dispc_write_reg(DISPC_SYSCONFIG, l);
1436 omap_writel(1 << 0, DSS_BASE + DSS_SYSCONFIG);
1437
1438 /* Set functional clock autogating */
1439 l = dispc_read_reg(DISPC_CONFIG);
1440 l |= 1 << 9;
1441 dispc_write_reg(DISPC_CONFIG, l);
1442
1443 l = dispc_read_reg(DISPC_IRQSTATUS);
1444 dispc_write_reg(DISPC_IRQSTATUS, l);
1445
1446 recalc_irq_mask();
1447
1448 if ((r = request_irq(INT_24XX_DSS_IRQ, omap_dispc_irq_handler,
1449 0, MODULE_NAME, fbdev)) < 0) {
1450 dev_err(dispc.fbdev->dev, "can't get DSS IRQ\n");
1451 goto fail1;
1452 }
1453
1454 /* L3 firewall setting: enable access to OCM RAM */
1455 ram_fw_base = ioremap(0x68005000, SZ_1K);
1456 if (!ram_fw_base) {
1457 dev_err(dispc.fbdev->dev, "Cannot ioremap to enable OCM RAM\n");
1458 goto fail1;
1459 }
1460 __raw_writel(0x402000b0, ram_fw_base + 0xa0);
1461 iounmap(ram_fw_base);
1462
1463 if ((r = alloc_palette_ram()) < 0)
1464 goto fail2;
1465
1466 if ((r = setup_fbmem(req_vram)) < 0)
1467 goto fail3;
1468
1469 if (!skip_init) {
1470 for (i = 0; i < dispc.mem_desc.region_cnt; i++) {
1471 memset(dispc.mem_desc.region[i].vaddr, 0,
1472 dispc.mem_desc.region[i].size);
1473 }
1474
1475 /* Set logic clock to fck, pixel clock to fck/2 for now */
1476 MOD_REG_FLD(DISPC_DIVISOR, FLD_MASK(16, 8), 1 << 16);
1477 MOD_REG_FLD(DISPC_DIVISOR, FLD_MASK(0, 8), 2 << 0);
1478
1479 setup_plane_fifo(0, ext_mode);
1480 setup_plane_fifo(1, ext_mode);
1481 setup_plane_fifo(2, ext_mode);
1482
1483 setup_color_conv_coef();
1484
1485 set_lcd_tft_mode(panel->config & OMAP_LCDC_PANEL_TFT);
1486 set_load_mode(DISPC_LOAD_FRAME_ONLY);
1487
1488 if (!ext_mode) {
1489 set_lcd_data_lines(panel->data_lines);
1490 omap_dispc_set_lcd_size(panel->x_res, panel->y_res);
1491 set_lcd_timings();
1492 } else
1493 set_lcd_data_lines(panel->bpp);
1494 enable_rfbi_mode(ext_mode);
1495 }
1496
1497 l = dispc_read_reg(DISPC_REVISION);
1498 pr_info("omapfb: DISPC version %d.%d initialized\n",
1499 l >> 4 & 0x0f, l & 0x0f);
1500 enable_lcd_clocks(0);
1501
1502 return 0;
1503fail3:
1504 free_palette_ram();
1505fail2:
1506 free_irq(INT_24XX_DSS_IRQ, fbdev);
1507fail1:
1508 enable_lcd_clocks(0);
1509 put_dss_clocks();
1510fail0:
1511 iounmap(dispc.base);
1512 return r;
1513}
1514
1515static void omap_dispc_cleanup(void)
1516{
1517 int i;
1518
1519 omap_dispc_set_update_mode(OMAPFB_UPDATE_DISABLED);
1520 /* This will also disable clocks that are on */
1521 for (i = 0; i < dispc.mem_desc.region_cnt; i++)
1522 omap_dispc_enable_plane(i, 0);
1523 cleanup_fbmem();
1524 free_palette_ram();
1525 free_irq(INT_24XX_DSS_IRQ, dispc.fbdev);
1526 put_dss_clocks();
1527 iounmap(dispc.base);
1528}
1529
1530const struct lcd_ctrl omap2_int_ctrl = {
1531 .name = "internal",
1532 .init = omap_dispc_init,
1533 .cleanup = omap_dispc_cleanup,
1534 .get_caps = omap_dispc_get_caps,
1535 .set_update_mode = omap_dispc_set_update_mode,
1536 .get_update_mode = omap_dispc_get_update_mode,
1537 .update_window = omap_dispc_update_window,
1538 .suspend = omap_dispc_suspend,
1539 .resume = omap_dispc_resume,
1540 .setup_plane = omap_dispc_setup_plane,
1541 .setup_mem = omap_dispc_setup_mem,
1542 .set_scale = omap_dispc_set_scale,
1543 .enable_plane = omap_dispc_enable_plane,
1544 .set_color_key = omap_dispc_set_color_key,
1545 .get_color_key = omap_dispc_get_color_key,
1546 .mmap = omap_dispc_mmap_user,
1547};
diff --git a/drivers/video/omap/dispc.h b/drivers/video/omap/dispc.h
deleted file mode 100644
index c15ea77f0604..000000000000
--- a/drivers/video/omap/dispc.h
+++ /dev/null
@@ -1,46 +0,0 @@
1#ifndef _DISPC_H
2#define _DISPC_H
3
4#include <linux/interrupt.h>
5
6#define DISPC_PLANE_GFX 0
7#define DISPC_PLANE_VID1 1
8#define DISPC_PLANE_VID2 2
9
10#define DISPC_RGB_1_BPP 0x00
11#define DISPC_RGB_2_BPP 0x01
12#define DISPC_RGB_4_BPP 0x02
13#define DISPC_RGB_8_BPP 0x03
14#define DISPC_RGB_12_BPP 0x04
15#define DISPC_RGB_16_BPP 0x06
16#define DISPC_RGB_24_BPP 0x08
17#define DISPC_RGB_24_BPP_UNPACK_32 0x09
18#define DISPC_YUV2_422 0x0a
19#define DISPC_UYVY_422 0x0b
20
21#define DISPC_BURST_4x32 0
22#define DISPC_BURST_8x32 1
23#define DISPC_BURST_16x32 2
24
25#define DISPC_LOAD_CLUT_AND_FRAME 0x00
26#define DISPC_LOAD_CLUT_ONLY 0x01
27#define DISPC_LOAD_FRAME_ONLY 0x02
28#define DISPC_LOAD_CLUT_ONCE_FRAME 0x03
29
30#define DISPC_TFT_DATA_LINES_12 0
31#define DISPC_TFT_DATA_LINES_16 1
32#define DISPC_TFT_DATA_LINES_18 2
33#define DISPC_TFT_DATA_LINES_24 3
34
35extern void omap_dispc_set_lcd_size(int width, int height);
36
37extern void omap_dispc_enable_lcd_out(int enable);
38extern void omap_dispc_enable_digit_out(int enable);
39
40extern int omap_dispc_request_irq(unsigned long irq_mask,
41 void (*callback)(void *data), void *data);
42extern void omap_dispc_free_irq(unsigned long irq_mask,
43 void (*callback)(void *data), void *data);
44
45extern const struct lcd_ctrl omap2_int_ctrl;
46#endif
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c
index 084aa0ac562b..9f1d23c319cb 100644
--- a/drivers/video/omap/hwa742.c
+++ b/drivers/video/omap/hwa742.c
@@ -28,7 +28,6 @@
28#include <linux/interrupt.h> 28#include <linux/interrupt.h>
29 29
30#include <plat/dma.h> 30#include <plat/dma.h>
31#include <plat/hwa742.h>
32#include "omapfb.h" 31#include "omapfb.h"
33 32
34#define HWA742_REV_CODE_REG 0x0 33#define HWA742_REV_CODE_REG 0x0
@@ -942,7 +941,6 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
942 unsigned long sys_clk, pix_clk; 941 unsigned long sys_clk, pix_clk;
943 int extif_mem_div; 942 int extif_mem_div;
944 struct omapfb_platform_data *omapfb_conf; 943 struct omapfb_platform_data *omapfb_conf;
945 struct hwa742_platform_data *ctrl_conf;
946 944
947 BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl); 945 BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl);
948 946
@@ -951,13 +949,6 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
951 hwa742.int_ctrl = fbdev->int_ctrl; 949 hwa742.int_ctrl = fbdev->int_ctrl;
952 950
953 omapfb_conf = fbdev->dev->platform_data; 951 omapfb_conf = fbdev->dev->platform_data;
954 ctrl_conf = omapfb_conf->ctrl_platform_data;
955
956 if (ctrl_conf == NULL) {
957 dev_err(fbdev->dev, "HWA742: missing platform data\n");
958 r = -ENOENT;
959 goto err1;
960 }
961 952
962 hwa742.sys_ck = clk_get(NULL, "hwa_sys_ck"); 953 hwa742.sys_ck = clk_get(NULL, "hwa_sys_ck");
963 954
@@ -995,14 +986,12 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
995 goto err4; 986 goto err4;
996 } 987 }
997 988
998 if (ctrl_conf->te_connected) { 989 if ((r = setup_tearsync(pix_clk, extif_mem_div)) < 0) {
999 if ((r = setup_tearsync(pix_clk, extif_mem_div)) < 0) { 990 dev_err(hwa742.fbdev->dev,
1000 dev_err(hwa742.fbdev->dev, 991 "HWA742: can't setup tearing synchronization\n");
1001 "HWA742: can't setup tearing synchronization\n"); 992 goto err4;
1002 goto err4;
1003 }
1004 hwa742.te_connected = 1;
1005 } 993 }
994 hwa742.te_connected = 1;
1006 995
1007 hwa742.max_transmit_size = hwa742.extif->max_transmit_size; 996 hwa742.max_transmit_size = hwa742.extif->max_transmit_size;
1008 997
diff --git a/drivers/video/omap/omapfb.h b/drivers/video/omap/omapfb.h
index af3c9e571ec3..2921d20e4fba 100644
--- a/drivers/video/omap/omapfb.h
+++ b/drivers/video/omap/omapfb.h
@@ -47,6 +47,27 @@
47 47
48struct omapfb_device; 48struct omapfb_device;
49 49
50#define OMAPFB_PLANE_NUM 1
51
52struct omapfb_mem_region {
53 u32 paddr;
54 void __iomem *vaddr;
55 unsigned long size;
56 u8 type; /* OMAPFB_PLANE_MEM_* */
57 enum omapfb_color_format format;/* OMAPFB_COLOR_* */
58 unsigned format_used:1; /* Must be set when format is set.
59 * Needed b/c of the badly chosen 0
60 * base for OMAPFB_COLOR_* values
61 */
62 unsigned alloc:1; /* allocated by the driver */
63 unsigned map:1; /* kernel mapped by the driver */
64};
65
66struct omapfb_mem_desc {
67 int region_cnt;
68 struct omapfb_mem_region region[OMAPFB_PLANE_NUM];
69};
70
50struct lcd_panel { 71struct lcd_panel {
51 const char *name; 72 const char *name;
52 int config; /* TFT/STN, signal inversion */ 73 int config; /* TFT/STN, signal inversion */
@@ -207,11 +228,7 @@ struct omapfb_device {
207 struct platform_device *dssdev; /* dummy dev for clocks */ 228 struct platform_device *dssdev; /* dummy dev for clocks */
208}; 229};
209 230
210#ifdef CONFIG_ARCH_OMAP1
211extern struct lcd_ctrl omap1_lcd_ctrl; 231extern struct lcd_ctrl omap1_lcd_ctrl;
212#else
213extern struct lcd_ctrl omap2_disp_ctrl;
214#endif
215 232
216extern void omapfb_register_panel(struct lcd_panel *panel); 233extern void omapfb_register_panel(struct lcd_panel *panel);
217extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval); 234extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index b291bfaac80e..f54b463709e9 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -34,7 +34,6 @@
34 34
35#include "omapfb.h" 35#include "omapfb.h"
36#include "lcdc.h" 36#include "lcdc.h"
37#include "dispc.h"
38 37
39#define MODULE_NAME "omapfb" 38#define MODULE_NAME "omapfb"
40 39
@@ -104,29 +103,17 @@ static struct platform_device omapdss_device = {
104 * --------------------------------------------------------------------------- 103 * ---------------------------------------------------------------------------
105 */ 104 */
106extern struct lcd_ctrl hwa742_ctrl; 105extern struct lcd_ctrl hwa742_ctrl;
107extern struct lcd_ctrl blizzard_ctrl;
108 106
109static const struct lcd_ctrl *ctrls[] = { 107static const struct lcd_ctrl *ctrls[] = {
110#ifdef CONFIG_ARCH_OMAP1
111 &omap1_int_ctrl, 108 &omap1_int_ctrl,
112#else
113 &omap2_int_ctrl,
114#endif
115 109
116#ifdef CONFIG_FB_OMAP_LCDC_HWA742 110#ifdef CONFIG_FB_OMAP_LCDC_HWA742
117 &hwa742_ctrl, 111 &hwa742_ctrl,
118#endif 112#endif
119#ifdef CONFIG_FB_OMAP_LCDC_BLIZZARD
120 &blizzard_ctrl,
121#endif
122}; 113};
123 114
124#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL 115#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
125#ifdef CONFIG_ARCH_OMAP1
126extern struct lcd_ctrl_extif omap1_ext_if; 116extern struct lcd_ctrl_extif omap1_ext_if;
127#else
128extern struct lcd_ctrl_extif omap2_ext_if;
129#endif
130#endif 117#endif
131 118
132static void omapfb_rqueue_lock(struct omapfb_device *fbdev) 119static void omapfb_rqueue_lock(struct omapfb_device *fbdev)
@@ -170,11 +157,6 @@ static int ctrl_init(struct omapfb_device *fbdev)
170 fbdev->mem_desc.region[i].size = 157 fbdev->mem_desc.region[i].size =
171 PAGE_ALIGN(def_vram[i]); 158 PAGE_ALIGN(def_vram[i]);
172 fbdev->mem_desc.region_cnt = i; 159 fbdev->mem_desc.region_cnt = i;
173 } else {
174 struct omapfb_platform_data *conf;
175
176 conf = fbdev->dev->platform_data;
177 fbdev->mem_desc = conf->mem_desc;
178 } 160 }
179 161
180 if (!fbdev->mem_desc.region_cnt) { 162 if (!fbdev->mem_desc.region_cnt) {
@@ -880,7 +862,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
880 862
881 if (fbdev->ctrl->setup_mem == NULL) 863 if (fbdev->ctrl->setup_mem == NULL)
882 return -ENODEV; 864 return -ENODEV;
883 if (mi->type > OMAPFB_MEMTYPE_MAX) 865 if (mi->type != OMAPFB_MEMTYPE_SDRAM)
884 return -EINVAL; 866 return -EINVAL;
885 867
886 size = PAGE_ALIGN(mi->size); 868 size = PAGE_ALIGN(mi->size);
@@ -1721,17 +1703,10 @@ static int omapfb_do_probe(struct platform_device *pdev,
1721 1703
1722 mutex_init(&fbdev->rqueue_mutex); 1704 mutex_init(&fbdev->rqueue_mutex);
1723 1705
1724#ifdef CONFIG_ARCH_OMAP1
1725 fbdev->int_ctrl = &omap1_int_ctrl; 1706 fbdev->int_ctrl = &omap1_int_ctrl;
1726#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL 1707#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
1727 fbdev->ext_if = &omap1_ext_if; 1708 fbdev->ext_if = &omap1_ext_if;
1728#endif 1709#endif
1729#else /* OMAP2 */
1730 fbdev->int_ctrl = &omap2_int_ctrl;
1731#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
1732 fbdev->ext_if = &omap2_ext_if;
1733#endif
1734#endif
1735 if (omapfb_find_ctrl(fbdev) < 0) { 1710 if (omapfb_find_ctrl(fbdev) < 0) {
1736 dev_err(fbdev->dev, 1711 dev_err(fbdev->dev,
1737 "LCD controller not found, board not supported\n"); 1712 "LCD controller not found, board not supported\n");
@@ -1766,8 +1741,7 @@ static int omapfb_do_probe(struct platform_device *pdev,
1766 1741
1767#ifdef CONFIG_FB_OMAP_DMA_TUNE 1742#ifdef CONFIG_FB_OMAP_DMA_TUNE
1768 /* Set DMA priority for EMIFF access to highest */ 1743 /* Set DMA priority for EMIFF access to highest */
1769 if (cpu_class_is_omap1()) 1744 omap_set_dma_priority(0, OMAP_DMA_PORT_EMIFF, 15);
1770 omap_set_dma_priority(0, OMAP_DMA_PORT_EMIFF, 15);
1771#endif 1745#endif
1772 1746
1773 r = ctrl_change_mode(fbdev->fb_info[0]); 1747 r = ctrl_change_mode(fbdev->fb_info[0]);
diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c
deleted file mode 100644
index 2c1a3402bef0..000000000000
--- a/drivers/video/omap/rfbi.c
+++ /dev/null
@@ -1,598 +0,0 @@
1/*
2 * OMAP2 Remote Frame Buffer Interface support
3 *
4 * Copyright (C) 2005 Nokia Corporation
5 * Author: Juha Yrjölä <juha.yrjola@nokia.com>
6 * Imre Deak <imre.deak@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22#include <linux/module.h>
23#include <linux/delay.h>
24#include <linux/i2c.h>
25#include <linux/err.h>
26#include <linux/interrupt.h>
27#include <linux/clk.h>
28#include <linux/io.h>
29#include <linux/platform_device.h>
30
31#include "omapfb.h"
32#include "dispc.h"
33
34/* To work around an RFBI transfer rate limitation */
35#define OMAP_RFBI_RATE_LIMIT 1
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#define DISPC_IRQ_FRAMEMASK 0x0001
61
62static struct {
63 void __iomem *base;
64 void (*lcdc_callback)(void *data);
65 void *lcdc_callback_data;
66 unsigned long l4_khz;
67 int bits_per_cycle;
68 struct omapfb_device *fbdev;
69 struct clk *dss_ick;
70 struct clk *dss1_fck;
71 unsigned tearsync_pin_cnt;
72 unsigned tearsync_mode;
73} rfbi;
74
75static inline void rfbi_write_reg(int idx, u32 val)
76{
77 __raw_writel(val, rfbi.base + idx);
78}
79
80static inline u32 rfbi_read_reg(int idx)
81{
82 return __raw_readl(rfbi.base + idx);
83}
84
85static int rfbi_get_clocks(void)
86{
87 rfbi.dss_ick = clk_get(&rfbi.fbdev->dssdev->dev, "ick");
88 if (IS_ERR(rfbi.dss_ick)) {
89 dev_err(rfbi.fbdev->dev, "can't get ick\n");
90 return PTR_ERR(rfbi.dss_ick);
91 }
92
93 rfbi.dss1_fck = clk_get(&rfbi.fbdev->dssdev->dev, "fck");
94 if (IS_ERR(rfbi.dss1_fck)) {
95 dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n");
96 clk_put(rfbi.dss_ick);
97 return PTR_ERR(rfbi.dss1_fck);
98 }
99
100 return 0;
101}
102
103static void rfbi_put_clocks(void)
104{
105 clk_put(rfbi.dss1_fck);
106 clk_put(rfbi.dss_ick);
107}
108
109static void rfbi_enable_clocks(int enable)
110{
111 if (enable) {
112 clk_enable(rfbi.dss_ick);
113 clk_enable(rfbi.dss1_fck);
114 } else {
115 clk_disable(rfbi.dss1_fck);
116 clk_disable(rfbi.dss_ick);
117 }
118}
119
120
121#ifdef VERBOSE
122static void rfbi_print_timings(void)
123{
124 u32 l;
125 u32 time;
126
127 l = rfbi_read_reg(RFBI_CONFIG0);
128 time = 1000000000 / rfbi.l4_khz;
129 if (l & (1 << 4))
130 time *= 2;
131
132 dev_dbg(rfbi.fbdev->dev, "Tick time %u ps\n", time);
133 l = rfbi_read_reg(RFBI_ONOFF_TIME0);
134 dev_dbg(rfbi.fbdev->dev,
135 "CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
136 "REONTIME %d, REOFFTIME %d\n",
137 l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
138 (l >> 20) & 0x0f, (l >> 24) & 0x3f);
139
140 l = rfbi_read_reg(RFBI_CYCLE_TIME0);
141 dev_dbg(rfbi.fbdev->dev,
142 "WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
143 "ACCESSTIME %d\n",
144 (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f,
145 (l >> 22) & 0x3f);
146}
147#else
148static void rfbi_print_timings(void) {}
149#endif
150
151static void rfbi_set_timings(const struct extif_timings *t)
152{
153 u32 l;
154
155 BUG_ON(!t->converted);
156
157 rfbi_enable_clocks(1);
158 rfbi_write_reg(RFBI_ONOFF_TIME0, t->tim[0]);
159 rfbi_write_reg(RFBI_CYCLE_TIME0, t->tim[1]);
160
161 l = rfbi_read_reg(RFBI_CONFIG0);
162 l &= ~(1 << 4);
163 l |= (t->tim[2] ? 1 : 0) << 4;
164 rfbi_write_reg(RFBI_CONFIG0, l);
165
166 rfbi_print_timings();
167 rfbi_enable_clocks(0);
168}
169
170static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
171{
172 *clk_period = 1000000000 / rfbi.l4_khz;
173 *max_clk_div = 2;
174}
175
176static int ps_to_rfbi_ticks(int time, int div)
177{
178 unsigned long tick_ps;
179 int ret;
180
181 /* Calculate in picosecs to yield more exact results */
182 tick_ps = 1000000000 / (rfbi.l4_khz) * div;
183
184 ret = (time + tick_ps - 1) / tick_ps;
185
186 return ret;
187}
188
189#ifdef OMAP_RFBI_RATE_LIMIT
190static unsigned long rfbi_get_max_tx_rate(void)
191{
192 unsigned long l4_rate, dss1_rate;
193 int min_l4_ticks = 0;
194 int i;
195
196 /* According to TI this can't be calculated so make the
197 * adjustments for a couple of known frequencies and warn for
198 * others.
199 */
200 static const struct {
201 unsigned long l4_clk; /* HZ */
202 unsigned long dss1_clk; /* HZ */
203 unsigned long min_l4_ticks;
204 } ftab[] = {
205 { 55, 132, 7, }, /* 7.86 MPix/s */
206 { 110, 110, 12, }, /* 9.16 MPix/s */
207 { 110, 132, 10, }, /* 11 Mpix/s */
208 { 120, 120, 10, }, /* 12 Mpix/s */
209 { 133, 133, 10, }, /* 13.3 Mpix/s */
210 };
211
212 l4_rate = rfbi.l4_khz / 1000;
213 dss1_rate = clk_get_rate(rfbi.dss1_fck) / 1000000;
214
215 for (i = 0; i < ARRAY_SIZE(ftab); i++) {
216 /* Use a window instead of an exact match, to account
217 * for different DPLL multiplier / divider pairs.
218 */
219 if (abs(ftab[i].l4_clk - l4_rate) < 3 &&
220 abs(ftab[i].dss1_clk - dss1_rate) < 3) {
221 min_l4_ticks = ftab[i].min_l4_ticks;
222 break;
223 }
224 }
225 if (i == ARRAY_SIZE(ftab)) {
226 /* Can't be sure, return anyway the maximum not
227 * rate-limited. This might cause a problem only for the
228 * tearing synchronisation.
229 */
230 dev_err(rfbi.fbdev->dev,
231 "can't determine maximum RFBI transfer rate\n");
232 return rfbi.l4_khz * 1000;
233 }
234 return rfbi.l4_khz * 1000 / min_l4_ticks;
235}
236#else
237static int rfbi_get_max_tx_rate(void)
238{
239 return rfbi.l4_khz * 1000;
240}
241#endif
242
243
244static int rfbi_convert_timings(struct extif_timings *t)
245{
246 u32 l;
247 int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
248 int actim, recyc, wecyc;
249 int div = t->clk_div;
250
251 if (div <= 0 || div > 2)
252 return -1;
253
254 /* Make sure that after conversion it still holds that:
255 * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff,
256 * csoff > cson, csoff >= max(weoff, reoff), actim > reon
257 */
258 weon = ps_to_rfbi_ticks(t->we_on_time, div);
259 weoff = ps_to_rfbi_ticks(t->we_off_time, div);
260 if (weoff <= weon)
261 weoff = weon + 1;
262 if (weon > 0x0f)
263 return -1;
264 if (weoff > 0x3f)
265 return -1;
266
267 reon = ps_to_rfbi_ticks(t->re_on_time, div);
268 reoff = ps_to_rfbi_ticks(t->re_off_time, div);
269 if (reoff <= reon)
270 reoff = reon + 1;
271 if (reon > 0x0f)
272 return -1;
273 if (reoff > 0x3f)
274 return -1;
275
276 cson = ps_to_rfbi_ticks(t->cs_on_time, div);
277 csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
278 if (csoff <= cson)
279 csoff = cson + 1;
280 if (csoff < max(weoff, reoff))
281 csoff = max(weoff, reoff);
282 if (cson > 0x0f)
283 return -1;
284 if (csoff > 0x3f)
285 return -1;
286
287 l = cson;
288 l |= csoff << 4;
289 l |= weon << 10;
290 l |= weoff << 14;
291 l |= reon << 20;
292 l |= reoff << 24;
293
294 t->tim[0] = l;
295
296 actim = ps_to_rfbi_ticks(t->access_time, div);
297 if (actim <= reon)
298 actim = reon + 1;
299 if (actim > 0x3f)
300 return -1;
301
302 wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
303 if (wecyc < weoff)
304 wecyc = weoff;
305 if (wecyc > 0x3f)
306 return -1;
307
308 recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
309 if (recyc < reoff)
310 recyc = reoff;
311 if (recyc > 0x3f)
312 return -1;
313
314 cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
315 if (cs_pulse > 0x3f)
316 return -1;
317
318 l = wecyc;
319 l |= recyc << 6;
320 l |= cs_pulse << 12;
321 l |= actim << 22;
322
323 t->tim[1] = l;
324
325 t->tim[2] = div - 1;
326
327 t->converted = 1;
328
329 return 0;
330}
331
332static int rfbi_setup_tearsync(unsigned pin_cnt,
333 unsigned hs_pulse_time, unsigned vs_pulse_time,
334 int hs_pol_inv, int vs_pol_inv, int extif_div)
335{
336 int hs, vs;
337 int min;
338 u32 l;
339
340 if (pin_cnt != 1 && pin_cnt != 2)
341 return -EINVAL;
342
343 hs = ps_to_rfbi_ticks(hs_pulse_time, 1);
344 vs = ps_to_rfbi_ticks(vs_pulse_time, 1);
345 if (hs < 2)
346 return -EDOM;
347 if (pin_cnt == 2)
348 min = 2;
349 else
350 min = 4;
351 if (vs < min)
352 return -EDOM;
353 if (vs == hs)
354 return -EINVAL;
355 rfbi.tearsync_pin_cnt = pin_cnt;
356 dev_dbg(rfbi.fbdev->dev,
357 "setup_tearsync: pins %d hs %d vs %d hs_inv %d vs_inv %d\n",
358 pin_cnt, hs, vs, hs_pol_inv, vs_pol_inv);
359
360 rfbi_enable_clocks(1);
361 rfbi_write_reg(RFBI_HSYNC_WIDTH, hs);
362 rfbi_write_reg(RFBI_VSYNC_WIDTH, vs);
363
364 l = rfbi_read_reg(RFBI_CONFIG0);
365 if (hs_pol_inv)
366 l &= ~(1 << 21);
367 else
368 l |= 1 << 21;
369 if (vs_pol_inv)
370 l &= ~(1 << 20);
371 else
372 l |= 1 << 20;
373 rfbi_enable_clocks(0);
374
375 return 0;
376}
377
378static int rfbi_enable_tearsync(int enable, unsigned line)
379{
380 u32 l;
381
382 dev_dbg(rfbi.fbdev->dev, "tearsync %d line %d mode %d\n",
383 enable, line, rfbi.tearsync_mode);
384 if (line > (1 << 11) - 1)
385 return -EINVAL;
386
387 rfbi_enable_clocks(1);
388 l = rfbi_read_reg(RFBI_CONFIG0);
389 l &= ~(0x3 << 2);
390 if (enable) {
391 rfbi.tearsync_mode = rfbi.tearsync_pin_cnt;
392 l |= rfbi.tearsync_mode << 2;
393 } else
394 rfbi.tearsync_mode = 0;
395 rfbi_write_reg(RFBI_CONFIG0, l);
396 rfbi_write_reg(RFBI_LINE_NUMBER, line);
397 rfbi_enable_clocks(0);
398
399 return 0;
400}
401
402static void rfbi_write_command(const void *buf, unsigned int len)
403{
404 rfbi_enable_clocks(1);
405 if (rfbi.bits_per_cycle == 16) {
406 const u16 *w = buf;
407 BUG_ON(len & 1);
408 for (; len; len -= 2)
409 rfbi_write_reg(RFBI_CMD, *w++);
410 } else {
411 const u8 *b = buf;
412 BUG_ON(rfbi.bits_per_cycle != 8);
413 for (; len; len--)
414 rfbi_write_reg(RFBI_CMD, *b++);
415 }
416 rfbi_enable_clocks(0);
417}
418
419static void rfbi_read_data(void *buf, unsigned int len)
420{
421 rfbi_enable_clocks(1);
422 if (rfbi.bits_per_cycle == 16) {
423 u16 *w = buf;
424 BUG_ON(len & ~1);
425 for (; len; len -= 2) {
426 rfbi_write_reg(RFBI_READ, 0);
427 *w++ = rfbi_read_reg(RFBI_READ);
428 }
429 } else {
430 u8 *b = buf;
431 BUG_ON(rfbi.bits_per_cycle != 8);
432 for (; len; len--) {
433 rfbi_write_reg(RFBI_READ, 0);
434 *b++ = rfbi_read_reg(RFBI_READ);
435 }
436 }
437 rfbi_enable_clocks(0);
438}
439
440static void rfbi_write_data(const void *buf, unsigned int len)
441{
442 rfbi_enable_clocks(1);
443 if (rfbi.bits_per_cycle == 16) {
444 const u16 *w = buf;
445 BUG_ON(len & 1);
446 for (; len; len -= 2)
447 rfbi_write_reg(RFBI_PARAM, *w++);
448 } else {
449 const u8 *b = buf;
450 BUG_ON(rfbi.bits_per_cycle != 8);
451 for (; len; len--)
452 rfbi_write_reg(RFBI_PARAM, *b++);
453 }
454 rfbi_enable_clocks(0);
455}
456
457static void rfbi_transfer_area(int width, int height,
458 void (callback)(void * data), void *data)
459{
460 u32 w;
461
462 BUG_ON(callback == NULL);
463
464 rfbi_enable_clocks(1);
465 omap_dispc_set_lcd_size(width, height);
466
467 rfbi.lcdc_callback = callback;
468 rfbi.lcdc_callback_data = data;
469
470 rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
471
472 w = rfbi_read_reg(RFBI_CONTROL);
473 w |= 1; /* enable */
474 if (!rfbi.tearsync_mode)
475 w |= 1 << 4; /* internal trigger, reset by HW */
476 rfbi_write_reg(RFBI_CONTROL, w);
477
478 omap_dispc_enable_lcd_out(1);
479}
480
481static inline void _stop_transfer(void)
482{
483 u32 w;
484
485 w = rfbi_read_reg(RFBI_CONTROL);
486 rfbi_write_reg(RFBI_CONTROL, w & ~(1 << 0));
487 rfbi_enable_clocks(0);
488}
489
490static void rfbi_dma_callback(void *data)
491{
492 _stop_transfer();
493 rfbi.lcdc_callback(rfbi.lcdc_callback_data);
494}
495
496static void rfbi_set_bits_per_cycle(int bpc)
497{
498 u32 l;
499
500 rfbi_enable_clocks(1);
501 l = rfbi_read_reg(RFBI_CONFIG0);
502 l &= ~(0x03 << 0);
503
504 switch (bpc) {
505 case 8:
506 break;
507 case 16:
508 l |= 3;
509 break;
510 default:
511 BUG();
512 }
513 rfbi_write_reg(RFBI_CONFIG0, l);
514 rfbi.bits_per_cycle = bpc;
515 rfbi_enable_clocks(0);
516}
517
518static int rfbi_init(struct omapfb_device *fbdev)
519{
520 u32 l;
521 int r;
522
523 rfbi.fbdev = fbdev;
524 rfbi.base = ioremap(RFBI_BASE, SZ_1K);
525 if (!rfbi.base) {
526 dev_err(fbdev->dev, "can't ioremap RFBI\n");
527 return -ENOMEM;
528 }
529
530 if ((r = rfbi_get_clocks()) < 0)
531 return r;
532 rfbi_enable_clocks(1);
533
534 rfbi.l4_khz = clk_get_rate(rfbi.dss_ick) / 1000;
535
536 /* Reset */
537 rfbi_write_reg(RFBI_SYSCONFIG, 1 << 1);
538 while (!(rfbi_read_reg(RFBI_SYSSTATUS) & (1 << 0)));
539
540 l = rfbi_read_reg(RFBI_SYSCONFIG);
541 /* Enable autoidle and smart-idle */
542 l |= (1 << 0) | (2 << 3);
543 rfbi_write_reg(RFBI_SYSCONFIG, l);
544
545 /* 16-bit interface, ITE trigger mode, 16-bit data */
546 l = (0x03 << 0) | (0x00 << 2) | (0x01 << 5) | (0x02 << 7);
547 l |= (0 << 9) | (1 << 20) | (1 << 21);
548 rfbi_write_reg(RFBI_CONFIG0, l);
549
550 rfbi_write_reg(RFBI_DATA_CYCLE1_0, 0x00000010);
551
552 l = rfbi_read_reg(RFBI_CONTROL);
553 /* Select CS0, clear bypass mode */
554 l = (0x01 << 2);
555 rfbi_write_reg(RFBI_CONTROL, l);
556
557 r = omap_dispc_request_irq(DISPC_IRQ_FRAMEMASK, rfbi_dma_callback,
558 NULL);
559 if (r < 0) {
560 dev_err(fbdev->dev, "can't get DISPC irq\n");
561 rfbi_enable_clocks(0);
562 return r;
563 }
564
565 l = rfbi_read_reg(RFBI_REVISION);
566 pr_info("omapfb: RFBI version %d.%d initialized\n",
567 (l >> 4) & 0x0f, l & 0x0f);
568
569 rfbi_enable_clocks(0);
570
571 return 0;
572}
573
574static void rfbi_cleanup(void)
575{
576 omap_dispc_free_irq(DISPC_IRQ_FRAMEMASK, rfbi_dma_callback, NULL);
577 rfbi_put_clocks();
578 iounmap(rfbi.base);
579}
580
581const struct lcd_ctrl_extif omap2_ext_if = {
582 .init = rfbi_init,
583 .cleanup = rfbi_cleanup,
584 .get_clk_info = rfbi_get_clk_info,
585 .get_max_tx_rate = rfbi_get_max_tx_rate,
586 .set_bits_per_cycle = rfbi_set_bits_per_cycle,
587 .convert_timings = rfbi_convert_timings,
588 .set_timings = rfbi_set_timings,
589 .write_command = rfbi_write_command,
590 .read_data = rfbi_read_data,
591 .write_data = rfbi_write_data,
592 .transfer_area = rfbi_transfer_area,
593 .setup_tearsync = rfbi_setup_tearsync,
594 .enable_tearsync = rfbi_enable_tearsync,
595
596 .max_transmit_size = (u32) ~0,
597};
598