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