1.1 --- a/pkg/landfall-examples/ci20_hdmi_i2c/ci20_hdmi_i2c.c Fri May 22 00:25:28 2020 +0200
1.2 +++ b/pkg/landfall-examples/ci20_hdmi_i2c/ci20_hdmi_i2c.c Sat May 23 16:05:22 2020 +0200
1.3 @@ -14,6 +14,11 @@
1.4 #include <l4/devices/cpm-jz4780.h>
1.5 #include <l4/devices/gpio-jz4780.h>
1.6 #include <l4/devices/hdmi-jz4780.h>
1.7 +
1.8 +#include <l4/devices/lcd-jz4740.h>
1.9 +#include <l4/devices/lcd-jz4740-config.h>
1.10 +#include <l4/devices/lcd-jz4740-panel.h>
1.11 +
1.12 #include <l4/devices/memory.h>
1.13 #include <l4/io/io.h>
1.14 #include <l4/libedid/edid.h>
1.15 @@ -39,6 +44,30 @@
1.16
1.17
1.18
1.19 +/* Test panel. */
1.20 +
1.21 +static struct Jz4740_lcd_panel panel = {
1.22 + .config = (
1.23 + Jz4740_lcd_mode_tft_generic
1.24 + | Jz4740_lcd_pclock_negative
1.25 + | Jz4740_lcd_hsync_positive
1.26 + | Jz4740_lcd_vsync_positive
1.27 + | Jz4740_lcd_de_positive),
1.28 +
1.29 + .width = 1280,
1.30 + .height = 1024,
1.31 + .bpp = 32,
1.32 + .frame_rate = 60,
1.33 + .hsync = 112,
1.34 + .vsync = 3,
1.35 + .line_start = 248, // back porch (blanking - vsyn - offset)
1.36 + .line_end = 48, // front porch (sync offset)
1.37 + .frame_start = 36, // back porch (blanking - vsyn - offset)
1.38 + .frame_end = 3, // front porch (sync offset)
1.39 +};
1.40 +
1.41 +
1.42 +
1.43 /* Device and resource discovery. */
1.44
1.45 static long item_in_range(long start, long end, long index)
1.46 @@ -80,6 +109,7 @@
1.47 l4_addr_t cpm_base = 0, cpm_base_end = 0;
1.48 l4_addr_t gpio_base = 0, gpio_base_end = 0;
1.49 l4_addr_t hdmi_base = 0, hdmi_base_end = 0;
1.50 + l4_addr_t lcd_base = 0, lcd_base_end = 0;
1.51 l4_addr_t port_f, port_f_end;
1.52
1.53 /* Peripheral abstractions. */
1.54 @@ -87,13 +117,16 @@
1.55 void *cpm;
1.56 void *gpio_port_f;
1.57 void *hdmi;
1.58 + void *lcd;
1.59
1.60 /* Access to IRQs. */
1.61
1.62 l4_uint32_t hdmi_irq_start = 0, hdmi_irq_end = 0;
1.63 - l4_cap_idx_t icucap, irqcap;
1.64 + l4_uint32_t lcd_irq_start = 0, lcd_irq_end = 0;
1.65 + l4_cap_idx_t icucap, hdmi_irq, lcd_irq;
1.66
1.67 - irqcap = l4re_util_cap_alloc();
1.68 + hdmi_irq = l4re_util_cap_alloc();
1.69 + lcd_irq = l4re_util_cap_alloc();
1.70 icucap = l4re_env_get_cap("icu");
1.71
1.72 if (l4_is_invalid_cap(icucap))
1.73 @@ -102,7 +135,7 @@
1.74 return 1;
1.75 }
1.76
1.77 - if (l4_is_invalid_cap(irqcap))
1.78 + if (l4_is_invalid_cap(hdmi_irq) || l4_is_invalid_cap(lcd_irq))
1.79 {
1.80 printf("Capabilities not available for interrupts.\n");
1.81 return 1;
1.82 @@ -115,11 +148,17 @@
1.83 if (get_irq("jz4780-hdmi", &hdmi_irq_start, &hdmi_irq_end) < 0)
1.84 return 1;
1.85
1.86 - printf("IRQ range at %d...%d.\n", hdmi_irq_start, hdmi_irq_end);
1.87 + printf("HDMI IRQ range at %d...%d.\n", hdmi_irq_start, hdmi_irq_end);
1.88 +
1.89 + if (get_irq("jz4780-lcd", &lcd_irq_start, &lcd_irq_end) < 0)
1.90 + return 1;
1.91 +
1.92 + printf("LCD IRQ range at %d...%d.\n", lcd_irq_start, lcd_irq_end);
1.93
1.94 /* Create interrupt objects. */
1.95
1.96 - err = l4_error(l4_factory_create_irq(l4re_global_env->factory, irqcap));
1.97 + err = l4_error(l4_factory_create_irq(l4re_global_env->factory, hdmi_irq)) ||
1.98 + l4_error(l4_factory_create_irq(l4re_global_env->factory, lcd_irq));
1.99
1.100 if (err)
1.101 {
1.102 @@ -132,7 +171,10 @@
1.103
1.104 err = l4_error(l4_icu_bind(icucap,
1.105 item_in_range(hdmi_irq_start, hdmi_irq_end, 0),
1.106 - irqcap));
1.107 + hdmi_irq)) ||
1.108 + l4_error(l4_icu_bind(icucap,
1.109 + item_in_range(lcd_irq_start, lcd_irq_end, 0),
1.110 + lcd_irq));
1.111
1.112 if (err)
1.113 {
1.114 @@ -142,7 +184,8 @@
1.115
1.116 /* Attach ourselves to the interrupt handler. */
1.117
1.118 - err = l4_error(l4_rcv_ep_bind_thread(irqcap, l4re_env()->main_thread, 0));
1.119 + err = l4_error(l4_rcv_ep_bind_thread(hdmi_irq, l4re_env()->main_thread, 0)) ||
1.120 + l4_error(l4_rcv_ep_bind_thread(lcd_irq, l4re_env()->main_thread, 0));
1.121
1.122 if (err)
1.123 {
1.124 @@ -173,6 +216,13 @@
1.125
1.126 printf("HDMI at 0x%lx...0x%lx.\n", hdmi_base, hdmi_base_end);
1.127
1.128 + printf("Access LCD...\n");
1.129 +
1.130 + if (get_memory("jz4780-lcd", &lcd_base, &lcd_base_end) < 0)
1.131 + return 1;
1.132 +
1.133 + printf("LCD at 0x%lx...0x%lx.\n", lcd_base, lcd_base_end);
1.134 +
1.135 /* Obtain CPM object. */
1.136
1.137 cpm = jz4780_cpm_init(cpm_base);
1.138 @@ -207,7 +257,7 @@
1.139
1.140 printf("Set up HDMI...\n");
1.141
1.142 - hdmi = jz4780_hdmi_init(hdmi_base, hdmi_base_end, irqcap);
1.143 + hdmi = jz4780_hdmi_init(hdmi_base, hdmi_base_end, hdmi_irq);
1.144
1.145 printf("Read version...\n");
1.146
1.147 @@ -228,9 +278,31 @@
1.148
1.149 show_timings(edid);
1.150
1.151 - /* Detach from the interrupt. */
1.152 + /* Obtain LCD reference. */
1.153 +
1.154 + printf("Set up LCD...\n");
1.155 +
1.156 + lcd = jz4740_lcd_init(lcd_base, &panel);
1.157 +
1.158 + /* Test initialisation with a frequency appropriate for the test panel. */
1.159 +
1.160 + printf("LCD divider: %d\n", jz4780_cpm_get_lcd_pixel_divider(cpm));
1.161 + printf("LCD frequency: %d\n", jz4780_cpm_get_lcd_pixel_frequency(cpm));
1.162 + printf("Desired frequency: %d\n", jz4740_lcd_get_pixel_clock(lcd));
1.163
1.164 - err = l4_error(l4_irq_detach(irqcap));
1.165 + jz4780_cpm_stop_lcd(cpm);
1.166 +
1.167 + jz4780_cpm_set_lcd_frequencies(cpm, jz4740_lcd_get_pixel_clock(lcd), 3);
1.168 +
1.169 + printf("LCD divider: %d\n", jz4780_cpm_get_lcd_pixel_divider(cpm));
1.170 + printf("LCD frequency: %d\n", jz4780_cpm_get_lcd_pixel_frequency(cpm));
1.171 +
1.172 + jz4780_cpm_start_lcd(cpm);
1.173 +
1.174 + /* Detach from the interrupts. */
1.175 +
1.176 + err = l4_error(l4_irq_detach(hdmi_irq)) ||
1.177 + l4_error(l4_irq_detach(lcd_irq));
1.178
1.179 if (err)
1.180 printf("Error detaching from IRQ: %ld\n", err);