1 /* 2 * LCD peripheral support for the JZ4740 and related SoCs. 3 * 4 * Copyright (C) Xiangfu Liu <xiangfu@sharism.cc> 5 * Copyright (C) 2015, 2016, 2017, 2018, 6 * 2020 Paul Boddie <paul@boddie.org.uk> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 * Boston, MA 02110-1301, USA 22 */ 23 24 #include <l4/devices/hw_mmio_register_block.h> 25 #include <l4/sys/cache.h> 26 #include <l4/sys/irq.h> 27 #include <l4/sys/types.h> 28 #include <l4/util/util.h> 29 30 #include "lcd-jz4740.h" 31 #include "lcd-jz4740-config.h" 32 33 #include <stdint.h> 34 #include <stdio.h> 35 36 enum Regs : unsigned 37 { 38 Lcd_config = 0x000, // LCD_CFG 39 Lcd_vsync = 0x004, // LCD_VSYNC 40 Lcd_hsync = 0x008, // LCD_HSYNC 41 Virtual_area = 0x00c, // LCD_VAT 42 Display_hlimits = 0x010, // LCD_DAH 43 Display_vlimits = 0x014, // LCD_DAV 44 Lcd_ps = 0x018, // LCD_PS 45 Lcd_cls = 0x01c, // LCD_CLS 46 Lcd_spl = 0x020, // LCD_SPL 47 Lcd_rev = 0x024, // LCD_REV 48 Lcd_control = 0x030, // LCD_CTRL 49 Lcd_status = 0x034, // LCD_STATE 50 Lcd_irq_id = 0x038, // LCD_IID 51 Desc_address_0 = 0x040, // LCD_DA0 52 Source_address_0 = 0x044, // LCD_SA0 53 Frame_id_0 = 0x048, // LCD_FID0 54 Command_0 = 0x04c, // LCD_CMD0 55 Desc_address_1 = 0x050, // LCD_DA1 56 Source_address_1 = 0x054, // LCD_SA1 57 Frame_id_1 = 0x058, // LCD_FID1 58 Command_1 = 0x05c, // LCD_CMD1 59 Rgb_control = 0x090, // LCD_RGBC (JZ4780) 60 Priority_level = 0x2c0, // LCD_PCFG 61 62 // OSD registers. 63 64 Osd_config = 0x100, // LCD_OSDC 65 Osd_control = 0x104, // LCD_OSDCTRL 66 Osd_status = 0x108, // LCD_OSDS 67 }; 68 69 // Lcd_config descriptions. 70 71 enum Config_values : unsigned 72 { 73 Config_stn_pins_mask = 0x3, 74 Config_mode_mask = 0xf, 75 }; 76 77 // Field positions for registers employing two values, with the first typically 78 // being the start value and the second being an end value. 79 80 enum Value_pair_bits : unsigned 81 { 82 Value_first = 16, 83 Value_second = 0, 84 }; 85 86 // Virtual area bits. 87 88 enum Virtual_area_values : unsigned 89 { 90 Virtual_area_horizontal_size = Value_first, // sum of display and blank regions (dot/pixel clock periods) 91 Virtual_area_vertical_size = Value_second, // sum of display and blank regions (line periods) 92 }; 93 94 // Lcd_control descriptions. 95 96 enum Control_bits : unsigned 97 { 98 Control_pin_modify = 31, // PINMD (change pin usage from 15..0 to 17..10, 8..1) 99 Control_burst_length = 28, // BST (burst length selection) 100 Control_rgb_mode = 27, // RGB (RGB mode) 101 Control_out_underrun = 26, // OFUP (output FIFO underrun protection) 102 Control_frc_algorithm = 24, // FRC (STN FRC algorithm selection) 103 Control_palette_delay = 16, // PDD (load palette delay counter) 104 Control_dac_loopback_test = 14, // DACTE (DAC loopback test) 105 Control_frame_end_irq_enable = 13, // EOFM (end of frame interrupt enable) 106 Control_frame_start_irq_enable = 12, // SOFM (start of frame interrupt enable) 107 Control_out_underrun_irq_enable = 11, // OFUM (output FIFO underrun interrupt enable) 108 Control_in0_underrun_irq_enable = 10, // IFUM0 (input FIFO 0 underrun interrupt enable) 109 Control_in1_underrun_irq_enable = 9, // IFUM1 (input FIFO 1 underrun interrupt enable) 110 Control_disabled_irq_enable = 8, // LDDM (LCD disable done interrupt enable) 111 Control_quick_disabled_irq_enable = 7, // QDM (LCD quick disable done interrupt enable) 112 Control_endian_select = 6, // BEDN (endian selection) 113 Control_bit_order = 5, // PEDN (bit order in bytes) 114 Control_disable = 4, // DIS (disable controller) 115 Control_enable = 3, // ENA (enable controller) 116 Control_bpp = 0, // BPP (bits per pixel) 117 }; 118 119 enum Burst_length_values : unsigned 120 { 121 Burst_length_4 = 0, // 4 word 122 Burst_length_8 = 1, // 8 word 123 Burst_length_16 = 2, // 16 word 124 125 // JZ4780 extensions. 126 127 Burst_length_32 = 3, // 32 word 128 Burst_length_64 = 4, // 64 word 129 Burst_length_mask = 0x7, 130 }; 131 132 enum Rgb_mode_values : unsigned 133 { 134 Rgb_mode_565 = 0, 135 Rgb_mode_555 = 1, 136 Rgb_mode_mask = 0x1, 137 }; 138 139 enum Frc_algorithm_values : unsigned 140 { 141 Frc_greyscales_16 = 0, 142 Frc_greyscales_4 = 1, 143 Frc_greyscales_2 = 2, 144 Frc_greyscales_mask = 0x3, 145 }; 146 147 enum Control_bpp_values : unsigned 148 { 149 Control_bpp_1bpp = 0, 150 Control_bpp_2bpp = 1, 151 Control_bpp_4bpp = 2, 152 Control_bpp_8bpp = 3, 153 Control_bpp_15bpp = 4, 154 Control_bpp_16bpp = 4, 155 Control_bpp_18bpp = 5, 156 Control_bpp_24bpp = 5, 157 Control_bpp_24bpp_comp = 6, 158 Control_bpp_30bpp = 7, 159 Control_bpp_32bpp = 7, 160 Control_bpp_mask = 0x7, 161 }; 162 163 // Command descriptions. 164 165 enum Command_bits : unsigned 166 { 167 Command_frame_start_irq = 31, // SOFINT (start of frame interrupt) 168 Command_frame_end_irq = 30, // EOFINT (end of frame interrupt) 169 Command_lcm_command = 29, // JZ4780: CMD (LCM command/data via DMA0) 170 Command_palette_buffer = 28, // PAL (descriptor references palette, not display data) 171 Command_frame_compressed = 27, // JZ4780: COMPEN (16/24bpp compression enabled) 172 Command_frame_enable = 26, // JZ4780: FRM_EN 173 Command_field_even = 25, // JZ4780: FIELD_SEL (interlace even field) 174 Command_16x16_block = 24, // JZ4780: 16x16BLOCK (fetch data by 16x16 block) 175 Command_buffer_length = 0, // LEN 176 }; 177 178 enum Command_values : unsigned 179 { 180 Command_buffer_length_mask = 0x00ffffff, 181 }; 182 183 // Status descriptions. 184 185 enum Status_bits : unsigned 186 { 187 Status_frame_end_irq = 5, 188 Status_frame_start_irq = 4, 189 Status_disabled = 0, 190 }; 191 192 // OSD configuration bits (JZ4780). 193 194 enum Osd_config_bits : unsigned 195 { 196 Osd_config_fg1_frame_start_irq_enable = 15, 197 Osd_config_fg1_frame_end_irq_enable = 14, 198 Osd_config_fg0_frame_start_irq_enable = 11, 199 Osd_config_fg0_frame_end_irq_enable = 10, 200 Osd_config_enable = 0, 201 }; 202 203 // RGB control (JZ4780). 204 205 enum Rgb_control_bits : unsigned 206 { 207 Rgb_data_padded = 15, // RGBDM 208 Rgb_padding_mode = 14, // DMM 209 Rgb_422 = 8, // 422 210 Rgb_format_enable = 7, // RGBFMT 211 Rgb_odd_line = 4, // OddRGB 212 Rgb_even_line = 0, // EvenRGB 213 }; 214 215 enum Rgb_control_values : unsigned 216 { 217 Rgb_padding_end = 0U << Rgb_padding_mode, 218 Rgb_padding_start = 1U << Rgb_padding_mode, 219 Rgb_odd_line_rgb = 0U << Rgb_odd_line, 220 Rgb_odd_line_rbg = 1U << Rgb_odd_line, 221 Rgb_odd_line_grb = 2U << Rgb_odd_line, 222 Rgb_odd_line_gbr = 3U << Rgb_odd_line, 223 Rgb_odd_line_brg = 4U << Rgb_odd_line, 224 Rgb_odd_line_bgr = 5U << Rgb_odd_line, 225 Rgb_even_line_rgb = 0U << Rgb_even_line, 226 Rgb_even_line_rbg = 1U << Rgb_even_line, 227 Rgb_even_line_grb = 2U << Rgb_even_line, 228 Rgb_even_line_gbr = 3U << Rgb_even_line, 229 Rgb_even_line_brg = 4U << Rgb_even_line, 230 Rgb_even_line_bgr = 5U << Rgb_even_line, 231 }; 232 233 // Priority level. 234 235 enum Priority_level_bits : unsigned 236 { 237 Priority_mode = 31, 238 Priority_highest_burst = 28, 239 Priority_threshold2 = 18, 240 Priority_threshold1 = 9, 241 Priority_threshold0 = 0, 242 }; 243 244 enum Priority_level_values : unsigned 245 { 246 Priority_mode_dynamic = 0U << Priority_mode, 247 Priority_mode_arbiter = 1U << Priority_mode, 248 }; 249 250 enum Priority_burst_values : unsigned 251 { 252 Priority_burst_4 = 0, 253 Priority_burst_8 = 1, 254 Priority_burst_16 = 2, 255 Priority_burst_32 = 3, 256 Priority_burst_64 = 4, 257 Priority_burst_16_cont = 5, 258 Priority_burst_disable = 7, 259 }; 260 261 // Position descriptor member. 262 263 enum Position_bits : unsigned 264 { 265 Position_bpp = 27, 266 Position_premultiply_lcd = 26, 267 Position_coefficient = 24, 268 Position_y_position = 12, 269 Position_x_position = 0, 270 }; 271 272 enum Position_values : unsigned 273 { 274 Position_bpp_15_16bpp = 4, 275 Position_bpp_18_24bpp = 5, 276 Position_bpp_30bpp = 7, 277 }; 278 279 280 281 // Utility functions. 282 283 // Round values up according to the resolution. 284 285 static uint32_t align(uint32_t value, uint32_t resolution) 286 { 287 return (value + (resolution - 1)) & ~(resolution - 1); 288 } 289 290 // Value pair encoding. 291 292 static uint32_t encode_pair(uint32_t start, uint32_t end) 293 { 294 return (start << Value_first) | (end << Value_second); 295 } 296 297 // RGB conversions. 298 299 static uint16_t rgb8_to_rgb16(uint8_t rgb) 300 { 301 return ((((rgb & 0xe0) >> 5) * 4) << 11) | ((((rgb & 0x1c) >> 2) * 9) << 6) | ((rgb & 0x03) * 10); 302 } 303 304 static uint16_t rgb4_to_rgb16(uint8_t rgb) 305 { 306 return ((((rgb & 8) >> 3) * 0x1f) << 11) | ((((rgb & 6) >> 1) * 0x15) << 5) | ((rgb & 1) * 0x1f); 307 } 308 309 310 311 312 // If implemented as a Hw::Device, various properties would be 313 // initialised in the constructor and obtained from the device tree 314 // definitions. 315 316 Lcd_jz4740_chip::Lcd_jz4740_chip(l4_addr_t addr, Jz4740_lcd_panel *panel) 317 : _panel(panel) 318 { 319 _regs = new Hw::Mmio_register_block<32>(addr); 320 //_burst_size = 64; // 64-word burst size (JZ4780) 321 _burst_size = 16; // 16-word burst size 322 323 // add_cid("lcd"); 324 // add_cid("lcd-jz4740"); 325 } 326 327 struct Jz4740_lcd_panel * 328 Lcd_jz4740_chip::get_panel() 329 { 330 return _panel; 331 } 332 333 void 334 Lcd_jz4740_chip::disable() 335 { 336 // Set the disable bit for normal shutdown. 337 338 _regs[Lcd_control] = _regs[Lcd_control] | (1U << Control_disable); 339 } 340 341 void 342 Lcd_jz4740_chip::disable_quick() 343 { 344 // Clear the enable bit for quick shutdown. 345 346 _regs[Lcd_control] = _regs[Lcd_control] & ~(1U << Control_enable); 347 } 348 349 void 350 Lcd_jz4740_chip::enable() 351 { 352 // Clear the disable bit and set the enable bit. 353 // JZ4780: OSD status set. 354 355 _regs[Osd_status] = 0; 356 _regs[Lcd_status] = 0; 357 _regs[Lcd_control] = (_regs[Lcd_control] & ~(1U << Control_disable)) | (1U << Control_enable); 358 printf("LCD control: %x\n", (unsigned int) _regs[Lcd_control]); 359 } 360 361 bool 362 Lcd_jz4740_chip::enabled() 363 { 364 return !(_regs[Lcd_status] & (1U << Status_disabled)); 365 } 366 367 // Calculate and return the pixel clock frequency. 368 369 int 370 Lcd_jz4740_chip::get_pixel_clock() 371 { 372 int pclk, multiplier; 373 374 // Serial mode: 3 pixel clock cycles per pixel (one per channel). 375 // Parallel mode: 1 pixel clock cycle per pixel. 376 377 multiplier = have_serial_tft() ? 3 : 1; 378 379 // Derive pixel clock rate from frame rate. 380 // This multiplies the number of pixel periods in a line by the number of 381 // lines in a frame, thus obtaining the number of such periods in a frame. 382 // Multiplying this result with the frame rate yields the pixel frequency. 383 384 pclk = _panel->frame_rate * 385 (_panel->width * multiplier + 386 _panel->hsync + _panel->line_start + _panel->line_end) * 387 (_panel->height + 388 _panel->vsync + _panel->frame_start + _panel->frame_end); 389 390 // STN panel adjustments. 391 392 if (have_stn_panel()) 393 { 394 // Colour STN panels apparently need to be driven at three times the rate. 395 396 if (have_colour_stn()) pclk = (pclk * 3); 397 398 // Reduce the rate according to the width of the STN connection. 399 // Since the pins setting employs log2(pins), a shift by this value is 400 // equivalent to a division by the number of pins. 401 402 pclk = pclk >> ((_panel->config & Config_stn_pins_mask) >> Jz4740_lcd_config_stn_pins); 403 404 // Divide the rate by the number of panels. 405 406 pclk /= get_panels(); 407 } 408 409 return pclk; 410 } 411 412 413 414 // Return the panel mode. 415 416 uint32_t 417 Lcd_jz4740_chip::_mode() 418 { 419 return _panel->config & Config_mode_mask; 420 } 421 422 // Return the number of panels available. 423 424 int 425 Lcd_jz4740_chip::get_panels() 426 { 427 uint32_t mode = _mode(); 428 429 return (mode == Jz4740_lcd_mode_stn_dual_colour) || 430 (mode == Jz4740_lcd_mode_stn_dual_mono) ? 2 : 1; 431 } 432 433 // Return whether the panel is STN. 434 435 int 436 Lcd_jz4740_chip::have_stn_panel() 437 { 438 uint32_t mode = _mode(); 439 440 return ((mode == Jz4740_lcd_mode_stn_single_colour) || 441 (mode == Jz4740_lcd_mode_stn_dual_colour) || 442 (mode == Jz4740_lcd_mode_stn_single_mono) || 443 (mode == Jz4740_lcd_mode_stn_dual_mono)); 444 } 445 446 // Return whether the panel is colour STN. 447 448 int 449 Lcd_jz4740_chip::have_colour_stn() 450 { 451 uint32_t mode = _mode(); 452 453 return ((mode == Jz4740_lcd_mode_stn_single_colour) || 454 (mode == Jz4740_lcd_mode_stn_dual_colour)); 455 } 456 457 // Return whether the panel is colour STN. 458 459 int 460 Lcd_jz4740_chip::have_serial_tft() 461 { 462 return _mode() == Jz4740_lcd_mode_tft_serial; 463 } 464 465 466 467 // Return the pixel memory size in bits. 468 469 l4_size_t 470 Lcd_jz4740_chip::get_pixel_size() 471 { 472 if (_panel->bpp > 16) 473 return 32; 474 else if (_panel->bpp > 8) 475 return 16; 476 else 477 return _panel->bpp; 478 } 479 480 // Return the line memory size. 481 482 l4_size_t 483 Lcd_jz4740_chip::get_line_size() 484 { 485 // Lines must be aligned to a word boundary. 486 487 return align((_panel->width * get_pixel_size()) / 8, sizeof(uint32_t)); 488 } 489 490 // Return the screen memory size. 491 492 l4_size_t 493 Lcd_jz4740_chip::get_screen_size() 494 { 495 return get_line_size() * _panel->height; 496 } 497 498 // Return the aligned size for the DMA transfer. 499 500 l4_size_t 501 Lcd_jz4740_chip::get_aligned_size() 502 { 503 return align(get_screen_size(), _burst_size * sizeof(uint32_t)); 504 } 505 506 // Return the size of the palette. 507 508 l4_size_t 509 Lcd_jz4740_chip::get_palette_size() 510 { 511 // No palette for modes with more than eight bits per pixel. 512 513 if (_panel->bpp > 8) return 0; 514 515 // Get the size of a collection of two-byte entries, one per colour. 516 517 return (1U << (_panel->bpp)) * sizeof(uint16_t); 518 } 519 520 // Return the aligned size of the palette for the DMA transfer. 521 522 l4_size_t 523 Lcd_jz4740_chip::get_aligned_palette_size() 524 { 525 return align(get_palette_size(), _burst_size * sizeof(uint32_t)); 526 } 527 528 // Return the total memory requirements of the framebuffers and palette. 529 530 l4_size_t 531 Lcd_jz4740_chip::get_total_size() 532 { 533 return get_aligned_size() * get_panels() + get_aligned_palette_size(); 534 } 535 536 // Return the total memory requirements of any DMA descriptors. 537 538 l4_size_t 539 Lcd_jz4740_chip::get_descriptors_size() 540 { 541 return 3 * sizeof(struct Jz4740_lcd_descriptor); 542 } 543 544 545 546 // Functions returning addresses of each data region. 547 // The base parameter permits the retrieval of virtual or physical addresses. 548 549 l4_addr_t 550 Lcd_jz4740_chip::get_palette(l4_addr_t base) 551 { 552 // Use memory at the end of the allocated region for the palette. 553 554 return base + (get_panels() * get_aligned_size()) - get_aligned_palette_size(); 555 } 556 557 l4_addr_t 558 Lcd_jz4740_chip::get_framebuffer(int panel, l4_addr_t base) 559 { 560 // Framebuffers for panels are allocated at the start of the region. 561 562 return base + (panel * get_aligned_size()); 563 } 564 565 566 567 // Palette initialisation. 568 569 void 570 Lcd_jz4740_chip::init_palette(l4_addr_t palette) 571 { 572 uint8_t colours = 1U << (_panel->bpp); 573 uint16_t *entry = (uint16_t *) palette; 574 uint16_t *end = entry + colours; 575 uint8_t value = 0; 576 577 while (entry < end) 578 { 579 switch (_panel->bpp) 580 { 581 case 4: 582 *entry = rgb4_to_rgb16(value); 583 break; 584 585 case 8: 586 *entry = rgb8_to_rgb16(value); 587 break; 588 589 default: 590 break; 591 } 592 593 value++; 594 entry++; 595 } 596 } 597 598 599 600 // Return colour depth control value. 601 // NOTE: Not supporting JZ4780 options. 602 603 uint32_t 604 Lcd_jz4740_chip::_control_bpp() 605 { 606 switch (_panel->bpp) 607 { 608 case 1: return Control_bpp_1bpp; 609 case 2: return Control_bpp_2bpp; 610 case 3 ... 4: return Control_bpp_4bpp; 611 case 5 ... 8: return Control_bpp_8bpp; 612 case 9 ... 15: return Control_bpp_15bpp | (Rgb_mode_555 << Control_rgb_mode); 613 case 17 ... 18: return Control_bpp_18bpp; 614 case 19 ... 32: return Control_bpp_24bpp; 615 case 16: 616 default: return Control_bpp_16bpp; 617 } 618 } 619 620 // Return colour depth control value. 621 // JZ4780 position details only. 622 623 uint32_t 624 Lcd_jz4740_chip::_position_bpp() 625 { 626 uint32_t value; 627 628 switch (_panel->bpp) 629 { 630 case 15: case 16: value = Position_bpp_15_16bpp; break; 631 case 18: case 24: value = Position_bpp_18_24bpp; break; 632 case 30: value = Position_bpp_30bpp; break; 633 default: value = 0; break; 634 } 635 636 return value << Position_bpp; 637 } 638 639 // Return a panel-related control value. 640 641 uint32_t 642 Lcd_jz4740_chip::_control_panel() 643 { 644 if (have_stn_panel()) 645 return _control_stn_frc() << Control_frc_algorithm; 646 else 647 return 0; 648 } 649 650 // Return a STN-related control value. 651 652 uint32_t 653 Lcd_jz4740_chip::_control_stn_frc() 654 { 655 if (_panel->bpp <= 2) 656 return Frc_greyscales_2; 657 if (_panel->bpp <= 4) 658 return Frc_greyscales_4; 659 return Frc_greyscales_16; 660 } 661 662 // Return a transfer-related control value. 663 664 uint32_t 665 Lcd_jz4740_chip::_control_transfer() 666 { 667 uint32_t length; 668 669 switch (_burst_size) 670 { 671 case 4: length = Burst_length_4; break; 672 case 8: length = Burst_length_8; break; 673 case 32: length = Burst_length_32; break; 674 case 64: length = Burst_length_64; break; 675 case 16: 676 default: length = Burst_length_16; break; 677 } 678 679 return (length << Control_burst_length) | (1U << Control_out_underrun); 680 } 681 682 // Return an interrupt-related control value. 683 684 uint32_t 685 Lcd_jz4740_chip::_control_irq() 686 { 687 return ((_irq_conditions & Lcd_irq_frame_start) ? (1U << Control_frame_start_irq_enable) : 0) | 688 ((_irq_conditions & Lcd_irq_frame_end) ? (1U << Control_frame_end_irq_enable) : 0); 689 } 690 691 // Return an interrupt-related OSD configuration value. 692 693 uint32_t 694 Lcd_jz4740_chip::_osd_config_irq() 695 { 696 return ((_irq_conditions & Lcd_irq_frame_start) ? (1U << Osd_config_fg0_frame_start_irq_enable) : 0) | 697 ((_irq_conditions & Lcd_irq_frame_end) ? (1U << Osd_config_fg0_frame_end_irq_enable) : 0); 698 } 699 700 // Return an interrupt-related command value. 701 702 uint32_t 703 Lcd_jz4740_chip::_command_irq() 704 { 705 return ((_irq_conditions & Lcd_irq_frame_start) ? (1U << Command_frame_start_irq) : 0) | 706 ((_irq_conditions & Lcd_irq_frame_end) ? (1U << Command_frame_end_irq) : 0); 707 } 708 709 // Return an interrupt-related status value. 710 711 uint32_t 712 Lcd_jz4740_chip::_status_irq() 713 { 714 return ((_irq_conditions & Lcd_irq_frame_start) ? (1U << Status_frame_start_irq) : 0) | 715 ((_irq_conditions & Lcd_irq_frame_end) ? (1U << Status_frame_end_irq) : 0); 716 } 717 718 uint32_t 719 Lcd_jz4740_chip::_priority_transfer() 720 { 721 uint32_t length; 722 723 switch (_burst_size) 724 { 725 case 4: length = Priority_burst_4; break; 726 case 8: length = Priority_burst_8; break; 727 case 32: length = Priority_burst_32; break; 728 case 64: length = Priority_burst_64; break; 729 case 16: 730 default: length = Priority_burst_16; break; 731 } 732 733 return Priority_mode_arbiter | 734 (length << Priority_highest_burst) | 735 (511U << Priority_threshold2) | 736 (400U << Priority_threshold1) | 737 (256U << Priority_threshold0); 738 } 739 740 // STN panel-specific initialisation. 741 742 void 743 Lcd_jz4740_chip::_init_stn() 744 { 745 // Divide the height by the number of panels. 746 747 uint32_t height = _panel->height / get_panels(); 748 749 // Since the value is log2(pins), 1 << value yields the number of pins. 750 751 int pins = 1 << ((_panel->config & Config_stn_pins_mask) >> Jz4740_lcd_config_stn_pins); 752 753 // Round parameters up to a multiple of the number of pins. 754 755 uint32_t hsync = align(_panel->hsync, pins); 756 uint32_t line_start = align(_panel->line_start, pins); 757 uint32_t line_end = align(_panel->line_end, pins); 758 759 // Define the start and end positions of visible data on a line and in a frame. 760 // Visible frame data is anchored at line zero, with the start region 761 // preceding this line (and thus appearing at the end of the preceding frame). 762 763 uint32_t line_start_pos = line_start; 764 uint32_t line_end_pos = line_start_pos + _panel->width; 765 uint32_t frame_start_pos = 0; 766 uint32_t frame_end_pos = frame_start_pos + height; 767 768 // Define sync pulse locations, with hsync occurring after the visible data. 769 770 _regs[Lcd_hsync] = encode_pair(line_end_pos, line_end_pos + hsync); 771 _regs[Lcd_vsync] = encode_pair(0, _panel->vsync); 772 773 // Set the display area and limits. 774 775 _regs[Virtual_area] = encode_pair(line_end_pos + hsync + line_end, 776 frame_end_pos + _panel->vsync + _panel->frame_end + _panel->frame_start); 777 778 _regs[Display_hlimits] = encode_pair(line_start_pos, line_end_pos); 779 _regs[Display_vlimits] = encode_pair(frame_start_pos, frame_end_pos); 780 781 // Set the AC bias signal. 782 783 _regs[Lcd_ps] = encode_pair(0, _panel->frame_start + height + _panel->vsync + _panel->frame_end); 784 } 785 786 // TFT panel-specific initialisation. 787 788 void 789 Lcd_jz4740_chip::_init_tft() 790 { 791 // Define the start and end positions of visible data on a line and in a frame. 792 793 uint32_t line_start_pos = _panel->line_start + _panel->hsync; 794 uint32_t line_end_pos = line_start_pos + _panel->width; 795 uint32_t frame_start_pos = _panel->frame_start + _panel->vsync; 796 uint32_t frame_end_pos = frame_start_pos + _panel->height; 797 798 // Define sync pulse locations, with pulses appearing before visible data. 799 800 _regs[Lcd_hsync] = encode_pair(0, _panel->hsync); 801 _regs[Lcd_vsync] = encode_pair(0, _panel->vsync); 802 803 // Set the display area and limits. 804 805 _regs[Virtual_area] = encode_pair(line_end_pos + _panel->line_end, 806 frame_end_pos + _panel->frame_end); 807 808 _regs[Display_hlimits] = encode_pair(line_start_pos, line_end_pos); 809 _regs[Display_vlimits] = encode_pair(frame_start_pos, frame_end_pos); 810 } 811 812 // Initialise the panel. 813 // NOTE: Only generic STN and TFT panels are supported. 814 815 void 816 Lcd_jz4740_chip::_init_panel() 817 { 818 if (have_stn_panel()) 819 _init_stn(); 820 else 821 switch (_mode()) 822 { 823 case Jz4740_lcd_mode_tft_generic: 824 case Jz4740_lcd_mode_tft_casio: 825 case Jz4740_lcd_mode_tft_serial: _init_tft(); 826 827 default: break; 828 } 829 } 830 831 // Initialise a DMA descriptor. 832 833 void 834 Lcd_jz4740_chip::_set_descriptor(struct Jz4740_lcd_descriptor &desc, 835 l4_addr_t source, l4_size_t size, 836 struct Jz4740_lcd_descriptor *next, 837 uint32_t flags) 838 { 839 // In the command, indicate the number of words from the source for transfer. 840 841 desc.next = next; 842 desc.source = source; 843 desc.identifier = source; 844 desc.command = ((size / sizeof(uint32_t)) & Command_buffer_length_mask) | 845 (1U << Command_frame_enable) | 846 flags; 847 848 printf("next = %08x\n", desc.next); 849 printf("source = %08x\n", desc.source); 850 printf("identifier = %08x\n", desc.identifier); 851 printf("command = %08x\n", desc.command); 852 853 // Initialise "new" descriptor fields. 854 855 desc.offset = 0; 856 desc.page_width = 0; 857 desc.command_position = (1UL << Position_premultiply_lcd) | 858 (1UL << Position_coefficient) | 859 _position_bpp(); 860 desc.fg_size = 0xff000000 | (1023 << 12) | (1279 << 0); // JZ4780 driver magic 861 } 862 863 864 865 // Initialise the LCD controller with the memory, panel and framebuffer details. 866 // Any palette must be initialised separately using get_palette and init_palette. 867 868 void 869 Lcd_jz4740_chip::config(struct Jz4740_lcd_descriptor *desc_vaddr, 870 struct Jz4740_lcd_descriptor *desc_paddr, 871 l4_addr_t fb_paddr) 872 { 873 // NOTE: Remarks in the Ingenic Linux 3.0.8 driver suggest that the JZ4775 and 874 // NOTE: JZ4780 do not support palettes. 875 876 int have_palette = (_panel->bpp <= 8); 877 878 // Provide the first framebuffer descriptor in single and dual modes. 879 // Flip back and forth between any palette and the framebuffer. 880 881 _set_descriptor(desc_vaddr[0], get_framebuffer(0, fb_paddr), 882 get_aligned_size(), 883 have_palette ? desc_paddr + 2 : desc_paddr, 884 _command_irq()); 885 886 // Provide the second framebuffer descriptor only in dual-panel mode. 887 // Only employ this descriptor in the second DMA channel. 888 889 if (get_panels() == 2) 890 _set_descriptor(desc_vaddr[1], get_framebuffer(1, fb_paddr), 891 get_aligned_size(), 892 desc_paddr + 1, 893 _command_irq()); 894 895 // Initialise palette descriptor details for lower colour depths. 896 897 if (have_palette) 898 _set_descriptor(desc_vaddr[2], get_palette(fb_paddr), 899 get_aligned_palette_size(), 900 desc_paddr, 901 Command_palette_buffer); 902 903 // Flush cached structure data. 904 905 l4_cache_clean_data((unsigned long) desc_vaddr, 906 (unsigned long) desc_vaddr + get_descriptors_size()); 907 908 // Configure DMA by setting frame descriptor addresses. 909 910 // Provide the palette descriptor address first, if employed. 911 912 _regs[Desc_address_0] = (uint32_t) (have_palette ? desc_paddr + 2 : desc_paddr); 913 printf("descriptor = %08x\n", (uint32_t) _regs[Desc_address_0]); 914 915 // Provide a descriptor for the second DMA channel in dual-panel mode. 916 917 if (get_panels() == 2) 918 _regs[Desc_address_1] = (uint32_t) (desc_paddr + 1); 919 920 // Initialise panel-related registers. 921 922 _init_panel(); 923 924 // Initialise the control and configuration registers. 925 // NOTE: JZ4780 does not support bpp setting here. 926 927 _regs[Lcd_control] = _control_panel() | _control_bpp() | _control_transfer() | _control_irq(); 928 _regs[Lcd_config] = _panel->config; 929 930 // NOTE: JZ4780 only. 931 932 _regs[Rgb_control] = (1U << Rgb_format_enable) | Rgb_odd_line_rgb | Rgb_even_line_rgb; 933 _regs[Priority_level] = _priority_transfer(); 934 _regs[Osd_config] = 0; // (1U << Osd_config_enable) | _osd_config_irq(); 935 936 printf("LCD control: %08x\n", (unsigned int) _regs[Lcd_control]); 937 printf("LCD status: %08x\n", (unsigned int) _regs[Lcd_status]); 938 printf("OSD config: %08x\n", (unsigned int) _regs[Osd_config]); 939 printf("OSD status: %08x\n", (unsigned int) _regs[Osd_status]); 940 } 941 942 // Set the interrupt for controller-related events. 943 944 void 945 Lcd_jz4740_chip::set_irq(l4_cap_idx_t irq, enum Jz4740_lcd_irq_condition conditions) 946 { 947 _irq = irq; 948 _irq_conditions = conditions; 949 } 950 951 // Wait for an interrupt condition. 952 953 long 954 Lcd_jz4740_chip::wait_for_irq() 955 { 956 long err; 957 l4_msgtag_t tag; 958 959 _regs[Lcd_status] = _regs[Lcd_status] & ~(_status_irq()); 960 961 // Wait for a condition. 962 963 printf("Waiting for IRQ...\n"); 964 tag = l4_irq_receive(_irq, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4util_micros2l4to(1000000))); 965 printf("LCD status: %08x\n", (unsigned int) _regs[Lcd_status]); 966 printf("OSD status: %08x\n", (unsigned int) _regs[Osd_status]); 967 printf("LCD control: %08x\n", (unsigned int) _regs[Lcd_control]); 968 printf("LCD command: %08x\n", (unsigned int) _regs[Command_0]); 969 printf("LCD IRQ id: %08x\n", (unsigned int) _regs[Lcd_irq_id]); 970 printf("LCD descriptor: %08x\n", (unsigned int) _regs[Desc_address_0]); 971 printf("LCD source: %08x\n", (unsigned int) _regs[Source_address_0]); 972 printf("LCD frame id: %08x\n", (unsigned int) _regs[Frame_id_0]); 973 974 // Return errors immediately. 975 976 err = l4_ipc_error(tag, l4_utcb()); 977 if (err) 978 return err; 979 980 // Acknowledge interrupts. 981 982 _regs[Lcd_status] = _regs[Lcd_status] & ~(_status_irq()); 983 984 return L4_EOK; 985 } 986 987 988 989 // C language interface functions. 990 991 void * 992 jz4740_lcd_init(l4_addr_t lcd_base, struct Jz4740_lcd_panel *panel) 993 { 994 return (void *) new Lcd_jz4740_chip(lcd_base, panel); 995 } 996 997 void 998 jz4740_lcd_config(void *lcd, struct Jz4740_lcd_descriptor *desc_vaddr, 999 struct Jz4740_lcd_descriptor *desc_paddr, 1000 l4_addr_t fb_paddr) 1001 { 1002 static_cast<Lcd_jz4740_chip *>(lcd)->config(desc_vaddr, desc_paddr, fb_paddr); 1003 } 1004 1005 void 1006 jz4740_lcd_set_irq(void *lcd, l4_cap_idx_t irq, enum Jz4740_lcd_irq_condition conditions) 1007 { 1008 static_cast<Lcd_jz4740_chip *>(lcd)->set_irq(irq, conditions); 1009 } 1010 1011 long 1012 jz4740_lcd_wait_for_irq(void *lcd) 1013 { 1014 return static_cast<Lcd_jz4740_chip *>(lcd)->wait_for_irq(); 1015 } 1016 1017 void 1018 jz4740_lcd_disable(void *lcd) 1019 { 1020 static_cast<Lcd_jz4740_chip *>(lcd)->disable(); 1021 } 1022 1023 void 1024 jz4740_lcd_disable_quick(void *lcd) 1025 { 1026 static_cast<Lcd_jz4740_chip *>(lcd)->disable_quick(); 1027 } 1028 1029 void 1030 jz4740_lcd_enable(void *lcd) 1031 { 1032 static_cast<Lcd_jz4740_chip *>(lcd)->enable(); 1033 } 1034 1035 int 1036 jz4740_lcd_enabled(void *lcd) 1037 { 1038 return (int) static_cast<Lcd_jz4740_chip *>(lcd)->enabled(); 1039 } 1040 1041 int 1042 jz4740_lcd_get_pixel_clock(void *lcd) 1043 { 1044 return static_cast<Lcd_jz4740_chip *>(lcd)->get_pixel_clock(); 1045 } 1046 1047 l4_size_t 1048 jz4740_lcd_get_descriptors_size(void *lcd) 1049 { 1050 return static_cast<Lcd_jz4740_chip *>(lcd)->get_descriptors_size(); 1051 } 1052 1053 l4_size_t 1054 jz4740_lcd_get_screen_size(void *lcd) 1055 { 1056 return static_cast<Lcd_jz4740_chip *>(lcd)->get_screen_size(); 1057 } 1058 1059 l4_addr_t 1060 jz4740_lcd_get_palette(void *lcd, l4_addr_t base) 1061 { 1062 return static_cast<Lcd_jz4740_chip *>(lcd)->get_palette(base); 1063 } 1064 1065 void 1066 jz4740_lcd_init_palette(void *lcd, l4_addr_t palette) 1067 { 1068 static_cast<Lcd_jz4740_chip *>(lcd)->init_palette(palette); 1069 }