1.1 --- a/pkg/devices/lib/lcd/include/lcd-jz4740.h Mon Jun 01 15:43:34 2020 +0200
1.2 +++ b/pkg/devices/lib/lcd/include/lcd-jz4740.h Mon Jun 01 15:47:14 2020 +0200
1.3 @@ -28,7 +28,8 @@
1.4
1.5 #include <stdint.h>
1.6
1.7 -/* Descriptor referenced by the DMA mechanism. */
1.8 +/* Descriptor referenced by the DMA mechanism extended to 8 words for JZ4780
1.9 + support. */
1.10
1.11 struct Jz4740_lcd_descriptor
1.12 {
1.13 @@ -36,16 +37,9 @@
1.14 uint32_t source; /* FSADR: frame source address */
1.15 uint32_t identifier; /* FIDR: frame identifier */
1.16 uint32_t command; /* CMD: command */
1.17 -};
1.18 -
1.19 -/* 8-word "new descriptor" variant for the JZ4780. */
1.20
1.21 -struct Jz4780_lcd_descriptor
1.22 -{
1.23 - struct Jz4780_lcd_descriptor *next; /* FDADR: frame descriptor address */
1.24 - uint32_t source; /* FSADR: frame source address */
1.25 - uint32_t identifier; /* FIDR: frame identifier */
1.26 - uint32_t command; /* CMD: command */
1.27 + /* "New" descriptor fields. */
1.28 +
1.29 uint32_t offset; /* OFFSIZE: offset in words between lines */
1.30 uint32_t page_width; /* PW: number of words per line (16x16 block mode) */
1.31 uint32_t command_position; /* CNUM: command number (smart LCD mode) or
1.32 @@ -53,6 +47,15 @@
1.33 uint32_t fg_size; /* DESSIZE: foreground size and alpha properties */
1.34 };
1.35
1.36 +/* Interrupt conditions. */
1.37 +
1.38 +enum Jz4740_lcd_irq_condition
1.39 +{
1.40 + Lcd_irq_none = 0,
1.41 + Lcd_irq_frame_start = 1,
1.42 + Lcd_irq_frame_end = 2,
1.43 +};
1.44 +
1.45
1.46
1.47 /* C++ language interface. */
1.48 @@ -69,14 +72,37 @@
1.49 Hw::Register_block<32> _regs;
1.50 Jz4740_lcd_panel *_panel;
1.51 int _burst_size;
1.52 + enum Jz4740_lcd_irq_condition _irq_conditions = Lcd_irq_none;
1.53 + l4_cap_idx_t _irq = L4_INVALID_CAP;
1.54
1.55 /* Control register value calculation. */
1.56
1.57 uint32_t _control_bpp();
1.58 + uint32_t _control_irq();
1.59 uint32_t _control_panel();
1.60 uint32_t _control_stn_frc();
1.61 uint32_t _control_transfer();
1.62
1.63 + /* OSD configure register value calculation. */
1.64 +
1.65 + uint32_t _osd_config_irq();
1.66 +
1.67 + /* Command register value calculation. */
1.68 +
1.69 + uint32_t _command_irq();
1.70 +
1.71 + /* Status register value calculation. */
1.72 +
1.73 + uint32_t _status_irq();
1.74 +
1.75 + /* Priority level threshold value calculation. */
1.76 +
1.77 + uint32_t _priority_transfer();
1.78 +
1.79 + /* Position value calculation. */
1.80 +
1.81 + uint32_t _position_bpp();
1.82 +
1.83 /* Panel mode access. */
1.84
1.85 uint32_t _mode();
1.86 @@ -103,6 +129,7 @@
1.87 void disable();
1.88 void disable_quick();
1.89 void enable();
1.90 + bool enabled();
1.91
1.92 /* Peripheral properties. */
1.93
1.94 @@ -117,6 +144,7 @@
1.95
1.96 /* Memory properties. */
1.97
1.98 + l4_size_t get_pixel_size();
1.99 l4_size_t get_line_size();
1.100 l4_size_t get_screen_size();
1.101 l4_size_t get_aligned_size();
1.102 @@ -142,6 +170,14 @@
1.103 void config(struct Jz4740_lcd_descriptor *desc_vaddr,
1.104 struct Jz4740_lcd_descriptor *desc_paddr,
1.105 l4_addr_t fb_paddr);
1.106 +
1.107 + /* Interrupt configuration. */
1.108 +
1.109 + void set_irq(l4_cap_idx_t irq, enum Jz4740_lcd_irq_condition conditions);
1.110 +
1.111 + /* Interrupt handling. */
1.112 +
1.113 + long wait_for_irq();
1.114 };
1.115
1.116 #endif
1.117 @@ -158,9 +194,18 @@
1.118 struct Jz4740_lcd_descriptor *desc_paddr,
1.119 l4_addr_t fb_paddr);
1.120
1.121 +void jz4740_lcd_set_irq(void *lcd, l4_cap_idx_t irq,
1.122 + enum Jz4740_lcd_irq_condition conditions);
1.123 +
1.124 +long jz4740_lcd_wait_for_irq(void *lcd);
1.125 +
1.126 void jz4740_lcd_disable(void *lcd);
1.127 void jz4740_lcd_disable_quick(void *lcd);
1.128 void jz4740_lcd_enable(void *lcd);
1.129 +int jz4740_lcd_enabled(void *lcd);
1.130 +
1.131 +l4_size_t jz4740_lcd_get_descriptors_size(void *lcd);
1.132 +l4_size_t jz4740_lcd_get_screen_size(void *lcd);
1.133
1.134 l4_addr_t jz4740_lcd_get_palette(void *lcd, l4_addr_t base);
1.135 int jz4740_lcd_get_pixel_clock(void *lcd);
2.1 --- a/pkg/devices/lib/lcd/src/jz4740/lcd-jz4740.cc Mon Jun 01 15:43:34 2020 +0200
2.2 +++ b/pkg/devices/lib/lcd/src/jz4740/lcd-jz4740.cc Mon Jun 01 15:47:14 2020 +0200
2.3 @@ -23,19 +23,22 @@
2.4
2.5 #include <l4/devices/hw_mmio_register_block.h>
2.6 #include <l4/sys/cache.h>
2.7 +#include <l4/sys/irq.h>
2.8 #include <l4/sys/types.h>
2.9 +#include <l4/util/util.h>
2.10
2.11 #include "lcd-jz4740.h"
2.12 #include "lcd-jz4740-config.h"
2.13
2.14 #include <stdint.h>
2.15 +#include <stdio.h>
2.16
2.17 enum Regs : unsigned
2.18 {
2.19 Lcd_config = 0x000, // LCD_CFG
2.20 Lcd_vsync = 0x004, // LCD_VSYNC
2.21 Lcd_hsync = 0x008, // LCD_HSYNC
2.22 - Vertical_area = 0x00c, // LCD_VAT
2.23 + Virtual_area = 0x00c, // LCD_VAT
2.24 Display_hlimits = 0x010, // LCD_DAH
2.25 Display_vlimits = 0x014, // LCD_DAV
2.26 Lcd_ps = 0x018, // LCD_PS
2.27 @@ -53,6 +56,14 @@
2.28 Source_address_1 = 0x054, // LCD_SA1
2.29 Frame_id_1 = 0x058, // LCD_FID1
2.30 Command_1 = 0x05c, // LCD_CMD1
2.31 + Rgb_control = 0x090, // LCD_RGBC (JZ4780)
2.32 + Priority_level = 0x2c0, // LCD_PCFG
2.33 +
2.34 + // OSD registers.
2.35 +
2.36 + Osd_config = 0x100, // LCD_OSDC
2.37 + Osd_control = 0x104, // LCD_OSDCTRL
2.38 + Osd_status = 0x108, // LCD_OSDS
2.39 };
2.40
2.41 // Lcd_config descriptions.
2.42 @@ -72,12 +83,12 @@
2.43 Value_second = 0,
2.44 };
2.45
2.46 -// Vertical_area bits.
2.47 +// Virtual area bits.
2.48
2.49 -enum Vertical_area_values : unsigned
2.50 +enum Virtual_area_values : unsigned
2.51 {
2.52 - Vertical_area_horizontal_size = Value_first, // sum of display and blank regions (dot/pixel clock periods)
2.53 - Vertical_area_vertical_size = Value_second, // sum of display and blank regions (line periods)
2.54 + Virtual_area_horizontal_size = Value_first, // sum of display and blank regions (dot/pixel clock periods)
2.55 + Virtual_area_vertical_size = Value_second, // sum of display and blank regions (line periods)
2.56 };
2.57
2.58 // Lcd_control descriptions.
2.59 @@ -169,6 +180,102 @@
2.60 Command_buffer_length_mask = 0x00ffffff,
2.61 };
2.62
2.63 +// Status descriptions.
2.64 +
2.65 +enum Status_bits : unsigned
2.66 +{
2.67 + Status_frame_end_irq = 5,
2.68 + Status_frame_start_irq = 4,
2.69 + Status_disabled = 0,
2.70 +};
2.71 +
2.72 +// OSD configuration bits (JZ4780).
2.73 +
2.74 +enum Osd_config_bits : unsigned
2.75 +{
2.76 + Osd_config_fg1_frame_start_irq_enable = 15,
2.77 + Osd_config_fg1_frame_end_irq_enable = 14,
2.78 + Osd_config_fg0_frame_start_irq_enable = 11,
2.79 + Osd_config_fg0_frame_end_irq_enable = 10,
2.80 + Osd_config_enable = 0,
2.81 +};
2.82 +
2.83 +// RGB control (JZ4780).
2.84 +
2.85 +enum Rgb_control_bits : unsigned
2.86 +{
2.87 + Rgb_data_padded = 15, // RGBDM
2.88 + Rgb_padding_mode = 14, // DMM
2.89 + Rgb_422 = 8, // 422
2.90 + Rgb_format_enable = 7, // RGBFMT
2.91 + Rgb_odd_line = 4, // OddRGB
2.92 + Rgb_even_line = 0, // EvenRGB
2.93 +};
2.94 +
2.95 +enum Rgb_control_values : unsigned
2.96 +{
2.97 + Rgb_padding_end = 0U << Rgb_padding_mode,
2.98 + Rgb_padding_start = 1U << Rgb_padding_mode,
2.99 + Rgb_odd_line_rgb = 0U << Rgb_odd_line,
2.100 + Rgb_odd_line_rbg = 1U << Rgb_odd_line,
2.101 + Rgb_odd_line_grb = 2U << Rgb_odd_line,
2.102 + Rgb_odd_line_gbr = 3U << Rgb_odd_line,
2.103 + Rgb_odd_line_brg = 4U << Rgb_odd_line,
2.104 + Rgb_odd_line_bgr = 5U << Rgb_odd_line,
2.105 + Rgb_even_line_rgb = 0U << Rgb_even_line,
2.106 + Rgb_even_line_rbg = 1U << Rgb_even_line,
2.107 + Rgb_even_line_grb = 2U << Rgb_even_line,
2.108 + Rgb_even_line_gbr = 3U << Rgb_even_line,
2.109 + Rgb_even_line_brg = 4U << Rgb_even_line,
2.110 + Rgb_even_line_bgr = 5U << Rgb_even_line,
2.111 +};
2.112 +
2.113 +// Priority level.
2.114 +
2.115 +enum Priority_level_bits : unsigned
2.116 +{
2.117 + Priority_mode = 31,
2.118 + Priority_highest_burst = 28,
2.119 + Priority_threshold2 = 18,
2.120 + Priority_threshold1 = 9,
2.121 + Priority_threshold0 = 0,
2.122 +};
2.123 +
2.124 +enum Priority_level_values : unsigned
2.125 +{
2.126 + Priority_mode_dynamic = 0U << Priority_mode,
2.127 + Priority_mode_arbiter = 1U << Priority_mode,
2.128 +};
2.129 +
2.130 +enum Priority_burst_values : unsigned
2.131 +{
2.132 + Priority_burst_4 = 0,
2.133 + Priority_burst_8 = 1,
2.134 + Priority_burst_16 = 2,
2.135 + Priority_burst_32 = 3,
2.136 + Priority_burst_64 = 4,
2.137 + Priority_burst_16_cont = 5,
2.138 + Priority_burst_disable = 7,
2.139 +};
2.140 +
2.141 +// Position descriptor member.
2.142 +
2.143 +enum Position_bits : unsigned
2.144 +{
2.145 + Position_bpp = 27,
2.146 + Position_premultiply_lcd = 26,
2.147 + Position_coefficient = 24,
2.148 + Position_y_position = 12,
2.149 + Position_x_position = 0,
2.150 +};
2.151 +
2.152 +enum Position_values : unsigned
2.153 +{
2.154 + Position_bpp_15_16bpp = 4,
2.155 + Position_bpp_18_24bpp = 5,
2.156 + Position_bpp_30bpp = 7,
2.157 +};
2.158 +
2.159
2.160
2.161 // Utility functions.
2.162 @@ -210,6 +317,7 @@
2.163 : _panel(panel)
2.164 {
2.165 _regs = new Hw::Mmio_register_block<32>(addr);
2.166 + //_burst_size = 64; // 64-word burst size (JZ4780)
2.167 _burst_size = 16; // 16-word burst size
2.168
2.169 // add_cid("lcd");
2.170 @@ -227,7 +335,7 @@
2.171 {
2.172 // Set the disable bit for normal shutdown.
2.173
2.174 - _regs[Lcd_control] = _regs[Lcd_control] | (1 << Control_disable);
2.175 + _regs[Lcd_control] = _regs[Lcd_control] | (1U << Control_disable);
2.176 }
2.177
2.178 void
2.179 @@ -235,15 +343,25 @@
2.180 {
2.181 // Clear the enable bit for quick shutdown.
2.182
2.183 - _regs[Lcd_control] = _regs[Lcd_control] & ~(1 << Control_enable);
2.184 + _regs[Lcd_control] = _regs[Lcd_control] & ~(1U << Control_enable);
2.185 }
2.186
2.187 void
2.188 Lcd_jz4740_chip::enable()
2.189 {
2.190 // Clear the disable bit and set the enable bit.
2.191 + // JZ4780: OSD status set.
2.192
2.193 - _regs[Lcd_control] = (_regs[Lcd_control] & ~(1 << Control_disable)) | (1 << Control_enable);
2.194 + _regs[Osd_status] = 0;
2.195 + _regs[Lcd_status] = 0;
2.196 + _regs[Lcd_control] = (_regs[Lcd_control] & ~(1U << Control_disable)) | (1U << Control_enable);
2.197 + printf("LCD control: %x\n", (unsigned int) _regs[Lcd_control]);
2.198 +}
2.199 +
2.200 +bool
2.201 +Lcd_jz4740_chip::enabled()
2.202 +{
2.203 + return !(_regs[Lcd_status] & (1U << Status_disabled));
2.204 }
2.205
2.206 // Calculate and return the pixel clock frequency.
2.207 @@ -346,6 +464,19 @@
2.208
2.209
2.210
2.211 +// Return the pixel memory size in bits.
2.212 +
2.213 +l4_size_t
2.214 +Lcd_jz4740_chip::get_pixel_size()
2.215 +{
2.216 + if (_panel->bpp > 16)
2.217 + return 32;
2.218 + else if (_panel->bpp > 8)
2.219 + return 16;
2.220 + else
2.221 + return _panel->bpp;
2.222 +}
2.223 +
2.224 // Return the line memory size.
2.225
2.226 l4_size_t
2.227 @@ -353,7 +484,7 @@
2.228 {
2.229 // Lines must be aligned to a word boundary.
2.230
2.231 - return align((_panel->width * _panel->bpp) / 8, sizeof(uint32_t));
2.232 + return align((_panel->width * get_pixel_size()) / 8, sizeof(uint32_t));
2.233 }
2.234
2.235 // Return the screen memory size.
2.236 @@ -383,7 +514,7 @@
2.237
2.238 // Get the size of a collection of two-byte entries, one per colour.
2.239
2.240 - return (1 << (_panel->bpp)) * sizeof(uint16_t);
2.241 + return (1U << (_panel->bpp)) * sizeof(uint16_t);
2.242 }
2.243
2.244 // Return the aligned size of the palette for the DMA transfer.
2.245 @@ -438,7 +569,7 @@
2.246 void
2.247 Lcd_jz4740_chip::init_palette(l4_addr_t palette)
2.248 {
2.249 - uint8_t colours = 1 << (_panel->bpp);
2.250 + uint8_t colours = 1U << (_panel->bpp);
2.251 uint16_t *entry = (uint16_t *) palette;
2.252 uint16_t *end = entry + colours;
2.253 uint8_t value = 0;
2.254 @@ -486,13 +617,32 @@
2.255 }
2.256 }
2.257
2.258 +// Return colour depth control value.
2.259 +// JZ4780 position details only.
2.260 +
2.261 +uint32_t
2.262 +Lcd_jz4740_chip::_position_bpp()
2.263 +{
2.264 + uint32_t value;
2.265 +
2.266 + switch (_panel->bpp)
2.267 + {
2.268 + case 15: case 16: value = Position_bpp_15_16bpp; break;
2.269 + case 18: case 24: value = Position_bpp_18_24bpp; break;
2.270 + case 30: value = Position_bpp_30bpp; break;
2.271 + default: value = 0; break;
2.272 + }
2.273 +
2.274 + return value << Position_bpp;
2.275 +}
2.276 +
2.277 // Return a panel-related control value.
2.278
2.279 uint32_t
2.280 Lcd_jz4740_chip::_control_panel()
2.281 {
2.282 if (have_stn_panel())
2.283 - return _control_stn_frc();
2.284 + return _control_stn_frc() << Control_frc_algorithm;
2.285 else
2.286 return 0;
2.287 }
2.288 @@ -526,7 +676,65 @@
2.289 default: length = Burst_length_16; break;
2.290 }
2.291
2.292 - return (length << Control_burst_length) | (1 << Control_out_underrun);
2.293 + return (length << Control_burst_length) | (1U << Control_out_underrun);
2.294 +}
2.295 +
2.296 +// Return an interrupt-related control value.
2.297 +
2.298 +uint32_t
2.299 +Lcd_jz4740_chip::_control_irq()
2.300 +{
2.301 + return ((_irq_conditions & Lcd_irq_frame_start) ? (1U << Control_frame_start_irq_enable) : 0) |
2.302 + ((_irq_conditions & Lcd_irq_frame_end) ? (1U << Control_frame_end_irq_enable) : 0);
2.303 +}
2.304 +
2.305 +// Return an interrupt-related OSD configuration value.
2.306 +
2.307 +uint32_t
2.308 +Lcd_jz4740_chip::_osd_config_irq()
2.309 +{
2.310 + return ((_irq_conditions & Lcd_irq_frame_start) ? (1U << Osd_config_fg0_frame_start_irq_enable) : 0) |
2.311 + ((_irq_conditions & Lcd_irq_frame_end) ? (1U << Osd_config_fg0_frame_end_irq_enable) : 0);
2.312 +}
2.313 +
2.314 +// Return an interrupt-related command value.
2.315 +
2.316 +uint32_t
2.317 +Lcd_jz4740_chip::_command_irq()
2.318 +{
2.319 + return ((_irq_conditions & Lcd_irq_frame_start) ? (1U << Command_frame_start_irq) : 0) |
2.320 + ((_irq_conditions & Lcd_irq_frame_end) ? (1U << Command_frame_end_irq) : 0);
2.321 +}
2.322 +
2.323 +// Return an interrupt-related status value.
2.324 +
2.325 +uint32_t
2.326 +Lcd_jz4740_chip::_status_irq()
2.327 +{
2.328 + return ((_irq_conditions & Lcd_irq_frame_start) ? (1U << Status_frame_start_irq) : 0) |
2.329 + ((_irq_conditions & Lcd_irq_frame_end) ? (1U << Status_frame_end_irq) : 0);
2.330 +}
2.331 +
2.332 +uint32_t
2.333 +Lcd_jz4740_chip::_priority_transfer()
2.334 +{
2.335 + uint32_t length;
2.336 +
2.337 + switch (_burst_size)
2.338 + {
2.339 + case 4: length = Priority_burst_4; break;
2.340 + case 8: length = Priority_burst_8; break;
2.341 + case 32: length = Priority_burst_32; break;
2.342 + case 64: length = Priority_burst_64; break;
2.343 + case 16:
2.344 + default: length = Priority_burst_16; break;
2.345 + }
2.346 +
2.347 + return Priority_mode_arbiter |
2.348 + (length << Priority_highest_burst) |
2.349 + (511U << Priority_threshold2) |
2.350 + (400U << Priority_threshold1) |
2.351 + (256U << Priority_threshold0);
2.352 }
2.353
2.354 // STN panel-specific initialisation.
2.355 @@ -564,8 +772,8 @@
2.356
2.357 // Set the display area and limits.
2.358
2.359 - _regs[Vertical_area] = encode_pair(line_end_pos + hsync + line_end,
2.360 - frame_end_pos + _panel->vsync + _panel->frame_end + _panel->frame_start);
2.361 + _regs[Virtual_area] = encode_pair(line_end_pos + hsync + line_end,
2.362 + frame_end_pos + _panel->vsync + _panel->frame_end + _panel->frame_start);
2.363
2.364 _regs[Display_hlimits] = encode_pair(line_start_pos, line_end_pos);
2.365 _regs[Display_vlimits] = encode_pair(frame_start_pos, frame_end_pos);
2.366 @@ -594,8 +802,8 @@
2.367
2.368 // Set the display area and limits.
2.369
2.370 - _regs[Vertical_area] = encode_pair(line_end_pos + _panel->line_end,
2.371 - frame_end_pos + _panel->frame_end);
2.372 + _regs[Virtual_area] = encode_pair(line_end_pos + _panel->line_end,
2.373 + frame_end_pos + _panel->frame_end);
2.374
2.375 _regs[Display_hlimits] = encode_pair(line_start_pos, line_end_pos);
2.376 _regs[Display_vlimits] = encode_pair(frame_start_pos, frame_end_pos);
2.377 @@ -632,8 +840,24 @@
2.378
2.379 desc.next = next;
2.380 desc.source = source;
2.381 - desc.identifier = 0;
2.382 - desc.command = ((size / sizeof(uint32_t)) & Command_buffer_length_mask) | flags;
2.383 + desc.identifier = source;
2.384 + desc.command = ((size / sizeof(uint32_t)) & Command_buffer_length_mask) |
2.385 + (1U << Command_frame_enable) |
2.386 + flags;
2.387 +
2.388 + printf("next = %08x\n", desc.next);
2.389 + printf("source = %08x\n", desc.source);
2.390 + printf("identifier = %08x\n", desc.identifier);
2.391 + printf("command = %08x\n", desc.command);
2.392 +
2.393 + // Initialise "new" descriptor fields.
2.394 +
2.395 + desc.offset = 0;
2.396 + desc.page_width = 0;
2.397 + desc.command_position = (1UL << Position_premultiply_lcd) |
2.398 + (1UL << Position_coefficient) |
2.399 + _position_bpp();
2.400 + desc.fg_size = 0xff000000 | (1023 << 12) | (1279 << 0); // JZ4780 driver magic
2.401 }
2.402
2.403
2.404 @@ -646,28 +870,33 @@
2.405 struct Jz4740_lcd_descriptor *desc_paddr,
2.406 l4_addr_t fb_paddr)
2.407 {
2.408 + // NOTE: Remarks in the Ingenic Linux 3.0.8 driver suggest that the JZ4775 and
2.409 + // NOTE: JZ4780 do not support palettes.
2.410 +
2.411 int have_palette = (_panel->bpp <= 8);
2.412
2.413 // Provide the first framebuffer descriptor in single and dual modes.
2.414 // Flip back and forth between any palette and the framebuffer.
2.415
2.416 _set_descriptor(desc_vaddr[0], get_framebuffer(0, fb_paddr),
2.417 - get_screen_size(),
2.418 - have_palette ? desc_paddr + 2 : desc_paddr);
2.419 + get_aligned_size(),
2.420 + have_palette ? desc_paddr + 2 : desc_paddr,
2.421 + _command_irq());
2.422
2.423 // Provide the second framebuffer descriptor only in dual-panel mode.
2.424 // Only employ this descriptor in the second DMA channel.
2.425
2.426 if (get_panels() == 2)
2.427 _set_descriptor(desc_vaddr[1], get_framebuffer(1, fb_paddr),
2.428 - get_screen_size(),
2.429 - desc_paddr + 1);
2.430 + get_aligned_size(),
2.431 + desc_paddr + 1,
2.432 + _command_irq());
2.433
2.434 // Initialise palette descriptor details for lower colour depths.
2.435
2.436 if (have_palette)
2.437 _set_descriptor(desc_vaddr[2], get_palette(fb_paddr),
2.438 - get_palette_size(),
2.439 + get_aligned_palette_size(),
2.440 desc_paddr,
2.441 Command_palette_buffer);
2.442
2.443 @@ -681,6 +910,7 @@
2.444 // Provide the palette descriptor address first, if employed.
2.445
2.446 _regs[Desc_address_0] = (uint32_t) (have_palette ? desc_paddr + 2 : desc_paddr);
2.447 + printf("descriptor = %08x\n", (uint32_t) _regs[Desc_address_0]);
2.448
2.449 // Provide a descriptor for the second DMA channel in dual-panel mode.
2.450
2.451 @@ -692,9 +922,66 @@
2.452 _init_panel();
2.453
2.454 // Initialise the control and configuration registers.
2.455 + // NOTE: JZ4780 does not support bpp setting here.
2.456
2.457 - _regs[Lcd_control] = _control_panel() | _control_bpp() | _control_transfer();
2.458 + _regs[Lcd_control] = _control_panel() | _control_bpp() | _control_transfer() | _control_irq();
2.459 _regs[Lcd_config] = _panel->config;
2.460 +
2.461 + // NOTE: JZ4780 only.
2.462 +
2.463 + _regs[Rgb_control] = (1U << Rgb_format_enable) | Rgb_odd_line_rgb | Rgb_even_line_rgb;
2.464 + _regs[Priority_level] = _priority_transfer();
2.465 + _regs[Osd_config] = 0; // (1U << Osd_config_enable) | _osd_config_irq();
2.466 +
2.467 + printf("LCD control: %08x\n", (unsigned int) _regs[Lcd_control]);
2.468 + printf("LCD status: %08x\n", (unsigned int) _regs[Lcd_status]);
2.469 + printf("OSD config: %08x\n", (unsigned int) _regs[Osd_config]);
2.470 + printf("OSD status: %08x\n", (unsigned int) _regs[Osd_status]);
2.471 +}
2.472 +
2.473 +// Set the interrupt for controller-related events.
2.474 +
2.475 +void
2.476 +Lcd_jz4740_chip::set_irq(l4_cap_idx_t irq, enum Jz4740_lcd_irq_condition conditions)
2.477 +{
2.478 + _irq = irq;
2.479 + _irq_conditions = conditions;
2.480 +}
2.481 +
2.482 +// Wait for an interrupt condition.
2.483 +
2.484 +long
2.485 +Lcd_jz4740_chip::wait_for_irq()
2.486 +{
2.487 + long err;
2.488 + l4_msgtag_t tag;
2.489 +
2.490 + _regs[Lcd_status] = _regs[Lcd_status] & ~(_status_irq());
2.491 +
2.492 + // Wait for a condition.
2.493 +
2.494 + printf("Waiting for IRQ...\n");
2.495 + tag = l4_irq_receive(_irq, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4util_micros2l4to(1000000)));
2.496 + printf("LCD status: %08x\n", (unsigned int) _regs[Lcd_status]);
2.497 + printf("OSD status: %08x\n", (unsigned int) _regs[Osd_status]);
2.498 + printf("LCD control: %08x\n", (unsigned int) _regs[Lcd_control]);
2.499 + printf("LCD command: %08x\n", (unsigned int) _regs[Command_0]);
2.500 + printf("LCD IRQ id: %08x\n", (unsigned int) _regs[Lcd_irq_id]);
2.501 + printf("LCD descriptor: %08x\n", (unsigned int) _regs[Desc_address_0]);
2.502 + printf("LCD source: %08x\n", (unsigned int) _regs[Source_address_0]);
2.503 + printf("LCD frame id: %08x\n", (unsigned int) _regs[Frame_id_0]);
2.504 +
2.505 + // Return errors immediately.
2.506 +
2.507 + err = l4_ipc_error(tag, l4_utcb());
2.508 + if (err)
2.509 + return err;
2.510 +
2.511 + // Acknowledge interrupts.
2.512 +
2.513 + _regs[Lcd_status] = _regs[Lcd_status] & ~(_status_irq());
2.514 +
2.515 + return L4_EOK;
2.516 }
2.517
2.518
2.519 @@ -716,6 +1003,18 @@
2.520 }
2.521
2.522 void
2.523 +jz4740_lcd_set_irq(void *lcd, l4_cap_idx_t irq, enum Jz4740_lcd_irq_condition conditions)
2.524 +{
2.525 + static_cast<Lcd_jz4740_chip *>(lcd)->set_irq(irq, conditions);
2.526 +}
2.527 +
2.528 +long
2.529 +jz4740_lcd_wait_for_irq(void *lcd)
2.530 +{
2.531 + return static_cast<Lcd_jz4740_chip *>(lcd)->wait_for_irq();
2.532 +}
2.533 +
2.534 +void
2.535 jz4740_lcd_disable(void *lcd)
2.536 {
2.537 static_cast<Lcd_jz4740_chip *>(lcd)->disable();
2.538 @@ -734,11 +1033,29 @@
2.539 }
2.540
2.541 int
2.542 +jz4740_lcd_enabled(void *lcd)
2.543 +{
2.544 + return (int) static_cast<Lcd_jz4740_chip *>(lcd)->enabled();
2.545 +}
2.546 +
2.547 +int
2.548 jz4740_lcd_get_pixel_clock(void *lcd)
2.549 {
2.550 return static_cast<Lcd_jz4740_chip *>(lcd)->get_pixel_clock();
2.551 }
2.552
2.553 +l4_size_t
2.554 +jz4740_lcd_get_descriptors_size(void *lcd)
2.555 +{
2.556 + return static_cast<Lcd_jz4740_chip *>(lcd)->get_descriptors_size();
2.557 +}
2.558 +
2.559 +l4_size_t
2.560 +jz4740_lcd_get_screen_size(void *lcd)
2.561 +{
2.562 + return static_cast<Lcd_jz4740_chip *>(lcd)->get_screen_size();
2.563 +}
2.564 +
2.565 l4_addr_t
2.566 jz4740_lcd_get_palette(void *lcd, l4_addr_t base)
2.567 {