1
0
Fork 0

Thomas/epd init (#6)

* Working EPD init sequence.
* Read EPD temperature. Shutdown LCDIF after init.
* Working splash. Splash data is loaded from splash.dat on p1.
* Working grayscale splash screen using external proprietary binary.
* Using temperature to select waveforms. Loading compressed proprietary binary «zplash»
* Check zplash size and crc.
* Init charger before probe_serial_download.
* Renamed epd_init and epd_init.
zero-sugar
thomasing 2019-08-22 15:34:18 +02:00 committed by GitHub
parent bbd1774489
commit cd10002e83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 527 additions and 110 deletions

View File

@ -6,8 +6,8 @@
obj-y := zero-sugar.o \
uart_init.o \
wifi_init.o \
epd_init.o \
lcd_init.o \
epd_pmic_init.o \
epd_display_init.o \
touch_init.o \
digitizer_init.o \
charger_init.o \

View File

@ -0,0 +1,371 @@
#include "epd_display_init.h"
#include "epd_pmic_init.h"
#include <asm/arch/sys_proto.h>
#include <asm/mach-imx/iomux-v3.h>
#include <asm/arch/mx7-pins.h>
#include <asm/mach-imx/video.h>
#include <mxsfb.h>
#include <video_fb.h>
#include <stdlib.h>
#include <fat.h>
#include <memalign.h>
static int epd_splash(void);
static int splash_init(void);
static uint8_t *epd_load_image(const char *filename, u32 *x0, u32 *y0, u32 *width, u32 *height);
static GraphicDevice *pGD = NULL; /* Pointer to Graphic array */
#define LCD_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PUS_PU100KOHM | PAD_CTL_DSE_3P3V_49OHM)
//#define EPD_DISPLAY_INIT_DEBUG
/* Default temperature in case reading EPD temperature fails: */
#define EPD_DEFAULT_TEMPERATURE 24
static iomux_v3_cfg_t const lcd_pads[] = {
MX7D_PAD_LCD_CLK__LCD_CLK | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_ENABLE__LCD_ENABLE | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_HSYNC__LCD_HSYNC | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_VSYNC__LCD_VSYNC | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA00__LCD_DATA0 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA01__LCD_DATA1 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA02__LCD_DATA2 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA03__LCD_DATA3 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA04__LCD_DATA4 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA05__LCD_DATA5 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA06__LCD_DATA6 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA07__LCD_DATA7 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA08__LCD_DATA8 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA09__LCD_DATA9 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA10__LCD_DATA10 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA11__LCD_DATA11 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA12__LCD_DATA12 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA13__LCD_DATA13 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA14__LCD_DATA14 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA15__LCD_DATA15 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA16__LCD_DATA16 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA17__LCD_DATA17 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA18__LCD_DATA18 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA19__LCD_DATA19 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA20__LCD_DATA20 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA21__LCD_DATA21 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA22__LCD_DATA22 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA23__LCD_DATA23 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_RESET__GPIO3_IO4 | MUX_PAD_CTRL(LCD_PAD_CTRL),
};
void do_enable_parallel_lcd(struct display_info_t const *dev)
{
imx_iomux_v3_setup_multiple_pads(lcd_pads, ARRAY_SIZE(lcd_pads));
}
struct display_info_t const displays[] = {{
.bus = ELCDIF1_IPS_BASE_ADDR,
.addr = 0,
.pixfmt = 24,
.detect = NULL,
.enable = do_enable_parallel_lcd,
.mode = {
.name = "EPD",
.xres = 334,
.yres = 1405,
.pixclock = KHZ2PICOS(40000),
.left_margin = 1,
.right_margin = 1,
.upper_margin = 1,
.lower_margin = 1,
.hsync_len = 1,
.vsync_len = 1,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED
} } };
size_t display_count = ARRAY_SIZE(displays);
struct splash_functions {
int (*set_temp)(int);
int (*clear)(void*);
int (*fill)(void*, uint16_t);
int (*init_tbl)(const uint8_t**);
int (*blit_gc)(uint32_t*, const uint8_t*, int, int, int, int, int);
}splash;
static int splash_init(void)
{
// Load main.gz to 0x1C000000
const char *filename = "zplash";
const u32 max_inflated_size = 100*1024;
void *addr = (void*)0xC1000000;
// Check if it exists
if (!fat_exists(filename)) {
printf("%s: %s not found\n", __func__, filename);
return -1;
}
// Get file size
loff_t size;
if (fat_size(filename, &size)) {
printf("%s: unable to get file size of %s\n", __func__, filename);
return -1;
}
// Allocate memory
u8 *zdata = (u8*)malloc_cache_aligned(size);
if (!zdata) {
printf("%s: unable to allocate memory for splash library!\n", __func__);
return -1;
}
// Load binary into memory
if (file_fat_read(filename, zdata, size) != size) {
printf("%s: unable to load %s from disk\n", __func__, filename);
free(zdata);
return -1;
}
// Read expected crc and size
u32 expected_crc, expected_size;
memcpy(&expected_crc, zdata + size - 8, sizeof(expected_crc));
expected_crc = le32_to_cpu(expected_crc);
memcpy(&expected_size, zdata + size - 4, sizeof(expected_size));
expected_size = le32_to_cpu(expected_size);
if (expected_size > max_inflated_size) {
printf("%s: expected inflated size is too large! (>%u)\n", __func__,
max_inflated_size);
free(zdata);
return -1;
}
// Unzip into addr
unsigned long lenp = size;
if (gunzip(addr, max_inflated_size, zdata, &lenp)) {
printf("%s: unable to decompress %s\n", __func__, filename);
free(zdata);
return -1;
}
// Free memory
free(zdata);
// Check actual size vs expected size
if (lenp != expected_size) {
printf("%s: unexpected uncompressed size!\n", __func__);
return -1;
}
// Check actual checksum vs expected checksum
u32 crc = crc32(0, addr, lenp);
if (crc != expected_crc) {
printf("%s: wrong checksum!\n", __func__);
return -1;
}
// Run init
memset(&splash, 0, sizeof(splash));
ulong (*init_entry)(void*) = addr;
if (init_entry(&splash)) {
printf("%s: init_entry failed\n", __func__);
return -1;
}
if (splash.set_temp == NULL ||
splash.clear == NULL ||
splash.fill == NULL ||
splash.init_tbl == NULL ||
splash.blit_gc == NULL) {
printf("%s: splash not properly initialized\n", __func__);
return -1;
}
return 0;
}
int epd_display_init()
{
int i;
// Check that framebuffer is initialized
if (pGD == NULL)
return -1;
const int frame_size = pGD->plnSizeX * pGD->plnSizeY * pGD->gdfBytesPP;
// Load graphics library
if (splash_init()) {
printf("%s: splash_init failed!\n", __func__);
return -1;
}
// Read and set temperature
int temp;
if (epd_read_temp(&temp)) {
temp = EPD_DEFAULT_TEMPERATURE;
printf("%s: failed to read temperature, defaulting to %d\n", __func__, temp);
} else {
printf("%s: temperature = %d\n", __func__, temp);
}
splash.set_temp(temp);
mxs_pan(3);
// Pointers to first 3 frame buffers
u32 *frame0 = (u32*)(pGD->frameAdrs + 0 * frame_size);
u32 *frame1 = (u32*)(pGD->frameAdrs + 1 * frame_size);
u32 *frame2 = (u32*)(pGD->frameAdrs + 2 * frame_size);
// Clear frames
splash.clear(frame0);
memcpy(frame1, frame0, frame_size);
memcpy(frame2, frame0, frame_size);
// Fill frame1 and frame2
splash.fill(frame1, 0x5555);
splash.fill(frame2, 0xAAAA);
// Flush cache
flush_cache(pGD->frameAdrs, roundup(pGD->memSize, ARCH_DMA_MINALIGN));
// Get init sequence table
const u8 *wf_init;
int phases = splash.init_tbl(&wf_init);
if (phases == 0) {
printf("%s: unable to get init table\n", __func__);
return -1;
}
// Run INIT sequence
printf("%s: clearing epd\n", __func__);
for (i = 0; i < phases; i++) {
mxs_pan(wf_init[i]);
}
// Show splash screen
int ret = epd_splash();
if (ret) {
printf("%s: splash failed", __func__);
return ret;
}
return 0;
}
static uint8_t *epd_load_image(const char *filename, u32 *x0, u32 *y0, u32 *width, u32 *height)
{
// Check if splash.dat exists
if (!fat_exists(filename)) {
printf("%s: %s not found\n", __func__, filename);
return NULL;
}
// Get file size
loff_t size;
if (fat_size(filename, &size)) {
printf("%s: unable to get file size of %s\n", __func__, filename);
return NULL;
}
// Allocate memory
u8 *splash_data = (u8*)malloc_cache_aligned(size);
if (!splash_data) {
printf("%s: unable to allocate memory for splash data!\n", __func__);
return NULL;
}
// Load spash data into memory
if (file_fat_read(filename, splash_data, size) != size) {
printf("%s: unable to load %s from disk\n", __func__, filename);
free(splash_data);
return NULL;
}
// Get offset and dimensions
*x0 = *((u32*)&splash_data[0]);
*y0 = *((u32*)&splash_data[4]);
*width = *((u32*)&splash_data[8]);
*height = *((u32*)&splash_data[12]);
// Check if x0, y0, width and height are valid.
if ((size != 4*sizeof(u32) + *width * (*height)) ||
(*x0 + *width > 1872 || *y0 + *height > 1404) ) {
free(splash_data);
printf("%s: corrupt splash data\n", __func__);
return NULL;
}
return splash_data;
}
int epd_splash(void)
{
if (pGD == NULL) {
printf("%s: video not initialized, skipping splash", __func__);
return -1;
}
const int frame_size = pGD->plnSizeX * pGD->plnSizeY * pGD->gdfBytesPP;
// Pointers to first 2 frame buffers
u32 *frame0 = (u32*)(pGD->frameAdrs + 0 * frame_size);
u32 *frame1 = (u32*)(pGD->frameAdrs + 1 * frame_size);
// Clear frame1
memcpy(frame1, frame0, frame_size);
// Load splash image
u32 x0, y0, width, height;
const u8 *splash_data = epd_load_image("splash.dat", &x0, &y0, &width, &height);
if (splash_data == NULL) {
printf("%s: unable to load splash image, skipping splash\n", __func__);
return -1;
}
const u8 *bitmap = (const u8*)&splash_data[16];
int phase = 0;
// Insert waveform for phase into frame1/frame2
int ret = splash.blit_gc(frame0, bitmap, x0, y0, width, height, phase++);
while (ret) {
flush_cache((unsigned long)frame0, roundup(frame_size, ARCH_DMA_MINALIGN));
mxs_pan(0);
ret = splash.blit_gc(frame1, bitmap, x0, y0, width, height, phase++);
if (!ret) break;
flush_cache(rounddown((unsigned long)frame1,ARCH_DMA_MINALIGN), roundup(frame_size, ARCH_DMA_MINALIGN));
mxs_pan(1);
ret = splash.blit_gc(frame0, bitmap, x0, y0, width, height, phase++);
}
mxs_pan(3);
free((void*)splash_data);
return 0;
}
#ifdef EPD_DISPLAY_INIT_DEBUG
int epd_do_init(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
return epd_init();
}
U_BOOT_CMD(
epd_init, 1, 1, epd_do_init,
"Run EPD INIT sequence",
""
);
#endif
int drv_video_init(void)
{
/* Check if video initialization should be skipped */
if (board_video_skip())
return 0;
pGD = video_hw_init();
if (pGD == NULL)
return -1;
return 0;
}

View File

@ -0,0 +1,6 @@
#ifndef EPD_DISPLAY_INIT_H
#define EPD_DISPLAY_INIT_H
int epd_display_init(void);
#endif

View File

@ -1,9 +1,9 @@
#include "epd_init.h"
#include "epd_pmic_init.h"
#include <asm/arch/sys_proto.h>
#include <asm/gpio.h>
#include <dm/uclass.h>
#include <i2c.h>
#include <linux/errno.h>
#define SY7636A_I2C_BUS 3
@ -19,6 +19,8 @@
#define SY7636A_VCOMADJUST_LMASK 0xff
#define SY7636A_VCOMADJUST_HMASK 0x80
#define SY7636A_REG_THERMISTOR 0x08
static int sy7636a_i2c_reg_write(struct udevice *dev, uint addr, uint mask, uint data)
{
u8 valb;
@ -96,19 +98,68 @@ static int sy7636a_vcom_set(struct udevice *dev, int vcom)
return sy7636a_i2c_reg_write(dev, SY7636A_REG_VCOMADJUST_H, SY7636A_VCOMADJUST_HMASK, high);
}
static int sy7636a_thermistor_get(struct udevice *dev, int *temp)
{
u8 value;
int ret;
ret = sy7636a_i2c_reg_read(dev, SY7636A_REG_THERMISTOR, &value);
if (ret)
return ret;
*temp = *((s8*)&value);
return 0;
}
int zs_do_config_epd_powerctrl_pins(void)
{
printf("Configuring EPD PMIC I2C pullup..\n");
gpio_request(IMX_GPIO_NR(4, 22), "EPD_PMIC_I2C_PULLUP");
gpio_direction_output(IMX_GPIO_NR(4, 22), 1);
printf("Configuring EPD PMIC I2C pullup..\n");
gpio_request(IMX_GPIO_NR(4, 22), "EPD_PMIC_I2C_PULLUP");
gpio_direction_output(IMX_GPIO_NR(4, 22), 1);
printf("Configuring EPD PMIC LDO4VEN..\n");
gpio_request(IMX_GPIO_NR(7, 10), "PMIC_LDO4VEN");
gpio_direction_output(IMX_GPIO_NR(7, 10), 1);
printf("Configuring EPD PMIC LDO4VEN..\n");
gpio_request(IMX_GPIO_NR(7, 10), "PMIC_LDO4VEN");
gpio_direction_output(IMX_GPIO_NR(7, 10), 1);
printf("Configuring EPD PMIC powerup signal..\n");
gpio_request(IMX_GPIO_NR(7, 11), "EPD_PMIC_POWERUP");
gpio_direction_output(IMX_GPIO_NR(7, 11), 1);
printf("Configuring EPD PMIC powerup signal..\n");
gpio_request(IMX_GPIO_NR(7, 11), "EPD_PMIC_POWERUP");
gpio_direction_output(IMX_GPIO_NR(7, 11), 1);
return 0;
}
int zs_do_read_temp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
int temp, ret;
ret = epd_read_temp(&temp);
if (ret)
return ret;
printf("epd temperature: %d\n", temp);
return 0;
}
int epd_read_temp(int *temp)
{
int ret;
struct udevice *bus, *dev;
ret = uclass_get_device_by_seq(UCLASS_I2C, SY7636A_I2C_BUS, &bus);
if (ret) {
printf("%s: No bus %d\n", __func__, SY7636A_I2C_BUS);
return -1;
}
ret = dm_i2c_probe(bus, SY7636A_I2C_ADDR, 0, &dev);
if (ret) {
printf("%s: Can't find device id=0x%x, on bus %d\n",
__func__, SY7636A_I2C_ADDR, SY7636A_I2C_BUS);
return -1;
}
/* Read thermistor value */
return sy7636a_thermistor_get(dev, temp);
}
int zs_do_epd_power_on(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
@ -117,7 +168,6 @@ int zs_do_epd_power_on(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
u8 mask, val;
ulong vcom;
int ivcom;
int ret;
ret = uclass_get_device_by_seq(UCLASS_I2C, SY7636A_I2C_BUS, &bus);
@ -129,10 +179,11 @@ int zs_do_epd_power_on(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
ret = dm_i2c_probe(bus, SY7636A_I2C_ADDR, 0, &dev);
if (ret) {
printf("%s: Can't find device id=0x%x, on bus %d\n",
__func__, SY7636A_I2C_ADDR, SY7636A_I2C_BUS);
__func__, SY7636A_I2C_ADDR, SY7636A_I2C_BUS);
return -1;
}
/* Read initial vcom value */
ret = sy7636a_vcom_get(dev, &ivcom);
if (ret)
return ret;
@ -140,6 +191,7 @@ int zs_do_epd_power_on(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
vcom = env_get_ulong("vcom", 10, 1250);
printf("vcom was %dmV, setting to -%lumV\n", ivcom, vcom);
/* Set target vcom value */
ret = sy7636a_vcom_set(dev, vcom);
if (ret)
return ret;
@ -152,7 +204,13 @@ int zs_do_epd_power_on(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
}
U_BOOT_CMD(
epd_power_on, 1, 1, zs_do_epd_power_on,
"Turn on power for eInk Display",
""
);
epd_power_on, 1, 1, zs_do_epd_power_on,
"Turn on power for eInk Display",
""
);
U_BOOT_CMD(
epd_temp, 1, 1, zs_do_read_temp,
"Read epd temperature",
""
);

View File

@ -1,8 +1,9 @@
#ifndef EPD_INIT_H
#define EPD_INIT_H
#ifndef EPD_PMIC_INIT_H
#define EPD_PMIC_INIT_H
#include <command.h>
int epd_read_temp(int *temp);
extern int zs_do_config_epd_powerctrl_pins(void);
extern int zs_do_epd_power_on(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);

View File

@ -1,68 +0,0 @@
#include "lcd_init.h"
#include <asm/arch/sys_proto.h>
#include <asm/mach-imx/iomux-v3.h>
#include <asm/arch/mx7-pins.h>
#include <asm/mach-imx/video.h>
#define LCD_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PUS_PU100KOHM | PAD_CTL_DSE_3P3V_49OHM)
static iomux_v3_cfg_t const lcd_pads[] = {
MX7D_PAD_LCD_CLK__LCD_CLK | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_ENABLE__LCD_ENABLE | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_HSYNC__LCD_HSYNC | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_VSYNC__LCD_VSYNC | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA00__LCD_DATA0 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA01__LCD_DATA1 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA02__LCD_DATA2 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA03__LCD_DATA3 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA04__LCD_DATA4 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA05__LCD_DATA5 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA06__LCD_DATA6 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA07__LCD_DATA7 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA08__LCD_DATA8 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA09__LCD_DATA9 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA10__LCD_DATA10 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA11__LCD_DATA11 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA12__LCD_DATA12 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA13__LCD_DATA13 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA14__LCD_DATA14 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA15__LCD_DATA15 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA16__LCD_DATA16 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA17__LCD_DATA17 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA18__LCD_DATA18 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA19__LCD_DATA19 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA20__LCD_DATA20 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA21__LCD_DATA21 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA22__LCD_DATA22 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA23__LCD_DATA23 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_RESET__GPIO3_IO4 | MUX_PAD_CTRL(LCD_PAD_CTRL),
};
void do_enable_parallel_lcd(struct display_info_t const *dev)
{
imx_iomux_v3_setup_multiple_pads(lcd_pads, ARRAY_SIZE(lcd_pads));
}
struct display_info_t const displays[] = {{
.bus = ELCDIF1_IPS_BASE_ADDR,
.addr = 0,
.pixfmt = 24,
.detect = NULL,
.enable = do_enable_parallel_lcd,
.mode = {
.name = "TFT43AB",
.xres = 480,
.yres = 272,
.pixclock = 108695,
.left_margin = 8,
.right_margin = 4,
.upper_margin = 2,
.lower_margin = 4,
.hsync_len = 41,
.vsync_len = 10,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED
} } };
size_t display_count = ARRAY_SIZE(displays);

View File

@ -1,4 +0,0 @@
#ifndef LCD_INIT_H
#define LCD_INIT_H
#endif

View File

@ -1,5 +1,3 @@
#include "lcd_init.h"
#include <asm/arch/sys_proto.h>
#include <asm/gpio.h>

View File

@ -10,8 +10,8 @@
#include "wifi_init.h"
#include "uart_init.h"
#include "lcd_init.h"
#include "epd_init.h"
#include "epd_display_init.h"
#include "epd_pmic_init.h"
#include "touch_init.h"
#include "digitizer_init.h"
#include "charger_init.h"
@ -63,14 +63,16 @@ static void power_perfs(void)
printk("Powering up peripherals\n");
printf("----------------------------------------------\n");
/* Introduce a 1 sec delay before any powerup is done */
udelay(1000000);
/* EPD */
zs_do_config_epd_powerctrl_pins();
udelay(500000);
zs_do_epd_power_on(NULL, 0, 0, NULL);
udelay(500000);
udelay(10000);
/* enable display and run init sequence */
epd_display_init();
// Shutdown LCDIF
lcdif_power_down();
/* TOUCH */
zs_do_config_touch_powerctrl_pins();
@ -153,9 +155,17 @@ int board_late_init(void)
*/
clrsetbits_le16(&wdog->wcr, 0, 0x10);
init_charger();
init_charger();
probe_serial_download_trap();
/*
* Enable icache and dcache: we need this to be able to show splash
* screen.
*/
icache_enable();
dcache_enable();
power_perfs();
probe_serial_download_trap();
/* Try to store console log so far to mmc 0:1 */
// printf("Initializing dummy buffer to be written to file ..\n");
@ -169,5 +179,5 @@ int board_late_init(void)
// fat_fswrite_mem("uboot_console_log", &gd->console_out, 10);
// }
return 0;
return 0;
}

View File

@ -36,7 +36,7 @@ CONFIG_CMD_USB_MASS_STORAGE=y
CONFIG_CMD_DHCP=y
CONFIG_CMD_MII=y
CONFIG_CMD_PING=y
CONFIG_CMD_BMP=y
CONFIG_CMD_BMP=n
CONFIG_CMD_CACHE=y
CONFIG_CMD_PMIC=y
CONFIG_CMD_REGULATOR=y
@ -88,4 +88,7 @@ CONFIG_CI_UDC=y
CONFIG_USB_HOST_ETHER=y
CONFIG_USB_ETHER_ASIX=y
CONFIG_VIDEO=y
CONFIG_VIDEO_MXS=y
CONFIG_ERRNO_STR=y
CONFIG_CFB_CONSOLE=n
CONFIG_VIDEO_SW_CURSOR=n

View File

@ -35,6 +35,7 @@
#endif
#define PS2KHZ(ps) (1000000000UL / (ps))
#define NUM_BUFS 4
static GraphicDevice panel;
struct mxs_dma_desc desc;
@ -167,6 +168,9 @@ static void mxs_lcd_init(GraphicDevice *panel,
writel(panel->frameAdrs, &regs->hw_lcdif_cur_buf);
writel(panel->frameAdrs, &regs->hw_lcdif_next_buf);
/* Enable frame done irq */
writel(LCDIF_CTRL1_CUR_FRAME_DONE_IRQ_EN, &regs->hw_lcdif_ctrl1_set);
/* Flush FIFO first */
writel(LCDIF_CTRL1_FIFO_CLEAR, &regs->hw_lcdif_ctrl1_set);
@ -182,6 +186,38 @@ static void mxs_lcd_init(GraphicDevice *panel,
writel(LCDIF_CTRL_RUN, &regs->hw_lcdif_ctrl_set);
}
int mxs_pan(int buf)
{
struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)(ulong)(panel.isaBase);
const int frame_size = panel.plnSizeX * panel.plnSizeY * panel.gdfBytesPP;
unsigned int next_addr = panel.frameAdrs + buf * frame_size;
int timeout = 1000000;
// Set next pointer
writel(next_addr, &regs->hw_lcdif_next_buf);
// Wait until current frame is done
writel(LCDIF_CTRL1_CUR_FRAME_DONE_IRQ, &regs->hw_lcdif_ctrl1_clr);
while (--timeout) {
if (readl(&regs->hw_lcdif_ctrl1_reg) &
LCDIF_CTRL1_CUR_FRAME_DONE_IRQ) {
break;
}
udelay(1);
}
next_addr = panel.frameAdrs + (NUM_BUFS-1) * frame_size;
writel(next_addr, &regs->hw_lcdif_next_buf);
if (!timeout) {
printf("pan: timeout\n");
return -1;
}
return 0;
}
void lcdif_power_down(void)
{
struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)(ulong)(panel.isaBase);
@ -200,10 +236,14 @@ void lcdif_power_down(void)
writel(panel.frameAdrs, &regs->hw_lcdif_cur_buf_reg);
writel(panel.frameAdrs, &regs->hw_lcdif_next_buf_reg);
/* Enable vsync edge irq */
writel(LCDIF_CTRL1_VSYNC_EDGE_IRQ_EN, &regs->hw_lcdif_ctrl1_set);
writel(LCDIF_CTRL1_VSYNC_EDGE_IRQ, &regs->hw_lcdif_ctrl1_clr);
while (--timeout) {
if (readl(&regs->hw_lcdif_ctrl1_reg) &
LCDIF_CTRL1_VSYNC_EDGE_IRQ)
LCDIF_CTRL1_VSYNC_EDGE_IRQ)
break;
udelay(1);
}
@ -280,8 +320,7 @@ void *video_hw_init(void)
return NULL;
}
panel.memSize = mode.xres * mode.yres * panel.gdfBytesPP;
panel.memSize = NUM_BUFS * mode.xres * mode.yres * panel.gdfBytesPP;
/* Allocate framebuffer */
fb = memalign(ARCH_DMA_MINALIGN,

View File

@ -117,7 +117,7 @@
"fdt_file=/boot/zero-sugar.dtb\0" \
"fdt_addr=0x83000000\0" \
"ip_dyn=yes\0" \
"panel=TFT43AB\0" \
"panel=EPD\0" \
"mmcdev=0\0" \
"active_partition=2\0" \
"fallback_partition=3\0 " \

View File

@ -22,6 +22,9 @@ void mxs_lcd_get_panel(struct display_panel *panel);
void lcdif_power_down(void);
int mxs_lcd_panel_setup(struct fb_videomode mode, int bpp,
uint32_t base_addr);
int mxs_pan(int buf);
#endif
#endif /* __MXSFB_H__ */