1 /* 2 * jz4740 LCD controller configuration. 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 "board.h" 26 #include "xburst_types.h" /* for REG32 */ 27 28 /* Useful alignment operations. */ 29 30 static inline void align2(uint32_t *n) 31 { 32 *n = (((*n)+1)>>1)<<1; 33 } 34 35 static inline void align4(uint32_t *n) 36 { 37 *n = (((*n)+3)>>2)<<2; 38 } 39 40 static inline void align8(uint32_t *n) 41 { 42 *n = (((*n)+7)>>3)<<3; 43 } 44 45 46 47 /* Register operations. */ 48 49 static inline uint32_t lcd_ctrl_get(vidinfo_t *vid, uint32_t reg) 50 { 51 return REG32(vid->lcd + reg); 52 } 53 54 static inline void lcd_ctrl_set(vidinfo_t *vid, uint32_t reg, uint32_t value) 55 { 56 REG32(vid->lcd + reg) = value; 57 } 58 59 60 61 /* Configuration operations. */ 62 63 /* Return the number of panels available. */ 64 65 static uint8_t lcd_get_panels(vidinfo_t *vid) 66 { 67 struct jzfb_info *jzfb = vid->jz_fb; 68 return ((jzfb->cfg & MODE_MASK) == MODE_STN_MONO_DUAL) || 69 ((jzfb->cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ? 2 : 1; 70 } 71 72 /* Calculate and return the pixel clock frequency. */ 73 74 static uint32_t lcd_get_pixel_clock(vidinfo_t *vid) 75 { 76 struct jzfb_info *jzfb = vid->jz_fb; 77 uint32_t pclk, width_cycles, mode = jzfb->cfg & MODE_MASK; 78 79 /* 80 Serial mode: 3 pixel clock cycles per pixel (one per channel). 81 Parallel mode: 1 pixel clock cycle per pixel. 82 */ 83 84 if (mode == MODE_8BIT_SERIAL_TFT) 85 width_cycles = jzfb->w * 3; 86 else 87 width_cycles = jzfb->w; 88 89 /* Derive pixel clock from frame clock. */ 90 91 pclk = jzfb->fclk * 92 (width_cycles + jzfb->hsw + jzfb->elw + jzfb->blw) * 93 (jzfb->h + jzfb->vsw + jzfb->efw + jzfb->bfw); 94 95 if ((mode == MODE_STN_COLOR_SINGLE) || (mode == MODE_STN_COLOR_DUAL)) 96 pclk = (pclk * 3); 97 98 if ((mode == MODE_STN_COLOR_SINGLE) || (mode == MODE_STN_COLOR_DUAL) || 99 (mode == MODE_STN_MONO_SINGLE) || (mode == MODE_STN_MONO_DUAL)) 100 pclk = pclk >> ((jzfb->cfg & STN_DAT_PINMASK) >> 4); 101 102 if ((mode == MODE_STN_COLOR_DUAL) || (mode == MODE_STN_MONO_DUAL)) 103 pclk >>= 1; 104 105 return pclk; 106 } 107 108 109 110 /* Functions returning region sizes. */ 111 112 static uint32_t lcd_get_size(vidinfo_t *vid) 113 { 114 /* Lines must be aligned to a word boundary. */ 115 116 uint32_t line_length = ALIGN((vid->jz_fb->w * vid->jz_fb->bpp) / 8, sizeof(uint32_t)); 117 return line_length * vid->jz_fb->h; 118 } 119 120 static uint32_t lcd_get_aligned_size(vidinfo_t *vid) 121 { 122 /* LCD_CTRL_BST_16 requires 16-word alignment. */ 123 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 131 uint32_t line_length = ALIGN((vid->jz_fb->w * 32) / 8, sizeof(uint32_t)); 132 return line_length * vid->jz_fb->h; 133 } 134 135 static uint32_t lcd_get_aligned_min_size(vidinfo_t *vid) 136 { 137 /* LCD_CTRL_BST_16 requires 16-word alignment. */ 138 139 return ALIGN(lcd_get_min_size(vid), 16 * sizeof(uint32_t)); 140 } 141 142 static uint32_t lcd_get_palette_size(vidinfo_t *vid) 143 { 144 /* Get a collection of two-byte entries, one per colour. */ 145 146 if (vid->jz_fb->bpp < 12) 147 return (1 << (vid->jz_fb->bpp)) * sizeof(uint16_t); 148 else 149 return 0; 150 } 151 152 static uint32_t lcd_get_aligned_palette_size(vidinfo_t *vid) 153 { 154 /* LCD_CTRL_BST_16 requires 16-word alignment. */ 155 return ALIGN(lcd_get_palette_size(vid), 16 * sizeof(uint32_t)); 156 } 157 158 static uint32_t lcd_get_descriptors_size() 159 { 160 return 3 * sizeof(struct jz_fb_dma_descriptor); 161 } 162 163 164 165 /* Functions returning addresses of each data region. */ 166 167 static uint32_t lcd_get_palette(vidinfo_t *vid) 168 { 169 /* Use memory at the end of the allocated region for the palette. */ 170 171 return vid->jz_mem.screen + vid->jz_mem.total - lcd_get_aligned_palette_size(vid); 172 } 173 174 static uint32_t lcd_get_descriptors(vidinfo_t *vid) 175 { 176 /* Use memory before the palette for the descriptor array. */ 177 178 return lcd_get_palette(vid) - lcd_get_descriptors_size(); 179 } 180 181 static uint32_t lcd_get_framebuffer(uint8_t panel, vidinfo_t *vid) 182 { 183 /* Framebuffers for panels are allocated at the start of the region. */ 184 185 return vid->jz_mem.screen + (panel * lcd_get_aligned_size(vid)); 186 } 187 188 189 190 /* Initialisation functions. */ 191 192 static uint32_t jz_lcd_stn_init(uint32_t stnH, vidinfo_t *vid) 193 { 194 struct jzfb_info *jzfb = vid->jz_fb; 195 uint32_t val = 0; 196 197 switch (jzfb->bpp) { 198 case 1: 199 /* val |= LCD_CTRL_PEDN; */ 200 case 2: 201 val |= LCD_CTRL_FRC_2; 202 break; 203 204 case 4: 205 val |= LCD_CTRL_FRC_4; 206 break; 207 208 case 8: 209 default: 210 val |= LCD_CTRL_FRC_16; 211 break; 212 } 213 214 switch (jzfb->cfg & STN_DAT_PINMASK) { 215 case STN_DAT_PIN1: 216 /* Do not adjust the hori-param value. */ 217 break; 218 219 case STN_DAT_PIN2: 220 align2(&jzfb->hsw); 221 align2(&jzfb->elw); 222 align2(&jzfb->blw); 223 break; 224 225 case STN_DAT_PIN4: 226 align4(&jzfb->hsw); 227 align4(&jzfb->elw); 228 align4(&jzfb->blw); 229 break; 230 231 case STN_DAT_PIN8: 232 align8(&jzfb->hsw); 233 align8(&jzfb->elw); 234 align8(&jzfb->blw); 235 break; 236 } 237 238 lcd_ctrl_set(vid, LCD_VSYNC, jzfb->vsw); 239 lcd_ctrl_set(vid, LCD_HSYNC, ((jzfb->blw + jzfb->w) << 16) | (jzfb->blw + jzfb->w + jzfb->hsw)); 240 241 /* Screen setting */ 242 lcd_ctrl_set(vid, LCD_VAT, ((jzfb->blw + jzfb->w + jzfb->hsw + jzfb->elw) << 16) | (stnH + jzfb->vsw + jzfb->bfw + jzfb->efw)); 243 lcd_ctrl_set(vid, LCD_DAH, (jzfb->blw << 16) | (jzfb->blw + jzfb->w)); 244 lcd_ctrl_set(vid, LCD_DAV, stnH); 245 246 /* AC BIAs signal */ 247 lcd_ctrl_set(vid, LCD_PS, stnH+jzfb->vsw+jzfb->efw+jzfb->bfw); 248 249 return val; 250 } 251 252 static void jz_lcd_tft_init(vidinfo_t *vid) 253 { 254 struct jzfb_info *jzfb = vid->jz_fb; 255 256 lcd_ctrl_set(vid, LCD_VSYNC, jzfb->vsw); 257 lcd_ctrl_set(vid, LCD_HSYNC, jzfb->hsw); 258 lcd_ctrl_set(vid, LCD_DAV, ((jzfb->vsw + jzfb->bfw) << 16) | (jzfb->vsw + jzfb->bfw + jzfb->h)); 259 lcd_ctrl_set(vid, LCD_DAH, ((jzfb->hsw + jzfb->blw) << 16) | (jzfb->hsw + jzfb->blw + jzfb->w)); 260 lcd_ctrl_set(vid, LCD_VAT, (((jzfb->blw + jzfb->w + jzfb->elw + jzfb->hsw)) << 16) | 261 (jzfb->vsw + jzfb->bfw + jzfb->h + jzfb->efw)); 262 } 263 264 static void jz_lcd_samsung_init(vidinfo_t *vid) 265 { 266 struct jzfb_info *jzfb = vid->jz_fb; 267 uint32_t pclk = lcd_get_pixel_clock(vid); 268 uint32_t total, tp_s, tp_e, ckv_s, ckv_e; 269 uint32_t rev_s, rev_e, inv_s, inv_e; 270 271 jz_lcd_tft_init(vid); 272 273 total = jzfb->blw + jzfb->w + jzfb->elw + jzfb->hsw; 274 tp_s = jzfb->blw + jzfb->w + 1; 275 tp_e = tp_s + 1; 276 /* ckv_s = tp_s - jz_clocks.pixclk/(1000000000/4100); */ 277 ckv_s = tp_s - pclk/(1000000000/4100); 278 ckv_e = tp_s + total; 279 rev_s = tp_s - 11; /* -11.5 clk */ 280 rev_e = rev_s + total; 281 inv_s = tp_s; 282 inv_e = inv_s + total; 283 lcd_ctrl_set(vid, LCD_CLS, (tp_s << 16) | tp_e); 284 lcd_ctrl_set(vid, LCD_PS, (ckv_s << 16) | ckv_e); 285 lcd_ctrl_set(vid, LCD_SPL, (rev_s << 16) | rev_e); 286 lcd_ctrl_set(vid, LCD_REV, (inv_s << 16) | inv_e); 287 jzfb->cfg |= STFT_REVHI | STFT_SPLHI; 288 } 289 290 static void jz_lcd_sharp_init(vidinfo_t *vid) 291 { 292 struct jzfb_info *jzfb = vid->jz_fb; 293 uint32_t total, cls_s, cls_e, ps_s, ps_e; 294 uint32_t spl_s, spl_e, rev_s, rev_e; 295 296 jz_lcd_tft_init(vid); 297 298 total = jzfb->blw + jzfb->w + jzfb->elw + jzfb->hsw; 299 spl_s = 1; 300 spl_e = spl_s + 1; 301 cls_s = 0; 302 cls_e = total - 60; /* > 4us (pclk = 80ns) */ 303 ps_s = cls_s; 304 ps_e = cls_e; 305 rev_s = total - 40; /* > 3us (pclk = 80ns) */ 306 rev_e = rev_s + total; 307 jzfb->cfg |= STFT_PSHI; 308 lcd_ctrl_set(vid, LCD_SPL, (spl_s << 16) | spl_e); 309 lcd_ctrl_set(vid, LCD_CLS, (cls_s << 16) | cls_e); 310 lcd_ctrl_set(vid, LCD_PS, (ps_s << 16) | ps_e); 311 lcd_ctrl_set(vid, LCD_REV, (rev_s << 16) | rev_e); 312 } 313 314 315 316 /* Palette initialisation. */ 317 318 static inline uint16_t rgb8_to_rgb16(uint8_t rgb) 319 { 320 return ((((rgb & 0xe0) >> 5) * 4) << 11) | ((((rgb & 0x1c) >> 2) * 9) << 6) | ((rgb & 0x03) * 10); 321 } 322 323 static inline uint16_t rgb4_to_rgb16(uint8_t rgb) 324 { 325 return ((((rgb & 8) >> 3) * 0x1f) << 11) | ((((rgb & 6) >> 1) * 0x15) << 5) | ((rgb & 1) * 0x1f); 326 } 327 328 static void lcd_init_palette(vidinfo_t *vid) 329 { 330 uint16_t *palette = (uint16_t *) vid->jz_mem.palette; 331 uint16_t *end = (uint16_t *) palette + (1 << (vid->jz_fb->bpp)); 332 uint8_t value = 0; 333 334 while (palette < end) 335 { 336 switch (vid->jz_fb->bpp) 337 { 338 case 4: 339 *palette = rgb4_to_rgb16(value); 340 break; 341 342 case 8: 343 default: 344 *palette = rgb8_to_rgb16(value); 345 break; 346 } 347 348 value++; 349 palette++; 350 } 351 } 352 353 354 355 /* Public functions. */ 356 357 /* Return the total size of the required memory. */ 358 359 uint32_t jz4740_lcd_get_total_size(vidinfo_t *vid) 360 { 361 uint32_t size = lcd_get_aligned_size(vid) * lcd_get_panels(vid); 362 uint32_t min_size = lcd_get_aligned_min_size(vid); 363 364 /* Round up to nearest full page, or MMU section if defined. */ 365 366 return ALIGN((size >= min_size ? size : min_size) + 367 lcd_get_aligned_palette_size(vid) + lcd_get_descriptors_size(), 368 PAGE_SIZE); 369 } 370 371 /* Return the calculated pixel clock frequency for the display. */ 372 373 uint32_t jz4740_lcd_get_pixel_clock(vidinfo_t *vid) 374 { 375 return lcd_get_pixel_clock(vid); 376 } 377 378 /* Initialise the LCD controller with the memory, panel and framebuffer details. 379 Return the pixel clock frequency. */ 380 381 void jz4740_lcd_ctrl_init(void *lcd_base, void *fb_vaddr, vidinfo_t *vid) 382 { 383 struct jz_mem_info *fbi = &vid->jz_mem; 384 struct jz_fb_dma_descriptor *descriptors; 385 386 /* Set the LCD controller address. */ 387 388 vid->lcd = lcd_base; 389 390 /* Initialise the total region size. */ 391 392 fbi->total = jz4740_lcd_get_total_size(vid); 393 394 /* Obtain a reference to the descriptors. */ 395 396 descriptors = (struct jz_fb_dma_descriptor *) lcd_get_descriptors(vid); 397 398 /* Position framebuffer regions at the given address. */ 399 400 fbi->screen = (uint32_t) fb_vaddr; 401 402 /* Obtain the palette address. */ 403 404 fbi->palette = lcd_get_palette(vid); 405 406 /* Initialise a palette for lower colour depths. */ 407 408 if (vid->jz_fb->bpp < 12) 409 lcd_init_palette(vid); 410 411 /* Reference the descriptors in memory. */ 412 413 fbi->dmadesc_fb0 = &descriptors[0]; 414 fbi->dmadesc_fb1 = &descriptors[1]; 415 fbi->dmadesc_palette = &descriptors[2]; 416 417 /* Populate descriptors. */ 418 419 /* Provide the first framebuffer descriptor in single and dual modes. */ 420 421 fbi->dmadesc_fb0->fsadr = lcd_get_framebuffer(0, vid); 422 fbi->dmadesc_fb0->fidr = 0; 423 fbi->dmadesc_fb0->ldcmd = lcd_get_size(vid) / 4; /* length in words */ 424 425 /* Provide the second framebuffer descriptor only in dual-panel mode. */ 426 427 if (lcd_get_panels(vid) == 2) 428 { 429 fbi->dmadesc_fb1->fdadr = fbi->dmadesc_fb1; 430 fbi->dmadesc_fb1->fsadr = lcd_get_framebuffer(1, vid); 431 fbi->dmadesc_fb1->fidr = 0; 432 fbi->dmadesc_fb1->ldcmd = lcd_get_size(vid) / 4; 433 434 /* Note the address to be provided for the second channel. */ 435 436 fbi->fdadr1 = fbi->dmadesc_fb1; 437 } 438 439 /* Initialise palette descriptor details if a palette is to be used. */ 440 441 /* Assume any mode with <12 bpp is palette driven. */ 442 443 if (vid->jz_fb->bpp < 12) 444 { 445 fbi->dmadesc_palette->fsadr = fbi->palette; 446 fbi->dmadesc_palette->fidr = 0; 447 fbi->dmadesc_palette->ldcmd = (lcd_get_palette_size(vid) / 4) | LCD_CMD_PAL; 448 449 /* Flip back and forth between the palette and framebuffer. */ 450 451 fbi->dmadesc_palette->fdadr = fbi->dmadesc_fb0; 452 fbi->dmadesc_fb0->fdadr = fbi->dmadesc_palette; 453 454 /* Provide the palette descriptor address first. */ 455 456 fbi->fdadr0 = fbi->dmadesc_palette; 457 } 458 else 459 { 460 /* No palette: always use the framebuffer descriptor. */ 461 462 fbi->dmadesc_fb0->fdadr = fbi->dmadesc_fb0; 463 fbi->fdadr0 = fbi->dmadesc_fb0; 464 } 465 } 466 467 /* Initialise the LCD registers. */ 468 469 void jz4740_lcd_hw_init(vidinfo_t *vid) 470 { 471 struct jzfb_info *jzfb = vid->jz_fb; 472 uint32_t val = 0; 473 474 /* Compute control register flags. */ 475 476 switch (jzfb->bpp) { 477 case 1: 478 val |= LCD_CTRL_BPP_1; 479 break; 480 481 case 2: 482 val |= LCD_CTRL_BPP_2; 483 break; 484 485 case 4: 486 val |= LCD_CTRL_BPP_4; 487 break; 488 489 case 8: 490 val |= LCD_CTRL_BPP_8; 491 break; 492 493 case 15: 494 val |= LCD_CTRL_RGB555; 495 case 16: 496 val |= LCD_CTRL_BPP_16; 497 break; 498 499 case 17 ... 32: 500 val |= LCD_CTRL_BPP_18_24; /* target is 4bytes/pixel */ 501 break; 502 503 default: 504 val |= LCD_CTRL_BPP_16; /* default to 16bpp */ 505 break; 506 } 507 508 /* Set various configuration registers for the panel. */ 509 510 switch (jzfb->cfg & MODE_MASK) { 511 case MODE_STN_MONO_DUAL: 512 case MODE_STN_COLOR_DUAL: 513 val |= jz_lcd_stn_init(jzfb->h >> 1, vid); 514 break; 515 516 case MODE_STN_MONO_SINGLE: 517 case MODE_STN_COLOR_SINGLE: 518 val |= jz_lcd_stn_init(jzfb->h, vid); 519 break; 520 521 case MODE_TFT_GEN: 522 case MODE_TFT_CASIO: 523 case MODE_8BIT_SERIAL_TFT: 524 case MODE_TFT_18BIT: 525 jz_lcd_tft_init(vid); 526 break; 527 528 case MODE_TFT_SAMSUNG: 529 jz_lcd_samsung_init(vid); 530 break; 531 532 case MODE_TFT_SHARP: 533 jz_lcd_sharp_init(vid); 534 break; 535 536 default: 537 break; 538 } 539 540 /* Further control register and panel configuration. */ 541 542 val |= LCD_CTRL_BST_16; /* Burst Length is 16WORD=64Byte */ 543 val |= LCD_CTRL_OFUP; /* OutFIFO underrun protect */ 544 545 lcd_ctrl_set(vid, LCD_CTRL, val); 546 lcd_ctrl_set(vid, LCD_CFG, jzfb->cfg); 547 } 548 549 /* Initialise DMA for the driver. */ 550 551 void jz4740_lcd_dma_init(vidinfo_t *vid) 552 { 553 struct jz_mem_info *fbi = &vid->jz_mem; 554 uint32_t mode = vid->jz_fb->cfg & MODE_MASK; 555 556 /* Configure DMA by setting frame descriptor addresses. */ 557 558 lcd_ctrl_set(vid, LCD_DA0, (uint32_t) fbi->fdadr0); 559 560 if ((mode == MODE_STN_COLOR_DUAL) || (mode == MODE_STN_MONO_DUAL)) 561 lcd_ctrl_set(vid, LCD_DA1, (uint32_t) fbi->fdadr1); 562 } 563 564 /* Set the colour depth. */ 565 566 void jz4740_lcd_set_bpp(uint8_t bpp, vidinfo_t *vid) 567 { 568 vid->jz_fb->bpp = bpp; 569 } 570 571 void jz4740_lcd_enable(vidinfo_t *vid) 572 { 573 /* Clear the disable bit (DIS) and set the enable bit (ENA). */ 574 575 lcd_ctrl_set(vid, LCD_CTRL, (lcd_ctrl_get(vid, LCD_CTRL) & ~LCD_CTRL_DIS) | LCD_CTRL_ENA); 576 } 577 578 void jz4740_lcd_disable(vidinfo_t *vid) 579 { 580 /* Set the disable bit (DIS). */ 581 582 lcd_ctrl_set(vid, LCD_CTRL, lcd_ctrl_get(vid, LCD_CTRL) | LCD_CTRL_DIS); 583 } 584 585 void jz4740_lcd_quick_disable(vidinfo_t *vid) 586 { 587 /* Clear the enable bit (ENA) for quick disable. */ 588 589 lcd_ctrl_set(vid, LCD_CTRL, lcd_ctrl_get(vid, LCD_CTRL) & ~LCD_CTRL_ENA); 590 }