1 /* 2 * JzRISC LCD controller 3 * 4 * Copyright (C) Xiangfu Liu <xiangfu@sharism.cc> 5 * Copyright (C) 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 of 10 * the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 * Boston, MA 02110-1301, USA 21 */ 22 23 #include "sdram.h" 24 #include "jzlcd.h" 25 #include "cpu.h" 26 #include "board.h" 27 28 extern vidinfo_t panel_info; 29 30 /* Useful alignment operations. */ 31 32 static inline void align2(uint32_t *n) 33 { 34 *n = (((*n)+1)>>1)<<1; 35 } 36 37 static inline void align4(uint32_t *n) 38 { 39 *n = (((*n)+3)>>2)<<2; 40 } 41 42 static inline void align8(uint32_t *n) 43 { 44 *n = (((*n)+7)>>3)<<3; 45 } 46 47 48 49 /* Register operations. */ 50 51 static inline uint32_t lcd_ctrl_get(vidinfo_t *vid, uint32_t reg) 52 { 53 return REG32(vid->lcd + reg); 54 } 55 56 static inline void lcd_ctrl_set(vidinfo_t *vid, uint32_t reg, uint32_t value) 57 { 58 REG32(vid->lcd + reg) = value; 59 } 60 61 62 63 /* Configuration operations. */ 64 65 /* Return the number of panels available. */ 66 67 static uint16_t lcd_get_panels(vidinfo_t *vid) 68 { 69 struct jzfb_info *jzfb = vid->jz_fb; 70 return ((jzfb->cfg & MODE_MASK) == MODE_STN_MONO_DUAL) || 71 ((jzfb->cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ? 2 : 1; 72 } 73 74 /* Calculate and return the pixel clock frequency. */ 75 76 static uint32_t jz_lcd_get_pixel_clock(vidinfo_t *vid) 77 { 78 struct jzfb_info *jzfb = vid->jz_fb; 79 uint32_t pclk, width_cycles, mode = jzfb->cfg & MODE_MASK; 80 81 /* 82 Serial mode: 3 pixel clock cycles per pixel (one per channel). 83 Parallel mode: 1 pixel clock cycle per pixel. 84 */ 85 86 if (mode == MODE_8BIT_SERIAL_TFT) 87 width_cycles = jzfb->w * 3; 88 else 89 width_cycles = jzfb->w; 90 91 /* Derive pixel clock from frame clock. */ 92 93 pclk = jzfb->fclk * 94 (width_cycles + jzfb->hsw + jzfb->elw + jzfb->blw) * 95 (jzfb->h + jzfb->vsw + jzfb->efw + jzfb->bfw); 96 97 if ((mode == MODE_STN_COLOR_SINGLE) || (mode == MODE_STN_COLOR_DUAL)) 98 pclk = (pclk * 3); 99 100 if ((mode == MODE_STN_COLOR_SINGLE) || (mode == MODE_STN_COLOR_DUAL) || 101 (mode == MODE_STN_MONO_SINGLE) || (mode == MODE_STN_MONO_DUAL)) 102 pclk = pclk >> ((jzfb->cfg & STN_DAT_PINMASK) >> 4); 103 104 if ((mode == MODE_STN_COLOR_DUAL) || (mode == MODE_STN_MONO_DUAL)) 105 pclk >>= 1; 106 107 return pclk; 108 } 109 110 111 112 /* Functions returning region sizes. */ 113 114 static uint32_t lcd_get_size(vidinfo_t *vid) 115 { 116 /* Lines must be aligned to a word boundary. */ 117 uint32_t line_length = ALIGN((vid->jz_fb->w * vid->jz_fb->bpp) / 8, sizeof(uint32_t)); 118 return line_length * vid->jz_fb->h; 119 } 120 121 static uint32_t lcd_get_aligned_size(vidinfo_t *vid) 122 { 123 /* LCD_CTRL_BST_16 requires 16-word alignment. */ 124 return ALIGN(lcd_get_size(vid), 16 * sizeof(uint32_t)); 125 } 126 127 static uint32_t lcd_get_min_size(vidinfo_t *vid) 128 { 129 /* Lines must be aligned to a word boundary. */ 130 uint32_t line_length = ALIGN((vid->jz_fb->w * 32) / 8, sizeof(uint32_t)); 131 return line_length * vid->jz_fb->h; 132 } 133 134 static uint32_t lcd_get_aligned_min_size(vidinfo_t *vid) 135 { 136 /* LCD_CTRL_BST_16 requires 16-word alignment. */ 137 return ALIGN(lcd_get_min_size(vid), 16 * sizeof(uint32_t)); 138 } 139 140 static uint32_t lcd_get_palette_size(vidinfo_t *vid) 141 { 142 if (vid->jz_fb->bpp < 12) 143 return (1 << (vid->jz_fb->bpp)) * sizeof(uint16_t); 144 else 145 return 0; 146 } 147 148 static uint32_t lcd_get_aligned_palette_size(vidinfo_t *vid) 149 { 150 /* LCD_CTRL_BST_16 requires 16-word alignment. */ 151 return ALIGN(lcd_get_palette_size(vid), 16 * sizeof(uint32_t)); 152 } 153 154 static uint32_t lcd_get_descriptors_size() 155 { 156 return 3 * sizeof(struct jz_fb_dma_descriptor); 157 } 158 159 static uint32_t lcd_get_total_size(vidinfo_t *vid) 160 { 161 uint32_t size = lcd_get_aligned_size(vid) * lcd_get_panels(vid); 162 uint32_t min_size = lcd_get_aligned_min_size(vid); 163 164 /* Round up to nearest full page, or MMU section if defined. */ 165 return ALIGN((size >= min_size ? size : min_size) + lcd_get_aligned_palette_size(vid) + lcd_get_descriptors_size(), PAGE_SIZE); 166 } 167 168 169 170 /* Functions returning addresses of each data region. */ 171 172 static uint32_t lcd_get_palette(uint32_t addr, vidinfo_t *vid) 173 { 174 /* Allocate memory at the end of the region for the palette. */ 175 return addr - lcd_get_aligned_palette_size(vid); 176 } 177 178 static uint32_t lcd_get_descriptors(uint32_t addr, vidinfo_t *vid) 179 { 180 /* Allocate memory before the palette for the descriptor array. */ 181 return lcd_get_palette(addr, vid) - lcd_get_descriptors_size(); 182 } 183 184 static uint32_t lcd_get_framebuffer(uint32_t addr, uint16_t panel, vidinfo_t *vid) 185 { 186 /* Allocate pages for the frame buffer and palette. */ 187 return addr - lcd_get_total_size(vid) + (panel * lcd_get_aligned_size(vid)); 188 } 189 190 191 192 /* Initialisation functions. */ 193 194 static void jz_lcd_desc_init(vidinfo_t *vid) 195 { 196 struct jz_fb_dma_descriptor *descriptors; 197 struct jz_mem_info * fbi; 198 199 fbi = &vid->jz_mem; 200 201 /* Allocate space for descriptors before the palette entries. */ 202 203 descriptors = (struct jz_fb_dma_descriptor *) lcd_get_descriptors(get_memory_size(), vid); 204 fbi->dmadesc_fblow = (struct jz_fb_dma_descriptor *) &descriptors[0]; 205 fbi->dmadesc_fbhigh = (struct jz_fb_dma_descriptor *) &descriptors[1]; 206 fbi->dmadesc_palette = (struct jz_fb_dma_descriptor *) &descriptors[2]; 207 208 /* Populate descriptors. */ 209 210 if (lcd_get_panels(vid) == 2) 211 { 212 fbi->dmadesc_fblow->fdadr = fbi->dmadesc_fblow; 213 fbi->dmadesc_fblow->fsadr = lcd_get_framebuffer(get_memory_size(), 1, vid); 214 fbi->dmadesc_fblow->fidr = 0; 215 fbi->dmadesc_fblow->ldcmd = lcd_get_size(vid) / 4 ; 216 217 fbi->fdadr1 = fbi->dmadesc_fblow; /* only used in dual-panel mode */ 218 } 219 220 fbi->dmadesc_fbhigh->fsadr = fbi->screen; 221 fbi->dmadesc_fbhigh->fidr = 0; 222 fbi->dmadesc_fbhigh->ldcmd = lcd_get_size(vid) / 4; /* length in words */ 223 224 if (vid->jz_fb->bpp < 12) 225 { 226 fbi->dmadesc_palette->fsadr = fbi->palette; 227 fbi->dmadesc_palette->fidr = 0; 228 fbi->dmadesc_palette->ldcmd = (lcd_get_palette_size(vid) / 4) | (1<<28); 229 230 /* assume any mode with <12 bpp is palette driven */ 231 fbi->dmadesc_palette->fdadr = fbi->dmadesc_fbhigh; 232 fbi->dmadesc_fbhigh->fdadr = fbi->dmadesc_palette; 233 /* flips back and forth between pal and fbhigh */ 234 fbi->fdadr0 = fbi->dmadesc_palette; 235 } else { 236 /* palette shouldn't be loaded in true-color mode */ 237 fbi->dmadesc_fbhigh->fdadr = fbi->dmadesc_fbhigh; 238 fbi->fdadr0 = fbi->dmadesc_fbhigh; /* no pal just fbhigh */ 239 } 240 241 flush_cache_all(); 242 } 243 244 static uint32_t jz_lcd_stn_init(uint32_t stnH, vidinfo_t *vid) 245 { 246 struct jzfb_info *jzfb = vid->jz_fb; 247 uint32_t val = 0; 248 249 switch (jzfb->bpp) { 250 case 1: 251 /* val |= LCD_CTRL_PEDN; */ 252 case 2: 253 val |= LCD_CTRL_FRC_2; 254 break; 255 256 case 4: 257 val |= LCD_CTRL_FRC_4; 258 break; 259 260 case 8: 261 default: 262 val |= LCD_CTRL_FRC_16; 263 break; 264 } 265 266 switch (jzfb->cfg & STN_DAT_PINMASK) { 267 case STN_DAT_PIN1: 268 /* Do not adjust the hori-param value. */ 269 break; 270 271 case STN_DAT_PIN2: 272 align2(&jzfb->hsw); 273 align2(&jzfb->elw); 274 align2(&jzfb->blw); 275 break; 276 277 case STN_DAT_PIN4: 278 align4(&jzfb->hsw); 279 align4(&jzfb->elw); 280 align4(&jzfb->blw); 281 break; 282 283 case STN_DAT_PIN8: 284 align8(&jzfb->hsw); 285 align8(&jzfb->elw); 286 align8(&jzfb->blw); 287 break; 288 } 289 290 lcd_ctrl_set(vid, LCD_VSYNC, jzfb->vsw); 291 lcd_ctrl_set(vid, LCD_HSYNC, ((jzfb->blw+jzfb->w) << 16) | (jzfb->blw+jzfb->w+jzfb->hsw)); 292 293 /* Screen setting */ 294 lcd_ctrl_set(vid, LCD_VAT, ((jzfb->blw + jzfb->w + jzfb->hsw + jzfb->elw) << 16) | (stnH + jzfb->vsw + jzfb->bfw + jzfb->efw)); 295 lcd_ctrl_set(vid, LCD_DAH, (jzfb->blw << 16) | (jzfb->blw + jzfb->w)); 296 lcd_ctrl_set(vid, LCD_DAV, stnH); 297 298 /* AC BIAs signal */ 299 lcd_ctrl_set(vid, LCD_PS, stnH+jzfb->vsw+jzfb->efw+jzfb->bfw); 300 301 return val; 302 } 303 304 static void jz_lcd_tft_init(vidinfo_t *vid) 305 { 306 struct jzfb_info *jzfb = vid->jz_fb; 307 lcd_ctrl_set(vid, LCD_VSYNC, jzfb->vsw); 308 lcd_ctrl_set(vid, LCD_HSYNC, jzfb->hsw); 309 lcd_ctrl_set(vid, LCD_DAV, ((jzfb->vsw+jzfb->bfw) << 16) | (jzfb->vsw +jzfb->bfw+jzfb->h)); 310 lcd_ctrl_set(vid, LCD_DAH, ((jzfb->hsw + jzfb->blw) << 16) | (jzfb->hsw + jzfb->blw + jzfb->w)); 311 lcd_ctrl_set(vid, LCD_VAT, (((jzfb->blw + jzfb->w + jzfb->elw + jzfb->hsw)) << 16) | 312 (jzfb->vsw + jzfb->bfw + jzfb->h + jzfb->efw)); 313 } 314 315 static void jz_lcd_samsung_init(vidinfo_t *vid) 316 { 317 struct jzfb_info *jzfb = vid->jz_fb; 318 uint32_t pclk = jz_lcd_get_pixel_clock(vid); 319 uint32_t total, tp_s, tp_e, ckv_s, ckv_e; 320 uint32_t rev_s, rev_e, inv_s, inv_e; 321 322 jz_lcd_tft_init(vid); 323 324 total = jzfb->blw + jzfb->w + jzfb->elw + jzfb->hsw; 325 tp_s = jzfb->blw + jzfb->w + 1; 326 tp_e = tp_s + 1; 327 /* ckv_s = tp_s - jz_clocks.pixclk/(1000000000/4100); */ 328 ckv_s = tp_s - pclk/(1000000000/4100); 329 ckv_e = tp_s + total; 330 rev_s = tp_s - 11; /* -11.5 clk */ 331 rev_e = rev_s + total; 332 inv_s = tp_s; 333 inv_e = inv_s + total; 334 lcd_ctrl_set(vid, LCD_CLS, (tp_s << 16) | tp_e); 335 lcd_ctrl_set(vid, LCD_PS, (ckv_s << 16) | ckv_e); 336 lcd_ctrl_set(vid, LCD_SPL, (rev_s << 16) | rev_e); 337 lcd_ctrl_set(vid, LCD_REV, (inv_s << 16) | inv_e); 338 jzfb->cfg |= STFT_REVHI | STFT_SPLHI; 339 } 340 341 static void jz_lcd_sharp_init(vidinfo_t *vid) 342 { 343 struct jzfb_info *jzfb = vid->jz_fb; 344 uint32_t total, cls_s, cls_e, ps_s, ps_e; 345 uint32_t spl_s, spl_e, rev_s, rev_e; 346 347 jz_lcd_tft_init(vid); 348 349 total = jzfb->blw + jzfb->w + jzfb->elw + jzfb->hsw; 350 spl_s = 1; 351 spl_e = spl_s + 1; 352 cls_s = 0; 353 cls_e = total - 60; /* > 4us (pclk = 80ns) */ 354 ps_s = cls_s; 355 ps_e = cls_e; 356 rev_s = total - 40; /* > 3us (pclk = 80ns) */ 357 rev_e = rev_s + total; 358 jzfb->cfg |= STFT_PSHI; 359 lcd_ctrl_set(vid, LCD_SPL, (spl_s << 16) | spl_e); 360 lcd_ctrl_set(vid, LCD_CLS, (cls_s << 16) | cls_e); 361 lcd_ctrl_set(vid, LCD_PS, (ps_s << 16) | ps_e); 362 lcd_ctrl_set(vid, LCD_REV, (rev_s << 16) | rev_e); 363 } 364 365 366 367 /* Palette initialisation. */ 368 369 static inline uint16_t rgb8_to_rgb16(uint8_t rgb) 370 { 371 return ((((rgb & 0xe0) >> 5) * 4) << 11) | ((((rgb & 0x1c) >> 2) * 9) << 6) | ((rgb & 0x03) * 10); 372 } 373 374 static inline uint16_t rgb4_to_rgb16(uint8_t rgb) 375 { 376 return ((((rgb & 8) >> 3) * 0x1f) << 11) | ((((rgb & 6) >> 1) * 0x15) << 5) | ((rgb & 1) * 0x1f); 377 } 378 379 static void lcd_init_palette(vidinfo_t *vid) 380 { 381 uint16_t *palette = (uint16_t *) vid->jz_mem.palette; 382 uint16_t *end = (uint16_t *) palette + (1 << (vid->jz_fb->bpp)); 383 uint8_t value = 0; 384 385 while (palette < end) 386 { 387 switch (vid->jz_fb->bpp) 388 { 389 case 4: 390 *palette = rgb4_to_rgb16(value); 391 break; 392 393 case 8: 394 default: 395 *palette = rgb8_to_rgb16(value); 396 break; 397 } 398 399 value++; 400 palette++; 401 } 402 } 403 404 405 406 static void jz_lcd_set_timing(vidinfo_t *vid) 407 { 408 uint32_t pclk = jz_lcd_get_pixel_clock(vid); 409 uint32_t val; 410 411 #ifdef CONFIG_CPU_JZ4730 412 val = __cpm_get_pllout() / pclk; 413 lcd_ctrl_set(vid, CPM_CFCR2, val - 1); 414 val = pclk * 4 ; 415 if ( val > 150000000 ) { 416 val = 150000000; 417 } 418 val = __cpm_get_pllout() / val; 419 val--; 420 if ( val > 0xF ) 421 val = 0xF; 422 #else 423 int pll_div; 424 425 pll_div = lcd_ctrl_get(vid, CPM_CPCCR) & lcd_ctrl_get(vid, CPM_CPCCR_PCS); /* clock source,0:pllout/2 1: pllout */ 426 pll_div = pll_div ? 1 : 2 ; 427 val = ( __cpm_get_pllout()/pll_div ) / pclk; 428 val--; 429 if ( val > 0x1ff ) { 430 val = 0x1ff; 431 } 432 __cpm_set_pixdiv(val); 433 434 val = pclk * 3 ; /* LCDClock > 2.5*Pixclock */ 435 if ( val > 150000000 ) { 436 val = 150000000; 437 } 438 val = ( __cpm_get_pllout()/pll_div ) / val; 439 val--; 440 if ( val > 0x1f ) { 441 val = 0x1f; 442 } 443 #endif 444 __cpm_set_ldiv( val ); 445 lcd_ctrl_set(vid, CPM_CPCCR, lcd_ctrl_get(vid, CPM_CPCCR) | CPM_CPCCR_CE); /* update divide */ 446 } 447 448 static void jz_lcd_hw_init(vidinfo_t *vid) 449 { 450 struct jzfb_info *jzfb = vid->jz_fb; 451 uint32_t val = 0; 452 453 /* Compute control register flags. */ 454 455 switch (jzfb->bpp) { 456 case 1: 457 val |= LCD_CTRL_BPP_1; 458 break; 459 460 case 2: 461 val |= LCD_CTRL_BPP_2; 462 break; 463 464 case 4: 465 val |= LCD_CTRL_BPP_4; 466 break; 467 468 case 8: 469 val |= LCD_CTRL_BPP_8; 470 break; 471 472 case 15: 473 val |= LCD_CTRL_RGB555; 474 case 16: 475 val |= LCD_CTRL_BPP_16; 476 break; 477 478 case 17 ... 32: 479 val |= LCD_CTRL_BPP_18_24; /* target is 4bytes/pixel */ 480 break; 481 482 default: 483 val |= LCD_CTRL_BPP_16; /* default to 16bpp */ 484 break; 485 } 486 487 /* Set various configuration registers for the panel. */ 488 489 switch (jzfb->cfg & MODE_MASK) { 490 case MODE_STN_MONO_DUAL: 491 case MODE_STN_COLOR_DUAL: 492 val |= jz_lcd_stn_init(jzfb->h >> 1, vid); 493 break; 494 495 case MODE_STN_MONO_SINGLE: 496 case MODE_STN_COLOR_SINGLE: 497 val |= jz_lcd_stn_init(jzfb->h, vid); 498 break; 499 500 case MODE_TFT_GEN: 501 case MODE_TFT_CASIO: 502 case MODE_8BIT_SERIAL_TFT: 503 case MODE_TFT_18BIT: 504 jz_lcd_tft_init(vid); 505 break; 506 507 case MODE_TFT_SAMSUNG: 508 jz_lcd_samsung_init(vid); 509 break; 510 511 case MODE_TFT_SHARP: 512 jz_lcd_sharp_init(vid); 513 break; 514 515 default: 516 break; 517 } 518 519 /* Further control register and panel configuration. */ 520 521 val |= LCD_CTRL_BST_16; /* Burst Length is 16WORD=64Byte */ 522 val |= LCD_CTRL_OFUP; /* OutFIFO underrun protect */ 523 524 lcd_ctrl_set(vid, LCD_CTRL, val); 525 lcd_ctrl_set(vid, LCD_CFG, jzfb->cfg); 526 } 527 528 static void jz_lcd_timing_init(vidinfo_t *vid) 529 { 530 __cpm_stop_lcd(); 531 jz_lcd_set_timing(vid); 532 __cpm_start_lcd(); 533 udelay(1000); 534 } 535 536 /* Initialise DMA for the driver. */ 537 538 static void jz_lcd_dma_init(vidinfo_t *vid) 539 { 540 struct jz_mem_info *fbi = &vid->jz_mem; 541 uint32_t mode = vid->jz_fb->cfg & MODE_MASK; 542 543 /* Configure DMA by setting frame descriptor addresses. */ 544 545 lcd_ctrl_set(vid, LCD_DA0, (uint32_t) fbi->fdadr0); 546 547 if ((mode == MODE_STN_COLOR_DUAL) || (mode == MODE_STN_MONO_DUAL)) 548 lcd_ctrl_set(vid, LCD_DA1, (uint32_t) fbi->fdadr1); 549 } 550 551 /* Public operations. */ 552 553 void lcd_set_bpp(uint8_t bpp) 554 { 555 vidinfo_t *vid = &panel_info; 556 struct jzfb_info *jzfb = vid->jz_fb; 557 jzfb->bpp = bpp; 558 } 559 560 void lcd_enable() 561 { 562 vidinfo_t *vid = &panel_info; 563 564 /* Clear the disable bit (DIS) and set the enable bit (ENA). */ 565 566 lcd_ctrl_set(vid, LCD_CTRL, (lcd_ctrl_get(vid, LCD_CTRL) & ~LCD_CTRL_DIS) | LCD_CTRL_ENA); 567 } 568 569 void lcd_disable() 570 { 571 vidinfo_t *vid = &panel_info; 572 573 /* Set the disable bit (DIS). */ 574 575 lcd_ctrl_set(vid, LCD_CTRL, lcd_ctrl_get(vid, LCD_CTRL) | LCD_CTRL_DIS); 576 } 577 578 void lcd_quick_disable() 579 { 580 vidinfo_t *vid = &panel_info; 581 582 /* Clear the enable bit (ENA) for quick disable. */ 583 584 lcd_ctrl_set(vid, LCD_CTRL, lcd_ctrl_get(vid, LCD_CTRL) & ~LCD_CTRL_ENA); 585 } 586 587 uint32_t lcd_ctrl_init() 588 { 589 vidinfo_t *vid = &panel_info; 590 struct jz_mem_info *fbi = &vid->jz_mem; 591 592 /* Start from the top of memory and obtain palette and framebuffer regions. */ 593 594 fbi->screen = lcd_get_framebuffer(get_memory_size(), 0, vid); 595 fbi->palette = lcd_get_palette(get_memory_size(), vid); 596 597 if (vid->jz_fb->bpp < 12) 598 lcd_init_palette(vid); 599 600 jz_lcd_desc_init(vid); 601 jz_lcd_hw_init(vid); 602 jz_lcd_timing_init(vid); 603 jz_lcd_dma_init(vid); 604 605 return fbi->screen; 606 }