]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/video/omap/hwa742.c
ARM: OMAP: A whopping FB driver update
[linux-2.6-omap-h63xx.git] / drivers / video / omap / hwa742.c
1 /*
2  * File: drivers/video/omap/hwa742.c
3  *
4  * Epson HWA742 LCD controller driver
5  *
6  * Copyright (C) 2004-2005 Nokia Corporation
7  * Authors:     Juha Yrjölä   <juha.yrjola@nokia.com>
8  *              Imre Deak     <imre.deak@nokia.com>
9  * YUV support: Jussi Laako   <jussi.laako@nokia.com>
10  *
11  * This program is free software; you can redistribute it and/or modify it
12  * under the terms of the GNU General Public License as published by the
13  * Free Software Foundation; either version 2 of the License, or (at your
14  * option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25 #include <linux/config.h>
26 #include <linux/module.h>
27 #include <linux/mm.h>
28 #include <linux/fb.h>
29 #include <linux/delay.h>
30 #include <linux/clk.h>
31
32 #include <asm/arch/dma.h>
33 #include <asm/arch/omapfb.h>
34
35 /* #define OMAPFB_DBG 1 */
36
37 #include "hwa742.h"
38 #include "debug.h"
39
40 #define MODULE_NAME                     "omapfb-hwa742"
41
42 #define HWA742_REV_CODE_REG       0x0
43 #define HWA742_CONFIG_REG         0x2
44 #define HWA742_PLL_DIV_REG        0x4
45 #define HWA742_PLL_0_REG          0x6
46 #define HWA742_PLL_1_REG          0x8
47 #define HWA742_PLL_2_REG          0xa
48 #define HWA742_PLL_3_REG          0xc
49 #define HWA742_PLL_4_REG          0xe
50 #define HWA742_CLK_SRC_REG        0x12
51 #define HWA742_PANEL_TYPE_REG     0x14
52 #define HWA742_H_DISP_REG         0x16
53 #define HWA742_H_NDP_REG          0x18
54 #define HWA742_V_DISP_1_REG       0x1a
55 #define HWA742_V_DISP_2_REG       0x1c
56 #define HWA742_V_NDP_REG          0x1e
57 #define HWA742_HS_W_REG           0x20
58 #define HWA742_HP_S_REG           0x22
59 #define HWA742_VS_W_REG           0x24
60 #define HWA742_VP_S_REG           0x26
61 #define HWA742_PCLK_POL_REG       0x28
62 #define HWA742_INPUT_MODE_REG     0x2a
63 #define HWA742_TRANSL_MODE_REG1   0x2e
64 #define HWA742_DISP_MODE_REG      0x34
65 #define HWA742_WINDOW_TYPE        0x36
66 #define HWA742_WINDOW_X_START_0   0x38
67 #define HWA742_WINDOW_X_START_1   0x3a
68 #define HWA742_WINDOW_Y_START_0   0x3c
69 #define HWA742_WINDOW_Y_START_1   0x3e
70 #define HWA742_WINDOW_X_END_0     0x40
71 #define HWA742_WINDOW_X_END_1     0x42
72 #define HWA742_WINDOW_Y_END_0     0x44
73 #define HWA742_WINDOW_Y_END_1     0x46
74 #define HWA742_MEMORY_WRITE_LSB   0x48
75 #define HWA742_MEMORY_WRITE_MSB   0x49
76 #define HWA742_MEMORY_READ_0      0x4a
77 #define HWA742_MEMORY_READ_1      0x4c
78 #define HWA742_MEMORY_READ_2      0x4e
79 #define HWA742_POWER_SAVE         0x56
80 #define HWA742_NDP_CTRL           0x58
81
82 #define HWA742_AUTO_UPDATE_TIME         (HZ / 20)
83
84 #define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
85
86 /* Reserve 4 request slots for requests in irq context */
87 #define REQ_POOL_SIZE                   24
88 #define IRQ_REQ_POOL_SIZE               4
89
90 struct update_param {
91         int     x, y, width, height;
92         int     color_mode;
93         int     flags;
94 };
95
96 #define REQ_FROM_IRQ_POOL 0x01
97
98 #define REQ_COMPLETE    0
99 #define REQ_PENDING     1
100
101 struct hwa742_request {
102         struct list_head entry;
103         unsigned int     flags;
104
105         int              (*handler)(struct hwa742_request *req);
106         void             (*complete)(void *data);
107         void             *complete_data;
108
109         union {
110                 struct update_param     update;
111                 struct completion       *sync;
112         } par;
113 };
114
115 struct hwa742_struct {
116         enum omapfb_update_mode update_mode;
117         enum omapfb_update_mode update_mode_before_suspend;
118
119         struct timer_list       auto_update_timer;
120         int                     stop_auto_update;
121         struct omapfb_update_window     auto_update_window;
122
123         struct hwa742_request   req_pool[REQ_POOL_SIZE];
124         struct list_head        pending_req_list;
125         struct list_head        free_req_list;
126         struct semaphore        req_sema;
127         spinlock_t              req_lock;
128
129         struct clk              *sys_ck;
130         struct extif_timings    reg_timings, lut_timings;
131
132         int                     prev_color_mode;
133         int                     prev_flags;
134         int                     window_type;
135
136         u32                     max_transmit_size;
137         u32                     extif_clk_period;
138
139         struct omapfb_device    *fbdev;
140         struct lcd_ctrl_extif   *extif;
141         struct lcd_ctrl         *int_ctrl;
142 } hwa742;
143
144 static u8 hwa742_read_reg(u8 reg)
145 {
146         u8 data;
147
148         hwa742.extif->set_bits_per_cycle(8);
149         hwa742.extif->write_command(&reg, 1);
150         hwa742.extif->read_data(&data, 1);
151
152         return data;
153 }
154
155 static void hwa742_write_reg(u8 reg, u8 data)
156 {
157         hwa742.extif->set_bits_per_cycle(8);
158         hwa742.extif->write_command(&reg, 1);
159         hwa742.extif->write_data(&data, 1);
160 }
161
162 void hwa742_read_id(int *rev_code, int *config)
163 {
164         *rev_code = hwa742_read_reg(HWA742_REV_CODE_REG);
165         *config = hwa742_read_reg(HWA742_CONFIG_REG);
166 }
167 EXPORT_SYMBOL(hwa742_read_id);
168
169 static void set_window_regs(int x_start, int y_start, int x_end, int y_end)
170 {
171         u8 tmp[8];
172         u8 cmd;
173
174         x_end--;
175         y_end--;
176         tmp[0] = x_start;
177         tmp[1] = x_start >> 8;
178         tmp[2] = y_start;
179         tmp[3] = y_start >> 8;
180         tmp[4] = x_end;
181         tmp[5] = x_end >> 8;
182         tmp[6] = y_end;
183         tmp[7] = y_end >> 8;
184
185         hwa742.extif->set_bits_per_cycle(8);
186         cmd = HWA742_WINDOW_X_START_0;
187
188         hwa742.extif->write_command(&cmd, 1);
189
190         hwa742.extif->write_data(tmp, 8);
191 }
192
193 static void set_format_regs(int conv, int transl, int flags)
194 {
195         if (flags & OMAPFB_FORMAT_FLAG_DOUBLE) {
196                 hwa742.window_type = ((hwa742.window_type & 0xfc) | 0x01);
197                 DBGPRINT(2, "hwa742: enabled pixel doubling\n");
198         } else {
199                 hwa742.window_type = (hwa742.window_type & 0xfc);
200                 DBGPRINT(2, "hwa742: disabled pixel doubling\n");
201         }
202
203         hwa742_write_reg(HWA742_INPUT_MODE_REG, conv);
204         hwa742_write_reg(HWA742_TRANSL_MODE_REG1, transl);
205         hwa742_write_reg(HWA742_WINDOW_TYPE, hwa742.window_type);
206 }
207
208 static inline struct hwa742_request *alloc_req(void)
209 {
210         unsigned long flags;
211         struct hwa742_request *req;
212         int req_flags = 0;
213
214         if (!in_interrupt())
215                 down(&hwa742.req_sema);
216         else
217                 req_flags = REQ_FROM_IRQ_POOL;
218
219         spin_lock_irqsave(&hwa742.req_lock, flags);
220         BUG_ON(list_empty(&hwa742.free_req_list));
221         req = list_entry(hwa742.free_req_list.next,
222                          struct hwa742_request, entry);
223         list_del(&req->entry);
224         spin_unlock_irqrestore(&hwa742.req_lock, flags);
225
226         INIT_LIST_HEAD(&req->entry);
227         req->flags = req_flags;
228
229         return req;
230 }
231
232 static inline void free_req(struct hwa742_request *req)
233 {
234         unsigned long flags;
235
236         spin_lock_irqsave(&hwa742.req_lock, flags);
237
238         list_del(&req->entry);
239         list_add(&req->entry, &hwa742.free_req_list);
240         if (!(req->flags & REQ_FROM_IRQ_POOL))
241                 up(&hwa742.req_sema);
242
243         spin_unlock_irqrestore(&hwa742.req_lock, flags);
244 }
245
246 static void process_pending_requests(void)
247 {
248         unsigned long flags;
249
250         DBGENTER(2);
251
252         spin_lock_irqsave(&hwa742.req_lock, flags);
253
254         while (!list_empty(&hwa742.pending_req_list)) {
255                 struct hwa742_request *req;
256                 void (*complete)(void *);
257                 void *complete_data;
258
259                 req = list_entry(hwa742.pending_req_list.next,
260                                  struct hwa742_request, entry);
261                 spin_unlock_irqrestore(&hwa742.req_lock, flags);
262
263                 if (req->handler(req) == REQ_PENDING)
264                         return;
265
266                 complete = req->complete;
267                 complete_data = req->complete_data;
268                 free_req(req);
269
270                 if (complete)
271                         complete(complete_data);
272
273                 spin_lock_irqsave(&hwa742.req_lock, flags);
274         }
275
276         spin_unlock_irqrestore(&hwa742.req_lock, flags);
277
278         DBGLEAVE(2);
279 }
280
281 static void submit_req_list(struct list_head *head)
282 {
283         unsigned long flags;
284         int process = 1;
285
286         DBGENTER(2);
287
288         spin_lock_irqsave(&hwa742.req_lock, flags);
289         if (likely(!list_empty(&hwa742.pending_req_list)))
290                 process = 0;
291         list_splice_init(head, hwa742.pending_req_list.prev);
292         spin_unlock_irqrestore(&hwa742.req_lock, flags);
293
294         if (process)
295                 process_pending_requests();
296
297         DBGLEAVE(2);
298 }
299
300 static void request_complete(void *data)
301 {
302         struct hwa742_request   *req = (struct hwa742_request *)data;
303         void                    (*complete)(void *);
304         void                    *complete_data;
305
306         complete = req->complete;
307         complete_data = req->complete_data;
308
309         free_req(req);
310
311         if (complete)
312                 complete(complete_data);
313
314         process_pending_requests();
315 }
316
317 static int send_frame_handler(struct hwa742_request *req)
318 {
319         struct update_param *par = &req->par.update;
320         int x = par->x;
321         int y = par->y;
322         int w = par->width;
323         int h = par->height;
324         int bpp;
325         int conv, transl;
326         unsigned long offset;
327         int color_mode = par->color_mode;
328         int flags = par->flags;
329         int scr_width = 800;
330
331         DBGPRINT(2, "x %d y %d w %d h %d scr_width %d color_mode %d flags %d\n",
332                 x, y, w, h, scr_width, color_mode, flags);
333
334         switch (color_mode) {
335         case OMAPFB_COLOR_YUV422:
336                 bpp = 16;
337                 conv = 0x08;
338                 transl = 0x25;
339                 break;
340         case OMAPFB_COLOR_YUV420:
341                 bpp = 12;
342                 conv = 0x09;
343                 transl = 0x25;
344                 break;
345         case OMAPFB_COLOR_RGB565:
346                 bpp = 16;
347                 conv = 0x01;
348                 transl = 0x05;
349                 break;
350         default:
351                 return -EINVAL;
352         }
353
354         if (hwa742.prev_flags != flags ||
355             hwa742.prev_color_mode != color_mode) {
356                 set_format_regs(conv, transl, flags);
357                 hwa742.prev_color_mode = color_mode;
358                 hwa742.prev_flags = flags;
359         }
360
361         set_window_regs(x, y, x + w, y + h);
362
363         offset = (scr_width * y + x) * bpp / 8;
364
365         hwa742.int_ctrl->setup_plane(OMAPFB_PLANE_GFX,
366                         OMAPFB_CHANNEL_OUT_LCD, offset, scr_width, 0, 0, w, h,
367                         color_mode);
368
369         hwa742.extif->set_bits_per_cycle(16);
370
371         hwa742.int_ctrl->enable_plane(OMAPFB_PLANE_GFX, 1);
372         hwa742.extif->transfer_area(w, h, request_complete, req);
373
374         return REQ_PENDING;
375 }
376
377 static void send_frame_complete(void *data)
378 {
379         hwa742.int_ctrl->enable_plane(OMAPFB_PLANE_GFX, 0);
380 }
381
382 #define ADD_PREQ(_x, _y, _w, _h) do {           \
383         req = alloc_req();                      \
384         req->handler    = send_frame_handler;   \
385         req->complete   = send_frame_complete;  \
386         req->par.update.x = _x;                 \
387         req->par.update.y = _y;                 \
388         req->par.update.width  = _w;            \
389         req->par.update.height = _h;            \
390         req->par.update.color_mode = color_mode;\
391         req->par.update.flags     = flags;      \
392         list_add_tail(&req->entry, req_head);   \
393 } while(0)
394
395 static void create_req_list(struct omapfb_update_window *win,
396                             struct list_head *req_head)
397 {
398         struct hwa742_request *req;
399         int x = win->x;
400         int y = win->y;
401         int width = win->width;
402         int height = win->height;
403         int color_mode;
404         int flags;
405
406         flags = win->format & OMAPFB_FORMAT_FLAG_DOUBLE;
407         color_mode = win->format & OMAPFB_FORMAT_MASK;
408
409         if (x & 1) {
410                 ADD_PREQ(x, y, 1, height);
411                 width--;
412                 x++;
413         }
414         if (width & ~1) {
415                 unsigned int xspan = width & ~1;
416                 unsigned int ystart = y;
417                 unsigned int yspan = height;
418
419                 if (xspan * height * 2 > hwa742.max_transmit_size) {
420                         yspan = hwa742.max_transmit_size / (xspan * 2);
421                         ADD_PREQ(x, ystart, xspan, yspan);
422                         ystart += yspan;
423                         yspan = height - yspan;
424                 }
425
426                 ADD_PREQ(x, ystart, xspan, yspan);
427                 x += xspan;
428                 width -= xspan;
429         }
430         if (width)
431                 ADD_PREQ(x, y, 1, height);
432 }
433
434 static void auto_update_complete(void *data)
435 {
436         DBGENTER(2);
437
438         if (!hwa742.stop_auto_update)
439                 mod_timer(&hwa742.auto_update_timer,
440                           jiffies + HWA742_AUTO_UPDATE_TIME);
441
442         DBGLEAVE(2);
443 }
444
445 static void hwa742_update_window_auto(unsigned long arg)
446 {
447         LIST_HEAD(req_list);
448         struct hwa742_request *last;
449
450         DBGENTER(2);
451
452         create_req_list(&hwa742.auto_update_window, &req_list);
453         last = list_entry(req_list.prev, struct hwa742_request, entry);
454
455         last->complete = auto_update_complete;
456         last->complete_data = NULL;
457
458         submit_req_list(&req_list);
459
460         DBGLEAVE(2);
461 }
462
463 int hwa742_update_window_async(struct omapfb_update_window *win,
464                                  void (*complete_callback)(void *arg),
465                                  void *complete_callback_data)
466 {
467         LIST_HEAD(req_list);
468         struct hwa742_request *last;
469         int r = 0;
470
471         DBGENTER(2);
472
473         if (hwa742.update_mode != OMAPFB_MANUAL_UPDATE) {
474                 r = -EINVAL;
475                 goto out;
476         }
477         if (unlikely(win->format & ~(0x03 | OMAPFB_FORMAT_FLAG_DOUBLE))) {
478                 r = -EINVAL;
479                 goto out;
480         }
481
482         create_req_list(win, &req_list);
483         last = list_entry(req_list.prev, struct hwa742_request, entry);
484
485         last->complete = complete_callback;
486         last->complete_data = (void *)complete_callback_data;
487
488         submit_req_list(&req_list);
489
490 out:
491         DBGLEAVE(2);
492         return r;
493 }
494 EXPORT_SYMBOL(hwa742_update_window_async);
495
496 static int hwa742_setup_plane(int plane, int channel_out,
497                                   unsigned long offset, int screen_width,
498                                   int pos_x, int pos_y, int width, int height,
499                                   int color_mode)
500 {
501         if (plane != OMAPFB_PLANE_GFX ||
502             channel_out != OMAPFB_CHANNEL_OUT_LCD)
503                 return -EINVAL;
504
505         return 0;
506 }
507
508 static int hwa742_enable_plane(int plane, int enable)
509 {
510         if (plane != 0)
511                 return -EINVAL;
512
513         hwa742.int_ctrl->enable_plane(plane, enable);
514
515         return 0;
516 }
517
518 static int sync_handler(struct hwa742_request *req)
519 {
520         complete(req->par.sync);
521         return REQ_COMPLETE;
522 }
523
524 static void hwa742_sync(void)
525 {
526         LIST_HEAD(req_list);
527         struct hwa742_request *req;
528         struct completion comp;
529
530         DBGENTER(2);
531
532         req = alloc_req();
533
534         req->handler = sync_handler;
535         req->complete = NULL;
536         init_completion(&comp);
537         req->par.sync = &comp;
538
539         list_add(&req->entry, &req_list);
540         submit_req_list(&req_list);
541
542         wait_for_completion(&comp);
543
544         DBGLEAVE(2);
545 }
546
547 static struct notifier_block *hwa742_client_list;
548
549 int hwa742_register_client(struct hwa742_notifier_block *hwa742_nb,
550                             hwa742_notifier_callback_t callback,
551                             void *callback_data)
552 {
553         int r;
554
555         DBGPRINT(1, "update_mode %d\n", hwa742.update_mode);
556         hwa742_nb->nb.notifier_call = (int (*)(struct notifier_block *,
557                                         unsigned long, void *))callback;
558         hwa742_nb->data = callback_data;
559         r = notifier_chain_register(&hwa742_client_list, &hwa742_nb->nb);
560         if (r)
561                 return r;
562         if (hwa742.update_mode == OMAPFB_MANUAL_UPDATE) {
563                 DBGPRINT(1, "calling client list\n");
564                 notifier_call_chain(&hwa742_client_list,
565                                     HWA742_EVENT_READY,
566                                     hwa742.fbdev);
567         }
568         return 0;
569 }
570 EXPORT_SYMBOL(hwa742_register_client);
571
572 int hwa742_unregister_client(struct hwa742_notifier_block *hwa742_nb)
573 {
574         return notifier_chain_unregister(&hwa742_client_list,
575                                          &hwa742_nb->nb);
576 }
577 EXPORT_SYMBOL(hwa742_unregister_client);
578
579 static int hwa742_set_update_mode(enum omapfb_update_mode mode)
580 {
581         int r = 0;
582
583         DBGENTER(1);
584
585         if (mode != OMAPFB_MANUAL_UPDATE && mode != OMAPFB_AUTO_UPDATE &&
586             mode != OMAPFB_UPDATE_DISABLED) {
587                 r = -EINVAL;
588                 goto out;
589         }
590
591         if (mode == hwa742.update_mode)
592                 goto out;
593
594         printk(KERN_INFO "hwa742: setting update mode to %s\n",
595                         mode == OMAPFB_UPDATE_DISABLED ? "disabled" :
596                         (mode == OMAPFB_AUTO_UPDATE ? "auto" : "manual"));
597
598         switch (hwa742.update_mode) {
599         case OMAPFB_MANUAL_UPDATE:
600                 notifier_call_chain(&hwa742_client_list,
601                                     HWA742_EVENT_DISABLED,
602                                     hwa742.fbdev);
603                 break;
604         case OMAPFB_AUTO_UPDATE:
605                 hwa742.stop_auto_update = 1;
606                 del_timer_sync(&hwa742.auto_update_timer);
607                 break;
608         case OMAPFB_UPDATE_DISABLED:
609                 break;
610         }
611
612         hwa742.update_mode = mode;
613         hwa742_sync();
614         hwa742.stop_auto_update = 0;
615
616         switch (mode) {
617         case OMAPFB_MANUAL_UPDATE:
618                 notifier_call_chain(&hwa742_client_list,
619                                     HWA742_EVENT_READY,
620                                     hwa742.fbdev);
621                 break;
622         case OMAPFB_AUTO_UPDATE:
623                 hwa742_update_window_auto(0);
624                 break;
625         case OMAPFB_UPDATE_DISABLED:
626                 break;
627         }
628 out:
629
630         DBGLEAVE(1);
631         return r;
632 }
633
634 static enum omapfb_update_mode hwa742_get_update_mode(void)
635 {
636         return hwa742.update_mode;
637 }
638
639 static unsigned long round_to_extif_ticks(unsigned long ps, int div)
640 {
641         int bus_tick = hwa742.extif_clk_period * div;
642         return (ps + bus_tick - 1) / bus_tick * bus_tick;
643 }
644
645 static int calc_reg_timing(unsigned long sysclk, int div)
646 {
647         struct extif_timings *t;
648         unsigned long systim;
649
650         /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
651          * AccessTime 2 ns + 12.2 ns (regs),
652          * WEOffTime = WEOnTime + 1 ns,
653          * REOffTime = REOnTime + 16 ns (regs),
654          * CSOffTime = REOffTime + 1 ns
655          * ReadCycle = 2ns + 2*SYSCLK  (regs),
656          * WriteCycle = 2*SYSCLK + 2 ns,
657          * CSPulseWidth = 10 ns */
658         systim = 1000000000 / (sysclk / 1000);
659         DBGPRINT(1, "HWA742 systim %lu ps extif_clk_period %u ps"
660                   "extif_clk_div %d\n", systim, hwa742.extif_clk_period, div);
661
662         t = &hwa742.reg_timings;
663         memset(t, 0, sizeof(*t));
664         t->clk_div = div;
665         t->cs_on_time = 0;
666         t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
667         t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
668         t->access_time = round_to_extif_ticks(t->re_on_time + 12200, div);
669         t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
670         t->re_off_time = round_to_extif_ticks(t->re_on_time + 16000, div);
671         t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
672         t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
673         if (t->we_cycle_time < t->we_off_time)
674                 t->we_cycle_time = t->we_off_time;
675         t->re_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
676         if (t->re_cycle_time < t->re_off_time)
677                 t->re_cycle_time = t->re_off_time;
678         t->cs_pulse_width = 0;
679
680         DBGPRINT(1, "[reg]cson %d csoff %d reon %d reoff %d\n",
681                  t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
682         DBGPRINT(1, "[reg]weon %d weoff %d recyc %d wecyc %d\n",
683                  t->we_on_time, t->we_off_time, t->re_cycle_time,
684                  t->we_cycle_time);
685         DBGPRINT(1, "[reg]rdaccess %d cspulse %d\n",
686                  t->access_time, t->cs_pulse_width);
687
688         return hwa742.extif->convert_timings(t);
689 }
690
691 static int calc_lut_timing(unsigned long sysclk, int div)
692 {
693         struct extif_timings *t;
694         unsigned long systim;
695
696         /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
697          * AccessTime 2 ns + 4 * SYSCLK + 26 (lut),
698          * WEOffTime = WEOnTime + 1 ns,
699          * REOffTime = REOnTime + 4*SYSCLK + 26 ns (lut),
700          * CSOffTime = REOffTime + 1 ns
701          * ReadCycle = 2ns + 4*SYSCLK + 26 ns (lut),
702          * WriteCycle = 2*SYSCLK + 2 ns,
703          * CSPulseWidth = 10 ns
704          */
705         systim = 1000000000 / (sysclk / 1000);
706         DBGPRINT(1, "HWA742 systim %lu ps extif_clk_period %u ps"
707                   "extif_clk_div %d\n", systim, hwa742.extif_clk_period, div);
708
709         t = &hwa742.lut_timings;
710         memset(t, 0, sizeof(*t));
711
712         t->clk_div = div;
713
714         t->cs_on_time = 0;
715         t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
716         t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
717         t->access_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
718                                               26000, div);
719         t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
720         t->re_off_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
721                                               26000, div);
722         t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
723         t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
724         if (t->we_cycle_time < t->we_off_time)
725                 t->we_cycle_time = t->we_off_time;
726         t->re_cycle_time = round_to_extif_ticks(2000 + 4 * systim + 26000, div);
727         if (t->re_cycle_time < t->re_off_time)
728                 t->re_cycle_time = t->re_off_time;
729         t->cs_pulse_width = 0;
730
731         DBGPRINT(1, "[lut]cson %d csoff %d reon %d reoff %d\n",
732                  t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
733         DBGPRINT(1, "[lut]weon %d weoff %d recyc %d wecyc %d\n",
734                  t->we_on_time, t->we_off_time, t->re_cycle_time,
735                  t->we_cycle_time);
736         DBGPRINT(1, "[lut]rdaccess %d cspulse %d\n",
737                  t->access_time, t->cs_pulse_width);
738
739         return hwa742.extif->convert_timings(t);
740 }
741
742 static int calc_extif_timings(unsigned long sysclk)
743 {
744         int max_clk_div;
745         int div;
746
747         hwa742.extif->get_clk_info(&hwa742.extif_clk_period, &max_clk_div);
748         for (div = 1; div < max_clk_div; div++) {
749                 if (calc_reg_timing(sysclk, div) == 0)
750                         break;
751         }
752         if (div == max_clk_div)
753                 goto err;
754
755         for (div = 1; div < max_clk_div; div++) {
756                 if (calc_lut_timing(sysclk, div) == 0)
757                         break;
758         }
759
760         if (div < max_clk_div)
761                 return 0;
762
763 err:
764         pr_err("can't setup timings\n");
765         return -1;
766 }
767
768 static unsigned long hwa742_get_caps(void)
769 {
770         return OMAPFB_CAPS_MANUAL_UPDATE;
771 }
772
773 static void hwa742_suspend(void)
774 {
775         hwa742.update_mode_before_suspend = hwa742.update_mode;
776         hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED);
777         /* Enable sleep mode */
778         hwa742_write_reg(HWA742_POWER_SAVE, 1 << 1);
779         clk_disable(hwa742.sys_ck);
780 }
781
782 static void hwa742_resume(void)
783 {
784         if (clk_enable(hwa742.sys_ck) != 0)
785                 pr_err("failed to enable SYS clock\n");
786         /* Disable sleep mode */
787         hwa742_write_reg(HWA742_POWER_SAVE, 0);
788         while (1) {
789                 /* Loop until PLL output is stabilized */
790                 if (hwa742_read_reg(HWA742_PLL_DIV_REG) & (1 << 7))
791                         break;
792                 set_current_state(TASK_UNINTERRUPTIBLE);
793                 schedule_timeout(msecs_to_jiffies(5));
794         }
795         hwa742_set_update_mode(hwa742.update_mode_before_suspend);
796 }
797
798 struct lcd_ctrl hwa742_ctrl;
799
800 static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, int req_vram_size)
801 {
802         int r = 0, i;
803         u8 rev, conf;
804         unsigned long sysfreq;
805         int div, nd;
806
807         DBGENTER(1);
808
809         hwa742.sys_ck = clk_get(0, "bclk");
810         if (IS_ERR(hwa742.sys_ck)) {
811                 pr_err("can't get SYS clock\n");
812                 return PTR_ERR(hwa742.sys_ck);
813         }
814
815         if ((r = clk_enable(hwa742.sys_ck)) != 0) {
816                 pr_err("can't enable SYS clock\n");
817                 clk_put(hwa742.sys_ck);
818                 return r;
819         }
820
821         BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl);
822
823         hwa742.fbdev = fbdev;
824         hwa742.extif = fbdev->ext_if;
825         hwa742.int_ctrl = fbdev->int_ctrl;
826
827         spin_lock_init(&hwa742.req_lock);
828
829         if ((r = hwa742.int_ctrl->init(fbdev, 1, req_vram_size)) < 0)
830                 goto err1;
831
832         if ((r = hwa742.extif->init()) < 0)
833                 goto err2;
834
835         hwa742_ctrl.get_vram_layout = hwa742.int_ctrl->get_vram_layout;
836         hwa742_ctrl.mmap = hwa742.int_ctrl->mmap;
837
838         sysfreq = clk_get_rate(hwa742.sys_ck);
839         if ((r = calc_extif_timings(sysfreq)) < 0)
840                 goto err3;
841         hwa742.extif->set_timings(&hwa742.reg_timings);
842
843         div = (hwa742_read_reg(HWA742_PLL_DIV_REG) & 0x3f) + 1;
844
845         nd = (hwa742_read_reg(HWA742_PLL_4_REG) & 0x7f) + 1;
846
847         if ((r = calc_extif_timings(sysfreq / div * nd)) < 0)
848                 goto err3;
849         hwa742.extif->set_timings(&hwa742.reg_timings);
850
851         rev = hwa742_read_reg(HWA742_REV_CODE_REG);
852         if ((rev & 0xfc) != 0x80) {
853                 pr_err("invalid revision %02x\n", rev);
854                 r = -ENODEV;
855                 goto err3;
856         }
857
858         conf = hwa742_read_reg(HWA742_CONFIG_REG);
859         pr_info(MODULE_NAME ": Epson HWA742 LCD controller rev. %d "
860                         "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
861
862         if (!(hwa742_read_reg(HWA742_PLL_DIV_REG) & 0x80)) {
863                 pr_err("controller not initialized by the bootloader\n");
864                 r = -ENODEV;
865                 goto err2;
866         }
867
868         hwa742.max_transmit_size = hwa742.extif->max_transmit_size;
869
870         hwa742.update_mode = OMAPFB_UPDATE_DISABLED;
871
872         hwa742.auto_update_window.x = 0;
873         hwa742.auto_update_window.y = 0;
874         hwa742.auto_update_window.width = fbdev->panel->x_res;
875         hwa742.auto_update_window.height = fbdev->panel->y_res;
876         hwa742.auto_update_window.format = 0;
877
878         init_timer(&hwa742.auto_update_timer);
879         hwa742.auto_update_timer.function = hwa742_update_window_auto;
880         hwa742.auto_update_timer.data = 0;
881
882         hwa742.prev_color_mode = -1;
883         hwa742.prev_flags = 0;
884
885         hwa742.fbdev = fbdev;
886
887         INIT_LIST_HEAD(&hwa742.free_req_list);
888         INIT_LIST_HEAD(&hwa742.pending_req_list);
889         for (i = 0; i < ARRAY_SIZE(hwa742.req_pool); i++)
890                 list_add(&hwa742.req_pool[i].entry, &hwa742.free_req_list);
891         BUG_ON(i <= IRQ_REQ_POOL_SIZE);
892         sema_init(&hwa742.req_sema, i - IRQ_REQ_POOL_SIZE);
893
894         return 0;
895 err3:
896         hwa742.extif->cleanup();
897 err2:
898         hwa742.int_ctrl->cleanup();
899 err1:
900         clk_disable(hwa742.sys_ck);
901         clk_put(hwa742.sys_ck);
902         return r;
903 }
904
905 static void hwa742_cleanup(void)
906 {
907         hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED);
908         hwa742.extif->cleanup();
909         hwa742.int_ctrl->cleanup();
910         clk_disable(hwa742.sys_ck);
911         clk_put(hwa742.sys_ck);
912 }
913
914 struct lcd_ctrl hwa742_ctrl = {
915         .name                   = "hwa742",
916         .init                   = hwa742_init,
917         .cleanup                = hwa742_cleanup,
918         .get_caps               = hwa742_get_caps,
919         .set_update_mode        = hwa742_set_update_mode,
920         .get_update_mode        = hwa742_get_update_mode,
921         .setup_plane            = hwa742_setup_plane,
922         .enable_plane           = hwa742_enable_plane,
923         .update_window          = hwa742_update_window_async,
924         .sync                   = hwa742_sync,
925         .suspend                = hwa742_suspend,
926         .resume                 = hwa742_resume,
927 };
928