1 /* 2 * Epson HWA742 LCD controller driver 3 * 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> 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 #include <linux/interrupt.h> 29 30 #include "omapfb.h" 31 32 #define HWA742_REV_CODE_REG 0x0 33 #define HWA742_CONFIG_REG 0x2 34 #define HWA742_PLL_DIV_REG 0x4 35 #define HWA742_PLL_0_REG 0x6 36 #define HWA742_PLL_1_REG 0x8 37 #define HWA742_PLL_2_REG 0xa 38 #define HWA742_PLL_3_REG 0xc 39 #define HWA742_PLL_4_REG 0xe 40 #define HWA742_CLK_SRC_REG 0x12 41 #define HWA742_PANEL_TYPE_REG 0x14 42 #define HWA742_H_DISP_REG 0x16 43 #define HWA742_H_NDP_REG 0x18 44 #define HWA742_V_DISP_1_REG 0x1a 45 #define HWA742_V_DISP_2_REG 0x1c 46 #define HWA742_V_NDP_REG 0x1e 47 #define HWA742_HS_W_REG 0x20 48 #define HWA742_HP_S_REG 0x22 49 #define HWA742_VS_W_REG 0x24 50 #define HWA742_VP_S_REG 0x26 51 #define HWA742_PCLK_POL_REG 0x28 52 #define HWA742_INPUT_MODE_REG 0x2a 53 #define HWA742_TRANSL_MODE_REG1 0x2e 54 #define HWA742_DISP_MODE_REG 0x34 55 #define HWA742_WINDOW_TYPE 0x36 56 #define HWA742_WINDOW_X_START_0 0x38 57 #define HWA742_WINDOW_X_START_1 0x3a 58 #define HWA742_WINDOW_Y_START_0 0x3c 59 #define HWA742_WINDOW_Y_START_1 0x3e 60 #define HWA742_WINDOW_X_END_0 0x40 61 #define HWA742_WINDOW_X_END_1 0x42 62 #define HWA742_WINDOW_Y_END_0 0x44 63 #define HWA742_WINDOW_Y_END_1 0x46 64 #define HWA742_MEMORY_WRITE_LSB 0x48 65 #define HWA742_MEMORY_WRITE_MSB 0x49 66 #define HWA742_MEMORY_READ_0 0x4a 67 #define HWA742_MEMORY_READ_1 0x4c 68 #define HWA742_MEMORY_READ_2 0x4e 69 #define HWA742_POWER_SAVE 0x56 70 #define HWA742_NDP_CTRL 0x58 71 72 #define HWA742_AUTO_UPDATE_TIME (HZ / 20) 73 74 /* Reserve 4 request slots for requests in irq context */ 75 #define REQ_POOL_SIZE 24 76 #define IRQ_REQ_POOL_SIZE 4 77 78 #define REQ_FROM_IRQ_POOL 0x01 79 80 #define REQ_COMPLETE 0 81 #define REQ_PENDING 1 82 83 struct update_param { 84 int x, y, width, height; 85 int color_mode; 86 int flags; 87 }; 88 89 struct hwa742_request { 90 struct list_head entry; 91 unsigned int flags; 92 93 int (*handler)(struct hwa742_request *req); 94 void (*complete)(void *data); 95 void *complete_data; 96 97 union { 98 struct update_param update; 99 struct completion *sync; 100 } par; 101 }; 102 103 struct { 104 enum omapfb_update_mode update_mode; 105 enum omapfb_update_mode update_mode_before_suspend; 106 107 struct timer_list auto_update_timer; 108 int stop_auto_update; 109 struct omapfb_update_window auto_update_window; 110 unsigned te_connected:1; 111 unsigned vsync_only:1; 112 113 struct hwa742_request req_pool[REQ_POOL_SIZE]; 114 struct list_head pending_req_list; 115 struct list_head free_req_list; 116 struct semaphore req_sema; 117 spinlock_t req_lock; 118 119 struct extif_timings reg_timings, lut_timings; 120 121 int prev_color_mode; 122 int prev_flags; 123 int window_type; 124 125 u32 max_transmit_size; 126 u32 extif_clk_period; 127 unsigned long pix_tx_time; 128 unsigned long line_upd_time; 129 130 131 struct omapfb_device *fbdev; 132 struct lcd_ctrl_extif *extif; 133 const struct lcd_ctrl *int_ctrl; 134 135 struct clk *sys_ck; 136 } hwa742; 137 138 struct lcd_ctrl hwa742_ctrl; 139 140 static u8 hwa742_read_reg(u8 reg) 141 { 142 u8 data; 143 144 hwa742.extif->set_bits_per_cycle(8); 145 hwa742.extif->write_command(®, 1); 146 hwa742.extif->read_data(&data, 1); 147 148 return data; 149 } 150 151 static void hwa742_write_reg(u8 reg, u8 data) 152 { 153 hwa742.extif->set_bits_per_cycle(8); 154 hwa742.extif->write_command(®, 1); 155 hwa742.extif->write_data(&data, 1); 156 } 157 158 static void set_window_regs(int x_start, int y_start, int x_end, int y_end) 159 { 160 u8 tmp[8]; 161 u8 cmd; 162 163 x_end--; 164 y_end--; 165 tmp[0] = x_start; 166 tmp[1] = x_start >> 8; 167 tmp[2] = y_start; 168 tmp[3] = y_start >> 8; 169 tmp[4] = x_end; 170 tmp[5] = x_end >> 8; 171 tmp[6] = y_end; 172 tmp[7] = y_end >> 8; 173 174 hwa742.extif->set_bits_per_cycle(8); 175 cmd = HWA742_WINDOW_X_START_0; 176 177 hwa742.extif->write_command(&cmd, 1); 178 179 hwa742.extif->write_data(tmp, 8); 180 } 181 182 static void set_format_regs(int conv, int transl, int flags) 183 { 184 if (flags & OMAPFB_FORMAT_FLAG_DOUBLE) { 185 hwa742.window_type = ((hwa742.window_type & 0xfc) | 0x01); 186 #ifdef VERBOSE 187 dev_dbg(hwa742.fbdev->dev, "hwa742: enabled pixel doubling\n"); 188 #endif 189 } else { 190 hwa742.window_type = (hwa742.window_type & 0xfc); 191 #ifdef VERBOSE 192 dev_dbg(hwa742.fbdev->dev, "hwa742: disabled pixel doubling\n"); 193 #endif 194 } 195 196 hwa742_write_reg(HWA742_INPUT_MODE_REG, conv); 197 hwa742_write_reg(HWA742_TRANSL_MODE_REG1, transl); 198 hwa742_write_reg(HWA742_WINDOW_TYPE, hwa742.window_type); 199 } 200 201 static void enable_tearsync(int y, int width, int height, int screen_height, 202 int force_vsync) 203 { 204 u8 b; 205 206 b = hwa742_read_reg(HWA742_NDP_CTRL); 207 b |= 1 << 2; 208 hwa742_write_reg(HWA742_NDP_CTRL, b); 209 210 if (likely(hwa742.vsync_only || force_vsync)) { 211 hwa742.extif->enable_tearsync(1, 0); 212 return; 213 } 214 215 if (width * hwa742.pix_tx_time < hwa742.line_upd_time) { 216 hwa742.extif->enable_tearsync(1, 0); 217 return; 218 } 219 220 if ((width * hwa742.pix_tx_time / 1000) * height < 221 (y + height) * (hwa742.line_upd_time / 1000)) { 222 hwa742.extif->enable_tearsync(1, 0); 223 return; 224 } 225 226 hwa742.extif->enable_tearsync(1, y + 1); 227 } 228 229 static void disable_tearsync(void) 230 { 231 u8 b; 232 233 hwa742.extif->enable_tearsync(0, 0); 234 235 b = hwa742_read_reg(HWA742_NDP_CTRL); 236 b &= ~(1 << 2); 237 hwa742_write_reg(HWA742_NDP_CTRL, b); 238 } 239 240 static inline struct hwa742_request *alloc_req(void) 241 { 242 unsigned long flags; 243 struct hwa742_request *req; 244 int req_flags = 0; 245 246 if (!in_interrupt()) 247 down(&hwa742.req_sema); 248 else 249 req_flags = REQ_FROM_IRQ_POOL; 250 251 spin_lock_irqsave(&hwa742.req_lock, flags); 252 BUG_ON(list_empty(&hwa742.free_req_list)); 253 req = list_entry(hwa742.free_req_list.next, 254 struct hwa742_request, entry); 255 list_del(&req->entry); 256 spin_unlock_irqrestore(&hwa742.req_lock, flags); 257 258 INIT_LIST_HEAD(&req->entry); 259 req->flags = req_flags; 260 261 return req; 262 } 263 264 static inline void free_req(struct hwa742_request *req) 265 { 266 unsigned long flags; 267 268 spin_lock_irqsave(&hwa742.req_lock, flags); 269 270 list_move(&req->entry, &hwa742.free_req_list); 271 if (!(req->flags & REQ_FROM_IRQ_POOL)) 272 up(&hwa742.req_sema); 273 274 spin_unlock_irqrestore(&hwa742.req_lock, flags); 275 } 276 277 static void process_pending_requests(void) 278 { 279 unsigned long flags; 280 281 spin_lock_irqsave(&hwa742.req_lock, flags); 282 283 while (!list_empty(&hwa742.pending_req_list)) { 284 struct hwa742_request *req; 285 void (*complete)(void *); 286 void *complete_data; 287 288 req = list_entry(hwa742.pending_req_list.next, 289 struct hwa742_request, entry); 290 spin_unlock_irqrestore(&hwa742.req_lock, flags); 291 292 if (req->handler(req) == REQ_PENDING) 293 return; 294 295 complete = req->complete; 296 complete_data = req->complete_data; 297 free_req(req); 298 299 if (complete) 300 complete(complete_data); 301 302 spin_lock_irqsave(&hwa742.req_lock, flags); 303 } 304 305 spin_unlock_irqrestore(&hwa742.req_lock, flags); 306 } 307 308 static void submit_req_list(struct list_head *head) 309 { 310 unsigned long flags; 311 int process = 1; 312 313 spin_lock_irqsave(&hwa742.req_lock, flags); 314 if (likely(!list_empty(&hwa742.pending_req_list))) 315 process = 0; 316 list_splice_init(head, hwa742.pending_req_list.prev); 317 spin_unlock_irqrestore(&hwa742.req_lock, flags); 318 319 if (process) 320 process_pending_requests(); 321 } 322 323 static void request_complete(void *data) 324 { 325 struct hwa742_request *req = (struct hwa742_request *)data; 326 void (*complete)(void *); 327 void *complete_data; 328 329 complete = req->complete; 330 complete_data = req->complete_data; 331 332 free_req(req); 333 334 if (complete) 335 complete(complete_data); 336 337 process_pending_requests(); 338 } 339 340 static int send_frame_handler(struct hwa742_request *req) 341 { 342 struct update_param *par = &req->par.update; 343 int x = par->x; 344 int y = par->y; 345 int w = par->width; 346 int h = par->height; 347 int bpp; 348 int conv, transl; 349 unsigned long offset; 350 int color_mode = par->color_mode; 351 int flags = par->flags; 352 int scr_width = hwa742.fbdev->panel->x_res; 353 int scr_height = hwa742.fbdev->panel->y_res; 354 355 #ifdef VERBOSE 356 dev_dbg(hwa742.fbdev->dev, "x %d y %d w %d h %d scr_width %d " 357 "color_mode %d flags %d\n", 358 x, y, w, h, scr_width, color_mode, flags); 359 #endif 360 361 switch (color_mode) { 362 case OMAPFB_COLOR_YUV422: 363 bpp = 16; 364 conv = 0x08; 365 transl = 0x25; 366 break; 367 case OMAPFB_COLOR_YUV420: 368 bpp = 12; 369 conv = 0x09; 370 transl = 0x25; 371 break; 372 case OMAPFB_COLOR_RGB565: 373 bpp = 16; 374 conv = 0x01; 375 transl = 0x05; 376 break; 377 default: 378 return -EINVAL; 379 } 380 381 if (hwa742.prev_flags != flags || 382 hwa742.prev_color_mode != color_mode) { 383 set_format_regs(conv, transl, flags); 384 hwa742.prev_color_mode = color_mode; 385 hwa742.prev_flags = flags; 386 } 387 flags = req->par.update.flags; 388 if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC) 389 enable_tearsync(y, scr_width, h, scr_height, 390 flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC); 391 else 392 disable_tearsync(); 393 394 set_window_regs(x, y, x + w, y + h); 395 396 offset = (scr_width * y + x) * bpp / 8; 397 398 hwa742.int_ctrl->setup_plane(OMAPFB_PLANE_GFX, 399 OMAPFB_CHANNEL_OUT_LCD, offset, scr_width, 0, 0, w, h, 400 color_mode); 401 402 hwa742.extif->set_bits_per_cycle(16); 403 404 hwa742.int_ctrl->enable_plane(OMAPFB_PLANE_GFX, 1); 405 hwa742.extif->transfer_area(w, h, request_complete, req); 406 407 return REQ_PENDING; 408 } 409 410 static void send_frame_complete(void *data) 411 { 412 hwa742.int_ctrl->enable_plane(OMAPFB_PLANE_GFX, 0); 413 } 414 415 #define ADD_PREQ(_x, _y, _w, _h) do { \ 416 req = alloc_req(); \ 417 req->handler = send_frame_handler; \ 418 req->complete = send_frame_complete; \ 419 req->par.update.x = _x; \ 420 req->par.update.y = _y; \ 421 req->par.update.width = _w; \ 422 req->par.update.height = _h; \ 423 req->par.update.color_mode = color_mode;\ 424 req->par.update.flags = flags; \ 425 list_add_tail(&req->entry, req_head); \ 426 } while(0) 427 428 static void create_req_list(struct omapfb_update_window *win, 429 struct list_head *req_head) 430 { 431 struct hwa742_request *req; 432 int x = win->x; 433 int y = win->y; 434 int width = win->width; 435 int height = win->height; 436 int color_mode; 437 int flags; 438 439 flags = win->format & ~OMAPFB_FORMAT_MASK; 440 color_mode = win->format & OMAPFB_FORMAT_MASK; 441 442 if (x & 1) { 443 ADD_PREQ(x, y, 1, height); 444 width--; 445 x++; 446 flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC; 447 } 448 if (width & ~1) { 449 unsigned int xspan = width & ~1; 450 unsigned int ystart = y; 451 unsigned int yspan = height; 452 453 if (xspan * height * 2 > hwa742.max_transmit_size) { 454 yspan = hwa742.max_transmit_size / (xspan * 2); 455 ADD_PREQ(x, ystart, xspan, yspan); 456 ystart += yspan; 457 yspan = height - yspan; 458 flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC; 459 } 460 461 ADD_PREQ(x, ystart, xspan, yspan); 462 x += xspan; 463 width -= xspan; 464 flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC; 465 } 466 if (width) 467 ADD_PREQ(x, y, 1, height); 468 } 469 470 static void auto_update_complete(void *data) 471 { 472 if (!hwa742.stop_auto_update) 473 mod_timer(&hwa742.auto_update_timer, 474 jiffies + HWA742_AUTO_UPDATE_TIME); 475 } 476 477 static void hwa742_update_window_auto(unsigned long arg) 478 { 479 LIST_HEAD(req_list); 480 struct hwa742_request *last; 481 482 create_req_list(&hwa742.auto_update_window, &req_list); 483 last = list_entry(req_list.prev, struct hwa742_request, entry); 484 485 last->complete = auto_update_complete; 486 last->complete_data = NULL; 487 488 submit_req_list(&req_list); 489 } 490 491 int hwa742_update_window_async(struct fb_info *fbi, 492 struct omapfb_update_window *win, 493 void (*complete_callback)(void *arg), 494 void *complete_callback_data) 495 { 496 LIST_HEAD(req_list); 497 struct hwa742_request *last; 498 int r = 0; 499 500 if (hwa742.update_mode != OMAPFB_MANUAL_UPDATE) { 501 dev_dbg(hwa742.fbdev->dev, "invalid update mode\n"); 502 r = -EINVAL; 503 goto out; 504 } 505 if (unlikely(win->format & 506 ~(0x03 | OMAPFB_FORMAT_FLAG_DOUBLE | 507 OMAPFB_FORMAT_FLAG_TEARSYNC | OMAPFB_FORMAT_FLAG_FORCE_VSYNC))) { 508 dev_dbg(hwa742.fbdev->dev, "invalid window flag\n"); 509 r = -EINVAL; 510 goto out; 511 } 512 513 create_req_list(win, &req_list); 514 last = list_entry(req_list.prev, struct hwa742_request, entry); 515 516 last->complete = complete_callback; 517 last->complete_data = (void *)complete_callback_data; 518 519 submit_req_list(&req_list); 520 521 out: 522 return r; 523 } 524 EXPORT_SYMBOL(hwa742_update_window_async); 525 526 static int hwa742_setup_plane(int plane, int channel_out, 527 unsigned long offset, int screen_width, 528 int pos_x, int pos_y, int width, int height, 529 int color_mode) 530 { 531 if (plane != OMAPFB_PLANE_GFX || 532 channel_out != OMAPFB_CHANNEL_OUT_LCD) 533 return -EINVAL; 534 535 return 0; 536 } 537 538 static int hwa742_enable_plane(int plane, int enable) 539 { 540 if (plane != 0) 541 return -EINVAL; 542 543 hwa742.int_ctrl->enable_plane(plane, enable); 544 545 return 0; 546 } 547 548 static int sync_handler(struct hwa742_request *req) 549 { 550 complete(req->par.sync); 551 return REQ_COMPLETE; 552 } 553 554 static void hwa742_sync(void) 555 { 556 LIST_HEAD(req_list); 557 struct hwa742_request *req; 558 struct completion comp; 559 560 req = alloc_req(); 561 562 req->handler = sync_handler; 563 req->complete = NULL; 564 init_completion(&comp); 565 req->par.sync = ∁ 566 567 list_add(&req->entry, &req_list); 568 submit_req_list(&req_list); 569 570 wait_for_completion(&comp); 571 } 572 573 static void hwa742_bind_client(struct omapfb_notifier_block *nb) 574 { 575 dev_dbg(hwa742.fbdev->dev, "update_mode %d\n", hwa742.update_mode); 576 if (hwa742.update_mode == OMAPFB_MANUAL_UPDATE) { 577 omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_READY); 578 } 579 } 580 581 static int hwa742_set_update_mode(enum omapfb_update_mode mode) 582 { 583 if (mode != OMAPFB_MANUAL_UPDATE && mode != OMAPFB_AUTO_UPDATE && 584 mode != OMAPFB_UPDATE_DISABLED) 585 return -EINVAL; 586 587 if (mode == hwa742.update_mode) 588 return 0; 589 590 dev_info(hwa742.fbdev->dev, "HWA742: setting update mode to %s\n", 591 mode == OMAPFB_UPDATE_DISABLED ? "disabled" : 592 (mode == OMAPFB_AUTO_UPDATE ? "auto" : "manual")); 593 594 switch (hwa742.update_mode) { 595 case OMAPFB_MANUAL_UPDATE: 596 omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_DISABLED); 597 break; 598 case OMAPFB_AUTO_UPDATE: 599 hwa742.stop_auto_update = 1; 600 del_timer_sync(&hwa742.auto_update_timer); 601 break; 602 case OMAPFB_UPDATE_DISABLED: 603 break; 604 } 605 606 hwa742.update_mode = mode; 607 hwa742_sync(); 608 hwa742.stop_auto_update = 0; 609 610 switch (mode) { 611 case OMAPFB_MANUAL_UPDATE: 612 omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_READY); 613 break; 614 case OMAPFB_AUTO_UPDATE: 615 hwa742_update_window_auto(0); 616 break; 617 case OMAPFB_UPDATE_DISABLED: 618 break; 619 } 620 621 return 0; 622 } 623 624 static enum omapfb_update_mode hwa742_get_update_mode(void) 625 { 626 return hwa742.update_mode; 627 } 628 629 static unsigned long round_to_extif_ticks(unsigned long ps, int div) 630 { 631 int bus_tick = hwa742.extif_clk_period * div; 632 return (ps + bus_tick - 1) / bus_tick * bus_tick; 633 } 634 635 static int calc_reg_timing(unsigned long sysclk, int div) 636 { 637 struct extif_timings *t; 638 unsigned long systim; 639 640 /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns, 641 * AccessTime 2 ns + 12.2 ns (regs), 642 * WEOffTime = WEOnTime + 1 ns, 643 * REOffTime = REOnTime + 16 ns (regs), 644 * CSOffTime = REOffTime + 1 ns 645 * ReadCycle = 2ns + 2*SYSCLK (regs), 646 * WriteCycle = 2*SYSCLK + 2 ns, 647 * CSPulseWidth = 10 ns */ 648 systim = 1000000000 / (sysclk / 1000); 649 dev_dbg(hwa742.fbdev->dev, "HWA742 systim %lu ps extif_clk_period %u ps" 650 "extif_clk_div %d\n", systim, hwa742.extif_clk_period, div); 651 652 t = &hwa742.reg_timings; 653 memset(t, 0, sizeof(*t)); 654 t->clk_div = div; 655 t->cs_on_time = 0; 656 t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); 657 t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); 658 t->access_time = round_to_extif_ticks(t->re_on_time + 12200, div); 659 t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div); 660 t->re_off_time = round_to_extif_ticks(t->re_on_time + 16000, div); 661 t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div); 662 t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div); 663 if (t->we_cycle_time < t->we_off_time) 664 t->we_cycle_time = t->we_off_time; 665 t->re_cycle_time = round_to_extif_ticks(2 * systim + 2000, div); 666 if (t->re_cycle_time < t->re_off_time) 667 t->re_cycle_time = t->re_off_time; 668 t->cs_pulse_width = 0; 669 670 dev_dbg(hwa742.fbdev->dev, "[reg]cson %d csoff %d reon %d reoff %d\n", 671 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time); 672 dev_dbg(hwa742.fbdev->dev, "[reg]weon %d weoff %d recyc %d wecyc %d\n", 673 t->we_on_time, t->we_off_time, t->re_cycle_time, 674 t->we_cycle_time); 675 dev_dbg(hwa742.fbdev->dev, "[reg]rdaccess %d cspulse %d\n", 676 t->access_time, t->cs_pulse_width); 677 678 return hwa742.extif->convert_timings(t); 679 } 680 681 static int calc_lut_timing(unsigned long sysclk, int div) 682 { 683 struct extif_timings *t; 684 unsigned long systim; 685 686 /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns, 687 * AccessTime 2 ns + 4 * SYSCLK + 26 (lut), 688 * WEOffTime = WEOnTime + 1 ns, 689 * REOffTime = REOnTime + 4*SYSCLK + 26 ns (lut), 690 * CSOffTime = REOffTime + 1 ns 691 * ReadCycle = 2ns + 4*SYSCLK + 26 ns (lut), 692 * WriteCycle = 2*SYSCLK + 2 ns, 693 * CSPulseWidth = 10 ns 694 */ 695 systim = 1000000000 / (sysclk / 1000); 696 dev_dbg(hwa742.fbdev->dev, "HWA742 systim %lu ps extif_clk_period %u ps" 697 "extif_clk_div %d\n", systim, hwa742.extif_clk_period, div); 698 699 t = &hwa742.lut_timings; 700 memset(t, 0, sizeof(*t)); 701 702 t->clk_div = div; 703 704 t->cs_on_time = 0; 705 t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); 706 t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); 707 t->access_time = round_to_extif_ticks(t->re_on_time + 4 * systim + 708 26000, div); 709 t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div); 710 t->re_off_time = round_to_extif_ticks(t->re_on_time + 4 * systim + 711 26000, div); 712 t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div); 713 t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div); 714 if (t->we_cycle_time < t->we_off_time) 715 t->we_cycle_time = t->we_off_time; 716 t->re_cycle_time = round_to_extif_ticks(2000 + 4 * systim + 26000, div); 717 if (t->re_cycle_time < t->re_off_time) 718 t->re_cycle_time = t->re_off_time; 719 t->cs_pulse_width = 0; 720 721 dev_dbg(hwa742.fbdev->dev, "[lut]cson %d csoff %d reon %d reoff %d\n", 722 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time); 723 dev_dbg(hwa742.fbdev->dev, "[lut]weon %d weoff %d recyc %d wecyc %d\n", 724 t->we_on_time, t->we_off_time, t->re_cycle_time, 725 t->we_cycle_time); 726 dev_dbg(hwa742.fbdev->dev, "[lut]rdaccess %d cspulse %d\n", 727 t->access_time, t->cs_pulse_width); 728 729 return hwa742.extif->convert_timings(t); 730 } 731 732 static int calc_extif_timings(unsigned long sysclk, int *extif_mem_div) 733 { 734 int max_clk_div; 735 int div; 736 737 hwa742.extif->get_clk_info(&hwa742.extif_clk_period, &max_clk_div); 738 for (div = 1; div < max_clk_div; div++) { 739 if (calc_reg_timing(sysclk, div) == 0) 740 break; 741 } 742 if (div >= max_clk_div) 743 goto err; 744 745 *extif_mem_div = div; 746 747 for (div = 1; div < max_clk_div; div++) { 748 if (calc_lut_timing(sysclk, div) == 0) 749 break; 750 } 751 752 if (div >= max_clk_div) 753 goto err; 754 755 return 0; 756 757 err: 758 dev_err(hwa742.fbdev->dev, "can't setup timings\n"); 759 return -1; 760 } 761 762 static void calc_hwa742_clk_rates(unsigned long ext_clk, 763 unsigned long *sys_clk, unsigned long *pix_clk) 764 { 765 int pix_clk_src; 766 int sys_div = 0, sys_mul = 0; 767 int pix_div; 768 769 pix_clk_src = hwa742_read_reg(HWA742_CLK_SRC_REG); 770 pix_div = ((pix_clk_src >> 3) & 0x1f) + 1; 771 if ((pix_clk_src & (0x3 << 1)) == 0) { 772 /* Source is the PLL */ 773 sys_div = (hwa742_read_reg(HWA742_PLL_DIV_REG) & 0x3f) + 1; 774 sys_mul = (hwa742_read_reg(HWA742_PLL_4_REG) & 0x7f) + 1; 775 *sys_clk = ext_clk * sys_mul / sys_div; 776 } else /* else source is ext clk, or oscillator */ 777 *sys_clk = ext_clk; 778 779 *pix_clk = *sys_clk / pix_div; /* HZ */ 780 dev_dbg(hwa742.fbdev->dev, 781 "ext_clk %ld pix_src %d pix_div %d sys_div %d sys_mul %d\n", 782 ext_clk, pix_clk_src & (0x3 << 1), pix_div, sys_div, sys_mul); 783 dev_dbg(hwa742.fbdev->dev, "sys_clk %ld pix_clk %ld\n", 784 *sys_clk, *pix_clk); 785 } 786 787 788 static int setup_tearsync(unsigned long pix_clk, int extif_div) 789 { 790 int hdisp, vdisp; 791 int hndp, vndp; 792 int hsw, vsw; 793 int hs, vs; 794 int hs_pol_inv, vs_pol_inv; 795 int use_hsvs, use_ndp; 796 u8 b; 797 798 hsw = hwa742_read_reg(HWA742_HS_W_REG); 799 vsw = hwa742_read_reg(HWA742_VS_W_REG); 800 hs_pol_inv = !(hsw & 0x80); 801 vs_pol_inv = !(vsw & 0x80); 802 hsw = hsw & 0x7f; 803 vsw = vsw & 0x3f; 804 805 hdisp = (hwa742_read_reg(HWA742_H_DISP_REG) & 0x7f) * 8; 806 vdisp = hwa742_read_reg(HWA742_V_DISP_1_REG) + 807 ((hwa742_read_reg(HWA742_V_DISP_2_REG) & 0x3) << 8); 808 809 hndp = hwa742_read_reg(HWA742_H_NDP_REG) & 0x7f; 810 vndp = hwa742_read_reg(HWA742_V_NDP_REG); 811 812 /* time to transfer one pixel (16bpp) in ps */ 813 hwa742.pix_tx_time = hwa742.reg_timings.we_cycle_time; 814 if (hwa742.extif->get_max_tx_rate != NULL) { 815 /* 816 * The external interface might have a rate limitation, 817 * if so, we have to maximize our transfer rate. 818 */ 819 unsigned long min_tx_time; 820 unsigned long max_tx_rate = hwa742.extif->get_max_tx_rate(); 821 822 dev_dbg(hwa742.fbdev->dev, "max_tx_rate %ld HZ\n", 823 max_tx_rate); 824 min_tx_time = 1000000000 / (max_tx_rate / 1000); /* ps */ 825 if (hwa742.pix_tx_time < min_tx_time) 826 hwa742.pix_tx_time = min_tx_time; 827 } 828 829 /* time to update one line in ps */ 830 hwa742.line_upd_time = (hdisp + hndp) * 1000000 / (pix_clk / 1000); 831 hwa742.line_upd_time *= 1000; 832 if (hdisp * hwa742.pix_tx_time > hwa742.line_upd_time) 833 /* 834 * transfer speed too low, we might have to use both 835 * HS and VS 836 */ 837 use_hsvs = 1; 838 else 839 /* decent transfer speed, we'll always use only VS */ 840 use_hsvs = 0; 841 842 if (use_hsvs && (hs_pol_inv || vs_pol_inv)) { 843 /* 844 * HS or'ed with VS doesn't work, use the active high 845 * TE signal based on HNDP / VNDP 846 */ 847 use_ndp = 1; 848 hs_pol_inv = 0; 849 vs_pol_inv = 0; 850 hs = hndp; 851 vs = vndp; 852 } else { 853 /* 854 * Use HS or'ed with VS as a TE signal if both are needed 855 * or VNDP if only vsync is needed. 856 */ 857 use_ndp = 0; 858 hs = hsw; 859 vs = vsw; 860 if (!use_hsvs) { 861 hs_pol_inv = 0; 862 vs_pol_inv = 0; 863 } 864 } 865 866 hs = hs * 1000000 / (pix_clk / 1000); /* ps */ 867 hs *= 1000; 868 869 vs = vs * (hdisp + hndp) * 1000000 / (pix_clk / 1000); /* ps */ 870 vs *= 1000; 871 872 if (vs <= hs) 873 return -EDOM; 874 /* set VS to 120% of HS to minimize VS detection time */ 875 vs = hs * 12 / 10; 876 /* minimize HS too */ 877 hs = 10000; 878 879 b = hwa742_read_reg(HWA742_NDP_CTRL); 880 b &= ~0x3; 881 b |= use_hsvs ? 1 : 0; 882 b |= (use_ndp && use_hsvs) ? 0 : 2; 883 hwa742_write_reg(HWA742_NDP_CTRL, b); 884 885 hwa742.vsync_only = !use_hsvs; 886 887 dev_dbg(hwa742.fbdev->dev, 888 "pix_clk %ld HZ pix_tx_time %ld ps line_upd_time %ld ps\n", 889 pix_clk, hwa742.pix_tx_time, hwa742.line_upd_time); 890 dev_dbg(hwa742.fbdev->dev, 891 "hs %d ps vs %d ps mode %d vsync_only %d\n", 892 hs, vs, (b & 0x3), !use_hsvs); 893 894 return hwa742.extif->setup_tearsync(1, hs, vs, 895 hs_pol_inv, vs_pol_inv, extif_div); 896 } 897 898 static void hwa742_get_caps(int plane, struct omapfb_caps *caps) 899 { 900 hwa742.int_ctrl->get_caps(plane, caps); 901 caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE | 902 OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE; 903 if (hwa742.te_connected) 904 caps->ctrl |= OMAPFB_CAPS_TEARSYNC; 905 caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) | 906 (1 << OMAPFB_COLOR_YUV420); 907 } 908 909 static void hwa742_suspend(void) 910 { 911 hwa742.update_mode_before_suspend = hwa742.update_mode; 912 hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED); 913 /* Enable sleep mode */ 914 hwa742_write_reg(HWA742_POWER_SAVE, 1 << 1); 915 clk_disable(hwa742.sys_ck); 916 } 917 918 static void hwa742_resume(void) 919 { 920 clk_enable(hwa742.sys_ck); 921 922 /* Disable sleep mode */ 923 hwa742_write_reg(HWA742_POWER_SAVE, 0); 924 while (1) { 925 /* Loop until PLL output is stabilized */ 926 if (hwa742_read_reg(HWA742_PLL_DIV_REG) & (1 << 7)) 927 break; 928 set_current_state(TASK_UNINTERRUPTIBLE); 929 schedule_timeout(msecs_to_jiffies(5)); 930 } 931 hwa742_set_update_mode(hwa742.update_mode_before_suspend); 932 } 933 934 static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, 935 struct omapfb_mem_desc *req_vram) 936 { 937 int r = 0, i; 938 u8 rev, conf; 939 unsigned long ext_clk; 940 unsigned long sys_clk, pix_clk; 941 int extif_mem_div; 942 struct omapfb_platform_data *omapfb_conf; 943 944 BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl); 945 946 hwa742.fbdev = fbdev; 947 hwa742.extif = fbdev->ext_if; 948 hwa742.int_ctrl = fbdev->int_ctrl; 949 950 omapfb_conf = dev_get_platdata(fbdev->dev); 951 952 hwa742.sys_ck = clk_get(NULL, "hwa_sys_ck"); 953 954 spin_lock_init(&hwa742.req_lock); 955 956 if ((r = hwa742.int_ctrl->init(fbdev, 1, req_vram)) < 0) 957 goto err1; 958 959 if ((r = hwa742.extif->init(fbdev)) < 0) 960 goto err2; 961 962 ext_clk = clk_get_rate(hwa742.sys_ck); 963 if ((r = calc_extif_timings(ext_clk, &extif_mem_div)) < 0) 964 goto err3; 965 hwa742.extif->set_timings(&hwa742.reg_timings); 966 clk_enable(hwa742.sys_ck); 967 968 calc_hwa742_clk_rates(ext_clk, &sys_clk, &pix_clk); 969 if ((r = calc_extif_timings(sys_clk, &extif_mem_div)) < 0) 970 goto err4; 971 hwa742.extif->set_timings(&hwa742.reg_timings); 972 973 rev = hwa742_read_reg(HWA742_REV_CODE_REG); 974 if ((rev & 0xfc) != 0x80) { 975 dev_err(fbdev->dev, "HWA742: invalid revision %02x\n", rev); 976 r = -ENODEV; 977 goto err4; 978 } 979 980 981 if (!(hwa742_read_reg(HWA742_PLL_DIV_REG) & 0x80)) { 982 dev_err(fbdev->dev, 983 "HWA742: controller not initialized by the bootloader\n"); 984 r = -ENODEV; 985 goto err4; 986 } 987 988 if ((r = setup_tearsync(pix_clk, extif_mem_div)) < 0) { 989 dev_err(hwa742.fbdev->dev, 990 "HWA742: can't setup tearing synchronization\n"); 991 goto err4; 992 } 993 hwa742.te_connected = 1; 994 995 hwa742.max_transmit_size = hwa742.extif->max_transmit_size; 996 997 hwa742.update_mode = OMAPFB_UPDATE_DISABLED; 998 999 hwa742.auto_update_window.x = 0; 1000 hwa742.auto_update_window.y = 0; 1001 hwa742.auto_update_window.width = fbdev->panel->x_res; 1002 hwa742.auto_update_window.height = fbdev->panel->y_res; 1003 hwa742.auto_update_window.format = 0; 1004 1005 init_timer(&hwa742.auto_update_timer); 1006 hwa742.auto_update_timer.function = hwa742_update_window_auto; 1007 hwa742.auto_update_timer.data = 0; 1008 1009 hwa742.prev_color_mode = -1; 1010 hwa742.prev_flags = 0; 1011 1012 hwa742.fbdev = fbdev; 1013 1014 INIT_LIST_HEAD(&hwa742.free_req_list); 1015 INIT_LIST_HEAD(&hwa742.pending_req_list); 1016 for (i = 0; i < ARRAY_SIZE(hwa742.req_pool); i++) 1017 list_add(&hwa742.req_pool[i].entry, &hwa742.free_req_list); 1018 BUG_ON(i <= IRQ_REQ_POOL_SIZE); 1019 sema_init(&hwa742.req_sema, i - IRQ_REQ_POOL_SIZE); 1020 1021 conf = hwa742_read_reg(HWA742_CONFIG_REG); 1022 dev_info(fbdev->dev, ": Epson HWA742 LCD controller rev %d " 1023 "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07); 1024 1025 return 0; 1026 err4: 1027 clk_disable(hwa742.sys_ck); 1028 err3: 1029 hwa742.extif->cleanup(); 1030 err2: 1031 hwa742.int_ctrl->cleanup(); 1032 err1: 1033 return r; 1034 } 1035 1036 static void hwa742_cleanup(void) 1037 { 1038 hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED); 1039 hwa742.extif->cleanup(); 1040 hwa742.int_ctrl->cleanup(); 1041 clk_disable(hwa742.sys_ck); 1042 } 1043 1044 struct lcd_ctrl hwa742_ctrl = { 1045 .name = "hwa742", 1046 .init = hwa742_init, 1047 .cleanup = hwa742_cleanup, 1048 .bind_client = hwa742_bind_client, 1049 .get_caps = hwa742_get_caps, 1050 .set_update_mode = hwa742_set_update_mode, 1051 .get_update_mode = hwa742_get_update_mode, 1052 .setup_plane = hwa742_setup_plane, 1053 .enable_plane = hwa742_enable_plane, 1054 .update_window = hwa742_update_window_async, 1055 .sync = hwa742_sync, 1056 .suspend = hwa742_suspend, 1057 .resume = hwa742_resume, 1058 }; 1059 1060