# HG changeset patch # User Paul Boddie # Date 1591394352 -7200 # Node ID 19eb92c444df58886cbdaa6000c2b174f710c446 # Parent 3d98739acdc622db92212e03815441912d67eb17 Successfully generate a picture by initialising a second DMA channel descriptor. This keeps the LCD/OSD functionality happy since it seems that a well-formed descriptor must be present for foreground 1. By keeping the frame enable bit of the command word clear, the descriptor will not contribute to the image. diff -r 3d98739acdc6 -r 19eb92c444df pkg/devices/lib/lcd/include/lcd-jz4740.h --- a/pkg/devices/lib/lcd/include/lcd-jz4740.h Fri Jun 05 23:45:28 2020 +0200 +++ b/pkg/devices/lib/lcd/include/lcd-jz4740.h Fri Jun 05 23:59:12 2020 +0200 @@ -117,7 +117,7 @@ void _set_descriptor(struct Jz4740_lcd_descriptor &desc, l4_addr_t source, l4_size_t size, struct Jz4740_lcd_descriptor *next, - uint32_t flags = 0); + uint32_t flags = 0, bool frame_enable = true); public: Lcd_jz4740_chip(l4_addr_t addr, Jz4740_lcd_panel *panel); @@ -205,6 +205,7 @@ int jz4740_lcd_enabled(void *lcd); l4_size_t jz4740_lcd_get_descriptors_size(void *lcd); +l4_size_t jz4740_lcd_get_line_size(void *lcd); l4_size_t jz4740_lcd_get_screen_size(void *lcd); l4_addr_t jz4740_lcd_get_palette(void *lcd, l4_addr_t base); diff -r 3d98739acdc6 -r 19eb92c444df pkg/devices/lib/lcd/src/jz4740/lcd-jz4740.cc --- a/pkg/devices/lib/lcd/src/jz4740/lcd-jz4740.cc Fri Jun 05 23:45:28 2020 +0200 +++ b/pkg/devices/lib/lcd/src/jz4740/lcd-jz4740.cc Fri Jun 05 23:59:12 2020 +0200 @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -52,11 +53,16 @@ Source_address_0 = 0x044, // LCD_SA0 Frame_id_0 = 0x048, // LCD_FID0 Command_0 = 0x04c, // LCD_CMD0 + Counter_position_0 = 0x068, // LCD_CPOS0 + Foreground_size_0 = 0x06c, // LCD_DESSIZE0 Desc_address_1 = 0x050, // LCD_DA1 Source_address_1 = 0x054, // LCD_SA1 Frame_id_1 = 0x058, // LCD_FID1 Command_1 = 0x05c, // LCD_CMD1 + Counter_position_1 = 0x078, // LCD_CPOS1 + Foreground_size_1 = 0x07c, // LCD_DESSIZE1 Rgb_control = 0x090, // LCD_RGBC (JZ4780) + Alpha_levels = 0x108, // LCD_ALPHA (JZ4780) Priority_level = 0x2c0, // LCD_PCFG // OSD registers. @@ -186,6 +192,9 @@ { Status_frame_end_irq = 5, Status_frame_start_irq = 4, + Status_out_underrun_irq = 3, + Status_in0_underrun_irq = 2, + Status_in1_underrun_irq = 1, Status_disabled = 0, }; @@ -193,13 +202,23 @@ enum Osd_config_bits : unsigned { + Osd_config_fg1_pixel_alpha_enable = 17, Osd_config_fg1_frame_start_irq_enable = 15, Osd_config_fg1_frame_end_irq_enable = 14, Osd_config_fg0_frame_start_irq_enable = 11, Osd_config_fg0_frame_end_irq_enable = 10, + Osd_config_fg1_enable = 4, + Osd_config_fg0_enable = 3, + Osd_config_alpha_enable = 2, + Osd_config_fg0_pixel_alpha_enable = 1, Osd_config_enable = 0, }; +enum Osd_control_bits : unsigned +{ + Osd_control_ipu_clock_enable = 15, +}; + // RGB control (JZ4780). enum Rgb_control_bits : unsigned @@ -230,6 +249,20 @@ Rgb_even_line_bgr = 5U << Rgb_even_line, }; +// Alpha levels (JZ4780). + +enum Alpha_levels_bits : unsigned +{ + Alpha_level_fg1 = 8, + Alpha_level_fg0 = 0, +}; + +enum Alpha_levels_values : unsigned +{ + Alpha_level_fg1_mask = 0x0000ff00, + Alpha_level_fg0_mask = 0x000000ff, +}; + // Priority level. enum Priority_level_bits : unsigned @@ -317,8 +350,8 @@ : _panel(panel) { _regs = new Hw::Mmio_register_block<32>(addr); - //_burst_size = 64; // 64-word burst size (JZ4780) - _burst_size = 16; // 16-word burst size + _burst_size = 64; // 64-word burst size (JZ4780) + //_burst_size = 16; // 16-word burst size // add_cid("lcd"); // add_cid("lcd-jz4740"); @@ -684,7 +717,8 @@ uint32_t Lcd_jz4740_chip::_control_irq() { - return ((_irq_conditions & Lcd_irq_frame_start) ? (1U << Control_frame_start_irq_enable) : 0) | + return // (1U << Control_out_underrun_irq_enable) | + ((_irq_conditions & Lcd_irq_frame_start) ? (1U << Control_frame_start_irq_enable) : 0) | ((_irq_conditions & Lcd_irq_frame_end) ? (1U << Control_frame_end_irq_enable) : 0); } @@ -711,7 +745,8 @@ uint32_t Lcd_jz4740_chip::_status_irq() { - return ((_irq_conditions & Lcd_irq_frame_start) ? (1U << Status_frame_start_irq) : 0) | + return // (1U << Status_out_underrun_irq) | + ((_irq_conditions & Lcd_irq_frame_start) ? (1U << Status_frame_start_irq) : 0) | ((_irq_conditions & Lcd_irq_frame_end) ? (1U << Status_frame_end_irq) : 0); } @@ -834,30 +869,28 @@ Lcd_jz4740_chip::_set_descriptor(struct Jz4740_lcd_descriptor &desc, l4_addr_t source, l4_size_t size, struct Jz4740_lcd_descriptor *next, - uint32_t flags) + uint32_t flags, + bool frame_enable) { // In the command, indicate the number of words from the source for transfer. desc.next = next; - desc.source = source; + desc.source = frame_enable ? source : 0; desc.identifier = source; desc.command = ((size / sizeof(uint32_t)) & Command_buffer_length_mask) | - (1U << Command_frame_enable) | + (frame_enable ? (1U << Command_frame_enable) : 0) | flags; - printf("next = %08x\n", desc.next); - printf("source = %08x\n", desc.source); - printf("identifier = %08x\n", desc.identifier); - printf("command = %08x\n", desc.command); - // Initialise "new" descriptor fields. desc.offset = 0; desc.page_width = 0; - desc.command_position = (1UL << Position_premultiply_lcd) | - (1UL << Position_coefficient) | + desc.command_position = (1U << Position_premultiply_lcd) | + ((frame_enable ? 1U : 3U) << Position_coefficient) | _position_bpp(); - desc.fg_size = 0xff000000 | (1023 << 12) | (1279 << 0); // JZ4780 driver magic + desc.fg_size = 0xff000000 | + ((_panel->height - 1) << 12) | + ((_panel->width - 1) << 0); } @@ -875,6 +908,8 @@ int have_palette = (_panel->bpp <= 8); + bool _have_fg1 = true; // NOTE: To be formalised! + // Provide the first framebuffer descriptor in single and dual modes. // Flip back and forth between any palette and the framebuffer. @@ -886,11 +921,12 @@ // Provide the second framebuffer descriptor only in dual-panel mode. // Only employ this descriptor in the second DMA channel. - if (get_panels() == 2) + if ((get_panels() == 2) || _have_fg1) _set_descriptor(desc_vaddr[1], get_framebuffer(1, fb_paddr), get_aligned_size(), desc_paddr + 1, - _command_irq()); + _command_irq(), + false); // Initialise palette descriptor details for lower colour depths. @@ -910,11 +946,10 @@ // Provide the palette descriptor address first, if employed. _regs[Desc_address_0] = (uint32_t) (have_palette ? desc_paddr + 2 : desc_paddr); - printf("descriptor = %08x\n", (uint32_t) _regs[Desc_address_0]); // Provide a descriptor for the second DMA channel in dual-panel mode. - if (get_panels() == 2) + if ((get_panels() == 2) || _have_fg1) _regs[Desc_address_1] = (uint32_t) (desc_paddr + 1); // Initialise panel-related registers. @@ -931,10 +966,15 @@ _regs[Rgb_control] = (1U << Rgb_format_enable) | Rgb_odd_line_rgb | Rgb_even_line_rgb; _regs[Priority_level] = _priority_transfer(); - _regs[Osd_config] = 0; // (1U << Osd_config_enable) | _osd_config_irq(); + _regs[Osd_config] = //_osd_config_irq() | + (1U << Osd_config_enable) | + (1U << Osd_config_alpha_enable); + _regs[Alpha_levels] = ((255U << Alpha_level_fg1) & Alpha_level_fg1_mask) | + ((255U << Alpha_level_fg0) & Alpha_level_fg0_mask); printf("LCD control: %08x\n", (unsigned int) _regs[Lcd_control]); printf("LCD status: %08x\n", (unsigned int) _regs[Lcd_status]); + printf("OSD control: %08x\n", (unsigned int) _regs[Osd_control]); printf("OSD config: %08x\n", (unsigned int) _regs[Osd_config]); printf("OSD status: %08x\n", (unsigned int) _regs[Osd_status]); } @@ -953,35 +993,42 @@ long Lcd_jz4740_chip::wait_for_irq() { - long err; l4_msgtag_t tag; _regs[Lcd_status] = _regs[Lcd_status] & ~(_status_irq()); // Wait for a condition. - printf("Waiting for IRQ...\n"); - tag = l4_irq_receive(_irq, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4util_micros2l4to(1000000))); + //printf("Waiting for IRQ...\n"); + tag = l4_irq_receive(_irq, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4util_micros2l4to(2000000))); + + //if (_regs[Lcd_status] & (1U << Status_out_underrun_irq)) + // enable(); + +#if 0 + printf("LCD config: %08x\n", (unsigned int) _regs[Lcd_config]); + printf("LCD control: %08x\n", (unsigned int) _regs[Lcd_control]); printf("LCD status: %08x\n", (unsigned int) _regs[Lcd_status]); + printf("OSD config: %08x\n", (unsigned int) _regs[Osd_config]); + printf("OSD control: %08x\n", (unsigned int) _regs[Osd_control]); printf("OSD status: %08x\n", (unsigned int) _regs[Osd_status]); - printf("LCD control: %08x\n", (unsigned int) _regs[Lcd_control]); printf("LCD command: %08x\n", (unsigned int) _regs[Command_0]); printf("LCD IRQ id: %08x\n", (unsigned int) _regs[Lcd_irq_id]); printf("LCD descriptor: %08x\n", (unsigned int) _regs[Desc_address_0]); printf("LCD source: %08x\n", (unsigned int) _regs[Source_address_0]); printf("LCD frame id: %08x\n", (unsigned int) _regs[Frame_id_0]); - - // Return errors immediately. - - err = l4_ipc_error(tag, l4_utcb()); - if (err) - return err; + printf("LCD counter/position: %08x\n", (unsigned int) _regs[Counter_position_0]); + printf("LCD foreground size: %08x\n", (unsigned int) _regs[Foreground_size_0]); +#endif // Acknowledge interrupts. - _regs[Lcd_status] = _regs[Lcd_status] & ~(_status_irq()); + _regs[Lcd_status] = 0; - return L4_EOK; + // Return errors. + + //printf("Error: %s\n", l4sys_errtostr(l4_error(tag))); + return l4_error(tag); } @@ -1051,6 +1098,12 @@ } l4_size_t +jz4740_lcd_get_line_size(void *lcd) +{ + return static_cast(lcd)->get_line_size(); +} + +l4_size_t jz4740_lcd_get_screen_size(void *lcd) { return static_cast(lcd)->get_screen_size();