Landfall

Changeset

310:c729da7ceb33
5 months ago Paul Boddie raw files shortlog changelog graph Added a limited SPI-based LCD device component for the X1600 corresponding to the JZ4780-based component already used to drive the same ST7789-based display. cpm-library-improvements
pkg/devices/Control (file) pkg/devices/lcd/include/lcd-jz4780-spi-device.h (file) pkg/devices/lcd/include/lcd-x1600-spi-device.h (file) pkg/devices/lcd/src/Makefile (file) pkg/devices/lcd/src/jz4780/lcd-jz4780-spi-device.cc (file) pkg/devices/lcd/src/x1600/Makefile (file) pkg/devices/lcd/src/x1600/lcd-x1600-spi-device.cc (file)
     1.1 --- a/pkg/devices/Control	Fri Jun 07 16:14:04 2024 +0200
     1.2 +++ b/pkg/devices/Control	Fri Jun 07 16:16:49 2024 +0200
     1.3 @@ -21,6 +21,7 @@
     1.4  provides: libdevice-lcd
     1.5  provides: libdevice-lcd-jz4740
     1.6  provides: libdevice-lcd-jz4780-spi
     1.7 +provides: libdevice-lcd-x1600-spi
     1.8  provides: libdevice-util
     1.9  provides: libdrivers-aic
    1.10  provides: libdrivers-common
     2.1 --- a/pkg/devices/lcd/include/lcd-jz4780-spi-device.h	Fri Jun 07 16:14:04 2024 +0200
     2.2 +++ b/pkg/devices/lcd/include/lcd-jz4780-spi-device.h	Fri Jun 07 16:16:49 2024 +0200
     2.3 @@ -1,7 +1,7 @@
     2.4  /*
     2.5 - * LCD device support for the JZ4740 and related SoCs.
     2.6 + * LCD device support for the JZ4780.
     2.7   *
     2.8 - * Copyright (C) 2018, 2023 Paul Boddie <paul@boddie.org.uk>
     2.9 + * Copyright (C) 2018, 2023, 2024 Paul Boddie <paul@boddie.org.uk>
    2.10   *
    2.11   * This program is free software; you can redistribute it and/or
    2.12   * modify it under the terms of the GNU General Public License as
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/pkg/devices/lcd/include/lcd-x1600-spi-device.h	Fri Jun 07 16:16:49 2024 +0200
     3.3 @@ -0,0 +1,71 @@
     3.4 +/*
     3.5 + * LCD device support for the X1600.
     3.6 + *
     3.7 + * Copyright (C) 2018, 2023, 2024 Paul Boddie <paul@boddie.org.uk>
     3.8 + *
     3.9 + * This program is free software; you can redistribute it and/or
    3.10 + * modify it under the terms of the GNU General Public License as
    3.11 + * published by the Free Software Foundation; either version 2 of
    3.12 + * the License, or (at your option) any later version.
    3.13 + *
    3.14 + * This program is distributed in the hope that it will be useful,
    3.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.17 + * GNU General Public License for more details.
    3.18 + *
    3.19 + * You should have received a copy of the GNU General Public License
    3.20 + * along with this program; if not, write to the Free Software
    3.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
    3.22 + * Boston, MA  02110-1301, USA
    3.23 + */
    3.24 +
    3.25 +#pragma once
    3.26 +
    3.27 +#include <l4/devices/lcd.h>
    3.28 +#include <l4/devices/lcd-device.h>
    3.29 +
    3.30 +#include <l4/re/c/dma_space.h>
    3.31 +#include <l4/re/c/video/view.h>
    3.32 +#include <l4/sys/types.h>
    3.33 +
    3.34 +
    3.35 +
    3.36 +/* C++ language interface. */
    3.37 +
    3.38 +#ifdef __cplusplus
    3.39 +
    3.40 +/* Support for specific JZ4780-based devices. */
    3.41 +
    3.42 +class Lcd_x1600_spi_device : public Lcd_device
    3.43 +{
    3.44 +  /* DMA region providing the DMA descriptor virtual and physical addresses. */
    3.45 +
    3.46 +  struct dma_region _desc_region;
    3.47 +
    3.48 +protected:
    3.49 +  /* Device-specific memory allocation. */
    3.50 +
    3.51 +  int _setup_memory();
    3.52 +
    3.53 +public:
    3.54 +  Lcd_x1600_spi_device(Activation *display)
    3.55 +  : Lcd_device(display)
    3.56 +  {
    3.57 +    _setup_memory();
    3.58 +  }
    3.59 +
    3.60 +  /* Device operations. */
    3.61 +
    3.62 +  void disable();
    3.63 +  void enable();
    3.64 +
    3.65 +  l4_size_t get_framebuffer_size();
    3.66 +
    3.67 +  void get_view_info(l4re_video_view_info_t *view_info);
    3.68 +
    3.69 +  /* Common device instance. */
    3.70 +
    3.71 +  static Lcd_x1600_spi_device *device;
    3.72 +};
    3.73 +
    3.74 +#endif
     4.1 --- a/pkg/devices/lcd/src/Makefile	Fri Jun 07 16:14:04 2024 +0200
     4.2 +++ b/pkg/devices/lcd/src/Makefile	Fri Jun 07 16:16:49 2024 +0200
     4.3 @@ -1,9 +1,10 @@
     4.4  PKGDIR		?= ../..
     4.5  L4DIR		?= $(PKGDIR)/../..
     4.6  
     4.7 -TARGET := common jz4740 jz4780
     4.8 +TARGET := common jz4740 jz4780 x1600
     4.9  
    4.10  include $(L4DIR)/mk/subdir.mk
    4.11  
    4.12  jz4740: common
    4.13  jz4780: common
    4.14 +x1600: common
     5.1 --- a/pkg/devices/lcd/src/jz4780/lcd-jz4780-spi-device.cc	Fri Jun 07 16:14:04 2024 +0200
     5.2 +++ b/pkg/devices/lcd/src/jz4780/lcd-jz4780-spi-device.cc	Fri Jun 07 16:16:49 2024 +0200
     5.3 @@ -1,5 +1,5 @@
     5.4  /*
     5.5 - * Common SPI-based screen support for the JZ4780 and related SoCs.
     5.6 + * Common SPI-based screen support for the JZ4780.
     5.7   *
     5.8   * Copyright (C) 2018, 2020, 2021, 2023, 2024 Paul Boddie <paul@boddie.org.uk>
     5.9   *
    5.10 @@ -64,7 +64,7 @@
    5.11  
    5.12  static Dma_channel *dma_channel;
    5.13  static Spi_hybrid *spi_channel;
    5.14 -static Spi_jz4780_channel *spi_jz4780_channel;
    5.15 +static Spi_channel *spi_jz4780_channel;
    5.16  
    5.17  
    5.18  
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/pkg/devices/lcd/src/x1600/Makefile	Fri Jun 07 16:16:49 2024 +0200
     6.3 @@ -0,0 +1,41 @@
     6.4 +PKGDIR		?= ../../..
     6.5 +L4DIR		?= $(PKGDIR)/../..
     6.6 +
     6.7 +TARGET		= liblcd_dev_x1600.o.a liblcd_dev_x1600.o.so
     6.8 +PC_FILENAME	= libdevice-lcd-x1600-spi
     6.9 +
    6.10 +# Locations for interface input and generated output.
    6.11 +
    6.12 +IDL_DIR		= $(PKGDIR)/idl
    6.13 +IDL_MK_DIR	= $(L4DIR)/idl4re/mk
    6.14 +IDL_BUILD_DIR	= .
    6.15 +IDL_EXPORT_DIR	= $(OBJ_BASE)/include/l4/devices/lcd
    6.16 +
    6.17 +include $(IDL_MK_DIR)/idl.mk
    6.18 +
    6.19 +# Individual interfaces.
    6.20 +
    6.21 +CLIENT_INTERFACES_CC		= activation
    6.22 +
    6.23 +# Generated and plain source files.
    6.24 +
    6.25 +CLIENT_INTERFACES_SRC_CC	= $(call interfaces_to_client_cc,$(CLIENT_INTERFACES_CC))
    6.26 +
    6.27 +PLAIN_SRC_CC			= lcd-x1600-spi-device.cc
    6.28 +
    6.29 +# Normal definitions.
    6.30 +
    6.31 +SRC_CC				= $(CLIENT_INTERFACES_SRC_CC) $(PLAIN_SRC_CC)
    6.32 +
    6.33 +REQUIRES_LIBS	= \
    6.34 +		l4re_c l4re_c-util \
    6.35 +		libdevice-lcd \
    6.36 +		libdrivers-cpm libdrivers-dma libdrivers-gpio libdrivers-spi \
    6.37 +		libdevice-util
    6.38 +
    6.39 +PRIVATE_INCDIR	= $(PKGDIR)/lcd/include $(IDL_BUILD_DIR) $(IDL_EXPORT_DIR)
    6.40 +
    6.41 +include $(L4DIR)/mk/lib.mk
    6.42 +include $(IDL_MK_DIR)/interface_rules.mk
    6.43 +
    6.44 +$(PLAIN_SRC_CC): $(CLIENT_INTERFACES_SRC_CC)
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/pkg/devices/lcd/src/x1600/lcd-x1600-spi-device.cc	Fri Jun 07 16:16:49 2024 +0200
     7.3 @@ -0,0 +1,258 @@
     7.4 +/*
     7.5 + * Common SPI-based screen support for the X1600.
     7.6 + *
     7.7 + * Copyright (C) 2018, 2020, 2021, 2023, 2024 Paul Boddie <paul@boddie.org.uk>
     7.8 + *
     7.9 + * This program is free software; you can redistribute it and/or
    7.10 + * modify it under the terms of the GNU General Public License as
    7.11 + * published by the Free Software Foundation; either version 2 of
    7.12 + * the License, or (at your option) any later version.
    7.13 + *
    7.14 + * This program is distributed in the hope that it will be useful,
    7.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.17 + * GNU General Public License for more details.
    7.18 + *
    7.19 + * You should have received a copy of the GNU General Public License
    7.20 + * along with this program; if not, write to the Free Software
    7.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
    7.22 + * Boston, MA  02110-1301, USA
    7.23 + */
    7.24 +
    7.25 +#include <l4/devices/cpm-x1600.h>
    7.26 +#include <l4/devices/dma-x1600.h>
    7.27 +#include <l4/devices/gpio-x1600.h>
    7.28 +#include <l4/devices/spi-hybrid.h>
    7.29 +#include <l4/devices/spi-x1600.h>
    7.30 +
    7.31 +#include <l4/devices/dma.h>
    7.32 +#include <l4/devices/memory.h>
    7.33 +#include "lcd-x1600-spi-device.h"
    7.34 +
    7.35 +#include <l4/re/c/dataspace.h>
    7.36 +#include <l4/re/env.h>
    7.37 +#include <l4/sys/cache.h>
    7.38 +#include <l4/sys/types.h>
    7.39 +
    7.40 +#include <ipc/cap_alloc.h>
    7.41 +#include <ipc/mem_ipc.h>
    7.42 +
    7.43 +#include <stdio.h>
    7.44 +#include <unistd.h>
    7.45 +
    7.46 +
    7.47 +
    7.48 +/* Virtual addresses for the CPM, DMA, GPIO and SSI/SPI register blocks.
    7.49 +
    7.50 +   NOTE: Should be able to use component abstractions for some of these
    7.51 +         eventually. */
    7.52 +
    7.53 +static l4_addr_t cpm_virt_base = 0, cpm_virt_base_end = 0;
    7.54 +static l4_addr_t dma_virt_base = 0, dma_virt_base_end = 0;
    7.55 +static l4_addr_t gpio_virt_base = 0, gpio_virt_base_end = 0;
    7.56 +static l4_addr_t spi_virt_base = 0, spi_virt_base_end = 0;
    7.57 +static l4_addr_t spi_phys_base = 0, spi_phys_base_end = 0;
    7.58 +
    7.59 +static l4_uint32_t dma_irq_start = 0, dma_irq_end = 0;
    7.60 +
    7.61 +// CPM, DMA, GPIO, SSI/SPI and display device abstractions.
    7.62 +
    7.63 +static Cpm_x1600_chip *cpm_chip;
    7.64 +static Dma_x1600_chip *dma_chip;
    7.65 +static Gpio_x1600_chip *gpio_chip_a, *gpio_chip_b, *gpio_chip_c;
    7.66 +static Spi_x1600_chip *spi_chip;
    7.67 +
    7.68 +static Dma_channel *dma_channel;
    7.69 +static Spi_hybrid *spi_channel;
    7.70 +static Spi_channel *spi_x1600_channel;
    7.71 +
    7.72 +
    7.73 +
    7.74 +// Disable the display.
    7.75 +
    7.76 +void
    7.77 +Lcd_x1600_spi_device::disable()
    7.78 +{
    7.79 +  // NOTE: Need to support cancelling the transfer or disabling the peripheral.
    7.80 +
    7.81 +  //disable_display();
    7.82 +}
    7.83 +
    7.84 +// Configure the peripheral and enable the display.
    7.85 +
    7.86 +void
    7.87 +Lcd_x1600_spi_device::enable()
    7.88 +{
    7.89 +  // Set up the GPIO pins for the peripheral.
    7.90 +  // NOTE: Hard-coded pin usage!
    7.91 +
    7.92 +  gpio_chip_c->setup(26, Hw::Gpio_chip::Output, 1);             // backlight
    7.93 +  gpio_chip_b->config_pad(16, Hw::Gpio_chip::Function_alt, 1);  // CE1
    7.94 +  gpio_chip_a->config_pad(31, Hw::Gpio_chip::Function_alt, 0);  // SCLK
    7.95 +  gpio_chip_a->config_pad(30, Hw::Gpio_chip::Function_alt, 0);  // MOSI
    7.96 +  gpio_chip_a->setup(29, Hw::Gpio_chip::Output, 1);             // GPC
    7.97 +
    7.98 +  // Initialise the screen.
    7.99 +  // NOTE: Specific to the ST7789.
   7.100 +
   7.101 +  spi_channel->send_units(2, (const uint8_t []) {0x00, 0x01}, 2, 8);
   7.102 +  usleep(120000);
   7.103 +  spi_channel->send_units(2, (const uint8_t []) {0x00, 0x11}, 2, 8);
   7.104 +  usleep(5000);
   7.105 +  spi_channel->send_units(4, (const uint8_t []) {0x00, 0x36, 0x01, 0x00}, 2, 8);
   7.106 +  usleep(5000);
   7.107 +  spi_channel->send_units(10, (const uint8_t []) {0x00, 0x3a, 0x01, 0x05, 0x00, 0x13, 0x00, 0x29, 0x00, 0x21}, 2, 8);
   7.108 +  usleep(5000);
   7.109 +  spi_channel->send_units(22, (const uint8_t []) {0x00, 0x2a, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xef,
   7.110 +                                                  0x00, 0x2b, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xef,
   7.111 +                                                  0x00, 0x2c}, 2, 8);
   7.112 +  usleep(5000);
   7.113 +
   7.114 +  for (l4_addr_t addr = get_framebuffer(); addr < get_framebuffer() + get_framebuffer_size(); addr += sizeof(uint32_t))
   7.115 +      *((uint32_t *) addr) = 0;
   7.116 +
   7.117 +  l4_cache_clean_data(get_framebuffer(), get_framebuffer() + get_framebuffer_size());
   7.118 +
   7.119 +  // Initialise the display transfer.
   7.120 +  // NOTE: Asserting the data signal.
   7.121 +
   7.122 +  spi_channel->acquire_control(true);
   7.123 +
   7.124 +  spi_x1600_channel->transfer(_fb_region.vaddr, _fb_region.paddr,
   7.125 +                              get_framebuffer_size(), 2, 16,
   7.126 +                              _desc_region.vaddr, _desc_region.paddr);
   7.127 +
   7.128 +  //enable_display();
   7.129 +}
   7.130 +
   7.131 +// Set up memory addresses for the peripheral, initialising the framebuffer and
   7.132 +// descriptor members.
   7.133 +
   7.134 +int
   7.135 +Lcd_x1600_spi_device::_setup_memory()
   7.136 +{
   7.137 +  // Test for existing setup.
   7.138 +
   7.139 +  if (_fb_region.vaddr)
   7.140 +    return 0;
   7.141 +
   7.142 +  // Framebuffer and descriptor sizes.
   7.143 +
   7.144 +  unsigned long fb_size = get_framebuffer_size(), desc_size = 32;
   7.145 +
   7.146 +  // Allocate memory for the framebuffer and descriptors with 2**5 = 32 byte ==
   7.147 +  // 8 word alignment, sufficient for the descriptors.
   7.148 +
   7.149 +  long err = get_dma_region(fb_size, 5, &_fb_region);
   7.150 +
   7.151 +  if (err)
   7.152 +    return 1;
   7.153 +
   7.154 +  err = get_dma_region(desc_size, 5, &_desc_region);
   7.155 +
   7.156 +  if (err)
   7.157 +    return 1;
   7.158 +
   7.159 +  return 0;
   7.160 +}
   7.161 +
   7.162 +l4_size_t Lcd_x1600_spi_device::get_framebuffer_size()
   7.163 +{
   7.164 +  // NOTE: Hard-coded size.
   7.165 +
   7.166 +  return 240 * 240 * 2;
   7.167 +}
   7.168 +
   7.169 +// Populate a view information structure.
   7.170 +
   7.171 +void Lcd_x1600_spi_device::get_view_info(l4re_video_view_info_t *view_info)
   7.172 +{
   7.173 +  // NOTE: Hard-coded properties.
   7.174 +
   7.175 +  view_info->width                      = 240;
   7.176 +  view_info->height                     = 240;
   7.177 +  view_info->pixel_info.bytes_per_pixel = 2;
   7.178 +  view_info->bytes_per_line             = 480;
   7.179 +
   7.180 +  view_info->pixel_info.r.shift = 11; view_info->pixel_info.r.size = 5;
   7.181 +  view_info->pixel_info.g.shift = 5;  view_info->pixel_info.g.size = 6;
   7.182 +  view_info->pixel_info.b.shift = 0;  view_info->pixel_info.b.size = 5;
   7.183 +
   7.184 +  view_info->pixel_info.a.shift = 0;
   7.185 +  view_info->pixel_info.a.size  = 0;
   7.186 +}
   7.187 +
   7.188 +// Access to peripheral memory.
   7.189 +
   7.190 +static int setup_memory()
   7.191 +{
   7.192 +  if (get_memory("x1600-cpm", &cpm_virt_base, &cpm_virt_base_end))
   7.193 +    return 1;
   7.194 +
   7.195 +  if (get_memory("x1600-dma", &dma_virt_base, &dma_virt_base_end))
   7.196 +    return 1;
   7.197 +
   7.198 +  if (get_irq("x1600-dma", &dma_irq_start, &dma_irq_end) < 0)
   7.199 +    return 1;
   7.200 +
   7.201 +  if (get_memory("x1600-gpio", &gpio_virt_base, &gpio_virt_base_end))
   7.202 +    return 1;
   7.203 +
   7.204 +  if (get_memory_complete("x1600-ssi", &spi_virt_base, &spi_virt_base_end,
   7.205 +                          &spi_phys_base, &spi_phys_base_end))
   7.206 +    return 1;
   7.207 +
   7.208 +  // Initialise the abstractions.
   7.209 +  // NOTE: Using a preset GPIO configuration.
   7.210 +
   7.211 +  cpm_chip = new Cpm_x1600_chip(cpm_virt_base);
   7.212 +
   7.213 +  dma_chip = new Dma_x1600_chip(dma_virt_base, dma_virt_base_end, cpm_chip);
   7.214 +
   7.215 +  dma_chip->enable();
   7.216 +
   7.217 +  gpio_chip_a = new Gpio_x1600_chip(gpio_virt_base, 0);
   7.218 +  gpio_chip_b = new Gpio_x1600_chip(gpio_virt_base, 1);
   7.219 +  gpio_chip_c = new Gpio_x1600_chip(gpio_virt_base, 2);
   7.220 +
   7.221 +  // Initialise the clocks for the SPI peripheral before obtaining the
   7.222 +  // peripheral abstraction.
   7.223 +
   7.224 +  /* NOTE: Set a suitably high but arbitrary frequency to support the SPI bit
   7.225 +           clock. */
   7.226 +
   7.227 +  cpm_chip->set_frequency(Clock_ssi0, 100000000);
   7.228 +
   7.229 +  spi_chip = new Spi_x1600_chip(spi_phys_base, spi_virt_base,
   7.230 +                                spi_virt_base_end, cpm_chip);
   7.231 +
   7.232 +  // Obtain a DMA channel and an SPI channel for updating the display.
   7.233 +  // NOTE: Using preset channels, frequency and pin configuration.
   7.234 +
   7.235 +  dma_channel = dma_chip->get_channel(12);
   7.236 +
   7.237 +  spi_x1600_channel = spi_chip->get_channel(0, dma_channel, 25000000);
   7.238 +
   7.239 +  spi_channel = new Spi_hybrid(spi_x1600_channel, gpio_chip_a, 29, -1);
   7.240 +
   7.241 +  return 0;
   7.242 +}
   7.243 +
   7.244 +// Device initialisation.
   7.245 +
   7.246 +Lcd_x1600_spi_device *Lcd_x1600_spi_device::device = 0;
   7.247 +
   7.248 +Lcd_device *Lcd_device::get_device()
   7.249 +{
   7.250 +  if (Lcd_x1600_spi_device::device)
   7.251 +    return Lcd_x1600_spi_device::device;
   7.252 +
   7.253 +  if (setup_memory())
   7.254 +    return 0;
   7.255 +
   7.256 +  // Initialise the common device.
   7.257 +
   7.258 +  Lcd_x1600_spi_device::device = new Lcd_x1600_spi_device(NULL /* display_device */);
   7.259 +
   7.260 +  return Lcd_x1600_spi_device::device;
   7.261 +}