1.1 --- a/pkg/landfall-examples/ci20_hdmi_i2c/ci20_hdmi_i2c.c Sat Jun 06 00:02:05 2020 +0200
1.2 +++ b/pkg/landfall-examples/ci20_hdmi_i2c/ci20_hdmi_i2c.c Sat Jun 06 00:04:50 2020 +0200
1.3 @@ -28,20 +28,29 @@
1.4 #include <l4/devices/lcd-jz4740-panel.h>
1.5
1.6 #include <l4/devices/memory.h>
1.7 -#include <l4/io/io.h>
1.8 -#include <l4/libedid/edid.h>
1.9 +
1.10 +#include <l4/re/c/dataspace.h>
1.11 +#include <l4/re/c/mem_alloc.h>
1.12 +#include <l4/re/c/rm.h>
1.13 +#include <l4/re/c/util/cap_alloc.h>
1.14 #include <l4/re/env.h>
1.15 -#include <l4/re/c/util/cap_alloc.h>
1.16 +
1.17 +#include <l4/sys/cache.h>
1.18 #include <l4/sys/factory.h>
1.19 #include <l4/sys/icu.h>
1.20 #include <l4/sys/ipc.h>
1.21 #include <l4/sys/irq.h>
1.22 #include <l4/sys/rcv_endpoint.h>
1.23 +
1.24 +#include <l4/io/io.h>
1.25 +#include <l4/libedid/edid.h>
1.26 #include <l4/vbus/vbus.h>
1.27 +
1.28 #include <stdio.h>
1.29 #include <unistd.h>
1.30 #include <stdint.h>
1.31 #include <string.h>
1.32 +#include <stdlib.h>
1.33
1.34
1.35
1.36 @@ -57,6 +66,13 @@
1.37 static struct Jz4740_lcd_panel panel = {
1.38 .config = (
1.39 Jz4740_lcd_mode_tft_generic
1.40 + | Jz4740_lcd_bpp_24
1.41 + | Jz4740_lcd_desc_8_word
1.42 + | Jz4740_lcd_underrun_recover
1.43 + | Jz4740_lcd_ps_disabled
1.44 + | Jz4740_lcd_cls_disabled
1.45 + | Jz4740_lcd_spl_disabled
1.46 + | Jz4740_lcd_rev_disabled
1.47 | Jz4740_lcd_pclock_negative
1.48 | Jz4740_lcd_hsync_positive
1.49 | Jz4740_lcd_vsync_positive
1.50 @@ -64,13 +80,13 @@
1.51
1.52 .width = 1280,
1.53 .height = 1024,
1.54 - .bpp = 32,
1.55 + .bpp = 24,
1.56 .frame_rate = 60,
1.57 .hsync = 112,
1.58 .vsync = 3,
1.59 - .line_start = 248, // back porch (blanking - vsyn - offset)
1.60 + .line_start = 248, // back porch (blanking - hsync - offset)
1.61 .line_end = 48, // front porch (sync offset)
1.62 - .frame_start = 36, // back porch (blanking - vsyn - offset)
1.63 + .frame_start = 36, // back porch (blanking - vsync - offset)
1.64 .frame_end = 3, // front porch (sync offset)
1.65 };
1.66
1.67 @@ -111,6 +127,7 @@
1.68
1.69 uint8_t hdmi_major;
1.70 uint16_t hdmi_minor;
1.71 + const struct Phy_capabilities *phy_def;
1.72
1.73 /* Peripheral memory. */
1.74
1.75 @@ -127,12 +144,25 @@
1.76 void *hdmi;
1.77 void *lcd;
1.78
1.79 + /* Allocated memory. */
1.80 +
1.81 + l4_cap_idx_t desc_mem, fb_mem;
1.82 + l4_size_t desc_size, desc_psize, fb_size, fb_psize;
1.83 + l4_addr_t desc_addr, desc_paddr, fb_addr, fb_paddr;
1.84 + unsigned char *picture;
1.85 + unsigned char *fb_picture, *fb_picture_row;
1.86 + unsigned int x, y;
1.87 +
1.88 /* Access to IRQs. */
1.89
1.90 l4_uint32_t hdmi_irq_start = 0, hdmi_irq_end = 0;
1.91 l4_uint32_t lcd_irq_start = 0, lcd_irq_end = 0;
1.92 l4_cap_idx_t icucap, hdmi_irq, lcd_irq;
1.93
1.94 + /* Capability allocation. */
1.95 +
1.96 + desc_mem = l4re_util_cap_alloc();
1.97 + fb_mem = l4re_util_cap_alloc();
1.98 hdmi_irq = l4re_util_cap_alloc();
1.99 lcd_irq = l4re_util_cap_alloc();
1.100 icucap = l4re_env_get_cap("icu");
1.101 @@ -143,9 +173,10 @@
1.102 return 1;
1.103 }
1.104
1.105 - if (l4_is_invalid_cap(hdmi_irq) || l4_is_invalid_cap(lcd_irq))
1.106 + if (l4_is_invalid_cap(desc_mem) || l4_is_invalid_cap(fb_mem) ||
1.107 + l4_is_invalid_cap(hdmi_irq) || l4_is_invalid_cap(lcd_irq))
1.108 {
1.109 - printf("Capabilities not available for interrupts.\n");
1.110 + printf("Capabilities could not be reserved.\n");
1.111 return 1;
1.112 }
1.113
1.114 @@ -190,10 +221,10 @@
1.115 return 1;
1.116 }
1.117
1.118 - /* Attach ourselves to the interrupt handler. */
1.119 + /* Attach ourselves to the interrupt handler with some arbitrary labels. */
1.120
1.121 - err = l4_error(l4_rcv_ep_bind_thread(hdmi_irq, l4re_env()->main_thread, 0)) ||
1.122 - l4_error(l4_rcv_ep_bind_thread(lcd_irq, l4re_env()->main_thread, 0));
1.123 + err = l4_error(l4_rcv_ep_bind_thread(hdmi_irq, l4re_env()->main_thread, 0x00)) ||
1.124 + l4_error(l4_rcv_ep_bind_thread(lcd_irq, l4re_env()->main_thread, 0x10));
1.125
1.126 if (err)
1.127 {
1.128 @@ -265,7 +296,7 @@
1.129
1.130 printf("Set up HDMI...\n");
1.131
1.132 - hdmi = jz4780_hdmi_init(hdmi_base, hdmi_base_end, hdmi_irq);
1.133 + hdmi = jz4780_hdmi_init(hdmi_base, hdmi_base_end, hdmi_irq, &panel);
1.134
1.135 printf("Read version...\n");
1.136
1.137 @@ -273,6 +304,10 @@
1.138
1.139 printf("HDMI version is %x.%03x\n", hdmi_major, hdmi_minor);
1.140
1.141 + jz4780_hdmi_get_phy_capabilities(hdmi, &phy_def);
1.142 +
1.143 + printf("PHY type: %s\n", phy_def->name);
1.144 +
1.145 printf("Connected: %s\n", jz4780_hdmi_connected(hdmi) ? "yes" : "no");
1.146
1.147 while (!jz4780_hdmi_connected(hdmi))
1.148 @@ -299,18 +334,114 @@
1.149
1.150 /* Test initialisation with a frequency appropriate for the test panel. */
1.151
1.152 + printf("LCD source: %d\n", jz4780_cpm_get_lcd_source(cpm));
1.153 printf("LCD divider: %d\n", jz4780_cpm_get_lcd_pixel_divider(cpm));
1.154 printf("LCD frequency: %d\n", jz4780_cpm_get_lcd_pixel_frequency(cpm));
1.155 printf("Desired frequency: %d\n", jz4740_lcd_get_pixel_clock(lcd));
1.156
1.157 jz4780_cpm_stop_lcd(cpm);
1.158 -
1.159 jz4780_cpm_set_lcd_frequencies(cpm, jz4740_lcd_get_pixel_clock(lcd), 3);
1.160
1.161 + printf("LCD source: %d\n", jz4780_cpm_get_lcd_source(cpm));
1.162 printf("LCD divider: %d\n", jz4780_cpm_get_lcd_pixel_divider(cpm));
1.163 printf("LCD frequency: %d\n", jz4780_cpm_get_lcd_pixel_frequency(cpm));
1.164 + printf("AHB0 frequency: %d\n", jz4780_cpm_get_hclock0_frequency(cpm));
1.165 +
1.166 + /* With the LCD pixel clock set up, bring up the HDMI. */
1.167 +
1.168 + printf("Enable HDMI output...\n");
1.169 +
1.170 + jz4780_hdmi_enable(hdmi, jz4780_cpm_get_lcd_pixel_frequency(cpm));
1.171 +
1.172 + /* Allocate descriptors and framebuffer at 2**8 == 256 byte == 64 word alignment. */
1.173 +
1.174 + desc_size = jz4740_lcd_get_descriptors_size(lcd);
1.175 + fb_size = jz4740_lcd_get_screen_size(lcd);
1.176 +
1.177 + if (l4re_ma_alloc_align(desc_size, desc_mem, L4RE_MA_CONTINUOUS | L4RE_MA_PINNED, 8) ||
1.178 + l4re_ma_alloc_align(fb_size, fb_mem, L4RE_MA_CONTINUOUS | L4RE_MA_PINNED, 8))
1.179 + {
1.180 + printf("Could not allocate memory.\n");
1.181 + return 1;
1.182 + }
1.183 +
1.184 + if (l4re_rm_attach((void **) &desc_addr, desc_size,
1.185 + L4RE_RM_SEARCH_ADDR | L4RE_RM_EAGER_MAP,
1.186 + desc_mem, 0, L4_PAGESHIFT) ||
1.187 + l4re_rm_attach((void **) &fb_addr, fb_size,
1.188 + L4RE_RM_SEARCH_ADDR | L4RE_RM_EAGER_MAP,
1.189 + fb_mem, 0, L4_PAGESHIFT))
1.190 + {
1.191 + printf("Could not map memory.\n");
1.192 + return 1;
1.193 + }
1.194 +
1.195 + if (l4re_ds_phys(desc_mem, 0, &desc_paddr, &desc_psize) ||
1.196 + l4re_ds_phys(fb_mem, 0, &fb_paddr, &fb_psize))
1.197 + {
1.198 + printf("Could not get physical addresses for memory.\n");
1.199 + return 1;
1.200 + }
1.201 +
1.202 + printf("Descriptors at %lx/%lx, size %d/%d.\n", desc_addr, desc_paddr, desc_size, desc_psize);
1.203 + printf("Framebuffer at %lx/%lx, size %d/%d.\n", fb_addr, fb_paddr, fb_size, fb_psize);
1.204 +
1.205 + //memset((void *) fb_addr, 0x7f, fb_size);
1.206 +
1.207 + picture = (unsigned char *) malloc(gimp_image.width * gimp_image.height * gimp_image.bytes_per_pixel);
1.208 +
1.209 + GIMP_IMAGE_RUN_LENGTH_DECODE(picture,
1.210 + gimp_image.rle_pixel_data,
1.211 + gimp_image.width * gimp_image.height,
1.212 + gimp_image.bytes_per_pixel);
1.213 +
1.214 + fb_picture_row = (unsigned char *) fb_addr;
1.215 +
1.216 + for (y = 0; y < gimp_image.height; y++)
1.217 + {
1.218 + fb_picture = fb_picture_row;
1.219 +
1.220 + for (x = 0; x < gimp_image.width; x++)
1.221 + {
1.222 + *(fb_picture + 2) = *picture++;
1.223 + *(fb_picture + 1) = *picture++;
1.224 + *fb_picture = *picture++;
1.225 + *(fb_picture + 3) = 0;
1.226 + fb_picture += 4;
1.227 + }
1.228 +
1.229 + fb_picture_row += jz4740_lcd_get_line_size(lcd);
1.230 + }
1.231 +
1.232 + l4_cache_clean_data((unsigned long) fb_addr, (unsigned long) fb_addr + fb_size);
1.233 +
1.234 + printf("Start LCD clock and initialise LCD...\n");
1.235
1.236 jz4780_cpm_start_lcd(cpm);
1.237 + l4_sleep(1); // 1ms == 1000us
1.238 +
1.239 + jz4740_lcd_disable(lcd);
1.240 +
1.241 + jz4740_lcd_set_irq(lcd, lcd_irq, Lcd_irq_frame_end);
1.242 +
1.243 + jz4740_lcd_config(lcd, (struct Jz4740_lcd_descriptor *) desc_addr,
1.244 + (struct Jz4740_lcd_descriptor *) desc_paddr,
1.245 + fb_paddr);
1.246 +
1.247 + jz4740_lcd_enable(lcd);
1.248 +
1.249 + printf("LCD enabled: %s\n", jz4740_lcd_enabled(lcd) ? "yes" : "no");
1.250 +
1.251 + printf("Wait for interrupt conditions...\n");
1.252 +
1.253 + for (i = 0; i < 30000; i++)
1.254 + {
1.255 + if (jz4740_lcd_wait_for_irq(lcd))
1.256 + continue;
1.257 +
1.258 + if (!(i % 60))
1.259 + printf("IRQ #%d\n", i);
1.260 + }
1.261
1.262 /* Detach from the interrupts. */
1.263