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/types.h> 27 28 #include "lcd-jz4740.h" 29 #include "lcd-jz4740-config.h" 30 31 #include <stdint.h> 32 33 enum Regs : unsigned 34 { 35 Lcd_config = 0x000, // LCD_CFG 36 Lcd_vsync = 0x004, // LCD_VSYNC 37 Lcd_hsync = 0x008, // LCD_HSYNC 38 Vertical_area = 0x00c, // LCD_VAT 39 Display_hlimits = 0x010, // LCD_DAH 40 Display_vlimits = 0x014, // LCD_DAV 41 Lcd_ps = 0x018, // LCD_PS 42 Lcd_cls = 0x01c, // LCD_CLS 43 Lcd_spl = 0x020, // LCD_SPL 44 Lcd_rev = 0x024, // LCD_REV 45 Lcd_control = 0x030, // LCD_CTRL 46 Lcd_status = 0x034, // LCD_STATE 47 Lcd_irq_id = 0x038, // LCD_IID 48 Desc_address_0 = 0x040, // LCD_DA0 49 Source_address_0 = 0x044, // LCD_SA0 50 Frame_id_0 = 0x048, // LCD_FID0 51 Command_0 = 0x04c, // LCD_CMD0 52 Desc_address_1 = 0x050, // LCD_DA1 53 Source_address_1 = 0x054, // LCD_SA1 54 Frame_id_1 = 0x058, // LCD_FID1 55 Command_1 = 0x05c, // LCD_CMD1 56 }; 57 58 // Lcd_config descriptions. 59 60 enum Config_values : unsigned 61 { 62 Config_stn_pins_mask = 0x3, 63 Config_mode_mask = 0xf, 64 }; 65 66 // Field positions for registers employing two values, with the first typically 67 // being the start value and the second being an end value. 68 69 enum Value_pair_bits : unsigned 70 { 71 Value_first = 16, 72 Value_second = 0, 73 }; 74 75 // Vertical_area bits. 76 77 enum Vertical_area_values : unsigned 78 { 79 Vertical_area_horizontal_size = Value_first, // sum of display and blank regions (dot/pixel clock periods) 80 Vertical_area_vertical_size = Value_second, // sum of display and blank regions (line periods) 81 }; 82 83 // Lcd_control descriptions. 84 85 enum Control_bits : unsigned 86 { 87 Control_pin_modify = 31, // PINMD (change pin usage from 15..0 to 17..10, 8..1) 88 Control_burst_length = 28, // BST (burst length selection) 89 Control_rgb_mode = 27, // RGB (RGB mode) 90 Control_out_underrun = 26, // OFUP (output FIFO underrun protection) 91 Control_frc_algorithm = 24, // FRC (STN FRC algorithm selection) 92 Control_palette_delay = 16, // PDD (load palette delay counter) 93 Control_dac_loopback_test = 14, // DACTE (DAC loopback test) 94 Control_frame_end_irq_enable = 13, // EOFM (end of frame interrupt enable) 95 Control_frame_start_irq_enable = 12, // SOFM (start of frame interrupt enable) 96 Control_out_underrun_irq_enable = 11, // OFUM (output FIFO underrun interrupt enable) 97 Control_in0_underrun_irq_enable = 10, // IFUM0 (input FIFO 0 underrun interrupt enable) 98 Control_in1_underrun_irq_enable = 9, // IFUM1 (input FIFO 1 underrun interrupt enable) 99 Control_disabled_irq_enable = 8, // LDDM (LCD disable done interrupt enable) 100 Control_quick_disabled_irq_enable = 7, // QDM (LCD quick disable done interrupt enable) 101 Control_endian_select = 6, // BEDN (endian selection) 102 Control_bit_order = 5, // PEDN (bit order in bytes) 103 Control_disable = 4, // DIS (disable controller) 104 Control_enable = 3, // ENA (enable controller) 105 Control_bpp = 0, // BPP (bits per pixel) 106 }; 107 108 enum Burst_length_values : unsigned 109 { 110 Burst_length_4 = 0, // 4 word 111 Burst_length_8 = 1, // 8 word 112 Burst_length_16 = 2, // 16 word 113 114 // JZ4780 extensions. 115 116 Burst_length_32 = 3, // 32 word 117 Burst_length_64 = 4, // 64 word 118 Burst_length_mask = 0x7, 119 }; 120 121 enum Rgb_mode_values : unsigned 122 { 123 Rgb_mode_565 = 0, 124 Rgb_mode_555 = 1, 125 Rgb_mode_mask = 0x1, 126 }; 127 128 enum Frc_algorithm_values : unsigned 129 { 130 Frc_greyscales_16 = 0, 131 Frc_greyscales_4 = 1, 132 Frc_greyscales_2 = 2, 133 Frc_greyscales_mask = 0x3, 134 }; 135 136 enum Control_bpp_values : unsigned 137 { 138 Control_bpp_1bpp = 0, 139 Control_bpp_2bpp = 1, 140 Control_bpp_4bpp = 2, 141 Control_bpp_8bpp = 3, 142 Control_bpp_15bpp = 4, 143 Control_bpp_16bpp = 4, 144 Control_bpp_18bpp = 5, 145 Control_bpp_24bpp = 5, 146 Control_bpp_24bpp_comp = 6, 147 Control_bpp_30bpp = 7, 148 Control_bpp_32bpp = 7, 149 Control_bpp_mask = 0x7, 150 }; 151 152 // Command descriptions. 153 154 enum Command_bits : unsigned 155 { 156 Command_frame_start_irq = 31, // SOFINT (start of frame interrupt) 157 Command_frame_end_irq = 30, // EOFINT (end of frame interrupt) 158 Command_lcm_command = 29, // JZ4780: CMD (LCM command/data via DMA0) 159 Command_palette_buffer = 28, // PAL (descriptor references palette, not display data) 160 Command_frame_compressed = 27, // JZ4780: COMPEN (16/24bpp compression enabled) 161 Command_frame_enable = 26, // JZ4780: FRM_EN 162 Command_field_even = 25, // JZ4780: FIELD_SEL (interlace even field) 163 Command_16x16_block = 24, // JZ4780: 16x16BLOCK (fetch data by 16x16 block) 164 Command_buffer_length = 0, // LEN 165 }; 166 167 enum Command_values : unsigned 168 { 169 Command_buffer_length_mask = 0x00ffffff, 170 }; 171 172 173 174 // Utility functions. 175 176 // Round values up according to the resolution. 177 178 static uint32_t align(uint32_t value, uint32_t resolution) 179 { 180 return (value + (resolution - 1)) & ~(resolution - 1); 181 } 182 183 // Value pair encoding. 184 185 static uint32_t encode_pair(uint32_t start, uint32_t end) 186 { 187 return (start << Value_first) | (end << Value_second); 188 } 189 190 // RGB conversions. 191 192 static uint16_t rgb8_to_rgb16(uint8_t rgb) 193 { 194 return ((((rgb & 0xe0) >> 5) * 4) << 11) | ((((rgb & 0x1c) >> 2) * 9) << 6) | ((rgb & 0x03) * 10); 195 } 196 197 static uint16_t rgb4_to_rgb16(uint8_t rgb) 198 { 199 return ((((rgb & 8) >> 3) * 0x1f) << 11) | ((((rgb & 6) >> 1) * 0x15) << 5) | ((rgb & 1) * 0x1f); 200 } 201 202 203 204 205 // If implemented as a Hw::Device, various properties would be 206 // initialised in the constructor and obtained from the device tree 207 // definitions. 208 209 Lcd_jz4740_chip::Lcd_jz4740_chip(l4_addr_t addr, Jz4740_lcd_panel *panel) 210 : _panel(panel) 211 { 212 _regs = new Hw::Mmio_register_block<32>(addr); 213 _burst_size = 16; // 16-word burst size 214 215 // add_cid("lcd"); 216 // add_cid("lcd-jz4740"); 217 } 218 219 struct Jz4740_lcd_panel * 220 Lcd_jz4740_chip::get_panel() 221 { 222 return _panel; 223 } 224 225 void 226 Lcd_jz4740_chip::disable() 227 { 228 // Set the disable bit for normal shutdown. 229 230 _regs[Lcd_control] = _regs[Lcd_control] | (1 << Control_disable); 231 } 232 233 void 234 Lcd_jz4740_chip::disable_quick() 235 { 236 // Clear the enable bit for quick shutdown. 237 238 _regs[Lcd_control] = _regs[Lcd_control] & ~(1 << Control_enable); 239 } 240 241 void 242 Lcd_jz4740_chip::enable() 243 { 244 // Clear the disable bit and set the enable bit. 245 246 _regs[Lcd_control] = (_regs[Lcd_control] & ~(1 << Control_disable)) | (1 << Control_enable); 247 } 248 249 // Calculate and return the pixel clock frequency. 250 251 int 252 Lcd_jz4740_chip::get_pixel_clock() 253 { 254 int pclk, multiplier; 255 256 // Serial mode: 3 pixel clock cycles per pixel (one per channel). 257 // Parallel mode: 1 pixel clock cycle per pixel. 258 259 multiplier = have_serial_tft() ? 3 : 1; 260 261 // Derive pixel clock rate from frame rate. 262 // This multiplies the number of pixel periods in a line by the number of 263 // lines in a frame, thus obtaining the number of such periods in a frame. 264 // Multiplying this result with the frame rate yields the pixel frequency. 265 266 pclk = _panel->frame_rate * 267 (_panel->width * multiplier + 268 _panel->hsync + _panel->line_start + _panel->line_end) * 269 (_panel->height + 270 _panel->vsync + _panel->frame_start + _panel->frame_end); 271 272 // STN panel adjustments. 273 274 if (have_stn_panel()) 275 { 276 // Colour STN panels apparently need to be driven at three times the rate. 277 278 if (have_colour_stn()) pclk = (pclk * 3); 279 280 // Reduce the rate according to the width of the STN connection. 281 // Since the pins setting employs log2(pins), a shift by this value is 282 // equivalent to a division by the number of pins. 283 284 pclk = pclk >> ((_panel->config & Config_stn_pins_mask) >> Jz4740_lcd_config_stn_pins); 285 286 // Divide the rate by the number of panels. 287 288 pclk /= get_panels(); 289 } 290 291 return pclk; 292 } 293 294 295 296 // Return the panel mode. 297 298 uint32_t 299 Lcd_jz4740_chip::_mode() 300 { 301 return _panel->config & Config_mode_mask; 302 } 303 304 // Return the number of panels available. 305 306 int 307 Lcd_jz4740_chip::get_panels() 308 { 309 uint32_t mode = _mode(); 310 311 return (mode == Jz4740_lcd_mode_stn_dual_colour) || 312 (mode == Jz4740_lcd_mode_stn_dual_mono) ? 2 : 1; 313 } 314 315 // Return whether the panel is STN. 316 317 int 318 Lcd_jz4740_chip::have_stn_panel() 319 { 320 uint32_t mode = _mode(); 321 322 return ((mode == Jz4740_lcd_mode_stn_single_colour) || 323 (mode == Jz4740_lcd_mode_stn_dual_colour) || 324 (mode == Jz4740_lcd_mode_stn_single_mono) || 325 (mode == Jz4740_lcd_mode_stn_dual_mono)); 326 } 327 328 // Return whether the panel is colour STN. 329 330 int 331 Lcd_jz4740_chip::have_colour_stn() 332 { 333 uint32_t mode = _mode(); 334 335 return ((mode == Jz4740_lcd_mode_stn_single_colour) || 336 (mode == Jz4740_lcd_mode_stn_dual_colour)); 337 } 338 339 // Return whether the panel is colour STN. 340 341 int 342 Lcd_jz4740_chip::have_serial_tft() 343 { 344 return _mode() == Jz4740_lcd_mode_tft_serial; 345 } 346 347 348 349 // Return the line memory size. 350 351 l4_size_t 352 Lcd_jz4740_chip::get_line_size() 353 { 354 // Lines must be aligned to a word boundary. 355 356 return align((_panel->width * _panel->bpp) / 8, sizeof(uint32_t)); 357 } 358 359 // Return the screen memory size. 360 361 l4_size_t 362 Lcd_jz4740_chip::get_screen_size() 363 { 364 return get_line_size() * _panel->height; 365 } 366 367 // Return the aligned size for the DMA transfer. 368 369 l4_size_t 370 Lcd_jz4740_chip::get_aligned_size() 371 { 372 return align(get_screen_size(), _burst_size * sizeof(uint32_t)); 373 } 374 375 // Return the size of the palette. 376 377 l4_size_t 378 Lcd_jz4740_chip::get_palette_size() 379 { 380 // No palette for modes with more than eight bits per pixel. 381 382 if (_panel->bpp > 8) return 0; 383 384 // Get the size of a collection of two-byte entries, one per colour. 385 386 return (1 << (_panel->bpp)) * sizeof(uint16_t); 387 } 388 389 // Return the aligned size of the palette for the DMA transfer. 390 391 l4_size_t 392 Lcd_jz4740_chip::get_aligned_palette_size() 393 { 394 return align(get_palette_size(), _burst_size * sizeof(uint32_t)); 395 } 396 397 // Return the total memory requirements of the framebuffers and palette. 398 399 l4_size_t 400 Lcd_jz4740_chip::get_total_size() 401 { 402 return get_aligned_size() * get_panels() + get_aligned_palette_size(); 403 } 404 405 // Return the total memory requirements of any DMA descriptors. 406 407 l4_size_t 408 Lcd_jz4740_chip::get_descriptors_size() 409 { 410 return 3 * sizeof(struct Jz4740_lcd_descriptor); 411 } 412 413 414 415 // Functions returning addresses of each data region. 416 // The base parameter permits the retrieval of virtual or physical addresses. 417 418 l4_addr_t 419 Lcd_jz4740_chip::get_palette(l4_addr_t base) 420 { 421 // Use memory at the end of the allocated region for the palette. 422 423 return base + (get_panels() * get_aligned_size()) - get_aligned_palette_size(); 424 } 425 426 l4_addr_t 427 Lcd_jz4740_chip::get_framebuffer(int panel, l4_addr_t base) 428 { 429 // Framebuffers for panels are allocated at the start of the region. 430 431 return base + (panel * get_aligned_size()); 432 } 433 434 435 436 // Palette initialisation. 437 438 void 439 Lcd_jz4740_chip::init_palette(l4_addr_t palette) 440 { 441 uint8_t colours = 1 << (_panel->bpp); 442 uint16_t *entry = (uint16_t *) palette; 443 uint16_t *end = entry + colours; 444 uint8_t value = 0; 445 446 while (entry < end) 447 { 448 switch (_panel->bpp) 449 { 450 case 4: 451 *entry = rgb4_to_rgb16(value); 452 break; 453 454 case 8: 455 *entry = rgb8_to_rgb16(value); 456 break; 457 458 default: 459 break; 460 } 461 462 value++; 463 entry++; 464 } 465 } 466 467 468 469 // Return colour depth control value. 470 // NOTE: Not supporting JZ4780 options. 471 472 uint32_t 473 Lcd_jz4740_chip::_control_bpp() 474 { 475 switch (_panel->bpp) 476 { 477 case 1: return Control_bpp_1bpp; 478 case 2: return Control_bpp_2bpp; 479 case 3 ... 4: return Control_bpp_4bpp; 480 case 5 ... 8: return Control_bpp_8bpp; 481 case 9 ... 15: return Control_bpp_15bpp | (Rgb_mode_555 << Control_rgb_mode); 482 case 17 ... 18: return Control_bpp_18bpp; 483 case 19 ... 32: return Control_bpp_24bpp; 484 case 16: 485 default: return Control_bpp_16bpp; 486 } 487 } 488 489 // Return a panel-related control value. 490 491 uint32_t 492 Lcd_jz4740_chip::_control_panel() 493 { 494 if (have_stn_panel()) 495 return _control_stn_frc(); 496 else 497 return 0; 498 } 499 500 // Return a STN-related control value. 501 502 uint32_t 503 Lcd_jz4740_chip::_control_stn_frc() 504 { 505 if (_panel->bpp <= 2) 506 return Frc_greyscales_2; 507 if (_panel->bpp <= 4) 508 return Frc_greyscales_4; 509 return Frc_greyscales_16; 510 } 511 512 // Return a transfer-related control value. 513 514 uint32_t 515 Lcd_jz4740_chip::_control_transfer() 516 { 517 uint32_t length; 518 519 switch (_burst_size) 520 { 521 case 4: length = Burst_length_4; break; 522 case 8: length = Burst_length_8; break; 523 case 32: length = Burst_length_32; break; 524 case 64: length = Burst_length_64; break; 525 case 16: 526 default: length = Burst_length_16; break; 527 } 528 529 return (length << Control_burst_length) | (1 << Control_out_underrun); 530 } 531 532 // STN panel-specific initialisation. 533 534 void 535 Lcd_jz4740_chip::_init_stn() 536 { 537 // Divide the height by the number of panels. 538 539 uint32_t height = _panel->height / get_panels(); 540 541 // Since the value is log2(pins), 1 << value yields the number of pins. 542 543 int pins = 1 << ((_panel->config & Config_stn_pins_mask) >> Jz4740_lcd_config_stn_pins); 544 545 // Round parameters up to a multiple of the number of pins. 546 547 uint32_t hsync = align(_panel->hsync, pins); 548 uint32_t line_start = align(_panel->line_start, pins); 549 uint32_t line_end = align(_panel->line_end, pins); 550 551 // Define the start and end positions of visible data on a line and in a frame. 552 // Visible frame data is anchored at line zero, with the start region 553 // preceding this line (and thus appearing at the end of the preceding frame). 554 555 uint32_t line_start_pos = line_start; 556 uint32_t line_end_pos = line_start_pos + _panel->width; 557 uint32_t frame_start_pos = 0; 558 uint32_t frame_end_pos = frame_start_pos + height; 559 560 // Define sync pulse locations, with hsync occurring after the visible data. 561 562 _regs[Lcd_hsync] = encode_pair(line_end_pos, line_end_pos + hsync); 563 _regs[Lcd_vsync] = encode_pair(0, _panel->vsync); 564 565 // Set the display area and limits. 566 567 _regs[Vertical_area] = encode_pair(line_end_pos + hsync + line_end, 568 frame_end_pos + _panel->vsync + _panel->frame_end + _panel->frame_start); 569 570 _regs[Display_hlimits] = encode_pair(line_start_pos, line_end_pos); 571 _regs[Display_vlimits] = encode_pair(frame_start_pos, frame_end_pos); 572 573 // Set the AC bias signal. 574 575 _regs[Lcd_ps] = encode_pair(0, _panel->frame_start + height + _panel->vsync + _panel->frame_end); 576 } 577 578 // TFT panel-specific initialisation. 579 580 void 581 Lcd_jz4740_chip::_init_tft() 582 { 583 // Define the start and end positions of visible data on a line and in a frame. 584 585 uint32_t line_start_pos = _panel->line_start + _panel->hsync; 586 uint32_t line_end_pos = line_start_pos + _panel->width; 587 uint32_t frame_start_pos = _panel->frame_start + _panel->vsync; 588 uint32_t frame_end_pos = frame_start_pos + _panel->height; 589 590 // Define sync pulse locations, with pulses appearing before visible data. 591 592 _regs[Lcd_hsync] = encode_pair(0, _panel->hsync); 593 _regs[Lcd_vsync] = encode_pair(0, _panel->vsync); 594 595 // Set the display area and limits. 596 597 _regs[Vertical_area] = encode_pair(line_end_pos + _panel->line_end, 598 frame_end_pos + _panel->frame_end); 599 600 _regs[Display_hlimits] = encode_pair(line_start_pos, line_end_pos); 601 _regs[Display_vlimits] = encode_pair(frame_start_pos, frame_end_pos); 602 } 603 604 // Initialise the panel. 605 // NOTE: Only generic STN and TFT panels are supported. 606 607 void 608 Lcd_jz4740_chip::_init_panel() 609 { 610 if (have_stn_panel()) 611 _init_stn(); 612 else 613 switch (_mode()) 614 { 615 case Jz4740_lcd_mode_tft_generic: 616 case Jz4740_lcd_mode_tft_casio: 617 case Jz4740_lcd_mode_tft_serial: _init_tft(); 618 619 default: break; 620 } 621 } 622 623 // Initialise a DMA descriptor. 624 625 void 626 Lcd_jz4740_chip::_set_descriptor(struct Jz4740_lcd_descriptor &desc, 627 l4_addr_t source, l4_size_t size, 628 struct Jz4740_lcd_descriptor *next, 629 uint32_t flags) 630 { 631 // In the command, indicate the number of words from the source for transfer. 632 633 desc.next = next; 634 desc.source = source; 635 desc.identifier = 0; 636 desc.command = ((size / sizeof(uint32_t)) & Command_buffer_length_mask) | flags; 637 } 638 639 640 641 // Initialise the LCD controller with the memory, panel and framebuffer details. 642 // Any palette must be initialised separately using get_palette and init_palette. 643 644 void 645 Lcd_jz4740_chip::config(struct Jz4740_lcd_descriptor *desc_vaddr, 646 struct Jz4740_lcd_descriptor *desc_paddr, 647 l4_addr_t fb_paddr) 648 { 649 int have_palette = (_panel->bpp <= 8); 650 651 // Provide the first framebuffer descriptor in single and dual modes. 652 // Flip back and forth between any palette and the framebuffer. 653 654 _set_descriptor(desc_vaddr[0], get_framebuffer(0, fb_paddr), 655 get_screen_size(), 656 have_palette ? desc_paddr + 2 : desc_paddr); 657 658 // Provide the second framebuffer descriptor only in dual-panel mode. 659 // Only employ this descriptor in the second DMA channel. 660 661 if (get_panels() == 2) 662 _set_descriptor(desc_vaddr[1], get_framebuffer(1, fb_paddr), 663 get_screen_size(), 664 desc_paddr + 1); 665 666 // Initialise palette descriptor details for lower colour depths. 667 668 if (have_palette) 669 _set_descriptor(desc_vaddr[2], get_palette(fb_paddr), 670 get_palette_size(), 671 desc_paddr, 672 Command_palette_buffer); 673 674 // Flush cached structure data. 675 676 l4_cache_clean_data((unsigned long) desc_vaddr, 677 (unsigned long) desc_vaddr + get_descriptors_size()); 678 679 // Configure DMA by setting frame descriptor addresses. 680 681 // Provide the palette descriptor address first, if employed. 682 683 _regs[Desc_address_0] = (uint32_t) (have_palette ? desc_paddr + 2 : desc_paddr); 684 685 // Provide a descriptor for the second DMA channel in dual-panel mode. 686 687 if (get_panels() == 2) 688 _regs[Desc_address_1] = (uint32_t) (desc_paddr + 1); 689 690 // Initialise panel-related registers. 691 692 _init_panel(); 693 694 // Initialise the control and configuration registers. 695 696 _regs[Lcd_control] = _control_panel() | _control_bpp() | _control_transfer(); 697 _regs[Lcd_config] = _panel->config; 698 } 699 700 701 702 // C language interface functions. 703 704 void * 705 jz4740_lcd_init(l4_addr_t lcd_base, struct Jz4740_lcd_panel *panel) 706 { 707 return (void *) new Lcd_jz4740_chip(lcd_base, panel); 708 } 709 710 void 711 jz4740_lcd_config(void *lcd, struct Jz4740_lcd_descriptor *desc_vaddr, 712 struct Jz4740_lcd_descriptor *desc_paddr, 713 l4_addr_t fb_paddr) 714 { 715 static_cast<Lcd_jz4740_chip *>(lcd)->config(desc_vaddr, desc_paddr, fb_paddr); 716 } 717 718 void 719 jz4740_lcd_disable(void *lcd) 720 { 721 static_cast<Lcd_jz4740_chip *>(lcd)->disable(); 722 } 723 724 void 725 jz4740_lcd_disable_quick(void *lcd) 726 { 727 static_cast<Lcd_jz4740_chip *>(lcd)->disable_quick(); 728 } 729 730 void 731 jz4740_lcd_enable(void *lcd) 732 { 733 static_cast<Lcd_jz4740_chip *>(lcd)->enable(); 734 } 735 736 int 737 jz4740_lcd_get_pixel_clock(void *lcd) 738 { 739 return static_cast<Lcd_jz4740_chip *>(lcd)->get_pixel_clock(); 740 } 741 742 l4_addr_t 743 jz4740_lcd_get_palette(void *lcd, l4_addr_t base) 744 { 745 return static_cast<Lcd_jz4740_chip *>(lcd)->get_palette(base); 746 } 747 748 void 749 jz4740_lcd_init_palette(void *lcd, l4_addr_t palette) 750 { 751 static_cast<Lcd_jz4740_chip *>(lcd)->init_palette(palette); 752 }