2 * Epson HWA742 LCD controller driver
4 * Copyright (C) 2004-2005 Nokia Corporation
5 * Authors: Juha Yrjölä <juha.yrjola@nokia.com>
6 * Imre Deak <imre.deak@nokia.com>
7 * YUV support: Jussi Laako <jussi.laako@nokia.com>
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.
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.
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.
23 #include <linux/module.h>
26 #include <linux/delay.h>
27 #include <linux/clk.h>
29 #include <asm/arch/dma.h>
30 #include <asm/arch/omapfb.h>
31 #include <asm/arch/hwa742.h>
33 #define HWA742_REV_CODE_REG 0x0
34 #define HWA742_CONFIG_REG 0x2
35 #define HWA742_PLL_DIV_REG 0x4
36 #define HWA742_PLL_0_REG 0x6
37 #define HWA742_PLL_1_REG 0x8
38 #define HWA742_PLL_2_REG 0xa
39 #define HWA742_PLL_3_REG 0xc
40 #define HWA742_PLL_4_REG 0xe
41 #define HWA742_CLK_SRC_REG 0x12
42 #define HWA742_PANEL_TYPE_REG 0x14
43 #define HWA742_H_DISP_REG 0x16
44 #define HWA742_H_NDP_REG 0x18
45 #define HWA742_V_DISP_1_REG 0x1a
46 #define HWA742_V_DISP_2_REG 0x1c
47 #define HWA742_V_NDP_REG 0x1e
48 #define HWA742_HS_W_REG 0x20
49 #define HWA742_HP_S_REG 0x22
50 #define HWA742_VS_W_REG 0x24
51 #define HWA742_VP_S_REG 0x26
52 #define HWA742_PCLK_POL_REG 0x28
53 #define HWA742_INPUT_MODE_REG 0x2a
54 #define HWA742_TRANSL_MODE_REG1 0x2e
55 #define HWA742_DISP_MODE_REG 0x34
56 #define HWA742_WINDOW_TYPE 0x36
57 #define HWA742_WINDOW_X_START_0 0x38
58 #define HWA742_WINDOW_X_START_1 0x3a
59 #define HWA742_WINDOW_Y_START_0 0x3c
60 #define HWA742_WINDOW_Y_START_1 0x3e
61 #define HWA742_WINDOW_X_END_0 0x40
62 #define HWA742_WINDOW_X_END_1 0x42
63 #define HWA742_WINDOW_Y_END_0 0x44
64 #define HWA742_WINDOW_Y_END_1 0x46
65 #define HWA742_MEMORY_WRITE_LSB 0x48
66 #define HWA742_MEMORY_WRITE_MSB 0x49
67 #define HWA742_MEMORY_READ_0 0x4a
68 #define HWA742_MEMORY_READ_1 0x4c
69 #define HWA742_MEMORY_READ_2 0x4e
70 #define HWA742_POWER_SAVE 0x56
71 #define HWA742_NDP_CTRL 0x58
73 #define HWA742_AUTO_UPDATE_TIME (HZ / 20)
75 /* Reserve 4 request slots for requests in irq context */
76 #define REQ_POOL_SIZE 24
77 #define IRQ_REQ_POOL_SIZE 4
79 #define REQ_FROM_IRQ_POOL 0x01
81 #define REQ_COMPLETE 0
85 int x
, y
, width
, height
;
90 struct hwa742_request
{
91 struct list_head entry
;
94 int (*handler
)(struct hwa742_request
*req
);
95 void (*complete
)(void *data
);
99 struct update_param update
;
100 struct completion
*sync
;
105 enum omapfb_update_mode update_mode
;
106 enum omapfb_update_mode update_mode_before_suspend
;
108 struct timer_list auto_update_timer
;
109 int stop_auto_update
;
110 struct omapfb_update_window auto_update_window
;
111 unsigned te_connected
:1;
112 unsigned vsync_only
:1;
114 struct hwa742_request req_pool
[REQ_POOL_SIZE
];
115 struct list_head pending_req_list
;
116 struct list_head free_req_list
;
117 struct semaphore req_sema
;
120 struct extif_timings reg_timings
, lut_timings
;
126 u32 max_transmit_size
;
127 u32 extif_clk_period
;
128 unsigned long pix_tx_time
;
129 unsigned long line_upd_time
;
132 struct omapfb_device
*fbdev
;
133 struct lcd_ctrl_extif
*extif
;
134 struct lcd_ctrl
*int_ctrl
;
136 void (*power_up
)(struct device
*dev
);
137 void (*power_down
)(struct device
*dev
);
140 struct lcd_ctrl hwa742_ctrl
;
142 static u8
hwa742_read_reg(u8 reg
)
146 hwa742
.extif
->set_bits_per_cycle(8);
147 hwa742
.extif
->write_command(®
, 1);
148 hwa742
.extif
->read_data(&data
, 1);
153 static void hwa742_write_reg(u8 reg
, u8 data
)
155 hwa742
.extif
->set_bits_per_cycle(8);
156 hwa742
.extif
->write_command(®
, 1);
157 hwa742
.extif
->write_data(&data
, 1);
160 static void set_window_regs(int x_start
, int y_start
, int x_end
, int y_end
)
168 tmp
[1] = x_start
>> 8;
170 tmp
[3] = y_start
>> 8;
176 hwa742
.extif
->set_bits_per_cycle(8);
177 cmd
= HWA742_WINDOW_X_START_0
;
179 hwa742
.extif
->write_command(&cmd
, 1);
181 hwa742
.extif
->write_data(tmp
, 8);
184 static void set_format_regs(int conv
, int transl
, int flags
)
186 if (flags
& OMAPFB_FORMAT_FLAG_DOUBLE
) {
187 hwa742
.window_type
= ((hwa742
.window_type
& 0xfc) | 0x01);
189 dev_dbg(hwa742
.fbdev
->dev
, "hwa742: enabled pixel doubling\n");
192 hwa742
.window_type
= (hwa742
.window_type
& 0xfc);
194 dev_dbg(hwa742
.fbdev
->dev
, "hwa742: disabled pixel doubling\n");
198 hwa742_write_reg(HWA742_INPUT_MODE_REG
, conv
);
199 hwa742_write_reg(HWA742_TRANSL_MODE_REG1
, transl
);
200 hwa742_write_reg(HWA742_WINDOW_TYPE
, hwa742
.window_type
);
203 static void enable_tearsync(int y
, int width
, int height
, int screen_height
,
208 b
= hwa742_read_reg(HWA742_NDP_CTRL
);
210 hwa742_write_reg(HWA742_NDP_CTRL
, b
);
212 if (likely(hwa742
.vsync_only
|| force_vsync
)) {
213 hwa742
.extif
->enable_tearsync(1, 0);
217 if (width
* hwa742
.pix_tx_time
< hwa742
.line_upd_time
) {
218 hwa742
.extif
->enable_tearsync(1, 0);
222 if ((width
* hwa742
.pix_tx_time
/ 1000) * height
<
223 (y
+ height
) * (hwa742
.line_upd_time
/ 1000)) {
224 hwa742
.extif
->enable_tearsync(1, 0);
228 hwa742
.extif
->enable_tearsync(1, y
+ 1);
231 static void disable_tearsync(void)
235 hwa742
.extif
->enable_tearsync(0, 0);
237 b
= hwa742_read_reg(HWA742_NDP_CTRL
);
239 hwa742_write_reg(HWA742_NDP_CTRL
, b
);
242 static inline struct hwa742_request
*alloc_req(void)
245 struct hwa742_request
*req
;
249 down(&hwa742
.req_sema
);
251 req_flags
= REQ_FROM_IRQ_POOL
;
253 spin_lock_irqsave(&hwa742
.req_lock
, flags
);
254 BUG_ON(list_empty(&hwa742
.free_req_list
));
255 req
= list_entry(hwa742
.free_req_list
.next
,
256 struct hwa742_request
, entry
);
257 list_del(&req
->entry
);
258 spin_unlock_irqrestore(&hwa742
.req_lock
, flags
);
260 INIT_LIST_HEAD(&req
->entry
);
261 req
->flags
= req_flags
;
266 static inline void free_req(struct hwa742_request
*req
)
270 spin_lock_irqsave(&hwa742
.req_lock
, flags
);
272 list_del(&req
->entry
);
273 list_add(&req
->entry
, &hwa742
.free_req_list
);
274 if (!(req
->flags
& REQ_FROM_IRQ_POOL
))
275 up(&hwa742
.req_sema
);
277 spin_unlock_irqrestore(&hwa742
.req_lock
, flags
);
280 static void process_pending_requests(void)
284 spin_lock_irqsave(&hwa742
.req_lock
, flags
);
286 while (!list_empty(&hwa742
.pending_req_list
)) {
287 struct hwa742_request
*req
;
288 void (*complete
)(void *);
291 req
= list_entry(hwa742
.pending_req_list
.next
,
292 struct hwa742_request
, entry
);
293 spin_unlock_irqrestore(&hwa742
.req_lock
, flags
);
295 if (req
->handler(req
) == REQ_PENDING
)
298 complete
= req
->complete
;
299 complete_data
= req
->complete_data
;
303 complete(complete_data
);
305 spin_lock_irqsave(&hwa742
.req_lock
, flags
);
308 spin_unlock_irqrestore(&hwa742
.req_lock
, flags
);
311 static void submit_req_list(struct list_head
*head
)
316 spin_lock_irqsave(&hwa742
.req_lock
, flags
);
317 if (likely(!list_empty(&hwa742
.pending_req_list
)))
319 list_splice_init(head
, hwa742
.pending_req_list
.prev
);
320 spin_unlock_irqrestore(&hwa742
.req_lock
, flags
);
323 process_pending_requests();
326 static void request_complete(void *data
)
328 struct hwa742_request
*req
= (struct hwa742_request
*)data
;
329 void (*complete
)(void *);
332 complete
= req
->complete
;
333 complete_data
= req
->complete_data
;
338 complete(complete_data
);
340 process_pending_requests();
343 static int send_frame_handler(struct hwa742_request
*req
)
345 struct update_param
*par
= &req
->par
.update
;
352 unsigned long offset
;
353 int color_mode
= par
->color_mode
;
354 int flags
= par
->flags
;
355 int scr_width
= hwa742
.fbdev
->panel
->x_res
;
356 int scr_height
= hwa742
.fbdev
->panel
->y_res
;
359 dev_dbg(hwa742
.fbdev
->dev
, "x %d y %d w %d h %d scr_width %d "
360 "color_mode %d flags %d\n",
361 x
, y
, w
, h
, scr_width
, color_mode
, flags
);
364 switch (color_mode
) {
365 case OMAPFB_COLOR_YUV422
:
370 case OMAPFB_COLOR_YUV420
:
375 case OMAPFB_COLOR_RGB565
:
384 if (hwa742
.prev_flags
!= flags
||
385 hwa742
.prev_color_mode
!= color_mode
) {
386 set_format_regs(conv
, transl
, flags
);
387 hwa742
.prev_color_mode
= color_mode
;
388 hwa742
.prev_flags
= flags
;
390 flags
= req
->par
.update
.flags
;
391 if (flags
& OMAPFB_FORMAT_FLAG_TEARSYNC
)
392 enable_tearsync(y
, scr_width
, h
, scr_height
,
393 flags
& OMAPFB_FORMAT_FLAG_FORCE_VSYNC
);
397 set_window_regs(x
, y
, x
+ w
, y
+ h
);
399 offset
= (scr_width
* y
+ x
) * bpp
/ 8;
401 hwa742
.int_ctrl
->setup_plane(OMAPFB_PLANE_GFX
,
402 OMAPFB_CHANNEL_OUT_LCD
, offset
, scr_width
, 0, 0, w
, h
,
405 hwa742
.extif
->set_bits_per_cycle(16);
407 hwa742
.int_ctrl
->enable_plane(OMAPFB_PLANE_GFX
, 1);
408 hwa742
.extif
->transfer_area(w
, h
, request_complete
, req
);
413 static void send_frame_complete(void *data
)
415 hwa742
.int_ctrl
->enable_plane(OMAPFB_PLANE_GFX
, 0);
418 #define ADD_PREQ(_x, _y, _w, _h) do { \
420 req->handler = send_frame_handler; \
421 req->complete = send_frame_complete; \
422 req->par.update.x = _x; \
423 req->par.update.y = _y; \
424 req->par.update.width = _w; \
425 req->par.update.height = _h; \
426 req->par.update.color_mode = color_mode;\
427 req->par.update.flags = flags; \
428 list_add_tail(&req->entry, req_head); \
431 static void create_req_list(struct omapfb_update_window
*win
,
432 struct list_head
*req_head
)
434 struct hwa742_request
*req
;
437 int width
= win
->width
;
438 int height
= win
->height
;
442 flags
= win
->format
& ~OMAPFB_FORMAT_MASK
;
443 color_mode
= win
->format
& OMAPFB_FORMAT_MASK
;
446 ADD_PREQ(x
, y
, 1, height
);
449 flags
&= ~OMAPFB_FORMAT_FLAG_TEARSYNC
;
452 unsigned int xspan
= width
& ~1;
453 unsigned int ystart
= y
;
454 unsigned int yspan
= height
;
456 if (xspan
* height
* 2 > hwa742
.max_transmit_size
) {
457 yspan
= hwa742
.max_transmit_size
/ (xspan
* 2);
458 ADD_PREQ(x
, ystart
, xspan
, yspan
);
460 yspan
= height
- yspan
;
461 flags
&= ~OMAPFB_FORMAT_FLAG_TEARSYNC
;
464 ADD_PREQ(x
, ystart
, xspan
, yspan
);
467 flags
&= ~OMAPFB_FORMAT_FLAG_TEARSYNC
;
470 ADD_PREQ(x
, y
, 1, height
);
473 static void auto_update_complete(void *data
)
475 if (!hwa742
.stop_auto_update
)
476 mod_timer(&hwa742
.auto_update_timer
,
477 jiffies
+ HWA742_AUTO_UPDATE_TIME
);
480 static void hwa742_update_window_auto(unsigned long arg
)
483 struct hwa742_request
*last
;
485 create_req_list(&hwa742
.auto_update_window
, &req_list
);
486 last
= list_entry(req_list
.prev
, struct hwa742_request
, entry
);
488 last
->complete
= auto_update_complete
;
489 last
->complete_data
= NULL
;
491 submit_req_list(&req_list
);
494 int hwa742_update_window_async(struct fb_info
*fbi
,
495 struct omapfb_update_window
*win
,
496 void (*complete_callback
)(void *arg
),
497 void *complete_callback_data
)
500 struct hwa742_request
*last
;
503 if (hwa742
.update_mode
!= OMAPFB_MANUAL_UPDATE
) {
504 dev_dbg(hwa742
.fbdev
->dev
, "invalid update mode\n");
508 if (unlikely(win
->format
&
509 ~(0x03 | OMAPFB_FORMAT_FLAG_DOUBLE
|
510 OMAPFB_FORMAT_FLAG_TEARSYNC
| OMAPFB_FORMAT_FLAG_FORCE_VSYNC
))) {
511 dev_dbg(hwa742
.fbdev
->dev
, "invalid window flag\n");
516 create_req_list(win
, &req_list
);
517 last
= list_entry(req_list
.prev
, struct hwa742_request
, entry
);
519 last
->complete
= complete_callback
;
520 last
->complete_data
= (void *)complete_callback_data
;
522 submit_req_list(&req_list
);
527 EXPORT_SYMBOL(hwa742_update_window_async
);
529 static int hwa742_setup_plane(int plane
, int channel_out
,
530 unsigned long offset
, int screen_width
,
531 int pos_x
, int pos_y
, int width
, int height
,
534 if (plane
!= OMAPFB_PLANE_GFX
||
535 channel_out
!= OMAPFB_CHANNEL_OUT_LCD
)
541 static int hwa742_enable_plane(int plane
, int enable
)
546 hwa742
.int_ctrl
->enable_plane(plane
, enable
);
551 static int sync_handler(struct hwa742_request
*req
)
553 complete(req
->par
.sync
);
557 static void hwa742_sync(void)
560 struct hwa742_request
*req
;
561 struct completion comp
;
565 req
->handler
= sync_handler
;
566 req
->complete
= NULL
;
567 init_completion(&comp
);
568 req
->par
.sync
= &comp
;
570 list_add(&req
->entry
, &req_list
);
571 submit_req_list(&req_list
);
573 wait_for_completion(&comp
);
576 static void hwa742_bind_client(struct omapfb_notifier_block
*nb
)
578 dev_dbg(hwa742
.fbdev
->dev
, "update_mode %d\n", hwa742
.update_mode
);
579 if (hwa742
.update_mode
== OMAPFB_MANUAL_UPDATE
) {
580 omapfb_notify_clients(hwa742
.fbdev
, OMAPFB_EVENT_READY
);
584 static int hwa742_set_update_mode(enum omapfb_update_mode mode
)
586 if (mode
!= OMAPFB_MANUAL_UPDATE
&& mode
!= OMAPFB_AUTO_UPDATE
&&
587 mode
!= OMAPFB_UPDATE_DISABLED
)
590 if (mode
== hwa742
.update_mode
)
593 dev_info(hwa742
.fbdev
->dev
, "HWA742: setting update mode to %s\n",
594 mode
== OMAPFB_UPDATE_DISABLED
? "disabled" :
595 (mode
== OMAPFB_AUTO_UPDATE
? "auto" : "manual"));
597 switch (hwa742
.update_mode
) {
598 case OMAPFB_MANUAL_UPDATE
:
599 omapfb_notify_clients(hwa742
.fbdev
, OMAPFB_EVENT_DISABLED
);
601 case OMAPFB_AUTO_UPDATE
:
602 hwa742
.stop_auto_update
= 1;
603 del_timer_sync(&hwa742
.auto_update_timer
);
605 case OMAPFB_UPDATE_DISABLED
:
609 hwa742
.update_mode
= mode
;
611 hwa742
.stop_auto_update
= 0;
614 case OMAPFB_MANUAL_UPDATE
:
615 omapfb_notify_clients(hwa742
.fbdev
, OMAPFB_EVENT_READY
);
617 case OMAPFB_AUTO_UPDATE
:
618 hwa742_update_window_auto(0);
620 case OMAPFB_UPDATE_DISABLED
:
627 static enum omapfb_update_mode
hwa742_get_update_mode(void)
629 return hwa742
.update_mode
;
632 static unsigned long round_to_extif_ticks(unsigned long ps
, int div
)
634 int bus_tick
= hwa742
.extif_clk_period
* div
;
635 return (ps
+ bus_tick
- 1) / bus_tick
* bus_tick
;
638 static int calc_reg_timing(unsigned long sysclk
, int div
)
640 struct extif_timings
*t
;
641 unsigned long systim
;
643 /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
644 * AccessTime 2 ns + 12.2 ns (regs),
645 * WEOffTime = WEOnTime + 1 ns,
646 * REOffTime = REOnTime + 16 ns (regs),
647 * CSOffTime = REOffTime + 1 ns
648 * ReadCycle = 2ns + 2*SYSCLK (regs),
649 * WriteCycle = 2*SYSCLK + 2 ns,
650 * CSPulseWidth = 10 ns */
651 systim
= 1000000000 / (sysclk
/ 1000);
652 dev_dbg(hwa742
.fbdev
->dev
, "HWA742 systim %lu ps extif_clk_period %u ps"
653 "extif_clk_div %d\n", systim
, hwa742
.extif_clk_period
, div
);
655 t
= &hwa742
.reg_timings
;
656 memset(t
, 0, sizeof(*t
));
659 t
->we_on_time
= round_to_extif_ticks(t
->cs_on_time
+ 2000, div
);
660 t
->re_on_time
= round_to_extif_ticks(t
->cs_on_time
+ 2000, div
);
661 t
->access_time
= round_to_extif_ticks(t
->re_on_time
+ 12200, div
);
662 t
->we_off_time
= round_to_extif_ticks(t
->we_on_time
+ 1000, div
);
663 t
->re_off_time
= round_to_extif_ticks(t
->re_on_time
+ 16000, div
);
664 t
->cs_off_time
= round_to_extif_ticks(t
->re_off_time
+ 1000, div
);
665 t
->we_cycle_time
= round_to_extif_ticks(2 * systim
+ 2000, div
);
666 if (t
->we_cycle_time
< t
->we_off_time
)
667 t
->we_cycle_time
= t
->we_off_time
;
668 t
->re_cycle_time
= round_to_extif_ticks(2 * systim
+ 2000, div
);
669 if (t
->re_cycle_time
< t
->re_off_time
)
670 t
->re_cycle_time
= t
->re_off_time
;
671 t
->cs_pulse_width
= 0;
673 dev_dbg(hwa742
.fbdev
->dev
, "[reg]cson %d csoff %d reon %d reoff %d\n",
674 t
->cs_on_time
, t
->cs_off_time
, t
->re_on_time
, t
->re_off_time
);
675 dev_dbg(hwa742
.fbdev
->dev
, "[reg]weon %d weoff %d recyc %d wecyc %d\n",
676 t
->we_on_time
, t
->we_off_time
, t
->re_cycle_time
,
678 dev_dbg(hwa742
.fbdev
->dev
, "[reg]rdaccess %d cspulse %d\n",
679 t
->access_time
, t
->cs_pulse_width
);
681 return hwa742
.extif
->convert_timings(t
);
684 static int calc_lut_timing(unsigned long sysclk
, int div
)
686 struct extif_timings
*t
;
687 unsigned long systim
;
689 /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
690 * AccessTime 2 ns + 4 * SYSCLK + 26 (lut),
691 * WEOffTime = WEOnTime + 1 ns,
692 * REOffTime = REOnTime + 4*SYSCLK + 26 ns (lut),
693 * CSOffTime = REOffTime + 1 ns
694 * ReadCycle = 2ns + 4*SYSCLK + 26 ns (lut),
695 * WriteCycle = 2*SYSCLK + 2 ns,
696 * CSPulseWidth = 10 ns
698 systim
= 1000000000 / (sysclk
/ 1000);
699 dev_dbg(hwa742
.fbdev
->dev
, "HWA742 systim %lu ps extif_clk_period %u ps"
700 "extif_clk_div %d\n", systim
, hwa742
.extif_clk_period
, div
);
702 t
= &hwa742
.lut_timings
;
703 memset(t
, 0, sizeof(*t
));
708 t
->we_on_time
= round_to_extif_ticks(t
->cs_on_time
+ 2000, div
);
709 t
->re_on_time
= round_to_extif_ticks(t
->cs_on_time
+ 2000, div
);
710 t
->access_time
= round_to_extif_ticks(t
->re_on_time
+ 4 * systim
+
712 t
->we_off_time
= round_to_extif_ticks(t
->we_on_time
+ 1000, div
);
713 t
->re_off_time
= round_to_extif_ticks(t
->re_on_time
+ 4 * systim
+
715 t
->cs_off_time
= round_to_extif_ticks(t
->re_off_time
+ 1000, div
);
716 t
->we_cycle_time
= round_to_extif_ticks(2 * systim
+ 2000, div
);
717 if (t
->we_cycle_time
< t
->we_off_time
)
718 t
->we_cycle_time
= t
->we_off_time
;
719 t
->re_cycle_time
= round_to_extif_ticks(2000 + 4 * systim
+ 26000, div
);
720 if (t
->re_cycle_time
< t
->re_off_time
)
721 t
->re_cycle_time
= t
->re_off_time
;
722 t
->cs_pulse_width
= 0;
724 dev_dbg(hwa742
.fbdev
->dev
, "[lut]cson %d csoff %d reon %d reoff %d\n",
725 t
->cs_on_time
, t
->cs_off_time
, t
->re_on_time
, t
->re_off_time
);
726 dev_dbg(hwa742
.fbdev
->dev
, "[lut]weon %d weoff %d recyc %d wecyc %d\n",
727 t
->we_on_time
, t
->we_off_time
, t
->re_cycle_time
,
729 dev_dbg(hwa742
.fbdev
->dev
, "[lut]rdaccess %d cspulse %d\n",
730 t
->access_time
, t
->cs_pulse_width
);
732 return hwa742
.extif
->convert_timings(t
);
735 static int calc_extif_timings(unsigned long sysclk
, int *extif_mem_div
)
740 hwa742
.extif
->get_clk_info(&hwa742
.extif_clk_period
, &max_clk_div
);
741 for (div
= 1; div
< max_clk_div
; div
++) {
742 if (calc_reg_timing(sysclk
, div
) == 0)
745 if (div
> max_clk_div
)
748 *extif_mem_div
= div
;
750 for (div
= 1; div
< max_clk_div
; div
++) {
751 if (calc_lut_timing(sysclk
, div
) == 0)
755 if (div
> max_clk_div
)
761 dev_err(hwa742
.fbdev
->dev
, "can't setup timings\n");
765 static void calc_hwa742_clk_rates(unsigned long ext_clk
,
766 unsigned long *sys_clk
, unsigned long *pix_clk
)
769 int sys_div
= 0, sys_mul
= 0;
772 pix_clk_src
= hwa742_read_reg(HWA742_CLK_SRC_REG
);
773 pix_div
= ((pix_clk_src
>> 3) & 0x1f) + 1;
774 if ((pix_clk_src
& (0x3 << 1)) == 0) {
775 /* Source is the PLL */
776 sys_div
= (hwa742_read_reg(HWA742_PLL_DIV_REG
) & 0x3f) + 1;
777 sys_mul
= (hwa742_read_reg(HWA742_PLL_4_REG
) & 0x7f) + 1;
778 *sys_clk
= ext_clk
* sys_mul
/ sys_div
;
779 } else /* else source is ext clk, or oscillator */
782 *pix_clk
= *sys_clk
/ pix_div
; /* HZ */
783 dev_dbg(hwa742
.fbdev
->dev
,
784 "ext_clk %ld pix_src %d pix_div %d sys_div %d sys_mul %d\n",
785 ext_clk
, pix_clk_src
& (0x3 << 1), pix_div
, sys_div
, sys_mul
);
786 dev_dbg(hwa742
.fbdev
->dev
, "sys_clk %ld pix_clk %ld\n",
791 static int setup_tearsync(unsigned long pix_clk
, int extif_div
)
797 int hs_pol_inv
, vs_pol_inv
;
798 int use_hsvs
, use_ndp
;
801 hsw
= hwa742_read_reg(HWA742_HS_W_REG
);
802 vsw
= hwa742_read_reg(HWA742_VS_W_REG
);
803 hs_pol_inv
= !(hsw
& 0x80);
804 vs_pol_inv
= !(vsw
& 0x80);
808 hdisp
= (hwa742_read_reg(HWA742_H_DISP_REG
) & 0x7f) * 8;
809 vdisp
= hwa742_read_reg(HWA742_V_DISP_1_REG
) +
810 ((hwa742_read_reg(HWA742_V_DISP_2_REG
) & 0x3) << 8);
812 hndp
= hwa742_read_reg(HWA742_H_NDP_REG
) & 0x7f;
813 vndp
= hwa742_read_reg(HWA742_V_NDP_REG
);
815 /* time to transfer one pixel (16bpp) in ps */
816 hwa742
.pix_tx_time
= hwa742
.reg_timings
.we_cycle_time
;
817 if (hwa742
.extif
->get_max_tx_rate
!= NULL
) {
819 * The external interface might have a rate limitation,
820 * if so, we have to maximize our transfer rate.
822 unsigned long min_tx_time
;
823 unsigned long max_tx_rate
= hwa742
.extif
->get_max_tx_rate();
825 dev_dbg(hwa742
.fbdev
->dev
, "max_tx_rate %ld HZ\n",
827 min_tx_time
= 1000000000 / (max_tx_rate
/ 1000); /* ps */
828 if (hwa742
.pix_tx_time
< min_tx_time
)
829 hwa742
.pix_tx_time
= min_tx_time
;
832 /* time to update one line in ps */
833 hwa742
.line_upd_time
= (hdisp
+ hndp
) * 1000000 / (pix_clk
/ 1000);
834 hwa742
.line_upd_time
*= 1000;
835 if (hdisp
* hwa742
.pix_tx_time
> hwa742
.line_upd_time
)
837 * transfer speed too low, we might have to use both
842 /* decent transfer speed, we'll always use only VS */
845 if (use_hsvs
&& (hs_pol_inv
|| vs_pol_inv
)) {
847 * HS or'ed with VS doesn't work, use the active high
848 * TE signal based on HNDP / VNDP
857 * Use HS or'ed with VS as a TE signal if both are needed
858 * or VNDP if only vsync is needed.
869 hs
= hs
* 1000000 / (pix_clk
/ 1000); /* ps */
872 vs
= vs
* (hdisp
+ hndp
) * 1000000 / (pix_clk
/ 1000); /* ps */
877 /* set VS to 120% of HS to minimize VS detection time */
879 /* minimize HS too */
882 b
= hwa742_read_reg(HWA742_NDP_CTRL
);
884 b
|= use_hsvs
? 1 : 0;
885 b
|= (use_ndp
&& use_hsvs
) ? 0 : 2;
886 hwa742_write_reg(HWA742_NDP_CTRL
, b
);
888 hwa742
.vsync_only
= !use_hsvs
;
890 dev_dbg(hwa742
.fbdev
->dev
,
891 "pix_clk %ld HZ pix_tx_time %ld ps line_upd_time %ld ps\n",
892 pix_clk
, hwa742
.pix_tx_time
, hwa742
.line_upd_time
);
893 dev_dbg(hwa742
.fbdev
->dev
,
894 "hs %d ps vs %d ps mode %d vsync_only %d\n",
895 hs
, vs
, (b
& 0x3), !use_hsvs
);
897 return hwa742
.extif
->setup_tearsync(1, hs
, vs
,
898 hs_pol_inv
, vs_pol_inv
, extif_div
);
901 static void hwa742_get_caps(int plane
, struct omapfb_caps
*caps
)
903 hwa742
.int_ctrl
->get_caps(plane
, caps
);
904 caps
->ctrl
|= OMAPFB_CAPS_MANUAL_UPDATE
|
905 OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE
;
906 if (hwa742
.te_connected
)
907 caps
->ctrl
|= OMAPFB_CAPS_TEARSYNC
;
908 caps
->wnd_color
|= (1 << OMAPFB_COLOR_RGB565
) |
909 (1 << OMAPFB_COLOR_YUV420
);
912 static void hwa742_suspend(void)
914 hwa742
.update_mode_before_suspend
= hwa742
.update_mode
;
915 hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED
);
916 /* Enable sleep mode */
917 hwa742_write_reg(HWA742_POWER_SAVE
, 1 << 1);
918 if (hwa742
.power_down
!= NULL
)
919 hwa742
.power_down(hwa742
.fbdev
->dev
);
922 static void hwa742_resume(void)
924 if (hwa742
.power_up
!= NULL
)
925 hwa742
.power_up(hwa742
.fbdev
->dev
);
926 /* Disable sleep mode */
927 hwa742_write_reg(HWA742_POWER_SAVE
, 0);
929 /* Loop until PLL output is stabilized */
930 if (hwa742_read_reg(HWA742_PLL_DIV_REG
) & (1 << 7))
932 set_current_state(TASK_UNINTERRUPTIBLE
);
933 schedule_timeout(msecs_to_jiffies(5));
935 hwa742_set_update_mode(hwa742
.update_mode_before_suspend
);
938 static int hwa742_init(struct omapfb_device
*fbdev
, int ext_mode
,
939 struct omapfb_mem_desc
*req_vram
)
943 unsigned long ext_clk
;
944 unsigned long sys_clk
, pix_clk
;
946 struct omapfb_platform_data
*omapfb_conf
;
947 struct hwa742_platform_data
*ctrl_conf
;
949 BUG_ON(!fbdev
->ext_if
|| !fbdev
->int_ctrl
);
951 hwa742
.fbdev
= fbdev
;
952 hwa742
.extif
= fbdev
->ext_if
;
953 hwa742
.int_ctrl
= fbdev
->int_ctrl
;
955 omapfb_conf
= fbdev
->dev
->platform_data
;
956 ctrl_conf
= omapfb_conf
->ctrl_platform_data
;
958 if (ctrl_conf
== NULL
|| ctrl_conf
->get_clock_rate
== NULL
) {
959 dev_err(fbdev
->dev
, "HWA742: missing platform data\n");
964 hwa742
.power_down
= ctrl_conf
->power_down
;
965 hwa742
.power_up
= ctrl_conf
->power_up
;
967 spin_lock_init(&hwa742
.req_lock
);
969 if ((r
= hwa742
.int_ctrl
->init(fbdev
, 1, req_vram
)) < 0)
972 if ((r
= hwa742
.extif
->init(fbdev
)) < 0)
975 ext_clk
= ctrl_conf
->get_clock_rate(fbdev
->dev
);
976 if ((r
= calc_extif_timings(ext_clk
, &extif_mem_div
)) < 0)
978 hwa742
.extif
->set_timings(&hwa742
.reg_timings
);
979 if (hwa742
.power_up
!= NULL
)
980 hwa742
.power_up(fbdev
->dev
);
982 calc_hwa742_clk_rates(ext_clk
, &sys_clk
, &pix_clk
);
983 if ((r
= calc_extif_timings(sys_clk
, &extif_mem_div
)) < 0)
985 hwa742
.extif
->set_timings(&hwa742
.reg_timings
);
987 rev
= hwa742_read_reg(HWA742_REV_CODE_REG
);
988 if ((rev
& 0xfc) != 0x80) {
989 dev_err(fbdev
->dev
, "HWA742: invalid revision %02x\n", rev
);
995 if (!(hwa742_read_reg(HWA742_PLL_DIV_REG
) & 0x80)) {
997 "HWA742: controller not initialized by the bootloader\n");
1002 if (ctrl_conf
->te_connected
) {
1003 if ((r
= setup_tearsync(pix_clk
, extif_mem_div
)) < 0) {
1004 dev_err(hwa742
.fbdev
->dev
,
1005 "HWA742: can't setup tearing synchronization\n");
1008 hwa742
.te_connected
= 1;
1011 hwa742
.max_transmit_size
= hwa742
.extif
->max_transmit_size
;
1013 hwa742
.update_mode
= OMAPFB_UPDATE_DISABLED
;
1015 hwa742
.auto_update_window
.x
= 0;
1016 hwa742
.auto_update_window
.y
= 0;
1017 hwa742
.auto_update_window
.width
= fbdev
->panel
->x_res
;
1018 hwa742
.auto_update_window
.height
= fbdev
->panel
->y_res
;
1019 hwa742
.auto_update_window
.format
= 0;
1021 init_timer(&hwa742
.auto_update_timer
);
1022 hwa742
.auto_update_timer
.function
= hwa742_update_window_auto
;
1023 hwa742
.auto_update_timer
.data
= 0;
1025 hwa742
.prev_color_mode
= -1;
1026 hwa742
.prev_flags
= 0;
1028 hwa742
.fbdev
= fbdev
;
1030 INIT_LIST_HEAD(&hwa742
.free_req_list
);
1031 INIT_LIST_HEAD(&hwa742
.pending_req_list
);
1032 for (i
= 0; i
< ARRAY_SIZE(hwa742
.req_pool
); i
++)
1033 list_add(&hwa742
.req_pool
[i
].entry
, &hwa742
.free_req_list
);
1034 BUG_ON(i
<= IRQ_REQ_POOL_SIZE
);
1035 sema_init(&hwa742
.req_sema
, i
- IRQ_REQ_POOL_SIZE
);
1037 conf
= hwa742_read_reg(HWA742_CONFIG_REG
);
1038 dev_info(fbdev
->dev
, ": Epson HWA742 LCD controller rev %d "
1039 "initialized (CNF pins %x)\n", rev
& 0x03, conf
& 0x07);
1043 if (hwa742
.power_down
!= NULL
)
1044 hwa742
.power_down(fbdev
->dev
);
1046 hwa742
.extif
->cleanup();
1048 hwa742
.int_ctrl
->cleanup();
1053 static void hwa742_cleanup(void)
1055 hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED
);
1056 hwa742
.extif
->cleanup();
1057 hwa742
.int_ctrl
->cleanup();
1058 if (hwa742
.power_down
!= NULL
)
1059 hwa742
.power_down(hwa742
.fbdev
->dev
);
1062 struct lcd_ctrl hwa742_ctrl
= {
1064 .init
= hwa742_init
,
1065 .cleanup
= hwa742_cleanup
,
1066 .bind_client
= hwa742_bind_client
,
1067 .get_caps
= hwa742_get_caps
,
1068 .set_update_mode
= hwa742_set_update_mode
,
1069 .get_update_mode
= hwa742_get_update_mode
,
1070 .setup_plane
= hwa742_setup_plane
,
1071 .enable_plane
= hwa742_enable_plane
,
1072 .update_window
= hwa742_update_window_async
,
1073 .sync
= hwa742_sync
,
1074 .suspend
= hwa742_suspend
,
1075 .resume
= hwa742_resume
,