Skip to content

Commit

Permalink
gpboot: Add rudimentary ST7585 LCD driver
Browse files Browse the repository at this point in the history
Add a basic, bit-banged ST7585 LCD driver, useful for
showing a boot logo on the Hero4's front panel display.

Signed-off-by: evilwombat <evilwombat@server.fake>
  • Loading branch information
evilwombat committed Dec 30, 2015
1 parent f1ab838 commit f967021
Show file tree
Hide file tree
Showing 2 changed files with 181 additions and 0 deletions.
178 changes: 178 additions & 0 deletions gp_lcd.c
@@ -0,0 +1,178 @@
#include <libusb.h>
#include "gp_api.h"

#define GPIO_BIT(a) (1 << (a & 0x1f))

#define GPIO_AFSEL_OFFSET 0x18
#define GPIO_DIR_OFFSET 0x04
#define GPIO_DATA_OFFSET 0x00

static unsigned int hero4_gpio_offsets[] = {
0x70009000,
0x7000a000,
0x7000e000,
0x70010000,
0x70011000,
};

struct lcd_hw_info {
int spi_clk_gpio;
int spi_mosi_gpio;
int spi_miso_gpio;
int spi_cs_gpio;
int enable_gpio;
int *gpio_offsets;
int last_addr, last_val;
int spi_all_cs_gpios[];
};

static struct lcd_hw_info hero4_lcd_hw_info = {
.spi_clk_gpio = 2,
.spi_mosi_gpio = 3,
.spi_miso_gpio = 4,
.spi_cs_gpio = 6,
.enable_gpio = 31,
.gpio_offsets = hero4_gpio_offsets,
.spi_all_cs_gpios = {5, 6, -1},
};

static void gpio_write_bit(libusb_device_handle *dev, struct lcd_hw_info *hw_info,
int gpio, int offset, int bit_value)
{
unsigned int addr;
unsigned int val;

addr = hw_info->gpio_offsets[gpio / 32] + offset;

if (hw_info->last_addr == addr)
val = hw_info->last_val;
else
val = gp_read_reg(dev, addr);

val &= ~(GPIO_BIT(gpio));

if (bit_value)
val |= GPIO_BIT(gpio);

gp_write_reg(dev, addr, val);

hw_info->last_addr = addr;
hw_info->last_val = val;
}

static void st7585_spi_send_word(struct libusb_device_handle *dev, struct lcd_hw_info *hw_info,
unsigned int w)
{
int i;

gpio_write_bit(dev, hw_info, hw_info->spi_cs_gpio, GPIO_DATA_OFFSET, 0);
for (i = 0; i < 9; i++) {
gpio_write_bit(dev, hw_info, hw_info->spi_clk_gpio, GPIO_DATA_OFFSET, 0);
gpio_write_bit(dev, hw_info, hw_info->spi_mosi_gpio, GPIO_DATA_OFFSET, w & (1 << (8 - i)));
gpio_write_bit(dev, hw_info, hw_info->spi_clk_gpio, GPIO_DATA_OFFSET, 1);
}

gpio_write_bit(dev, hw_info, hw_info->spi_cs_gpio, 0, 1);
}

static int st7585_upload_bitmap(libusb_device_handle *dev, struct lcd_hw_info *hw_info,
const unsigned char *buffer)
{
unsigned int row, col;

for (col = 0; col < 8; col++) {
st7585_spi_send_word(dev, hw_info, 0x40 | col);
st7585_spi_send_word(dev, hw_info, 0x8d);

for (row = 0; row < 75; row++)
st7585_spi_send_word(dev, hw_info, 0x100 | (buffer[col + row * 8]));
}

}

static int st7585_configure_panel(libusb_device_handle *dev, struct lcd_hw_info *hw_info)
{
int i = 0;

/* MISO as input */
gpio_write_bit(dev, &hero4_lcd_hw_info, hw_info->spi_miso_gpio, GPIO_DIR_OFFSET, 0);


/* Initialize all chip selects */
while (hw_info->spi_all_cs_gpios[i] != -1) {
gpio_write_bit(dev, &hero4_lcd_hw_info, hw_info->spi_all_cs_gpios[i], GPIO_AFSEL_OFFSET, 0);
gpio_write_bit(dev, &hero4_lcd_hw_info, hw_info->spi_all_cs_gpios[i], GPIO_DIR_OFFSET, 1);
gpio_write_bit(dev, &hero4_lcd_hw_info, hw_info->spi_all_cs_gpios[i], GPIO_DATA_OFFSET, 1);
i++;
}

gpio_write_bit(dev, &hero4_lcd_hw_info, hw_info->spi_clk_gpio, GPIO_AFSEL_OFFSET, 0);
gpio_write_bit(dev, &hero4_lcd_hw_info, hw_info->spi_clk_gpio, GPIO_DIR_OFFSET, 1);

gpio_write_bit(dev, &hero4_lcd_hw_info, hw_info->spi_mosi_gpio, GPIO_AFSEL_OFFSET, 0);
gpio_write_bit(dev, &hero4_lcd_hw_info, hw_info->spi_mosi_gpio, GPIO_DIR_OFFSET, 1);

if (hw_info->enable_gpio >= 0) {
gpio_write_bit(dev, &hero4_lcd_hw_info, hw_info->enable_gpio, GPIO_AFSEL_OFFSET, 0);
gpio_write_bit(dev, &hero4_lcd_hw_info, hw_info->enable_gpio, GPIO_DIR_OFFSET, 1);
gpio_write_bit(dev, &hero4_lcd_hw_info, hw_info->enable_gpio, GPIO_DATA_OFFSET, 1);
}

/* Initialize panel */
st7585_spi_send_word(dev, hw_info, 0x21);
st7585_spi_send_word(dev, hw_info, 0x9c);
st7585_spi_send_word(dev, hw_info, 0x20);
st7585_spi_send_word(dev, hw_info, 0x08);
}

