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
parent
bbd1774489
commit
cd10002e83
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef EPD_DISPLAY_INIT_H
|
||||
#define EPD_DISPLAY_INIT_H
|
||||
|
||||
int epd_display_init(void);
|
||||
|
||||
#endif
|
|
@ -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",
|
||||
""
|
||||
);
|
|
@ -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[]);
|
||||
|
|
@ -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);
|
|
@ -1,4 +0,0 @@
|
|||
#ifndef LCD_INIT_H
|
||||
#define LCD_INIT_H
|
||||
|
||||
#endif
|
|
@ -1,5 +1,3 @@
|
|||
#include "lcd_init.h"
|
||||
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include <asm/gpio.h>
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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, ®s->hw_lcdif_cur_buf);
|
||||
writel(panel->frameAdrs, ®s->hw_lcdif_next_buf);
|
||||
|
||||
/* Enable frame done irq */
|
||||
writel(LCDIF_CTRL1_CUR_FRAME_DONE_IRQ_EN, ®s->hw_lcdif_ctrl1_set);
|
||||
|
||||
/* Flush FIFO first */
|
||||
writel(LCDIF_CTRL1_FIFO_CLEAR, ®s->hw_lcdif_ctrl1_set);
|
||||
|
||||
|
@ -182,6 +186,38 @@ static void mxs_lcd_init(GraphicDevice *panel,
|
|||
writel(LCDIF_CTRL_RUN, ®s->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, ®s->hw_lcdif_next_buf);
|
||||
|
||||
// Wait until current frame is done
|
||||
writel(LCDIF_CTRL1_CUR_FRAME_DONE_IRQ, ®s->hw_lcdif_ctrl1_clr);
|
||||
while (--timeout) {
|
||||
if (readl(®s->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, ®s->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, ®s->hw_lcdif_cur_buf_reg);
|
||||
writel(panel.frameAdrs, ®s->hw_lcdif_next_buf_reg);
|
||||
|
||||
/* Enable vsync edge irq */
|
||||
writel(LCDIF_CTRL1_VSYNC_EDGE_IRQ_EN, ®s->hw_lcdif_ctrl1_set);
|
||||
|
||||
writel(LCDIF_CTRL1_VSYNC_EDGE_IRQ, ®s->hw_lcdif_ctrl1_clr);
|
||||
while (--timeout) {
|
||||
if (readl(®s->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,
|
||||
|
|
|
@ -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 " \
|
||||
|
|
|
@ -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__ */
|
||||
|
|
Loading…
Reference in New Issue