1 /* 2 * JzRISC LCD controller 3 * 4 * Copyright (C) Xiangfu Liu <xiangfu@sharism.cc> 5 * Copyright (C) 2015, 2016 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 #define align2(n) (n)=((((n)+1)>>1)<<1) 29 #define align4(n) (n)=((((n)+3)>>2)<<2) 30 #define align8(n) (n)=((((n)+7)>>3)<<3) 31 32 extern struct jzfb_info jzfb; 33 extern vidinfo_t panel_info; 34 35 static unsigned short lcd_get_panels() 36 { 37 return ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL) || 38 ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ? 2 : 1; 39 } 40 41 42 43 /* Functions returning region sizes. */ 44 45 static unsigned long lcd_get_size(vidinfo_t *vid) 46 { 47 /* Lines must be aligned to a word boundary. */ 48 unsigned long line_length = ALIGN((vid->vl_col * NBITS(vid->vl_bpix)) / 8, sizeof(u32)); 49 return line_length * vid->vl_row; 50 } 51 52 static unsigned long lcd_get_aligned_size(vidinfo_t *vid) 53 { 54 /* LCD_CTRL_BST_16 requires 16-word alignment. */ 55 return ALIGN(lcd_get_size(vid), 16 * sizeof(u32)); 56 } 57 58 static unsigned long lcd_get_min_size(vidinfo_t *vid) 59 { 60 /* Lines must be aligned to a word boundary. */ 61 unsigned long line_length = ALIGN((vid->vl_col * 32) / 8, sizeof(u32)); 62 return line_length * vid->vl_row; 63 } 64 65 static unsigned long lcd_get_aligned_min_size(vidinfo_t *vid) 66 { 67 /* LCD_CTRL_BST_16 requires 16-word alignment. */ 68 return ALIGN(lcd_get_min_size(vid), 16 * sizeof(u32)); 69 } 70 71 static unsigned long lcd_get_palette_size(vidinfo_t *vid) 72 { 73 if (NBITS(vid->vl_bpix) < 12) 74 return NCOLORS(vid->vl_bpix) * sizeof(u16); 75 else 76 return 0; 77 } 78 79 static unsigned long lcd_get_aligned_palette_size(vidinfo_t *vid) 80 { 81 /* LCD_CTRL_BST_16 requires 16-word alignment. */ 82 return ALIGN(lcd_get_palette_size(vid), 16 * sizeof(u32)); 83 } 84 85 static unsigned long lcd_get_descriptors_size() 86 { 87 return 3 * sizeof(struct jz_fb_dma_descriptor); 88 } 89 90 static unsigned long lcd_get_total_size(vidinfo_t *vid) 91 { 92 unsigned long size = lcd_get_aligned_size(vid) * lcd_get_panels(); 93 unsigned long min_size = lcd_get_aligned_min_size(vid); 94 95 /* Round up to nearest full page, or MMU section if defined. */ 96 return ALIGN((size >= min_size ? size : min_size) + lcd_get_aligned_palette_size(vid) + lcd_get_descriptors_size(), PAGE_SIZE); 97 } 98 99 100 101 /* Functions returning addresses of each data region. */ 102 103 static unsigned long lcd_get_palette(unsigned long addr) 104 { 105 /* Allocate memory at the end of the region for the palette. */ 106 return addr - lcd_get_aligned_palette_size(&panel_info); 107 } 108 109 static unsigned long lcd_get_descriptors(unsigned long addr) 110 { 111 /* Allocate memory before the palette for the descriptor array. */ 112 return lcd_get_palette(addr) - lcd_get_descriptors_size(); 113 } 114 115 static unsigned long lcd_get_framebuffer(unsigned long addr, unsigned short panel) 116 { 117 /* Allocate pages for the frame buffer and palette. */ 118 return addr - lcd_get_total_size(&panel_info) + (panel * lcd_get_aligned_size(&panel_info)); 119 } 120 121 122 123 /* Initialisation functions. */ 124 125 static void jz_lcd_desc_init(vidinfo_t *vid) 126 { 127 struct jz_fb_dma_descriptor *descriptors; 128 struct jz_fb_info * fbi; 129 130 fbi = &vid->jz_fb; 131 132 /* Allocate space for descriptors before the palette entries. */ 133 134 descriptors = (struct jz_fb_dma_descriptor *) lcd_get_descriptors(get_memory_size()); 135 fbi->dmadesc_fblow = (struct jz_fb_dma_descriptor *) &descriptors[0]; 136 fbi->dmadesc_fbhigh = (struct jz_fb_dma_descriptor *) &descriptors[1]; 137 fbi->dmadesc_palette = (struct jz_fb_dma_descriptor *) &descriptors[2]; 138 139 /* Populate descriptors. */ 140 141 if (lcd_get_panels() == 2) 142 { 143 fbi->dmadesc_fblow->fdadr = fbi->dmadesc_fblow; 144 fbi->dmadesc_fblow->fsadr = lcd_get_framebuffer(get_memory_size(), 1); 145 fbi->dmadesc_fblow->fidr = 0; 146 fbi->dmadesc_fblow->ldcmd = lcd_get_size(vid) / 4 ; 147 148 fbi->fdadr1 = fbi->dmadesc_fblow; /* only used in dual-panel mode */ 149 } 150 151 fbi->dmadesc_fbhigh->fsadr = fbi->screen; 152 fbi->dmadesc_fbhigh->fidr = 0; 153 fbi->dmadesc_fbhigh->ldcmd = lcd_get_size(vid) / 4; /* length in words */ 154 155 if (NBITS(vid->vl_bpix) < 12) 156 { 157 fbi->dmadesc_palette->fsadr = fbi->palette; 158 fbi->dmadesc_palette->fidr = 0; 159 fbi->dmadesc_palette->ldcmd = (lcd_get_palette_size(vid) / 4) | (1<<28); 160 161 /* assume any mode with <12 bpp is palette driven */ 162 fbi->dmadesc_palette->fdadr = fbi->dmadesc_fbhigh; 163 fbi->dmadesc_fbhigh->fdadr = fbi->dmadesc_palette; 164 /* flips back and forth between pal and fbhigh */ 165 fbi->fdadr0 = fbi->dmadesc_palette; 166 } else { 167 /* palette shouldn't be loaded in true-color mode */ 168 fbi->dmadesc_fbhigh->fdadr = fbi->dmadesc_fbhigh; 169 fbi->fdadr0 = fbi->dmadesc_fbhigh; /* no pal just fbhigh */ 170 } 171 172 flush_cache_all(); 173 } 174 175 static unsigned int jz_lcd_stn_init(unsigned int stnH) 176 { 177 unsigned int val = 0; 178 179 switch (jzfb.bpp) { 180 case 1: 181 /* val |= LCD_CTRL_PEDN; */ 182 case 2: 183 val |= LCD_CTRL_FRC_2; 184 break; 185 case 4: 186 val |= LCD_CTRL_FRC_4; 187 break; 188 case 8: 189 default: 190 val |= LCD_CTRL_FRC_16; 191 break; 192 } 193 194 switch (jzfb.cfg & STN_DAT_PINMASK) { 195 case STN_DAT_PIN1: 196 /* Do not adjust the hori-param value. */ 197 break; 198 case STN_DAT_PIN2: 199 align2(jzfb.hsw); 200 align2(jzfb.elw); 201 align2(jzfb.blw); 202 break; 203 case STN_DAT_PIN4: 204 align4(jzfb.hsw); 205 align4(jzfb.elw); 206 align4(jzfb.blw); 207 break; 208 case STN_DAT_PIN8: 209 align8(jzfb.hsw); 210 align8(jzfb.elw); 211 align8(jzfb.blw); 212 break; 213 } 214 215 REG_LCD_VSYNC = (0 << 16) | jzfb.vsw; 216 REG_LCD_HSYNC = ((jzfb.blw+jzfb.w) << 16) | (jzfb.blw+jzfb.w+jzfb.hsw); 217 218 /* Screen setting */ 219 REG_LCD_VAT = ((jzfb.blw + jzfb.w + jzfb.hsw + jzfb.elw) << 16) | (stnH + jzfb.vsw + jzfb.bfw + jzfb.efw); 220 REG_LCD_DAH = (jzfb.blw << 16) | (jzfb.blw + jzfb.w); 221 REG_LCD_DAV = (0 << 16) | (stnH); 222 223 /* AC BIAs signal */ 224 REG_LCD_PS = (0 << 16) | (stnH+jzfb.vsw+jzfb.efw+jzfb.bfw); 225 226 return val; 227 } 228 229 static void jz_lcd_tft_init() 230 { 231 REG_LCD_VSYNC = (0 << 16) | jzfb.vsw; 232 REG_LCD_HSYNC = (0 << 16) | jzfb.hsw; 233 REG_LCD_DAV =((jzfb.vsw+jzfb.bfw) << 16) | (jzfb.vsw +jzfb.bfw+jzfb.h); 234 REG_LCD_DAH = ((jzfb.hsw + jzfb.blw) << 16) | (jzfb.hsw + jzfb.blw + jzfb.w ); 235 REG_LCD_VAT = (((jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw)) << 16) \ 236 | (jzfb.vsw + jzfb.bfw + jzfb.h + jzfb.efw); 237 } 238 239 static void jz_lcd_samsung_init(unsigned int pclk) 240 { 241 unsigned int total, tp_s, tp_e, ckv_s, ckv_e; 242 unsigned int rev_s, rev_e, inv_s, inv_e; 243 244 jz_lcd_tft_init(); 245 246 total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw; 247 tp_s = jzfb.blw + jzfb.w + 1; 248 tp_e = tp_s + 1; 249 /* ckv_s = tp_s - jz_clocks.pixclk/(1000000000/4100); */ 250 ckv_s = tp_s - pclk/(1000000000/4100); 251 ckv_e = tp_s + total; 252 rev_s = tp_s - 11; /* -11.5 clk */ 253 rev_e = rev_s + total; 254 inv_s = tp_s; 255 inv_e = inv_s + total; 256 REG_LCD_CLS = (tp_s << 16) | tp_e; 257 REG_LCD_PS = (ckv_s << 16) | ckv_e; 258 REG_LCD_SPL = (rev_s << 16) | rev_e; 259 REG_LCD_REV = (inv_s << 16) | inv_e; 260 jzfb.cfg |= STFT_REVHI | STFT_SPLHI; 261 } 262 263 static void jz_lcd_sharp_init() 264 { 265 unsigned int total, cls_s, cls_e, ps_s, ps_e; 266 unsigned int spl_s, spl_e, rev_s, rev_e; 267 268 jz_lcd_tft_init(); 269 270 total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw; 271 spl_s = 1; 272 spl_e = spl_s + 1; 273 cls_s = 0; 274 cls_e = total - 60; /* > 4us (pclk = 80ns) */ 275 ps_s = cls_s; 276 ps_e = cls_e; 277 rev_s = total - 40; /* > 3us (pclk = 80ns) */ 278 rev_e = rev_s + total; 279 jzfb.cfg |= STFT_PSHI; 280 REG_LCD_SPL = (spl_s << 16) | spl_e; 281 REG_LCD_CLS = (cls_s << 16) | cls_e; 282 REG_LCD_PS = (ps_s << 16) | ps_e; 283 REG_LCD_REV = (rev_s << 16) | rev_e; 284 } 285 286 static unsigned int jz_lcd_get_pixel_clock() 287 { 288 unsigned int pclk; 289 290 /* Derive pixel clock from frame clock. */ 291 292 if ( (jzfb.cfg & MODE_MASK) != MODE_8BIT_SERIAL_TFT) { 293 pclk = jzfb.fclk * (jzfb.w + jzfb.hsw + jzfb.elw + jzfb.blw) * 294 (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); 295 } else { 296 /* serial mode: Hsync period = 3*Width_Pixel */ 297 pclk = jzfb.fclk * (jzfb.w*3 + jzfb.hsw + jzfb.elw + jzfb.blw) * 298 (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); 299 } 300 301 if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) || 302 ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL)) 303 pclk = (pclk * 3); 304 305 if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) || 306 ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || 307 ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_SINGLE) || 308 ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) 309 pclk = pclk >> ((jzfb.cfg & STN_DAT_PINMASK) >> 4); 310 311 if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || 312 ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) 313 pclk >>= 1; 314 315 return pclk; 316 } 317 318 static void jz_lcd_set_timing(unsigned int pclk) 319 { 320 unsigned int val; 321 322 #ifdef CONFIG_CPU_JZ4730 323 val = __cpm_get_pllout() / pclk; 324 REG_CPM_CFCR2 = val - 1; 325 val = pclk * 4 ; 326 if ( val > 150000000 ) { 327 val = 150000000; 328 } 329 val = __cpm_get_pllout() / val; 330 val--; 331 if ( val > 0xF ) 332 val = 0xF; 333 #else 334 int pll_div; 335 336 pll_div = ( REG_CPM_CPCCR & CPM_CPCCR_PCS ); /* clock source,0:pllout/2 1: pllout */ 337 pll_div = pll_div ? 1 : 2 ; 338 val = ( __cpm_get_pllout()/pll_div ) / pclk; 339 val--; 340 if ( val > 0x1ff ) { 341 val = 0x1ff; 342 } 343 __cpm_set_pixdiv(val); 344 345 val = pclk * 3 ; /* LCDClock > 2.5*Pixclock */ 346 if ( val > 150000000 ) { 347 val = 150000000; 348 } 349 val = ( __cpm_get_pllout()/pll_div ) / val; 350 val--; 351 if ( val > 0x1f ) { 352 val = 0x1f; 353 } 354 #endif 355 __cpm_set_ldiv( val ); 356 REG_CPM_CPCCR |= CPM_CPCCR_CE ; /* update divide */ 357 } 358 359 static int jz_lcd_hw_init(vidinfo_t *vid) 360 { 361 struct jz_fb_info *fbi = &vid->jz_fb; 362 unsigned int val = 0; 363 unsigned int pclk = jz_lcd_get_pixel_clock(); 364 365 /* Setting Control register */ 366 switch (jzfb.bpp) { 367 case 1: 368 val |= LCD_CTRL_BPP_1; 369 break; 370 case 2: 371 val |= LCD_CTRL_BPP_2; 372 break; 373 case 4: 374 val |= LCD_CTRL_BPP_4; 375 break; 376 case 8: 377 val |= LCD_CTRL_BPP_8; 378 break; 379 case 15: 380 val |= LCD_CTRL_RGB555; 381 case 16: 382 val |= LCD_CTRL_BPP_16; 383 break; 384 #ifndef CONFIG_CPU_JZ4730 385 case 17 ... 32: 386 val |= LCD_CTRL_BPP_18_24; /* target is 4bytes/pixel */ 387 break; 388 #endif 389 default: 390 /* printf("jz_lcd.c The BPP %d is not supported\n", jzfb.bpp); */ 391 val |= LCD_CTRL_BPP_16; 392 break; 393 } 394 395 switch (jzfb.cfg & MODE_MASK) { 396 case MODE_STN_MONO_DUAL: 397 case MODE_STN_COLOR_DUAL: 398 val |= jz_lcd_stn_init(jzfb.h >> 1); 399 break; 400 401 case MODE_STN_MONO_SINGLE: 402 case MODE_STN_COLOR_SINGLE: 403 val |= jz_lcd_stn_init(jzfb.h); 404 break; 405 406 case MODE_TFT_GEN: 407 case MODE_TFT_CASIO: 408 case MODE_8BIT_SERIAL_TFT: 409 case MODE_TFT_18BIT: 410 jz_lcd_tft_init(); 411 break; 412 413 case MODE_TFT_SAMSUNG: 414 { 415 jz_lcd_samsung_init(pclk); 416 break; 417 } 418 419 case MODE_TFT_SHARP: 420 { 421 jz_lcd_sharp_init(); 422 break; 423 } 424 425 default: 426 break; 427 } 428 429 /* Configure the LCD panel */ 430 431 val |= LCD_CTRL_BST_16; /* Burst Length is 16WORD=64Byte */ 432 val |= LCD_CTRL_OFUP; /* OutFIFO underrun protect */ 433 REG_LCD_CTRL = val; 434 REG_LCD_CFG = jzfb.cfg; 435 436 /* Timing reset. */ 437 438 __cpm_stop_lcd(); 439 jz_lcd_set_timing(pclk); 440 __cpm_start_lcd(); 441 udelay(1000); 442 443 /* Configure DMA. */ 444 445 REG_LCD_DA0 = (unsigned long) fbi->fdadr0; /* frame descriptor */ 446 447 if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || 448 ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) 449 REG_LCD_DA1 = (unsigned long) fbi->fdadr1; /* frame descriptor */ 450 451 return 0; 452 } 453 454 static inline u8 LCD_CODE(u8 bpp) 455 { 456 u8 code = 0; 457 while (bpp && !(bpp & 1)) 458 { 459 bpp >>= 1; 460 code += 1; 461 } 462 return code; 463 } 464 465 /* Public operations. */ 466 467 void lcd_set_bpp(u8 bpp) 468 { 469 jzfb.bpp = bpp; 470 panel_info.vl_bpix = LCD_CODE(bpp); 471 } 472 473 void lcd_enable() 474 { 475 /* Clear the disable bit and set the enable bit. */ 476 477 REG_LCD_CTRL &= ~(1<<4); /* LCDCTRL.DIS */ 478 REG_LCD_CTRL |= 1<<3; /* LCDCTRL.ENA*/ 479 } 480 481 void lcd_disable() 482 { 483 REG_LCD_CTRL |= (1<<4); /* LCDCTRL.DIS, regular disable */ 484 } 485 486 void lcd_quick_disable() 487 { 488 REG_LCD_CTRL &= ~(1<<4); /* LCDCTRL.ENA, quick disable */ 489 } 490 491 static inline u16 rgb8_to_rgb16(u8 rgb) 492 { 493 return ((((rgb & 0xe0) >> 5) * 4) << 11) | ((((rgb & 0x1c) >> 2) * 9) << 6) | ((rgb & 0x03) * 10); 494 } 495 496 static inline u16 rgb4_to_rgb16(u8 rgb) 497 { 498 return ((((rgb & 8) >> 3) * 0x1f) << 11) | ((((rgb & 6) >> 1) * 0x15) << 5) | ((rgb & 1) * 0x1f); 499 } 500 501 static void lcd_init_palette(vidinfo_t *vid) 502 { 503 u16 *palette = (u16 *) lcd_get_palette(get_memory_size()); 504 u16 *end = (u16 *) palette + NCOLORS(vid->vl_bpix); 505 u8 value = 0; 506 507 while (palette < end) 508 { 509 switch (vid->vl_bpix) 510 { 511 case LCD_COLOR4: 512 *palette = rgb4_to_rgb16(value); 513 break; 514 515 case LCD_COLOR8: 516 default: 517 *palette = rgb8_to_rgb16(value); 518 break; 519 } 520 521 value++; 522 palette++; 523 } 524 } 525 526 unsigned long lcd_ctrl_init() 527 { 528 struct jz_fb_info *fbi = &panel_info.jz_fb; 529 530 /* Start from the top of memory and obtain palette and framebuffer regions. */ 531 532 fbi->screen = lcd_get_framebuffer(get_memory_size(), 0); 533 fbi->palette = lcd_get_palette(get_memory_size()); 534 535 if (NBITS(panel_info.vl_bpix) < 12) 536 lcd_init_palette(&panel_info); 537 538 jz_lcd_desc_init(&panel_info); 539 jz_lcd_hw_init(&panel_info); 540 541 return fbi->screen; 542 }