1/* 2 * Epson Blizzard LCD controller driver 3 * 4 * Copyright (C) 2004-2005 Nokia Corporation 5 * Authors: Juha Yrjola <juha.yrjola@nokia.com> 6 * Imre Deak <imre.deak@nokia.com> 7 * YUV support: Jussi Laako <jussi.laako@nokia.com> 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the 11 * Free Software Foundation; either version 2 of the License, or (at your 12 * option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, but 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write to the Free Software Foundation, Inc., 21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 */ 23#include <linux/module.h> 24#include <linux/mm.h> 25#include <linux/fb.h> 26#include <linux/delay.h> 27#include <linux/clk.h> 28 29#include <plat/dma.h> 30#include <plat/blizzard.h> 31 32#include "omapfb.h" 33#include "dispc.h" 34 35#define MODULE_NAME "blizzard" 36 37#define BLIZZARD_REV_CODE 0x00 38#define BLIZZARD_CONFIG 0x02 39#define BLIZZARD_PLL_DIV 0x04 40#define BLIZZARD_PLL_LOCK_RANGE 0x06 41#define BLIZZARD_PLL_CLOCK_SYNTH_0 0x08 42#define BLIZZARD_PLL_CLOCK_SYNTH_1 0x0a 43#define BLIZZARD_PLL_MODE 0x0c 44#define BLIZZARD_CLK_SRC 0x0e 45#define BLIZZARD_MEM_BANK0_ACTIVATE 0x10 46#define BLIZZARD_MEM_BANK0_STATUS 0x14 47#define BLIZZARD_PANEL_CONFIGURATION 0x28 48#define BLIZZARD_HDISP 0x2a 49#define BLIZZARD_HNDP 0x2c 50#define BLIZZARD_VDISP0 0x2e 51#define BLIZZARD_VDISP1 0x30 52#define BLIZZARD_VNDP 0x32 53#define BLIZZARD_HSW 0x34 54#define BLIZZARD_VSW 0x38 55#define BLIZZARD_DISPLAY_MODE 0x68 56#define BLIZZARD_INPUT_WIN_X_START_0 0x6c 57#define BLIZZARD_DATA_SOURCE_SELECT 0x8e 58#define BLIZZARD_DISP_MEM_DATA_PORT 0x90 59#define BLIZZARD_DISP_MEM_READ_ADDR0 0x92 60#define BLIZZARD_POWER_SAVE 0xE6 61#define BLIZZARD_NDISP_CTRL_STATUS 0xE8 62 63/* Data source select */ 64/* For S1D13745 */ 65#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND 0x00 66#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE 0x01 67#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE 0x04 68#define BLIZZARD_SRC_DISABLE_OVERLAY 0x05 69/* For S1D13744 */ 70#define BLIZZARD_SRC_WRITE_LCD 0x00 71#define BLIZZARD_SRC_BLT_LCD 0x06 72 73#define BLIZZARD_COLOR_RGB565 0x01 74#define BLIZZARD_COLOR_YUV420 0x09 75 76#define BLIZZARD_VERSION_S1D13745 0x01 /* Hailstorm */ 77#define BLIZZARD_VERSION_S1D13744 0x02 /* Blizzard */ 78 79#define BLIZZARD_AUTO_UPDATE_TIME (HZ / 20) 80 81/* Reserve 4 request slots for requests in irq context */ 82#define REQ_POOL_SIZE 24 83#define IRQ_REQ_POOL_SIZE 4 84 85#define REQ_FROM_IRQ_POOL 0x01 86 87#define REQ_COMPLETE 0 88#define REQ_PENDING 1 89 90struct blizzard_reg_list { 91 int start; 92 int end; 93}; 94 95/* These need to be saved / restored separately from the rest. */ 96static const struct blizzard_reg_list blizzard_pll_regs[] = { 97 { 98 .start = 0x04, /* Don't save PLL ctrl (0x0C) */ 99 .end = 0x0a, 100 }, 101 { 102 .start = 0x0e, /* Clock configuration */ 103 .end = 0x0e, 104 }, 105}; 106 107static const struct blizzard_reg_list blizzard_gen_regs[] = { 108 { 109 .start = 0x18, /* SDRAM control */ 110 .end = 0x20, 111 }, 112 { 113 .start = 0x28, /* LCD Panel configuration */ 114 .end = 0x5a, /* HSSI interface, TV configuration */ 115 }, 116}; 117 118static u8 blizzard_reg_cache[0x5a / 2]; 119 120struct update_param { 121 int plane; 122 int x, y, width, height; 123 int out_x, out_y; 124 int out_width, out_height; 125 int color_mode; 126 int bpp; 127 int flags; 128}; 129 130struct blizzard_request { 131 struct list_head entry; 132 unsigned int flags; 133 134 int (*handler)(struct blizzard_request *req); 135 void (*complete)(void *data); 136 void *complete_data; 137 138 union { 139 struct update_param update; 140 struct completion *sync; 141 } par; 142}; 143 144struct plane_info { 145 unsigned long offset; 146 int pos_x, pos_y; 147 int width, height; 148 int out_width, out_height; 149 int scr_width; 150 int color_mode; 151 int bpp; 152}; 153 154struct blizzard_struct { 155 enum omapfb_update_mode update_mode; 156 enum omapfb_update_mode update_mode_before_suspend; 157 158 struct timer_list auto_update_timer; 159 int stop_auto_update; 160 struct omapfb_update_window auto_update_window; 161 int enabled_planes; 162 int vid_nonstd_color; 163 int vid_scaled; 164 int last_color_mode; 165 int zoom_on; 166 int zoom_area_gx1; 167 int zoom_area_gx2; 168 int zoom_area_gy1; 169 int zoom_area_gy2; 170 int screen_width; 171 int screen_height; 172 unsigned te_connected:1; 173 unsigned vsync_only:1; 174 175 struct plane_info plane[OMAPFB_PLANE_NUM]; 176 177 struct blizzard_request req_pool[REQ_POOL_SIZE]; 178 struct list_head pending_req_list; 179 struct list_head free_req_list; 180 struct semaphore req_sema; 181 spinlock_t req_lock; 182 183 unsigned long sys_ck_rate; 184 struct extif_timings reg_timings, lut_timings; 185 186 u32 max_transmit_size; 187 u32 extif_clk_period; 188 int extif_clk_div; 189 unsigned long pix_tx_time; 190 unsigned long line_upd_time; 191 192 struct omapfb_device *fbdev; 193 struct lcd_ctrl_extif *extif; 194 const struct lcd_ctrl *int_ctrl; 195 196 void (*power_up)(struct device *dev); 197 void (*power_down)(struct device *dev); 198 199 int version; 200} blizzard; 201 202struct lcd_ctrl blizzard_ctrl; 203 204static u8 blizzard_read_reg(u8 reg) 205{ 206 u8 data; 207 208 blizzard.extif->set_bits_per_cycle(8); 209 blizzard.extif->write_command(®, 1); 210 blizzard.extif->read_data(&data, 1); 211 212 return data; 213} 214 215static void blizzard_write_reg(u8 reg, u8 val) 216{ 217 blizzard.extif->set_bits_per_cycle(8); 218 blizzard.extif->write_command(®, 1); 219 blizzard.extif->write_data(&val, 1); 220} 221 222static void blizzard_restart_sdram(void) 223{ 224 unsigned long tmo; 225 226 blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 0); 227 udelay(50); 228 blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 1); 229 tmo = jiffies + msecs_to_jiffies(200); 230 while (!(blizzard_read_reg(BLIZZARD_MEM_BANK0_STATUS) & 0x01)) { 231 if (time_after(jiffies, tmo)) { 232 dev_err(blizzard.fbdev->dev, 233 "s1d1374x: SDRAM not ready\n"); 234 break; 235 } 236 msleep(1); 237 } 238} 239 240static void blizzard_stop_sdram(void) 241{ 242 blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 0); 243} 244 245/* Wait until the last window was completely written into the controllers 246 * SDRAM and we can start transferring the next window. 247 */ 248static void blizzard_wait_line_buffer(void) 249{ 250 unsigned long tmo = jiffies + msecs_to_jiffies(30); 251 252 while (blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS) & (1 << 7)) { 253 if (time_after(jiffies, tmo)) { 254 if (printk_ratelimit()) 255 dev_err(blizzard.fbdev->dev, 256 "s1d1374x: line buffer not ready\n"); 257 break; 258 } 259 } 260} 261 262/* Wait until the YYC color space converter is idle. */ 263static void blizzard_wait_yyc(void) 264{ 265 unsigned long tmo = jiffies + msecs_to_jiffies(30); 266 267 while (blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS) & (1 << 4)) { 268 if (time_after(jiffies, tmo)) { 269 if (printk_ratelimit()) 270 dev_err(blizzard.fbdev->dev, 271 "s1d1374x: YYC not ready\n"); 272 break; 273 } 274 } 275} 276 277static void disable_overlay(void) 278{ 279 blizzard_write_reg(BLIZZARD_DATA_SOURCE_SELECT, 280 BLIZZARD_SRC_DISABLE_OVERLAY); 281} 282 283static void set_window_regs(int x_start, int y_start, int x_end, int y_end, 284 int x_out_start, int y_out_start, 285 int x_out_end, int y_out_end, int color_mode, 286 int zoom_off, int flags) 287{ 288 u8 tmp[18]; 289 u8 cmd; 290 291 x_end--; 292 y_end--; 293 tmp[0] = x_start; 294 tmp[1] = x_start >> 8; 295 tmp[2] = y_start; 296 tmp[3] = y_start >> 8; 297 tmp[4] = x_end; 298 tmp[5] = x_end >> 8; 299 tmp[6] = y_end; 300 tmp[7] = y_end >> 8; 301 302 x_out_end--; 303 y_out_end--; 304 tmp[8] = x_out_start; 305 tmp[9] = x_out_start >> 8; 306 tmp[10] = y_out_start; 307 tmp[11] = y_out_start >> 8; 308 tmp[12] = x_out_end; 309 tmp[13] = x_out_end >> 8; 310 tmp[14] = y_out_end; 311 tmp[15] = y_out_end >> 8; 312 313 tmp[16] = color_mode; 314 if (zoom_off && blizzard.version == BLIZZARD_VERSION_S1D13745) 315 tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND; 316 else if (flags & OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY) 317 tmp[17] = BLIZZARD_SRC_WRITE_OVERLAY_ENABLE; 318 else 319 tmp[17] = blizzard.version == BLIZZARD_VERSION_S1D13744 ? 320 BLIZZARD_SRC_WRITE_LCD : 321 BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE; 322 323 blizzard.extif->set_bits_per_cycle(8); 324 cmd = BLIZZARD_INPUT_WIN_X_START_0; 325 blizzard.extif->write_command(&cmd, 1); 326 blizzard.extif->write_data(tmp, 18); 327} 328 329static void enable_tearsync(int y, int width, int height, int screen_height, 330 int out_height, int force_vsync) 331{ 332 u8 b; 333 334 b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS); 335 b |= 1 << 3; 336 blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b); 337 338 if (likely(blizzard.vsync_only || force_vsync)) { 339 blizzard.extif->enable_tearsync(1, 0); 340 return; 341 } 342 343 if (width * blizzard.pix_tx_time < blizzard.line_upd_time) { 344 blizzard.extif->enable_tearsync(1, 0); 345 return; 346 } 347 348 if ((width * blizzard.pix_tx_time / 1000) * height < 349 (y + out_height) * (blizzard.line_upd_time / 1000)) { 350 blizzard.extif->enable_tearsync(1, 0); 351 return; 352 } 353 354 blizzard.extif->enable_tearsync(1, y + 1); 355} 356 357static void disable_tearsync(void) 358{ 359 u8 b; 360 361 blizzard.extif->enable_tearsync(0, 0); 362 b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS); 363 b &= ~(1 << 3); 364 blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b); 365 b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS); 366} 367 368static inline void set_extif_timings(const struct extif_timings *t); 369 370static inline struct blizzard_request *alloc_req(void) 371{ 372 unsigned long flags; 373 struct blizzard_request *req; 374 int req_flags = 0; 375 376 if (!in_interrupt()) 377 down(&blizzard.req_sema); 378 else 379 req_flags = REQ_FROM_IRQ_POOL; 380 381 spin_lock_irqsave(&blizzard.req_lock, flags); 382 BUG_ON(list_empty(&blizzard.free_req_list)); 383 req = list_entry(blizzard.free_req_list.next, 384 struct blizzard_request, entry); 385 list_del(&req->entry); 386 spin_unlock_irqrestore(&blizzard.req_lock, flags); 387 388 INIT_LIST_HEAD(&req->entry); 389 req->flags = req_flags; 390 391 return req; 392} 393 394static inline void free_req(struct blizzard_request *req) 395{ 396 unsigned long flags; 397 398 spin_lock_irqsave(&blizzard.req_lock, flags); 399 400 list_del(&req->entry); 401 list_add(&req->entry, &blizzard.free_req_list); 402 if (!(req->flags & REQ_FROM_IRQ_POOL)) 403 up(&blizzard.req_sema); 404 405 spin_unlock_irqrestore(&blizzard.req_lock, flags); 406} 407 408static void process_pending_requests(void) 409{ 410 unsigned long flags; 411 412 spin_lock_irqsave(&blizzard.req_lock, flags); 413 414 while (!list_empty(&blizzard.pending_req_list)) { 415 struct blizzard_request *req; 416 void (*complete)(void *); 417 void *complete_data; 418 419 req = list_entry(blizzard.pending_req_list.next, 420 struct blizzard_request, entry); 421 spin_unlock_irqrestore(&blizzard.req_lock, flags); 422 423 if (req->handler(req) == REQ_PENDING) 424 return; 425 426 complete = req->complete; 427 complete_data = req->complete_data; 428 free_req(req); 429 430 if (complete) 431 complete(complete_data); 432 433 spin_lock_irqsave(&blizzard.req_lock, flags); 434 } 435 436 spin_unlock_irqrestore(&blizzard.req_lock, flags); 437} 438 439static void submit_req_list(struct list_head *head) 440{ 441 unsigned long flags; 442 int process = 1; 443 444 spin_lock_irqsave(&blizzard.req_lock, flags); 445 if (likely(!list_empty(&blizzard.pending_req_list))) 446 process = 0; 447 list_splice_init(head, blizzard.pending_req_list.prev); 448 spin_unlock_irqrestore(&blizzard.req_lock, flags); 449 450 if (process) 451 process_pending_requests(); 452} 453 454static void request_complete(void *data) 455{ 456 struct blizzard_request *req = (struct blizzard_request *)data; 457 void (*complete)(void *); 458 void *complete_data; 459 460 complete = req->complete; 461 complete_data = req->complete_data; 462 463 free_req(req); 464 465 if (complete) 466 complete(complete_data); 467 468 process_pending_requests(); 469} 470 471 472static int do_full_screen_update(struct blizzard_request *req) 473{ 474 int i; 475 int flags; 476 477 for (i = 0; i < 3; i++) { 478 struct plane_info *p = &blizzard.plane[i]; 479 if (!(blizzard.enabled_planes & (1 << i))) { 480 blizzard.int_ctrl->enable_plane(i, 0); 481 continue; 482 } 483 dev_dbg(blizzard.fbdev->dev, "pw %d ph %d\n", 484 p->width, p->height); 485 blizzard.int_ctrl->setup_plane(i, 486 OMAPFB_CHANNEL_OUT_LCD, p->offset, 487 p->scr_width, p->pos_x, p->pos_y, 488 p->width, p->height, 489 p->color_mode); 490 blizzard.int_ctrl->enable_plane(i, 1); 491 } 492 493 dev_dbg(blizzard.fbdev->dev, "sw %d sh %d\n", 494 blizzard.screen_width, blizzard.screen_height); 495 blizzard_wait_line_buffer(); 496 flags = req->par.update.flags; 497 if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC) 498 enable_tearsync(0, blizzard.screen_width, 499 blizzard.screen_height, 500 blizzard.screen_height, 501 blizzard.screen_height, 502 flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC); 503 else 504 disable_tearsync(); 505 506 set_window_regs(0, 0, blizzard.screen_width, blizzard.screen_height, 507 0, 0, blizzard.screen_width, blizzard.screen_height, 508 BLIZZARD_COLOR_RGB565, blizzard.zoom_on, flags); 509 blizzard.zoom_on = 0; 510 511 blizzard.extif->set_bits_per_cycle(16); 512 /* set_window_regs has left the register index at the right 513 * place, so no need to set it here. 514 */ 515 blizzard.extif->transfer_area(blizzard.screen_width, 516 blizzard.screen_height, 517 request_complete, req); 518 return REQ_PENDING; 519} 520 521static int check_1d_intersect(int a1, int a2, int b1, int b2) 522{ 523 if (a2 <= b1 || b2 <= a1) 524 return 0; 525 return 1; 526} 527 528/* Setup all planes with an overlapping area with the update window. */ 529static int do_partial_update(struct blizzard_request *req, int plane, 530 int x, int y, int w, int h, 531 int x_out, int y_out, int w_out, int h_out, 532 int wnd_color_mode, int bpp) 533{ 534 int i; 535 int gx1, gy1, gx2, gy2; 536 int gx1_out, gy1_out, gx2_out, gy2_out; 537 int color_mode; 538 int flags; 539 int zoom_off; 540 int have_zoom_for_this_update = 0; 541 542 /* Global coordinates, relative to pixel 0,0 of the LCD */ 543 gx1 = x + blizzard.plane[plane].pos_x; 544 gy1 = y + blizzard.plane[plane].pos_y; 545 gx2 = gx1 + w; 546 gy2 = gy1 + h; 547 548 flags = req->par.update.flags; 549 if (flags & OMAPFB_FORMAT_FLAG_DOUBLE) { 550 gx1_out = gx1; 551 gy1_out = gy1; 552 gx2_out = gx1 + w * 2; 553 gy2_out = gy1 + h * 2; 554 } else { 555 gx1_out = x_out + blizzard.plane[plane].pos_x; 556 gy1_out = y_out + blizzard.plane[plane].pos_y; 557 gx2_out = gx1_out + w_out; 558 gy2_out = gy1_out + h_out; 559 } 560 561 for (i = 0; i < OMAPFB_PLANE_NUM; i++) { 562 struct plane_info *p = &blizzard.plane[i]; 563 int px1, py1; 564 int px2, py2; 565 int pw, ph; 566 int pposx, pposy; 567 unsigned long offset; 568 569 if (!(blizzard.enabled_planes & (1 << i)) || 570 (wnd_color_mode && i != plane)) { 571 blizzard.int_ctrl->enable_plane(i, 0); 572 continue; 573 } 574 /* Plane coordinates */ 575 if (i == plane) { 576 /* Plane in which we are doing the update. 577 * Local coordinates are the one in the update 578 * request. 579 */ 580 px1 = x; 581 py1 = y; 582 px2 = x + w; 583 py2 = y + h; 584 pposx = 0; 585 pposy = 0; 586 } else { 587 /* Check if this plane has an overlapping part */ 588 px1 = gx1 - p->pos_x; 589 py1 = gy1 - p->pos_y; 590 px2 = gx2 - p->pos_x; 591 py2 = gy2 - p->pos_y; 592 if (px1 >= p->width || py1 >= p->height || 593 px2 <= 0 || py2 <= 0) { 594 blizzard.int_ctrl->enable_plane(i, 0); 595 continue; 596 } 597 /* Calculate the coordinates for the overlapping 598 * part in the plane's local coordinates. 599 */ 600 pposx = -px1; 601 pposy = -py1; 602 if (px1 < 0) 603 px1 = 0; 604 if (py1 < 0) 605 py1 = 0; 606 if (px2 > p->width) 607 px2 = p->width; 608 if (py2 > p->height) 609 py2 = p->height; 610 if (pposx < 0) 611 pposx = 0; 612 if (pposy < 0) 613 pposy = 0; 614 } 615 pw = px2 - px1; 616 ph = py2 - py1; 617 offset = p->offset + (p->scr_width * py1 + px1) * p->bpp / 8; 618 if (wnd_color_mode) 619 /* Window embedded in the plane with a differing 620 * color mode / bpp. Calculate the number of DMA 621 * transfer elements in terms of the plane's bpp. 622 */ 623 pw = (pw + 1) * bpp / p->bpp; 624#ifdef VERBOSE 625 dev_dbg(blizzard.fbdev->dev, 626 "plane %d offset %#08lx pposx %d pposy %d " 627 "px1 %d py1 %d pw %d ph %d\n", 628 i, offset, pposx, pposy, px1, py1, pw, ph); 629#endif 630 blizzard.int_ctrl->setup_plane(i, 631 OMAPFB_CHANNEL_OUT_LCD, offset, 632 p->scr_width, 633 pposx, pposy, pw, ph, 634 p->color_mode); 635 636 blizzard.int_ctrl->enable_plane(i, 1); 637 } 638 639 switch (wnd_color_mode) { 640 case OMAPFB_COLOR_YUV420: 641 color_mode = BLIZZARD_COLOR_YUV420; 642 /* Currently only the 16 bits/pixel cycle format is 643 * supported on the external interface. Adjust the number 644 * of transfer elements per line for 12bpp format. 645 */ 646 w = (w + 1) * 3 / 4; 647 break; 648 default: 649 color_mode = BLIZZARD_COLOR_RGB565; 650 break; 651 } 652 653 blizzard_wait_line_buffer(); 654 if (blizzard.last_color_mode == BLIZZARD_COLOR_YUV420) 655 blizzard_wait_yyc(); 656 blizzard.last_color_mode = color_mode; 657 if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC) 658 enable_tearsync(gy1, w, h, 659 blizzard.screen_height, 660 h_out, 661 flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC); 662 else 663 disable_tearsync(); 664 665 if ((gx2_out - gx1_out) != (gx2 - gx1) || 666 (gy2_out - gy1_out) != (gy2 - gy1)) 667 have_zoom_for_this_update = 1; 668 669 /* 'background' type of screen update (as opposed to 'destructive') 670 can be used to disable scaling if scaling is active */ 671 zoom_off = blizzard.zoom_on && !have_zoom_for_this_update && 672 (gx1_out == 0) && (gx2_out == blizzard.screen_width) && 673 (gy1_out == 0) && (gy2_out == blizzard.screen_height) && 674 (gx1 == 0) && (gy1 == 0); 675 676 if (blizzard.zoom_on && !have_zoom_for_this_update && !zoom_off && 677 check_1d_intersect(blizzard.zoom_area_gx1, blizzard.zoom_area_gx2, 678 gx1_out, gx2_out) && 679 check_1d_intersect(blizzard.zoom_area_gy1, blizzard.zoom_area_gy2, 680 gy1_out, gy2_out)) { 681 /* Previous screen update was using scaling, current update 682 * is not using it. Additionally, current screen update is 683 * going to overlap with the scaled area. Scaling needs to be 684 * disabled in order to avoid 'magnifying glass' effect. 685 * Dummy setup of background window can be used for this. 686 */ 687 set_window_regs(0, 0, blizzard.screen_width, 688 blizzard.screen_height, 689 0, 0, blizzard.screen_width, 690 blizzard.screen_height, 691 BLIZZARD_COLOR_RGB565, 1, flags); 692 blizzard.zoom_on = 0; 693 } 694 695 /* remember scaling settings if we have scaled update */ 696 if (have_zoom_for_this_update) { 697 blizzard.zoom_on = 1; 698 blizzard.zoom_area_gx1 = gx1_out; 699 blizzard.zoom_area_gx2 = gx2_out; 700 blizzard.zoom_area_gy1 = gy1_out; 701 blizzard.zoom_area_gy2 = gy2_out; 702 } 703 704 set_window_regs(gx1, gy1, gx2, gy2, gx1_out, gy1_out, gx2_out, gy2_out, 705 color_mode, zoom_off, flags); 706 if (zoom_off) 707 blizzard.zoom_on = 0; 708 709 blizzard.extif->set_bits_per_cycle(16); 710 /* set_window_regs has left the register index at the right 711 * place, so no need to set it here. 712 */ 713 blizzard.extif->transfer_area(w, h, request_complete, req); 714 715 return REQ_PENDING; 716} 717 718static int send_frame_handler(struct blizzard_request *req) 719{ 720 struct update_param *par = &req->par.update; 721 int plane = par->plane; 722 723#ifdef VERBOSE 724 dev_dbg(blizzard.fbdev->dev, 725 "send_frame: x %d y %d w %d h %d " 726 "x_out %d y_out %d w_out %d h_out %d " 727 "color_mode %04x flags %04x planes %01x\n", 728 par->x, par->y, par->width, par->height, 729 par->out_x, par->out_y, par->out_width, par->out_height, 730 par->color_mode, par->flags, blizzard.enabled_planes); 731#endif 732 if (par->flags & OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY) 733 disable_overlay(); 734 735 if ((blizzard.enabled_planes & blizzard.vid_nonstd_color) || 736 (blizzard.enabled_planes & blizzard.vid_scaled)) 737 return do_full_screen_update(req); 738 739 return do_partial_update(req, plane, par->x, par->y, 740 par->width, par->height, 741 par->out_x, par->out_y, 742 par->out_width, par->out_height, 743 par->color_mode, par->bpp); 744} 745 746static void send_frame_complete(void *data) 747{ 748} 749 750#define ADD_PREQ(_x, _y, _w, _h, _x_out, _y_out, _w_out, _h_out) do { \ 751 req = alloc_req(); \ 752 req->handler = send_frame_handler; \ 753 req->complete = send_frame_complete; \ 754 req->par.update.plane = plane_idx; \ 755 req->par.update.x = _x; \ 756 req->par.update.y = _y; \ 757 req->par.update.width = _w; \ 758 req->par.update.height = _h; \ 759 req->par.update.out_x = _x_out; \ 760 req->par.update.out_y = _y_out; \ 761 req->par.update.out_width = _w_out; \ 762 req->par.update.out_height = _h_out; \ 763 req->par.update.bpp = bpp; \ 764 req->par.update.color_mode = color_mode;\ 765 req->par.update.flags = flags; \ 766 list_add_tail(&req->entry, req_head); \ 767} while(0) 768 769static void create_req_list(int plane_idx, 770 struct omapfb_update_window *win, 771 struct list_head *req_head) 772{ 773 struct blizzard_request *req; 774 int x = win->x; 775 int y = win->y; 776 int width = win->width; 777 int height = win->height; 778 int x_out = win->out_x; 779 int y_out = win->out_y; 780 int width_out = win->out_width; 781 int height_out = win->out_height; 782 int color_mode; 783 int bpp; 784 int flags; 785 unsigned int ystart = y; 786 unsigned int yspan = height; 787 unsigned int ystart_out = y_out; 788 unsigned int yspan_out = height_out; 789 790 flags = win->format & ~OMAPFB_FORMAT_MASK; 791 color_mode = win->format & OMAPFB_FORMAT_MASK; 792 switch (color_mode) { 793 case OMAPFB_COLOR_YUV420: 794 /* Embedded window with different color mode */ 795 bpp = 12; 796 /* X, Y, height must be aligned at 2, width at 4 pixels */ 797 x &= ~1; 798 y &= ~1; 799 height = yspan = height & ~1; 800 width = width & ~3; 801 break; 802 default: 803 /* Same as the plane color mode */ 804 bpp = blizzard.plane[plane_idx].bpp; 805 break; 806 } 807 if (width * height * bpp / 8 > blizzard.max_transmit_size) { 808 yspan = blizzard.max_transmit_size / (width * bpp / 8); 809 yspan_out = yspan * height_out / height; 810 ADD_PREQ(x, ystart, width, yspan, x_out, ystart_out, 811 width_out, yspan_out); 812 ystart += yspan; 813 ystart_out += yspan_out; 814 yspan = height - yspan; 815 yspan_out = height_out - yspan_out; 816 flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC; 817 } 818 819 ADD_PREQ(x, ystart, width, yspan, x_out, ystart_out, 820 width_out, yspan_out); 821} 822 823static void auto_update_complete(void *data) 824{ 825 if (!blizzard.stop_auto_update) 826 mod_timer(&blizzard.auto_update_timer, 827 jiffies + BLIZZARD_AUTO_UPDATE_TIME); 828} 829 830static void blizzard_update_window_auto(unsigned long arg) 831{ 832 LIST_HEAD(req_list); 833 struct blizzard_request *last; 834 struct omapfb_plane_struct *plane; 835 836 plane = blizzard.fbdev->fb_info[0]->par; 837 create_req_list(plane->idx, 838 &blizzard.auto_update_window, &req_list); 839 last = list_entry(req_list.prev, struct blizzard_request, entry); 840 841 last->complete = auto_update_complete; 842 last->complete_data = NULL; 843 844 submit_req_list(&req_list); 845} 846 847int blizzard_update_window_async(struct fb_info *fbi, 848 struct omapfb_update_window *win, 849 void (*complete_callback)(void *arg), 850 void *complete_callback_data) 851{ 852 LIST_HEAD(req_list); 853 struct blizzard_request *last; 854 struct omapfb_plane_struct *plane = fbi->par; 855 856 if (unlikely(blizzard.update_mode != OMAPFB_MANUAL_UPDATE)) 857 return -EINVAL; 858 if (unlikely(!blizzard.te_connected && 859 (win->format & OMAPFB_FORMAT_FLAG_TEARSYNC))) 860 return -EINVAL; 861 862 create_req_list(plane->idx, win, &req_list); 863 last = list_entry(req_list.prev, struct blizzard_request, entry); 864 865 last->complete = complete_callback; 866 last->complete_data = (void *)complete_callback_data; 867 868 submit_req_list(&req_list); 869 870 return 0; 871} 872EXPORT_SYMBOL(blizzard_update_window_async); 873 874static int update_full_screen(void) 875{ 876 return blizzard_update_window_async(blizzard.fbdev->fb_info[0], 877 &blizzard.auto_update_window, NULL, NULL); 878 879} 880 881static int blizzard_setup_plane(int plane, int channel_out, 882 unsigned long offset, int screen_width, 883 int pos_x, int pos_y, int width, int height, 884 int color_mode) 885{ 886 struct plane_info *p; 887 888#ifdef VERBOSE 889 dev_dbg(blizzard.fbdev->dev, 890 "plane %d ch_out %d offset %#08lx scr_width %d " 891 "pos_x %d pos_y %d width %d height %d color_mode %d\n", 892 plane, channel_out, offset, screen_width, 893 pos_x, pos_y, width, height, color_mode); 894#endif 895 if ((unsigned)plane > OMAPFB_PLANE_NUM) 896 return -EINVAL; 897 p = &blizzard.plane[plane]; 898 899 switch (color_mode) { 900 case OMAPFB_COLOR_YUV422: 901 case OMAPFB_COLOR_YUY422: 902 p->bpp = 16; 903 blizzard.vid_nonstd_color &= ~(1 << plane); 904 break; 905 case OMAPFB_COLOR_YUV420: 906 p->bpp = 12; 907 blizzard.vid_nonstd_color |= 1 << plane; 908 break; 909 case OMAPFB_COLOR_RGB565: 910 p->bpp = 16; 911 blizzard.vid_nonstd_color &= ~(1 << plane); 912 break; 913 default: 914 return -EINVAL; 915 } 916 917 p->offset = offset; 918 p->pos_x = pos_x; 919 p->pos_y = pos_y; 920 p->width = width; 921 p->height = height; 922 p->scr_width = screen_width; 923 if (!p->out_width) 924 p->out_width = width; 925 if (!p->out_height) 926 p->out_height = height; 927 928 p->color_mode = color_mode; 929 930 return 0; 931} 932 933static int blizzard_set_scale(int plane, int orig_w, int orig_h, 934 int out_w, int out_h) 935{ 936 struct plane_info *p = &blizzard.plane[plane]; 937 int r; 938 939 dev_dbg(blizzard.fbdev->dev, 940 "plane %d orig_w %d orig_h %d out_w %d out_h %d\n", 941 plane, orig_w, orig_h, out_w, out_h); 942 if ((unsigned)plane > OMAPFB_PLANE_NUM) 943 return -ENODEV; 944 945 r = blizzard.int_ctrl->set_scale(plane, orig_w, orig_h, out_w, out_h); 946 if (r < 0) 947 return r; 948 949 p->width = orig_w; 950 p->height = orig_h; 951 p->out_width = out_w; 952 p->out_height = out_h; 953 if (orig_w == out_w && orig_h == out_h) 954 blizzard.vid_scaled &= ~(1 << plane); 955 else 956 blizzard.vid_scaled |= 1 << plane; 957 958 return 0; 959} 960 961static int blizzard_set_rotate(int angle) 962{ 963 u32 l; 964 965 l = blizzard_read_reg(BLIZZARD_PANEL_CONFIGURATION); 966 l &= ~0x03; 967 968 switch (angle) { 969 case 0: 970 l = l | 0x00; 971 break; 972 case 90: 973 l = l | 0x03; 974 break; 975 case 180: 976 l = l | 0x02; 977 break; 978 case 270: 979 l = l | 0x01; 980 break; 981 default: 982 return -EINVAL; 983 } 984 985 blizzard_write_reg(BLIZZARD_PANEL_CONFIGURATION, l); 986 987 return 0; 988} 989 990static int blizzard_enable_plane(int plane, int enable) 991{ 992 if (enable) 993 blizzard.enabled_planes |= 1 << plane; 994 else 995 blizzard.enabled_planes &= ~(1 << plane); 996 997 return 0; 998} 999 1000static int sync_handler(struct blizzard_request *req) 1001{ 1002 complete(req->par.sync); 1003 return REQ_COMPLETE; 1004} 1005 1006static void blizzard_sync(void) 1007{ 1008 LIST_HEAD(req_list); 1009 struct blizzard_request *req; 1010 struct completion comp; 1011 1012 req = alloc_req(); 1013 1014 req->handler = sync_handler; 1015 req->complete = NULL; 1016 init_completion(&comp); 1017 req->par.sync = ∁ 1018 1019 list_add(&req->entry, &req_list); 1020 submit_req_list(&req_list); 1021 1022 wait_for_completion(&comp); 1023} 1024 1025 1026static void blizzard_bind_client(struct omapfb_notifier_block *nb) 1027{ 1028 if (blizzard.update_mode == OMAPFB_MANUAL_UPDATE) { 1029 omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_READY); 1030 } 1031} 1032 1033static int blizzard_set_update_mode(enum omapfb_update_mode mode) 1034{ 1035 if (unlikely(mode != OMAPFB_MANUAL_UPDATE && 1036 mode != OMAPFB_AUTO_UPDATE && 1037 mode != OMAPFB_UPDATE_DISABLED)) 1038 return -EINVAL; 1039 1040 if (mode == blizzard.update_mode) 1041 return 0; 1042 1043 dev_info(blizzard.fbdev->dev, "s1d1374x: setting update mode to %s\n", 1044 mode == OMAPFB_UPDATE_DISABLED ? "disabled" : 1045 (mode == OMAPFB_AUTO_UPDATE ? "auto" : "manual")); 1046 1047 switch (blizzard.update_mode) { 1048 case OMAPFB_MANUAL_UPDATE: 1049 omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_DISABLED); 1050 break; 1051 case OMAPFB_AUTO_UPDATE: 1052 blizzard.stop_auto_update = 1; 1053 del_timer_sync(&blizzard.auto_update_timer); 1054 break; 1055 case OMAPFB_UPDATE_DISABLED: 1056 break; 1057 } 1058 1059 blizzard.update_mode = mode; 1060 blizzard_sync(); 1061 blizzard.stop_auto_update = 0; 1062 1063 switch (mode) { 1064 case OMAPFB_MANUAL_UPDATE: 1065 omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_READY); 1066 break; 1067 case OMAPFB_AUTO_UPDATE: 1068 blizzard_update_window_auto(0); 1069 break; 1070 case OMAPFB_UPDATE_DISABLED: 1071 break; 1072 } 1073 1074 return 0; 1075} 1076 1077static enum omapfb_update_mode blizzard_get_update_mode(void) 1078{ 1079 return blizzard.update_mode; 1080} 1081 1082static inline void set_extif_timings(const struct extif_timings *t) 1083{ 1084 blizzard.extif->set_timings(t); 1085} 1086 1087static inline unsigned long round_to_extif_ticks(unsigned long ps, int div) 1088{ 1089 int bus_tick = blizzard.extif_clk_period * div; 1090 return (ps + bus_tick - 1) / bus_tick * bus_tick; 1091} 1092 1093static int calc_reg_timing(unsigned long sysclk, int div) 1094{ 1095 struct extif_timings *t; 1096 unsigned long systim; 1097 1098 /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns, 1099 * AccessTime 2 ns + 12.2 ns (regs), 1100 * WEOffTime = WEOnTime + 1 ns, 1101 * REOffTime = REOnTime + 12 ns (regs), 1102 * CSOffTime = REOffTime + 1 ns 1103 * ReadCycle = 2ns + 2*SYSCLK (regs), 1104 * WriteCycle = 2*SYSCLK + 2 ns, 1105 * CSPulseWidth = 10 ns */ 1106 1107 systim = 1000000000 / (sysclk / 1000); 1108 dev_dbg(blizzard.fbdev->dev, 1109 "Blizzard systim %lu ps extif_clk_period %u div %d\n", 1110 systim, blizzard.extif_clk_period, div); 1111 1112 t = &blizzard.reg_timings; 1113 memset(t, 0, sizeof(*t)); 1114 1115 t->clk_div = div; 1116 1117 t->cs_on_time = 0; 1118 t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); 1119 t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); 1120 t->access_time = round_to_extif_ticks(t->re_on_time + 12200, div); 1121 t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div); 1122 t->re_off_time = round_to_extif_ticks(t->re_on_time + 13000, div); 1123 t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div); 1124 t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div); 1125 if (t->we_cycle_time < t->we_off_time) 1126 t->we_cycle_time = t->we_off_time; 1127 t->re_cycle_time = round_to_extif_ticks(2 * systim + 2000, div); 1128 if (t->re_cycle_time < t->re_off_time) 1129 t->re_cycle_time = t->re_off_time; 1130 t->cs_pulse_width = 0; 1131 1132 dev_dbg(blizzard.fbdev->dev, "[reg]cson %d csoff %d reon %d reoff %d\n", 1133 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time); 1134 dev_dbg(blizzard.fbdev->dev, "[reg]weon %d weoff %d recyc %d wecyc %d\n", 1135 t->we_on_time, t->we_off_time, t->re_cycle_time, 1136 t->we_cycle_time); 1137 dev_dbg(blizzard.fbdev->dev, "[reg]rdaccess %d cspulse %d\n", 1138 t->access_time, t->cs_pulse_width); 1139 1140 return blizzard.extif->convert_timings(t); 1141} 1142 1143static int calc_lut_timing(unsigned long sysclk, int div) 1144{ 1145 struct extif_timings *t; 1146 unsigned long systim; 1147 1148 /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns, 1149 * AccessTime 2 ns + 4 * SYSCLK + 26 (lut), 1150 * WEOffTime = WEOnTime + 1 ns, 1151 * REOffTime = REOnTime + 4*SYSCLK + 26 ns (lut), 1152 * CSOffTime = REOffTime + 1 ns 1153 * ReadCycle = 2ns + 4*SYSCLK + 26 ns (lut), 1154 * WriteCycle = 2*SYSCLK + 2 ns, 1155 * CSPulseWidth = 10 ns */ 1156 1157 systim = 1000000000 / (sysclk / 1000); 1158 dev_dbg(blizzard.fbdev->dev, 1159 "Blizzard systim %lu ps extif_clk_period %u div %d\n", 1160 systim, blizzard.extif_clk_period, div); 1161 1162 t = &blizzard.lut_timings; 1163 memset(t, 0, sizeof(*t)); 1164 1165 t->clk_div = div; 1166 1167 t->cs_on_time = 0; 1168 t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); 1169 t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); 1170 t->access_time = round_to_extif_ticks(t->re_on_time + 4 * systim + 1171 26000, div); 1172 t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div); 1173 t->re_off_time = round_to_extif_ticks(t->re_on_time + 4 * systim + 1174 26000, div); 1175 t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div); 1176 t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div); 1177 if (t->we_cycle_time < t->we_off_time) 1178 t->we_cycle_time = t->we_off_time; 1179 t->re_cycle_time = round_to_extif_ticks(2000 + 4 * systim + 26000, div); 1180 if (t->re_cycle_time < t->re_off_time) 1181 t->re_cycle_time = t->re_off_time; 1182 t->cs_pulse_width = 0; 1183 1184 dev_dbg(blizzard.fbdev->dev, 1185 "[lut]cson %d csoff %d reon %d reoff %d\n", 1186 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time); 1187 dev_dbg(blizzard.fbdev->dev, 1188 "[lut]weon %d weoff %d recyc %d wecyc %d\n", 1189 t->we_on_time, t->we_off_time, t->re_cycle_time, 1190 t->we_cycle_time); 1191 dev_dbg(blizzard.fbdev->dev, "[lut]rdaccess %d cspulse %d\n", 1192 t->access_time, t->cs_pulse_width); 1193 1194 return blizzard.extif->convert_timings(t); 1195} 1196 1197static int calc_extif_timings(unsigned long sysclk, int *extif_mem_div) 1198{ 1199 int max_clk_div; 1200 int div; 1201 1202 blizzard.extif->get_clk_info(&blizzard.extif_clk_period, &max_clk_div); 1203 for (div = 1; div <= max_clk_div; div++) { 1204 if (calc_reg_timing(sysclk, div) == 0) 1205 break; 1206 } 1207 if (div > max_clk_div) { 1208 dev_dbg(blizzard.fbdev->dev, "reg timing failed\n"); 1209 goto err; 1210 } 1211 *extif_mem_div = div; 1212 1213 for (div = 1; div <= max_clk_div; div++) { 1214 if (calc_lut_timing(sysclk, div) == 0) 1215 break; 1216 } 1217 1218 if (div > max_clk_div) 1219 goto err; 1220 1221 blizzard.extif_clk_div = div; 1222 1223 return 0; 1224err: 1225 dev_err(blizzard.fbdev->dev, "can't setup timings\n"); 1226 return -1; 1227} 1228 1229static void calc_blizzard_clk_rates(unsigned long ext_clk, 1230 unsigned long *sys_clk, unsigned long *pix_clk) 1231{ 1232 int pix_clk_src; 1233 int sys_div = 0, sys_mul = 0; 1234 int pix_div; 1235 1236 pix_clk_src = blizzard_read_reg(BLIZZARD_CLK_SRC); 1237 pix_div = ((pix_clk_src >> 3) & 0x1f) + 1; 1238 if ((pix_clk_src & (0x3 << 1)) == 0) { 1239 /* Source is the PLL */ 1240 sys_div = (blizzard_read_reg(BLIZZARD_PLL_DIV) & 0x3f) + 1; 1241 sys_mul = blizzard_read_reg(BLIZZARD_PLL_CLOCK_SYNTH_0); 1242 sys_mul |= ((blizzard_read_reg(BLIZZARD_PLL_CLOCK_SYNTH_1) 1243 & 0x0f) << 11); 1244 *sys_clk = ext_clk * sys_mul / sys_div; 1245 } else /* else source is ext clk, or oscillator */ 1246 *sys_clk = ext_clk; 1247 1248 *pix_clk = *sys_clk / pix_div; /* HZ */ 1249 dev_dbg(blizzard.fbdev->dev, 1250 "ext_clk %ld pix_src %d pix_div %d sys_div %d sys_mul %d\n", 1251 ext_clk, pix_clk_src & (0x3 << 1), pix_div, sys_div, sys_mul); 1252 dev_dbg(blizzard.fbdev->dev, "sys_clk %ld pix_clk %ld\n", 1253 *sys_clk, *pix_clk); 1254} 1255 1256static int setup_tearsync(unsigned long pix_clk, int extif_div) 1257{ 1258 int hdisp, vdisp; 1259 int hndp, vndp; 1260 int hsw, vsw; 1261 int hs, vs; 1262 int hs_pol_inv, vs_pol_inv; 1263 int use_hsvs, use_ndp; 1264 u8 b; 1265 1266 hsw = blizzard_read_reg(BLIZZARD_HSW); 1267 vsw = blizzard_read_reg(BLIZZARD_VSW); 1268 hs_pol_inv = !(hsw & 0x80); 1269 vs_pol_inv = !(vsw & 0x80); 1270 hsw = hsw & 0x7f; 1271 vsw = vsw & 0x3f; 1272 1273 hdisp = blizzard_read_reg(BLIZZARD_HDISP) * 8; 1274 vdisp = blizzard_read_reg(BLIZZARD_VDISP0) + 1275 ((blizzard_read_reg(BLIZZARD_VDISP1) & 0x3) << 8); 1276 1277 hndp = blizzard_read_reg(BLIZZARD_HNDP) & 0x3f; 1278 vndp = blizzard_read_reg(BLIZZARD_VNDP); 1279 1280 /* time to transfer one pixel (16bpp) in ps */ 1281 blizzard.pix_tx_time = blizzard.reg_timings.we_cycle_time; 1282 if (blizzard.extif->get_max_tx_rate != NULL) { 1283 /* The external interface might have a rate limitation, 1284 * if so, we have to maximize our transfer rate. 1285 */ 1286 unsigned long min_tx_time; 1287 unsigned long max_tx_rate = blizzard.extif->get_max_tx_rate(); 1288 1289 dev_dbg(blizzard.fbdev->dev, "max_tx_rate %ld HZ\n", 1290 max_tx_rate); 1291 min_tx_time = 1000000000 / (max_tx_rate / 1000); /* ps */ 1292 if (blizzard.pix_tx_time < min_tx_time) 1293 blizzard.pix_tx_time = min_tx_time; 1294 } 1295 1296 /* time to update one line in ps */ 1297 blizzard.line_upd_time = (hdisp + hndp) * 1000000 / (pix_clk / 1000); 1298 blizzard.line_upd_time *= 1000; 1299 if (hdisp * blizzard.pix_tx_time > blizzard.line_upd_time) 1300 /* transfer speed too low, we might have to use both 1301 * HS and VS */ 1302 use_hsvs = 1; 1303 else 1304 /* decent transfer speed, we'll always use only VS */ 1305 use_hsvs = 0; 1306 1307 if (use_hsvs && (hs_pol_inv || vs_pol_inv)) { 1308 /* HS or'ed with VS doesn't work, use the active high 1309 * TE signal based on HNDP / VNDP */ 1310 use_ndp = 1; 1311 hs_pol_inv = 0; 1312 vs_pol_inv = 0; 1313 hs = hndp; 1314 vs = vndp; 1315 } else { 1316 /* Use HS or'ed with VS as a TE signal if both are needed 1317 * or VNDP if only vsync is needed. */ 1318 use_ndp = 0; 1319 hs = hsw; 1320 vs = vsw; 1321 if (!use_hsvs) { 1322 hs_pol_inv = 0; 1323 vs_pol_inv = 0; 1324 } 1325 } 1326 1327 hs = hs * 1000000 / (pix_clk / 1000); /* ps */ 1328 hs *= 1000; 1329 1330 vs = vs * (hdisp + hndp) * 1000000 / (pix_clk / 1000); /* ps */ 1331 vs *= 1000; 1332 1333 if (vs <= hs) 1334 return -EDOM; 1335 /* set VS to 120% of HS to minimize VS detection time */ 1336 vs = hs * 12 / 10; 1337 /* minimize HS too */ 1338 if (hs > 10000) 1339 hs = 10000; 1340 1341 b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS); 1342 b &= ~0x3; 1343 b |= use_hsvs ? 1 : 0; 1344 b |= (use_ndp && use_hsvs) ? 0 : 2; 1345 blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b); 1346 1347 blizzard.vsync_only = !use_hsvs; 1348 1349 dev_dbg(blizzard.fbdev->dev, 1350 "pix_clk %ld HZ pix_tx_time %ld ps line_upd_time %ld ps\n", 1351 pix_clk, blizzard.pix_tx_time, blizzard.line_upd_time); 1352 dev_dbg(blizzard.fbdev->dev, 1353 "hs %d ps vs %d ps mode %d vsync_only %d\n", 1354 hs, vs, b & 0x3, !use_hsvs); 1355 1356 return blizzard.extif->setup_tearsync(1, hs, vs, 1357 hs_pol_inv, vs_pol_inv, 1358 extif_div); 1359} 1360 1361static void blizzard_get_caps(int plane, struct omapfb_caps *caps) 1362{ 1363 blizzard.int_ctrl->get_caps(plane, caps); 1364 caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE | 1365 OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE | 1366 OMAPFB_CAPS_WINDOW_SCALE | 1367 OMAPFB_CAPS_WINDOW_OVERLAY | 1368 OMAPFB_CAPS_WINDOW_ROTATE; 1369 if (blizzard.te_connected) 1370 caps->ctrl |= OMAPFB_CAPS_TEARSYNC; 1371 caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) | 1372 (1 << OMAPFB_COLOR_YUV420); 1373} 1374 1375static void _save_regs(const struct blizzard_reg_list *list, int cnt) 1376{ 1377 int i; 1378 1379 for (i = 0; i < cnt; i++, list++) { 1380 int reg; 1381 for (reg = list->start; reg <= list->end; reg += 2) 1382 blizzard_reg_cache[reg / 2] = blizzard_read_reg(reg); 1383 } 1384} 1385 1386static void _restore_regs(const struct blizzard_reg_list *list, int cnt) 1387{ 1388 int i; 1389 1390 for (i = 0; i < cnt; i++, list++) { 1391 int reg; 1392 for (reg = list->start; reg <= list->end; reg += 2) 1393 blizzard_write_reg(reg, blizzard_reg_cache[reg / 2]); 1394 } 1395} 1396 1397static void blizzard_save_all_regs(void) 1398{ 1399 _save_regs(blizzard_pll_regs, ARRAY_SIZE(blizzard_pll_regs)); 1400 _save_regs(blizzard_gen_regs, ARRAY_SIZE(blizzard_gen_regs)); 1401} 1402 1403static void blizzard_restore_pll_regs(void) 1404{ 1405 _restore_regs(blizzard_pll_regs, ARRAY_SIZE(blizzard_pll_regs)); 1406} 1407 1408static void blizzard_restore_gen_regs(void) 1409{ 1410 _restore_regs(blizzard_gen_regs, ARRAY_SIZE(blizzard_gen_regs)); 1411} 1412 1413static void blizzard_suspend(void) 1414{ 1415 u32 l; 1416 unsigned long tmo; 1417 1418 if (blizzard.last_color_mode) { 1419 update_full_screen(); 1420 blizzard_sync(); 1421 } 1422 blizzard.update_mode_before_suspend = blizzard.update_mode; 1423 /* the following will disable clocks as well */ 1424 blizzard_set_update_mode(OMAPFB_UPDATE_DISABLED); 1425 1426 blizzard_save_all_regs(); 1427 1428 blizzard_stop_sdram(); 1429 1430 l = blizzard_read_reg(BLIZZARD_POWER_SAVE); 1431 /* Standby, Sleep. We assume we use an external clock. */ 1432 l |= 0x03; 1433 blizzard_write_reg(BLIZZARD_POWER_SAVE, l); 1434 1435 tmo = jiffies + msecs_to_jiffies(100); 1436 while (!(blizzard_read_reg(BLIZZARD_PLL_MODE) & (1 << 1))) { 1437 if (time_after(jiffies, tmo)) { 1438 dev_err(blizzard.fbdev->dev, 1439 "s1d1374x: sleep timeout, stopping PLL manually\n"); 1440 l = blizzard_read_reg(BLIZZARD_PLL_MODE); 1441 l &= ~0x03; 1442 /* Disable PLL, counter function */ 1443 l |= 0x2; 1444 blizzard_write_reg(BLIZZARD_PLL_MODE, l); 1445 break; 1446 } 1447 msleep(1); 1448 } 1449 1450 if (blizzard.power_down != NULL) 1451 blizzard.power_down(blizzard.fbdev->dev); 1452} 1453 1454static void blizzard_resume(void) 1455{ 1456 u32 l; 1457 1458 if (blizzard.power_up != NULL) 1459 blizzard.power_up(blizzard.fbdev->dev); 1460 1461 l = blizzard_read_reg(BLIZZARD_POWER_SAVE); 1462 /* Standby, Sleep */ 1463 l &= ~0x03; 1464 blizzard_write_reg(BLIZZARD_POWER_SAVE, l); 1465 1466 blizzard_restore_pll_regs(); 1467 l = blizzard_read_reg(BLIZZARD_PLL_MODE); 1468 l &= ~0x03; 1469 /* Enable PLL, counter function */ 1470 l |= 0x1; 1471 blizzard_write_reg(BLIZZARD_PLL_MODE, l); 1472 1473 while (!(blizzard_read_reg(BLIZZARD_PLL_DIV) & (1 << 7))) 1474 msleep(1); 1475 1476 blizzard_restart_sdram(); 1477 1478 blizzard_restore_gen_regs(); 1479 1480 /* Enable display */ 1481 blizzard_write_reg(BLIZZARD_DISPLAY_MODE, 0x01); 1482 1483 /* the following will enable clocks as necessary */ 1484 blizzard_set_update_mode(blizzard.update_mode_before_suspend); 1485 1486 /* Force a background update */ 1487 blizzard.zoom_on = 1; 1488 update_full_screen(); 1489 blizzard_sync(); 1490} 1491 1492static int blizzard_init(struct omapfb_device *fbdev, int ext_mode, 1493 struct omapfb_mem_desc *req_vram) 1494{ 1495 int r = 0, i; 1496 u8 rev, conf; 1497 unsigned long ext_clk; 1498 int extif_div; 1499 unsigned long sys_clk, pix_clk; 1500 struct omapfb_platform_data *omapfb_conf; 1501 struct blizzard_platform_data *ctrl_conf; 1502 1503 blizzard.fbdev = fbdev; 1504 1505 BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl); 1506 1507 blizzard.fbdev = fbdev; 1508 blizzard.extif = fbdev->ext_if; 1509 blizzard.int_ctrl = fbdev->int_ctrl; 1510 1511 omapfb_conf = fbdev->dev->platform_data; 1512 ctrl_conf = omapfb_conf->ctrl_platform_data; 1513 if (ctrl_conf == NULL || ctrl_conf->get_clock_rate == NULL) { 1514 dev_err(fbdev->dev, "s1d1374x: missing platform data\n"); 1515 r = -ENOENT; 1516 goto err1; 1517 } 1518 1519 blizzard.power_down = ctrl_conf->power_down; 1520 blizzard.power_up = ctrl_conf->power_up; 1521 1522 spin_lock_init(&blizzard.req_lock); 1523 1524 if ((r = blizzard.int_ctrl->init(fbdev, 1, req_vram)) < 0) 1525 goto err1; 1526 1527 if ((r = blizzard.extif->init(fbdev)) < 0) 1528 goto err2; 1529 1530 blizzard_ctrl.set_color_key = blizzard.int_ctrl->set_color_key; 1531 blizzard_ctrl.get_color_key = blizzard.int_ctrl->get_color_key; 1532 blizzard_ctrl.setup_mem = blizzard.int_ctrl->setup_mem; 1533 blizzard_ctrl.mmap = blizzard.int_ctrl->mmap; 1534 1535 ext_clk = ctrl_conf->get_clock_rate(fbdev->dev); 1536 if ((r = calc_extif_timings(ext_clk, &extif_div)) < 0) 1537 goto err3; 1538 1539 set_extif_timings(&blizzard.reg_timings); 1540 1541 if (blizzard.power_up != NULL) 1542 blizzard.power_up(fbdev->dev); 1543 1544 calc_blizzard_clk_rates(ext_clk, &sys_clk, &pix_clk); 1545 1546 if ((r = calc_extif_timings(sys_clk, &extif_div)) < 0) 1547 goto err3; 1548 set_extif_timings(&blizzard.reg_timings); 1549 1550 if (!(blizzard_read_reg(BLIZZARD_PLL_DIV) & 0x80)) { 1551 dev_err(fbdev->dev, 1552 "controller not initialized by the bootloader\n"); 1553 r = -ENODEV; 1554 goto err3; 1555 } 1556 1557 if (ctrl_conf->te_connected) { 1558 if ((r = setup_tearsync(pix_clk, extif_div)) < 0) 1559 goto err3; 1560 blizzard.te_connected = 1; 1561 } 1562 1563 rev = blizzard_read_reg(BLIZZARD_REV_CODE); 1564 conf = blizzard_read_reg(BLIZZARD_CONFIG); 1565 1566 switch (rev & 0xfc) { 1567 case 0x9c: 1568 blizzard.version = BLIZZARD_VERSION_S1D13744; 1569 pr_info("omapfb: s1d13744 LCD controller rev %d " 1570 "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07); 1571 break; 1572 case 0xa4: 1573 blizzard.version = BLIZZARD_VERSION_S1D13745; 1574 pr_info("omapfb: s1d13745 LCD controller rev %d " 1575 "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07); 1576 break; 1577 default: 1578 dev_err(fbdev->dev, "invalid s1d1374x revision %02x\n", 1579 rev); 1580 r = -ENODEV; 1581 goto err3; 1582 } 1583 1584 blizzard.max_transmit_size = blizzard.extif->max_transmit_size; 1585 1586 blizzard.update_mode = OMAPFB_UPDATE_DISABLED; 1587 1588 blizzard.auto_update_window.x = 0; 1589 blizzard.auto_update_window.y = 0; 1590 blizzard.auto_update_window.width = fbdev->panel->x_res; 1591 blizzard.auto_update_window.height = fbdev->panel->y_res; 1592 blizzard.auto_update_window.out_x = 0; 1593 blizzard.auto_update_window.out_x = 0; 1594 blizzard.auto_update_window.out_width = fbdev->panel->x_res; 1595 blizzard.auto_update_window.out_height = fbdev->panel->y_res; 1596 blizzard.auto_update_window.format = 0; 1597 1598 blizzard.screen_width = fbdev->panel->x_res; 1599 blizzard.screen_height = fbdev->panel->y_res; 1600 1601 init_timer(&blizzard.auto_update_timer); 1602 blizzard.auto_update_timer.function = blizzard_update_window_auto; 1603 blizzard.auto_update_timer.data = 0; 1604 1605 INIT_LIST_HEAD(&blizzard.free_req_list); 1606 INIT_LIST_HEAD(&blizzard.pending_req_list); 1607 for (i = 0; i < ARRAY_SIZE(blizzard.req_pool); i++) 1608 list_add(&blizzard.req_pool[i].entry, &blizzard.free_req_list); 1609 BUG_ON(i <= IRQ_REQ_POOL_SIZE); 1610 sema_init(&blizzard.req_sema, i - IRQ_REQ_POOL_SIZE); 1611 1612 return 0; 1613err3: 1614 if (blizzard.power_down != NULL) 1615 blizzard.power_down(fbdev->dev); 1616 blizzard.extif->cleanup(); 1617err2: 1618 blizzard.int_ctrl->cleanup(); 1619err1: 1620 return r; 1621} 1622 1623static void blizzard_cleanup(void) 1624{ 1625 blizzard_set_update_mode(OMAPFB_UPDATE_DISABLED); 1626 blizzard.extif->cleanup(); 1627 blizzard.int_ctrl->cleanup(); 1628 if (blizzard.power_down != NULL) 1629 blizzard.power_down(blizzard.fbdev->dev); 1630} 1631 1632struct lcd_ctrl blizzard_ctrl = { 1633 .name = "blizzard", 1634 .init = blizzard_init, 1635 .cleanup = blizzard_cleanup, 1636 .bind_client = blizzard_bind_client, 1637 .get_caps = blizzard_get_caps, 1638 .set_update_mode = blizzard_set_update_mode, 1639 .get_update_mode = blizzard_get_update_mode, 1640 .setup_plane = blizzard_setup_plane, 1641 .set_scale = blizzard_set_scale, 1642 .enable_plane = blizzard_enable_plane, 1643 .set_rotate = blizzard_set_rotate, 1644 .update_window = blizzard_update_window_async, 1645 .sync = blizzard_sync, 1646 .suspend = blizzard_suspend, 1647 .resume = blizzard_resume, 1648}; 1649