Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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