const unsigned char boot_logo[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x60,0x00,0x00,0x00,
0x00,0x00,0x66,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0x43,0xc1,0xb0,0x00,0x00,0x00,
0x00,0x00,0xcf,0xff,0x10,0x00,0x00,0x00,0x00,0x00,0xc4,0x0f,0x30,0x00,0x00,0x00,
0x00,0x00,0x40,0x02,0x18,0x00,0x00,0x00,0x00,0x00,0xc0,0x02,0x18,0x00,0x00,0x00,
0x00,0x01,0x80,0x00,0x1c,0x00,0x00,0x00,0x00,0x03,0x80,0x00,0x06,0x00,0x00,0x00,
0x00,0x03,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x03,0x80,0x00,0x03,0xc0,0x00,0x00,
0x00,0x07,0xc0,0x00,0x00,0xe0,0x00,0x00,0x00,0x04,0x40,0x78,0x00,0x30,0x00,0x00,
0x00,0x04,0x00,0x60,0x06,0x38,0x00,0x00,0x00,0x0c,0x00,0x00,0x77,0x7c,0x00,0x00,
0x00,0x0c,0x00,0x00,0x7c,0xf6,0x00,0x00,0x00,0x0c,0x00,0x01,0xe4,0xf2,0x00,0x00,
0x00,0x3c,0x00,0x01,0xe0,0xe3,0x00,0x00,0x01,0xbc,0x00,0x03,0x80,0x21,0x00,0x00,
0x01,0xfc,0x00,0x06,0xc0,0x31,0x00,0x00,0x0f,0xe4,0x00,0x18,0x80,0x71,0x80,0x00,
0x07,0xc7,0x20,0x71,0xff,0xf1,0x80,0x00,0x0e,0x03,0xf0,0xc1,0xd8,0x61,0x80,0x00,
0x1c,0x01,0xe7,0x00,0x0c,0xc1,0x80,0x00,0x1c,0x07,0xf8,0x00,0x07,0x00,0xc0,0x00,
0x07,0x0e,0x08,0x00,0x00,0x00,0x60,0x00,0x01,0xf0,0x08,0x00,0x00,0x00,0x30,0x00,
0x00,0x00,0x0c,0x00,0x02,0x00,0x30,0x00,0x00,0x00,0x07,0x00,0x06,0x00,0x10,0x00,
0x00,0x00,0x07,0xe0,0x1f,0x00,0x18,0x00,0x00,0x00,0x06,0x3f,0xf1,0x80,0x1c,0x00,
0x00,0x00,0x06,0x01,0xc0,0xe0,0x04,0x00,0x00,0x00,0x06,0x00,0xc0,0x7e,0x06,0x00,
0x00,0x00,0x02,0x00,0x40,0x1c,0x1e,0x00,0x00,0x00,0x03,0x00,0x60,0x18,0x7f,0x00,
0x00,0x00,0x01,0x80,0x70,0x0d,0xbe,0x00,0x00,0x00,0x00,0xe0,0x10,0x07,0xf8,0x00,
0x00,0x00,0x00,0x7c,0x10,0x01,0xe0,0x00,0x00,0x00,0x00,0x10,0x18,0x00,0x00,0x00,
0x00,0x00,0x00,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xfc,0x00,0x00,0x00,
0x00,0x00,0x00,0x07,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xf0,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};

int st7585_show_logo(libusb_device_handle *dev)
{
st7585_configure_panel(dev, &hero4_lcd_hw_info);
st7585_upload_bitmap(dev, &hero4_lcd_hw_info, boot_logo);

/* Turn on panel */
st7585_spi_send_word(dev, &hero4_lcd_hw_info, 0x20);
st7585_spi_send_word(dev, &hero4_lcd_hw_info, 0x0c);
st7585_spi_send_word(dev, &hero4_lcd_hw_info, 0x8d);
}
3 changes: 3 additions & 0 deletions gp_lcd.h
@@ -0,0 +1,3 @@
/* Short and to the point */

int st7585_show_logo(libusb_device_handle *dev);

0 comments on commit f967021

Please sign in to comment.