diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2011-05-10 10:31:20 -0400 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2012-02-22 03:55:29 -0500 |
commit | fdcb68884b3b0def9cc410d07adbafe7c3a9e537 (patch) | |
tree | 364679efdf0e1d2ace211422e91bbaf0a1dcad0d /drivers/video | |
parent | b01543dfe67bb1d191998e90d20534dc354de059 (diff) |
OMAPFB: remove old blizzard driver
N8x0's blizzard driver has been ported to new omapdss driver, so we can
now remove the old blizzard driver.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/omap/Kconfig | 7 | ||||
-rw-r--r-- | drivers/video/omap/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/omap/blizzard.c | 1648 | ||||
-rw-r--r-- | drivers/video/omap/omapfb_main.c | 4 |
4 files changed, 0 insertions, 1660 deletions
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index 84ff23208c25..ab234d597110 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig | |||
@@ -23,13 +23,6 @@ config FB_OMAP_LCDC_HWA742 | |||
23 | Say Y here if you want to have support for the external | 23 | Say Y here if you want to have support for the external |
24 | Epson HWA742 LCD controller. | 24 | Epson HWA742 LCD controller. |
25 | 25 | ||
26 | config 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 | |||
33 | config FB_OMAP_MANUAL_UPDATE | 26 | config FB_OMAP_MANUAL_UPDATE |
34 | bool "Default to manual update mode" | 27 | bool "Default to manual update mode" |
35 | depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL | 28 | depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL |
diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile index ef78550917ff..7042a4ac7072 100644 --- a/drivers/video/omap/Makefile +++ b/drivers/video/omap/Makefile | |||
@@ -14,7 +14,6 @@ objs-$(CONFIG_ARCH_OMAP1)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += sossi.o | |||
14 | objs-$(CONFIG_ARCH_OMAP2)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += rfbi.o | 14 | objs-$(CONFIG_ARCH_OMAP2)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += rfbi.o |
15 | 15 | ||
16 | objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o | 16 | objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o |
17 | objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o | ||
18 | 17 | ||
19 | objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o | 18 | objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o |
20 | objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o | 19 | objs-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 | |||
90 | struct blizzard_reg_list { | ||
91 | int start; | ||
92 | int end; | ||
93 | }; | ||
94 | |||
95 | /* These need to be saved / restored separately from the rest. */ | ||
96 | static 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 | |||
107 | static 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 | |||
118 | static u8 blizzard_reg_cache[0x5a / 2]; | ||
119 | |||
120 | struct 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 | |||
130 | struct 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 | |||
144 | struct 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 | |||
154 | struct 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 | |||
202 | struct lcd_ctrl blizzard_ctrl; | ||
203 | |||
204 | static u8 blizzard_read_reg(u8 reg) | ||
205 | { | ||
206 | u8 data; | ||
207 | |||
208 | blizzard.extif->set_bits_per_cycle(8); | ||
209 | blizzard.extif->write_command(®, 1); | ||
210 | blizzard.extif->read_data(&data, 1); | ||
211 | |||
212 | return data; | ||
213 | } | ||
214 | |||
215 | static void blizzard_write_reg(u8 reg, u8 val) | ||
216 | { | ||
217 | blizzard.extif->set_bits_per_cycle(8); | ||
218 | blizzard.extif->write_command(®, 1); | ||
219 | blizzard.extif->write_data(&val, 1); | ||
220 | } | ||
221 | |||
222 | static 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 | |||
240 | static 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 | */ | ||
248 | static 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. */ | ||
263 | static 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 | |||
277 | static void disable_overlay(void) | ||
278 | { | ||
279 | blizzard_write_reg(BLIZZARD_DATA_SOURCE_SELECT, | ||
280 | BLIZZARD_SRC_DISABLE_OVERLAY); | ||
281 | } | ||
282 | |||
283 | static 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 | |||
329 | static 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 | |||
357 | static 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 | |||
368 | static inline void set_extif_timings(const struct extif_timings *t); | ||
369 | |||
370 | static 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 | |||
394 | static 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 | |||
407 | static 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 | |||
438 | static 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 | |||
453 | static 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 | |||
471 | static 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 | |||
520 | static 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. */ | ||
528 | static 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 | |||
717 | static 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 | |||
745 | static 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 | |||
768 | static 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 | |||
822 | static 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 | |||
829 | static 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 | |||
846 | int 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 | } | ||
871 | EXPORT_SYMBOL(blizzard_update_window_async); | ||
872 | |||
873 | static 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 | |||
880 | static 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 | |||
932 | static 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 | |||
960 | static 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 | |||
989 | static 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 | |||
999 | static int sync_handler(struct blizzard_request *req) | ||
1000 | { | ||
1001 | complete(req->par.sync); | ||
1002 | return REQ_COMPLETE; | ||
1003 | } | ||
1004 | |||
1005 | static 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 = ∁ | ||
1017 | |||
1018 | list_add(&req->entry, &req_list); | ||
1019 | submit_req_list(&req_list); | ||
1020 | |||
1021 | wait_for_completion(&comp); | ||
1022 | } | ||
1023 | |||
1024 | |||
1025 | static 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 | |||
1032 | static 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 | |||
1076 | static enum omapfb_update_mode blizzard_get_update_mode(void) | ||
1077 | { | ||
1078 | return blizzard.update_mode; | ||
1079 | } | ||
1080 | |||
1081 | static inline void set_extif_timings(const struct extif_timings *t) | ||
1082 | { | ||
1083 | blizzard.extif->set_timings(t); | ||
1084 | } | ||
1085 | |||
1086 | static 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 | |||
1092 | static 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 | |||
1142 | static 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 | |||
1196 | static 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; | ||
1223 | err: | ||
1224 | dev_err(blizzard.fbdev->dev, "can't setup timings\n"); | ||
1225 | return -1; | ||
1226 | } | ||
1227 | |||
1228 | static 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 | |||
1255 | static 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 | |||
1360 | static 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 | |||
1374 | static 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 | |||
1385 | static 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 | |||
1396 | static 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 | |||
1402 | static void blizzard_restore_pll_regs(void) | ||
1403 | { | ||
1404 | _restore_regs(blizzard_pll_regs, ARRAY_SIZE(blizzard_pll_regs)); | ||
1405 | } | ||
1406 | |||
1407 | static void blizzard_restore_gen_regs(void) | ||
1408 | { | ||
1409 | _restore_regs(blizzard_gen_regs, ARRAY_SIZE(blizzard_gen_regs)); | ||
1410 | } | ||
1411 | |||
1412 | static 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 | |||
1453 | static 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 | |||
1491 | static 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; | ||
1612 | err3: | ||
1613 | if (blizzard.power_down != NULL) | ||
1614 | blizzard.power_down(fbdev->dev); | ||
1615 | blizzard.extif->cleanup(); | ||
1616 | err2: | ||
1617 | blizzard.int_ctrl->cleanup(); | ||
1618 | err1: | ||
1619 | return r; | ||
1620 | } | ||
1621 | |||
1622 | static 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 | |||
1631 | struct 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/omapfb_main.c b/drivers/video/omap/omapfb_main.c index b291bfaac80e..440a5dd06654 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c | |||
@@ -104,7 +104,6 @@ static struct platform_device omapdss_device = { | |||
104 | * --------------------------------------------------------------------------- | 104 | * --------------------------------------------------------------------------- |
105 | */ | 105 | */ |
106 | extern struct lcd_ctrl hwa742_ctrl; | 106 | extern struct lcd_ctrl hwa742_ctrl; |
107 | extern struct lcd_ctrl blizzard_ctrl; | ||
108 | 107 | ||
109 | static const struct lcd_ctrl *ctrls[] = { | 108 | static const struct lcd_ctrl *ctrls[] = { |
110 | #ifdef CONFIG_ARCH_OMAP1 | 109 | #ifdef CONFIG_ARCH_OMAP1 |
@@ -116,9 +115,6 @@ static const struct lcd_ctrl *ctrls[] = { | |||
116 | #ifdef CONFIG_FB_OMAP_LCDC_HWA742 | 115 | #ifdef CONFIG_FB_OMAP_LCDC_HWA742 |
117 | &hwa742_ctrl, | 116 | &hwa742_ctrl, |
118 | #endif | 117 | #endif |
119 | #ifdef CONFIG_FB_OMAP_LCDC_BLIZZARD | ||
120 | &blizzard_ctrl, | ||
121 | #endif | ||
122 | }; | 118 | }; |
123 | 119 | ||
124 | #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL | 120 | #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL |