1.1 --- a/pkg/devices/lib/cpm/include/cpm-jz4780.h Fri May 22 00:25:28 2020 +0200
1.2 +++ b/pkg/devices/lib/cpm/include/cpm-jz4780.h Sat May 23 16:05:22 2020 +0200
1.3 @@ -215,6 +215,7 @@
1.4
1.5 void jz4780_cpm_set_hdmi_frequency(void *cpm, uint32_t pclk);
1.6 void jz4780_cpm_set_lcd_pixel_frequency(void *cpm, uint32_t pclk);
1.7 +void jz4780_cpm_set_lcd_frequencies(void *cpm, uint32_t pclk, uint8_t ratio);
1.8 void jz4780_cpm_set_mpll_parameters(void *cpm, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider);
1.9
1.10 EXTERN_C_END
2.1 --- a/pkg/devices/lib/cpm/src/jz4780.cc Fri May 22 00:25:28 2020 +0200
2.2 +++ b/pkg/devices/lib/cpm/src/jz4780.cc Sat May 23 16:05:22 2020 +0200
2.3 @@ -796,6 +796,7 @@
2.4 }
2.5
2.6 // NOTE: Compatibility method. Probably needs reviewing.
2.7 +// NOTE: HCLK/AHB0 must be 1.5 (for TFT) or 3 (for STN) times the pixel clock.
2.8
2.9 void
2.10 Cpm_jz4780_chip::set_lcd_frequencies(uint32_t pclk, uint8_t ratio)
2.11 @@ -805,6 +806,7 @@
2.12 }
2.13
2.14 // NOTE: Empty method for compatibility.
2.15 +// NOTE: It could potentially be combined with start_lcd.
2.16
2.17 void
2.18 Cpm_jz4780_chip::update_output_frequency()
2.19 @@ -1083,6 +1085,12 @@
2.20 }
2.21
2.22 void
2.23 +jz4780_cpm_set_lcd_frequencies(void *cpm, uint32_t pclk, uint8_t ratio)
2.24 +{
2.25 + static_cast<Cpm_jz4780_chip *>(cpm)->set_lcd_frequencies(pclk, ratio);
2.26 +}
2.27 +
2.28 +void
2.29 jz4780_cpm_set_mpll_parameters(void *cpm, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider)
2.30 {
2.31 static_cast<Cpm_jz4780_chip *>(cpm)->set_pll_parameters(Pll_control_M, multiplier, in_divider, out_divider);
3.1 --- a/pkg/devices/lib/lcd/src/jz4740/lcd-jz4740.cc Fri May 22 00:25:28 2020 +0200
3.2 +++ b/pkg/devices/lib/lcd/src/jz4740/lcd-jz4740.cc Sat May 23 16:05:22 2020 +0200
3.3 @@ -2,7 +2,8 @@
3.4 * LCD peripheral support for the JZ4740 and related SoCs.
3.5 *
3.6 * Copyright (C) Xiangfu Liu <xiangfu@sharism.cc>
3.7 - * Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
3.8 + * Copyright (C) 2015, 2016, 2017, 2018,
3.9 + * 2020 Paul Boddie <paul@boddie.org.uk>
3.10 *
3.11 * This program is free software; you can redistribute it and/or
3.12 * modify it under the terms of the GNU General Public License as
3.13 @@ -83,23 +84,25 @@
3.14
3.15 enum Control_bits : unsigned
3.16 {
3.17 - Control_burst_length = 28, // BST (burst length selection)
3.18 - Control_rgb_mode = 27, // RGB (RGB mode)
3.19 - Control_out_underrun = 26, // OFUP (output FIFO underrun protection)
3.20 - Control_frc_algorithm = 24, // FRC (STN FRC algorithm selection)
3.21 - Control_palette_delay = 16, // PDD (load palette delay counter)
3.22 - Control_frame_end_irq_mask = 13, // EOFM (end of frame interrupt mask)
3.23 - Control_frame_start_irq_mask = 12, // SOFM (start of frame interrupt mask)
3.24 - Control_out_underrun_irq_mask = 11, // OFUM (output FIFO underrun interrupt mask)
3.25 - Control_in0_underrun_irq_mask = 10, // IFUM0 (input FIFO 0 underrun interrupt mask)
3.26 - Control_in1_underrun_irq_mask = 9, // IFUM1 (input FIFO 1 underrun interrupt mask)
3.27 - Control_disabled_irq_mask = 8, // LDDM (LCD disable done interrupt mask)
3.28 - Control_quick_disabled_irq_mask = 7, // QDM (LCD quick disable done interrupt mask)
3.29 - Control_endian_select = 6, // BEDN (endian selection)
3.30 - Control_bit_order = 5, // PEDN (bit order in bytes)
3.31 - Control_disable = 4, // DIS (disable controller)
3.32 - Control_enable = 3, // ENA (enable controller)
3.33 - Control_bpp = 0, // BPP (bits per pixel)
3.34 + Control_pin_modify = 31, // PINMD (change pin usage from 15..0 to 17..10, 8..1)
3.35 + Control_burst_length = 28, // BST (burst length selection)
3.36 + Control_rgb_mode = 27, // RGB (RGB mode)
3.37 + Control_out_underrun = 26, // OFUP (output FIFO underrun protection)
3.38 + Control_frc_algorithm = 24, // FRC (STN FRC algorithm selection)
3.39 + Control_palette_delay = 16, // PDD (load palette delay counter)
3.40 + Control_dac_loopback_test = 14, // DACTE (DAC loopback test)
3.41 + Control_frame_end_irq_enable = 13, // EOFM (end of frame interrupt enable)
3.42 + Control_frame_start_irq_enable = 12, // SOFM (start of frame interrupt enable)
3.43 + Control_out_underrun_irq_enable = 11, // OFUM (output FIFO underrun interrupt enable)
3.44 + Control_in0_underrun_irq_enable = 10, // IFUM0 (input FIFO 0 underrun interrupt enable)
3.45 + Control_in1_underrun_irq_enable = 9, // IFUM1 (input FIFO 1 underrun interrupt enable)
3.46 + Control_disabled_irq_enable = 8, // LDDM (LCD disable done interrupt enable)
3.47 + Control_quick_disabled_irq_enable = 7, // QDM (LCD quick disable done interrupt enable)
3.48 + Control_endian_select = 6, // BEDN (endian selection)
3.49 + Control_bit_order = 5, // PEDN (bit order in bytes)
3.50 + Control_disable = 4, // DIS (disable controller)
3.51 + Control_enable = 3, // ENA (enable controller)
3.52 + Control_bpp = 0, // BPP (bits per pixel)
3.53 };
3.54
3.55 enum Burst_length_values : unsigned
4.1 --- a/pkg/landfall-examples/ci20_hdmi_i2c/Makefile Fri May 22 00:25:28 2020 +0200
4.2 +++ b/pkg/landfall-examples/ci20_hdmi_i2c/Makefile Sat May 23 16:05:22 2020 +0200
4.3 @@ -3,6 +3,6 @@
4.4
4.5 TARGET = ex_ci20_hdmi_i2c
4.6 SRC_C = ci20_hdmi_i2c.c
4.7 -REQUIRES_LIBS = libio l4re_c-util libdevice-util libdrivers-cpm libdrivers-hdmi libdrivers-gpio libedid
4.8 +REQUIRES_LIBS = libio l4re_c-util libdevice-util libdrivers-cpm libdrivers-hdmi libdrivers-lcd-jz4740 libdrivers-gpio libedid
4.9
4.10 include $(L4DIR)/mk/prog.mk
5.1 --- a/pkg/landfall-examples/ci20_hdmi_i2c/ci20_hdmi_i2c.c Fri May 22 00:25:28 2020 +0200
5.2 +++ b/pkg/landfall-examples/ci20_hdmi_i2c/ci20_hdmi_i2c.c Sat May 23 16:05:22 2020 +0200
5.3 @@ -14,6 +14,11 @@
5.4 #include <l4/devices/cpm-jz4780.h>
5.5 #include <l4/devices/gpio-jz4780.h>
5.6 #include <l4/devices/hdmi-jz4780.h>
5.7 +
5.8 +#include <l4/devices/lcd-jz4740.h>
5.9 +#include <l4/devices/lcd-jz4740-config.h>
5.10 +#include <l4/devices/lcd-jz4740-panel.h>
5.11 +
5.12 #include <l4/devices/memory.h>
5.13 #include <l4/io/io.h>
5.14 #include <l4/libedid/edid.h>
5.15 @@ -39,6 +44,30 @@
5.16
5.17
5.18
5.19 +/* Test panel. */
5.20 +
5.21 +static struct Jz4740_lcd_panel panel = {
5.22 + .config = (
5.23 + Jz4740_lcd_mode_tft_generic
5.24 + | Jz4740_lcd_pclock_negative
5.25 + | Jz4740_lcd_hsync_positive
5.26 + | Jz4740_lcd_vsync_positive
5.27 + | Jz4740_lcd_de_positive),
5.28 +
5.29 + .width = 1280,
5.30 + .height = 1024,
5.31 + .bpp = 32,
5.32 + .frame_rate = 60,
5.33 + .hsync = 112,
5.34 + .vsync = 3,
5.35 + .line_start = 248, // back porch (blanking - vsyn - offset)
5.36 + .line_end = 48, // front porch (sync offset)
5.37 + .frame_start = 36, // back porch (blanking - vsyn - offset)
5.38 + .frame_end = 3, // front porch (sync offset)
5.39 +};
5.40 +
5.41 +
5.42 +
5.43 /* Device and resource discovery. */
5.44
5.45 static long item_in_range(long start, long end, long index)
5.46 @@ -80,6 +109,7 @@
5.47 l4_addr_t cpm_base = 0, cpm_base_end = 0;
5.48 l4_addr_t gpio_base = 0, gpio_base_end = 0;
5.49 l4_addr_t hdmi_base = 0, hdmi_base_end = 0;
5.50 + l4_addr_t lcd_base = 0, lcd_base_end = 0;
5.51 l4_addr_t port_f, port_f_end;
5.52
5.53 /* Peripheral abstractions. */
5.54 @@ -87,13 +117,16 @@
5.55 void *cpm;
5.56 void *gpio_port_f;
5.57 void *hdmi;
5.58 + void *lcd;
5.59
5.60 /* Access to IRQs. */
5.61
5.62 l4_uint32_t hdmi_irq_start = 0, hdmi_irq_end = 0;
5.63 - l4_cap_idx_t icucap, irqcap;
5.64 + l4_uint32_t lcd_irq_start = 0, lcd_irq_end = 0;
5.65 + l4_cap_idx_t icucap, hdmi_irq, lcd_irq;
5.66
5.67 - irqcap = l4re_util_cap_alloc();
5.68 + hdmi_irq = l4re_util_cap_alloc();
5.69 + lcd_irq = l4re_util_cap_alloc();
5.70 icucap = l4re_env_get_cap("icu");
5.71
5.72 if (l4_is_invalid_cap(icucap))
5.73 @@ -102,7 +135,7 @@
5.74 return 1;
5.75 }
5.76
5.77 - if (l4_is_invalid_cap(irqcap))
5.78 + if (l4_is_invalid_cap(hdmi_irq) || l4_is_invalid_cap(lcd_irq))
5.79 {
5.80 printf("Capabilities not available for interrupts.\n");
5.81 return 1;
5.82 @@ -115,11 +148,17 @@
5.83 if (get_irq("jz4780-hdmi", &hdmi_irq_start, &hdmi_irq_end) < 0)
5.84 return 1;
5.85
5.86 - printf("IRQ range at %d...%d.\n", hdmi_irq_start, hdmi_irq_end);
5.87 + printf("HDMI IRQ range at %d...%d.\n", hdmi_irq_start, hdmi_irq_end);
5.88 +
5.89 + if (get_irq("jz4780-lcd", &lcd_irq_start, &lcd_irq_end) < 0)
5.90 + return 1;
5.91 +
5.92 + printf("LCD IRQ range at %d...%d.\n", lcd_irq_start, lcd_irq_end);
5.93
5.94 /* Create interrupt objects. */
5.95
5.96 - err = l4_error(l4_factory_create_irq(l4re_global_env->factory, irqcap));
5.97 + err = l4_error(l4_factory_create_irq(l4re_global_env->factory, hdmi_irq)) ||
5.98 + l4_error(l4_factory_create_irq(l4re_global_env->factory, lcd_irq));
5.99
5.100 if (err)
5.101 {
5.102 @@ -132,7 +171,10 @@
5.103
5.104 err = l4_error(l4_icu_bind(icucap,
5.105 item_in_range(hdmi_irq_start, hdmi_irq_end, 0),
5.106 - irqcap));
5.107 + hdmi_irq)) ||
5.108 + l4_error(l4_icu_bind(icucap,
5.109 + item_in_range(lcd_irq_start, lcd_irq_end, 0),
5.110 + lcd_irq));
5.111
5.112 if (err)
5.113 {
5.114 @@ -142,7 +184,8 @@
5.115
5.116 /* Attach ourselves to the interrupt handler. */
5.117
5.118 - err = l4_error(l4_rcv_ep_bind_thread(irqcap, l4re_env()->main_thread, 0));
5.119 + err = l4_error(l4_rcv_ep_bind_thread(hdmi_irq, l4re_env()->main_thread, 0)) ||
5.120 + l4_error(l4_rcv_ep_bind_thread(lcd_irq, l4re_env()->main_thread, 0));
5.121
5.122 if (err)
5.123 {
5.124 @@ -173,6 +216,13 @@
5.125
5.126 printf("HDMI at 0x%lx...0x%lx.\n", hdmi_base, hdmi_base_end);
5.127
5.128 + printf("Access LCD...\n");
5.129 +
5.130 + if (get_memory("jz4780-lcd", &lcd_base, &lcd_base_end) < 0)
5.131 + return 1;
5.132 +
5.133 + printf("LCD at 0x%lx...0x%lx.\n", lcd_base, lcd_base_end);
5.134 +
5.135 /* Obtain CPM object. */
5.136
5.137 cpm = jz4780_cpm_init(cpm_base);
5.138 @@ -207,7 +257,7 @@
5.139
5.140 printf("Set up HDMI...\n");
5.141
5.142 - hdmi = jz4780_hdmi_init(hdmi_base, hdmi_base_end, irqcap);
5.143 + hdmi = jz4780_hdmi_init(hdmi_base, hdmi_base_end, hdmi_irq);
5.144
5.145 printf("Read version...\n");
5.146
5.147 @@ -228,9 +278,31 @@
5.148
5.149 show_timings(edid);
5.150
5.151 - /* Detach from the interrupt. */
5.152 + /* Obtain LCD reference. */
5.153 +
5.154 + printf("Set up LCD...\n");
5.155 +
5.156 + lcd = jz4740_lcd_init(lcd_base, &panel);
5.157 +
5.158 + /* Test initialisation with a frequency appropriate for the test panel. */
5.159 +
5.160 + printf("LCD divider: %d\n", jz4780_cpm_get_lcd_pixel_divider(cpm));
5.161 + printf("LCD frequency: %d\n", jz4780_cpm_get_lcd_pixel_frequency(cpm));
5.162 + printf("Desired frequency: %d\n", jz4740_lcd_get_pixel_clock(lcd));
5.163
5.164 - err = l4_error(l4_irq_detach(irqcap));
5.165 + jz4780_cpm_stop_lcd(cpm);
5.166 +
5.167 + jz4780_cpm_set_lcd_frequencies(cpm, jz4740_lcd_get_pixel_clock(lcd), 3);
5.168 +
5.169 + printf("LCD divider: %d\n", jz4780_cpm_get_lcd_pixel_divider(cpm));
5.170 + printf("LCD frequency: %d\n", jz4780_cpm_get_lcd_pixel_frequency(cpm));
5.171 +
5.172 + jz4780_cpm_start_lcd(cpm);
5.173 +
5.174 + /* Detach from the interrupts. */
5.175 +
5.176 + err = l4_error(l4_irq_detach(hdmi_irq)) ||
5.177 + l4_error(l4_irq_detach(lcd_irq));
5.178
5.179 if (err)
5.180 printf("Error detaching from IRQ: %ld\n", err);