blob: f0c1da33affc854ba1341913ddd9a06f25a5a7be [file]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#include <linux/init.h>
#include <linux/time.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/spinlock.h>
#include <linux/irq.h>
#include <linux/notifier.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>
#include <linux/sched/clock.h>
#include <linux/amlogic/media/vout/peripheral_lcd.h>
#include <linux/io.h>
#include "peripheral_lcd_drv.h"
#include "peripheral_lcd_dev.h"
#define CFG_WR_DATA_TOGETHER 1
#define CFG_VIRTUL_REG 1
#define CFG_RS_SEL_OUT (1)
static int init_flag;
static unsigned int vir_reg_pad_gpio0_o;
static void *vir_io_base;
static struct per_lcd_dev_config_s *dev_conf;
unsigned int rgb565_color_data[8] = {0xffff, 0xf800, 0x7e0, 0x7ff,
0xf81f, 0xffe0, 0x0000, 0x001f};
unsigned int rgb666_color_data[8] = {0x3ffff, 0x3f000, 0x00fc0, 0x00fff,
0x3f03f, 0x3ffc0, 0x00000, 0x0003f};
unsigned int rgb888_color_data[8] = {0xffffff, 0xff0000, 0x00ff00, 0x00ffff,
0xff00ff, 0xffff00, 0x000000, 0x0000ff};
unsigned long long test_t[3];
/**
* GPIO simulating intel 8080 8bits interface
*
* data 0 - 7:
* 0-1: gpioa_4-5
* 2-3: gpioa_10-11
* 4-7: gpioa_15-18
* cs: gpioa_0
* rd: gpioa_1
* rs: gpioa_9
* reset: gpioa_8
* wr: gpioa_14
*/
static inline void clrCS(void)
{
//CLR_CS;
#if (CFG_VIRTUL_REG)
vir_reg_pad_gpio0_o &= ~(1 << dev_conf->nCS_index);
writel(vir_reg_pad_gpio0_o, vir_io_base);
#else
per_lcd_gpio_set(dev_conf->nCS_index, 0);
#endif
};
static inline void setCS(void)
{
//SET_CS;
#if (CFG_VIRTUL_REG)
vir_reg_pad_gpio0_o |= 1 << dev_conf->nCS_index;
writel(vir_reg_pad_gpio0_o, vir_io_base);
#else
per_lcd_gpio_set(dev_conf->nCS_index, 1);
#endif
};
static inline void clrRESET(void)
{
//clrRESET();
#if (CFG_VIRTUL_REG)
vir_reg_pad_gpio0_o &= ~(1 << dev_conf->reset_index);
writel(vir_reg_pad_gpio0_o, vir_io_base);
#else
per_lcd_gpio_set(dev_conf->reset_index, 0);
#endif
};
static inline void setRESET(void)
{
//setRESET();
#if (CFG_VIRTUL_REG)
vir_reg_pad_gpio0_o |= 1 << dev_conf->reset_index;
writel(vir_reg_pad_gpio0_o, vir_io_base);
#else
per_lcd_gpio_set(dev_conf->reset_index, 1);
#endif
};
static inline void clrRS(void)
{
//CLR_RS;
#if (CFG_VIRTUL_REG)
vir_reg_pad_gpio0_o &= ~(1 << dev_conf->nRS_index);
writel(vir_reg_pad_gpio0_o, vir_io_base);
#else
per_lcd_gpio_set(dev_conf->nRS_index, 0);
#endif
};
static inline void setRS(void)
{
//setRS();
#if (CFG_VIRTUL_REG)
vir_reg_pad_gpio0_o |= 1 << dev_conf->nRS_index;
writel(vir_reg_pad_gpio0_o, vir_io_base);
#else
per_lcd_gpio_set(dev_conf->nRS_index, 1);
#endif
};
static inline void clrWR(void)
{
//clrWR();
#if (CFG_VIRTUL_REG)
vir_reg_pad_gpio0_o &= ~(1 << dev_conf->nWR_index);
writel(vir_reg_pad_gpio0_o, vir_io_base);
#else
per_lcd_gpio_set(dev_conf->nWR_index, 0);
#endif
};
static inline void setWR(void)
{
//setWR();
#if (CFG_VIRTUL_REG)
vir_reg_pad_gpio0_o |= 1 << dev_conf->nWR_index;
writel(vir_reg_pad_gpio0_o, vir_io_base);
#else
per_lcd_gpio_set(dev_conf->nWR_index, 1);
#endif
};
static inline void clrRD(void)
{
//clrRD();
#if (CFG_VIRTUL_REG)
vir_reg_pad_gpio0_o &= ~(1 << dev_conf->nRD_index);
writel(vir_reg_pad_gpio0_o, vir_io_base);
#else
per_lcd_gpio_set(dev_conf->nRD_index, 0);
#endif
};
static inline void setRD(void)
{
//setRD();
#if (CFG_VIRTUL_REG)
vir_reg_pad_gpio0_o |= 1 << dev_conf->nRD_index;
writel(vir_reg_pad_gpio0_o, vir_io_base);
#else
per_lcd_gpio_set(dev_conf->nRD_index, 1);
#endif
};
static inline void parallel_clk_direction(uint8_t dir)
{
#if (CFG_VIRTUL_REG)
if (dir)
vir_reg_pad_gpio0_o |= (1 << dev_conf->nRD_index) |
(1 << dev_conf->reset_index) |
(1 << dev_conf->nWR_index) |
(1 << dev_conf->nRS_index) |
(1 << dev_conf->nCS_index);
else
vir_reg_pad_gpio0_o &= ~((1 << dev_conf->nRD_index) |
(1 << dev_conf->reset_index) |
(1 << dev_conf->nWR_index) |
(1 << dev_conf->nRS_index) |
(1 << dev_conf->nCS_index));
writel(vir_reg_pad_gpio0_o, vir_io_base);
#else
per_lcd_gpio_set(dev_conf->reset_index, dir);
per_lcd_gpio_set(dev_conf->nRS_index, dir);
per_lcd_gpio_set(dev_conf->nRD_index, dir);
per_lcd_gpio_set(dev_conf->nWR_index, dir);
per_lcd_gpio_set(dev_conf->nCS_index, dir);
#endif
}
static inline void parallel_data_direction(uint8_t dir)
{
/* TODO: */
#if (CFG_VIRTUL_REG)
if (dir)
vir_reg_pad_gpio0_o |= (1 << dev_conf->data0_index) |
(1 << dev_conf->data1_index) |
(1 << dev_conf->data2_index) |
(1 << dev_conf->data3_index) |
(1 << dev_conf->data4_index) |
(1 << dev_conf->data5_index) |
(1 << dev_conf->data6_index) |
(1 << dev_conf->data7_index);
else
vir_reg_pad_gpio0_o &=
~((1 << dev_conf->data0_index) |
(1 << dev_conf->data1_index) |
(1 << dev_conf->data2_index) |
(1 << dev_conf->data3_index) |
(1 << dev_conf->data4_index) |
(1 << dev_conf->data5_index) |
(1 << dev_conf->data6_index) |
(1 << dev_conf->data7_index));
writel(vir_reg_pad_gpio0_o, vir_io_base);
#else
per_lcd_gpio_set(dev_conf->data0_index, dir);
per_lcd_gpio_set(dev_conf->data1_index, dir);
per_lcd_gpio_set(dev_conf->data2_index, dir);
per_lcd_gpio_set(dev_conf->data3_index, dir);
per_lcd_gpio_set(dev_conf->data4_index, dir);
LCDPR("%s: read gpio_reg:0x%x\n", __func__, vir_reg_pad_gpio0_o);
per_lcd_gpio_set(dev_conf->data5_index, dir);
per_lcd_gpio_set(dev_conf->data6_index, dir);
per_lcd_gpio_set(dev_conf->data7_index, dir);
#endif
}
static inline void parallel_data_set(unsigned char data)
{
unsigned int mask, val;
#if (CFG_VIRTUL_REG)
/* TODO */
mask = (0x1 << dev_conf->data0_index) |
(0x1 << dev_conf->data1_index) |
(0x1 << dev_conf->data2_index) |
(0x1 << dev_conf->data3_index) |
(0x1 << dev_conf->data4_index) |
(0x1 << dev_conf->data5_index) |
(0x1 << dev_conf->data6_index) |
(0x1 << dev_conf->data7_index);
val = ((data & 0x1) << dev_conf->data0_index) |
(((data >> 0x1) & 0x1) << dev_conf->data1_index) |
(((data >> 0x2) & 0x1) << dev_conf->data2_index) |
(((data >> 0x3) & 0x1) << dev_conf->data3_index) |
(((data >> 0x4) & 0x1) << dev_conf->data4_index) |
(((data >> 0x5) & 0x1) << dev_conf->data5_index) |
(((data >> 0x6) & 0x1) << dev_conf->data6_index) |
(((data >> 0x7) & 0x1) << dev_conf->data7_index);
vir_reg_pad_gpio0_o = ((vir_reg_pad_gpio0_o & (~mask)) | val);
writel(vir_reg_pad_gpio0_o, vir_io_base);
#else
/* TODO */
per_lcd_gpio_set(dev_conf->data0_index, data & 0x1);
per_lcd_gpio_set(dev_conf->data1_index,
(data >> 1) & 0x1);
per_lcd_gpio_set(dev_conf->data2_index,
(data >> 2) & 0x1);
per_lcd_gpio_set(dev_conf->data3_index,
(data >> 3) & 0x1);
per_lcd_gpio_set(dev_conf->data4_index,
(data >> 4) & 0x1);
per_lcd_gpio_set(dev_conf->data5_index,
(data >> 5) & 0x1);
per_lcd_gpio_set(dev_conf->data6_index,
(data >> 6) & 0x1);
per_lcd_gpio_set(dev_conf->data7_index,
(data >> 7) & 0x1);
#endif
}
#if (CFG_WR_DATA_TOGETHER)
static inline void parallel_data_wr_set(unsigned char data, unsigned char wr)
{
unsigned int mask, val;
/* TODO */
mask = (0x1 << dev_conf->data0_index) |
(0x1 << dev_conf->data1_index) |
(0x1 << dev_conf->data2_index) |
(0x1 << dev_conf->data3_index) |
(0x1 << dev_conf->data4_index) |
(0x1 << dev_conf->data5_index) |
(0x1 << dev_conf->data6_index) |
(0x1 << dev_conf->data7_index) |
(0x1 << dev_conf->nWR_index);
val = ((data & 0x1) << dev_conf->data0_index) |
(((data >> 0x1) & 0x1) << dev_conf->data1_index) |
(((data >> 0x2) & 0x1) << dev_conf->data2_index) |
(((data >> 0x3) & 0x1) << dev_conf->data3_index) |
(((data >> 0x4) & 0x1) << dev_conf->data4_index) |
(((data >> 0x5) & 0x1) << dev_conf->data5_index) |
(((data >> 0x6) & 0x1) << dev_conf->data6_index) |
(((data >> 0x7) & 0x1) << dev_conf->data7_index) |
((wr & 0x1) << dev_conf->nWR_index);
vir_reg_pad_gpio0_o = ((vir_reg_pad_gpio0_o & (~mask)) | val);
writel(vir_reg_pad_gpio0_o, vir_io_base);
}
#endif
static inline uint8_t parallel_data_get(void)
{
return 0;
}
static uint8_t read_data(void)
{
unsigned char data;
setRS();
/* Clear data */
parallel_data_set(0x00);
/* Set data to input */
parallel_data_direction(1);
clrRD();
per_lcd_delay_us(1);
setRD();
per_lcd_delay_us(10);
/* read from the port */
data = parallel_data_get();
/* Set data to output */
parallel_data_direction(0);
per_lcd_delay_us(10);
return data;
}
static void reset_display(void)
{
clrRESET();
per_lcd_delay_us(15);
setRESET();
per_lcd_delay_us(10);
setRD();
}
static void write_command(unsigned char command)
{
clrRS();
parallel_data_set(command & 0xFF);
clrWR();
setWR();
}
static void write_data(unsigned char data)
{
setRS();
setRD();
parallel_data_set(data & 0xFF);
clrWR();
setWR();
}
static void write_regs(unsigned char cmd, unsigned char *buf, unsigned int len)
{
int i;
write_command(cmd);
for (i = 0; i < len; i++)
write_data(buf[i]);
}
/* buf[0] is command
* buf[1] : buf[len-2] are datas
* len
*/
static void intel_8080_wreg_buf(unsigned char *buf, unsigned int len)
{
if (len == 1)
write_command(buf[0]);
else
write_regs(buf[0], &buf[1], len - 1);
}
static void write_block_888(unsigned int data)
{
#if (!CFG_RS_SEL_OUT)
setRS();
#endif
parallel_data_set((data >> 16) & 0xFF);
clrWR();
#if (!CFG_WR_DATA_TOGETHER)
setWR();
parallel_data_set((data >> 8) & 0xFF);
clrWR();
setWR();
parallel_data_set(data & 0xFF);
#else
parallel_data_wr_set((data >> 8) & 0xFF, 1);
clrWR();
parallel_data_wr_set(data & 0xFF, 1);
#endif
clrWR();
//udelay(1);
//udelay(1);
setWR();
}
static int frame_flush(void)
{
return 0;
}
static int set_color_format(unsigned int cfmt)
{
return 0;
}
static int set_gamma(unsigned char *table, unsigned int rgb_sel)
{
return 0;
}
static int set_flush_rate(unsigned int rate)
{
return 0;
}
static void write_color(unsigned int color)
{
#if (!CFG_RS_SEL_OUT)
setRS();
#endif
//udelay(1);
parallel_data_set((color >> 8) & 0xFF);
clrWR();
//udelay(1);
/* fixme */
#if (!CFG_WR_DATA_TOGETHER)
setWR();
parallel_data_set(color & 0xFF);
#else
parallel_data_wr_set(color & 0xFF, 1);
#endif
clrWR();
//udelay(1);
setWR();
}
static void set_intel_8080_display_window(unsigned short x0, unsigned short y0,
unsigned short x1, unsigned short y1)
{
write_command(0x2a); // Column Address Set
write_data(x0 >> 8); // X address start:
write_data(x0); // 0 <= XS <= X
write_data(x1 >> 8); // X address end:
write_data(x1); // S <= XE <= X
write_command(0x2b); // Row Address Set
write_data(y0 >> 8); // Y address start:
write_data(y0); // 0 <= YS <= Y
write_data(y1 >> 8); // Y address start:
write_data(y1); // S <= YE <= Y
/*This command is necessary to ensure*/
/*the addresses are set correctly, do not remove*/
write_command(0x2c); // Memory write
}
void display_home(void)
{
write_command(0x2c); // Memory write
// When this command is accepted, the column register and the page
// register are reset to the start column/start page positions.
}
void enter_sleep(void)
{
write_command(0x28); // Display Off
per_lcd_delay_us(20);
write_command(0x10); // Sleep In (Low power mode)
}
void exit_sleep(void)
{
write_command(0x11); // Exit Sleep Mode
per_lcd_delay_us(120);
write_command(0x29); // Display on
write_command(0x2c); // Memory write
// When this command is accepted, the column register and the page
// register are reset to the start column/start page positions.
}
void per_lcd_write_color(unsigned int *addr, unsigned short x0,
unsigned short x1, unsigned short y0,
unsigned short y1)
{
unsigned int i, j;
if (!addr) {
LCDERR("buff is null\n");
return;
}
set_intel_8080_display_window(x0, y0, (x1 - 1), (y1 - 1));
#if (CFG_RS_SEL_OUT)
setRS();
#endif
test_t[0] = sched_clock();
for (i = 0; i < (y1 - y0); i++)
for (j = 0; j < (x1 - x0); j++)
write_color(addr[i]);
test_t[1] = sched_clock();
test_t[2] = test_t[1] - test_t[0];
if (per_lcd_debug_flag)
LCDPR("%s: cast time: %lld\n", __func__, test_t[2]);
}
static void per_lcd_write_frame(unsigned char *addr, unsigned short x0,
unsigned short x1, unsigned short y0,
unsigned short y1)
{
unsigned int i, write_size;
unsigned int *buf;
unsigned int j = 0;
if (!addr) {
LCDERR("buff is null\n");
return;
}
set_intel_8080_display_window(x0, y0, (x1 - 1), (y1 - 1));
#if (CFG_RS_SEL_OUT)
setRS();
#endif
write_size = (x1 - x0) * (y1 - y0);
buf = kmalloc((sizeof(unsigned int) * write_size), GFP_KERNEL);
if (!buf) {
LCDERR("%s: failed to alloc buf\n", __func__);
return;
}
/*data_format: 0: 888, 1: 666, 2: 565*/
if (dev_conf->data_format == 0) {
for (i = 0; i < (write_size * 3); i += 3) {
buf[j] = (addr[i] & 0xff) |
((addr[i + 1] & 0xff) << 8) |
((addr[i + 2] & 0xff) << 16);
write_block_888(buf[j]);
j++;
}
} else if (dev_conf->data_format == 1) {
for (i = 0; i < (write_size * 3); i += 3) {
buf[j] = (addr[i] & 0xff) |
((addr[i + 1] & 0xff) << 8) |
((addr[i + 2] & 0x3) << 16);
write_block_888(buf[j]);
j++;
}
} else if (dev_conf->data_format == 2) {
for (i = 0; i < (write_size * 2); i += 2) {
buf[j] = (addr[i] & 0xff) |
((addr[i + 1] & 0xff) << 8);
write_color(buf[j]);
j++;
}
LCDPR("buf data: %x\n", buf[0]);
} else {
LCDERR("unsupport data_format: %d\n",
dev_conf->data_format);
}
kfree(buf);
buf = NULL;
}
static int frame_post(unsigned char *addr, unsigned short x0,
unsigned short x1, unsigned short y0, unsigned short y1)
{
if (!addr) {
LCDERR("buff is null\n");
return -1;
}
per_lcd_write_frame(addr, x0, x1, y0, y1);
return 0;
}
static void intel_8080_fill_screen_color(unsigned int index)
{
unsigned int *buf;
unsigned long c = 0;
unsigned int size;
int i = 0;
if (dev_conf->data_format == 0)
c = rgb888_color_data[index];
else if (dev_conf->data_format == 1)
c = rgb666_color_data[index];
else if (dev_conf->data_format == 2)
c = rgb565_color_data[i];
else
LCDERR("unsupport data_format\n");
size = dev_conf->row * dev_conf->col;
buf = kmalloc((sizeof(unsigned short) * size), GFP_KERNEL);
if (!buf) {
LCDERR("%s: failed to alloc buf\n", __func__);
return;
}
for (i = 0; i < size; i++)
buf[i] = c;
per_lcd_write_color(buf, 0, dev_conf->col, 0, dev_conf->row);
kfree(buf);
buf = NULL;
}
void read_ID(void)
{
unsigned char id[4] = {0, 0, 0, 0};
unsigned char x;
write_command(0x04);
for (x = 0; x < 4; x++)
id[x] = read_data();
LCDPR("ID: 0x%02x %02x %02x %02x\n", id[0], id[1], id[2], id[3]);
}
void intel_8080_write_color_bars(void)
{
unsigned int i, j;
unsigned int c0 = 0, c1 = 0, c2 = 0, c3 = 0;
unsigned int c4 = 0, c5 = 0, c6 = 0, c7 = 0;
set_intel_8080_display_window(0x0000, 0x0000, 0x00EF, 0x013F);
#if (CFG_RS_SEL_OUT)
setRS();
#endif
if (dev_conf->data_format == 0) {
c0 = rgb888_color_data[0];
c1 = rgb888_color_data[1];
c2 = rgb888_color_data[2];
c3 = rgb888_color_data[3];
c4 = rgb888_color_data[4];
c5 = rgb888_color_data[5];
c6 = rgb888_color_data[6];
c7 = rgb888_color_data[7];
} else if (dev_conf->data_format == 1) {
c0 = rgb666_color_data[0];
c1 = rgb666_color_data[1];
c2 = rgb666_color_data[2];
c3 = rgb666_color_data[3];
c4 = rgb666_color_data[4];
c5 = rgb666_color_data[5];
c6 = rgb666_color_data[6];
c7 = rgb666_color_data[7];
} else if (dev_conf->data_format == 2) {
c0 = rgb565_color_data[0];
c1 = rgb565_color_data[1];
c2 = rgb565_color_data[2];
c3 = rgb565_color_data[3];
c4 = rgb565_color_data[4];
c5 = rgb565_color_data[5];
c6 = rgb565_color_data[6];
c7 = rgb565_color_data[7];
} else {
LCDERR("unsupport data_format\n");
}
for (i = 0; i < 320; i++) {
for (j = 0; j < 240; j++) {
if (i > 279)
write_color(c7);
else if (i > 239)
write_color(c6);
else if (i > 199)
write_color(c5);
else if (i > 159)
write_color(c4);
else if (i > 119)
write_color(c3);
else if (i > 79)
write_color(c2);
else if (i > 39)
write_color(c1);
else
write_color(c0);
}
}
}
static int intel_8080_power_cmd_dynamic_size(int flag)
{
unsigned char *table;
int i = 0, j, step = 0, max_len = 0;
unsigned char type, cmd_size;
int delay_ms, ret = 0;
if (flag) {
table = dev_conf->init_on;
max_len = dev_conf->init_on_cnt;
} else {
table = dev_conf->init_off;
max_len = dev_conf->init_off_cnt;
}
while ((i + 1) < max_len) {
type = table[i];
if (type == PER_LCD_CMD_TYPE_END)
break;
if (per_lcd_debug_flag) {
LCDPR("%s: step %d: type=0x%02x, cmd_size=%d\n",
__func__, step, type, table[i + 1]);
}
cmd_size = table[i + 1];
if (cmd_size == 0)
goto power_cmd_dynamic_next;
if ((i + 2 + cmd_size) > max_len)
break;
if (type == PER_LCD_CMD_TYPE_NONE) {
/* do nothing */
} else if (type == PER_LCD_CMD_TYPE_GPIO) {
if (cmd_size < 2) {
LCDERR("step %d: invalid cmd_size %d for GPIO\n",
step, cmd_size);
goto power_cmd_dynamic_next;
}
if (table[i + 2] < PER_GPIO_MAX) {
#if (CFG_VIRTUL_REG)
if (table[i + 3])
vir_reg_pad_gpio0_o |=
1 << table[i + 2];
else
vir_reg_pad_gpio0_o &=
~(1 << table[i + 2]);
writel(vir_reg_pad_gpio0_o,
vir_io_base);
#else
per_lcd_gpio_set(table[i + 2],
table[i + 3]);
#endif
}
if (cmd_size > 2) {
if (table[i + 4] > 0)
per_lcd_delay_ms(table[i + 4]);
}
} else if (type == PER_LCD_CMD_TYPE_DELAY) {
delay_ms = 0;
for (j = 0; j < cmd_size; j++)
delay_ms += table[i + 2 + j];
if (delay_ms > 0)
per_lcd_delay_ms(delay_ms);
} else if (type == PER_LCD_CMD_TYPE_CMD) {
intel_8080_wreg_buf(&table[i + 2], cmd_size);
per_lcd_delay_us(1);
} else if (type == PER_LCD_CMD_TYPE_CMD_DELAY) {
intel_8080_wreg_buf(&table[i + 2], (cmd_size - 1));
per_lcd_delay_us(1);
if (table[i + cmd_size + 1] > 0)
per_lcd_delay_ms(table[i +
cmd_size + 1]);
} else {
LCDERR("%s: type 0x%02x invalid\n", __func__, type);
}
power_cmd_dynamic_next:
i += (cmd_size + 2);
step++;
}
return ret;
}
static int intel_8080_power_cmd_fixed_size(int flag)
{
unsigned char *table;
int i = 0, j, step = 0, max_len = 0;
unsigned char type, cmd_size;
int delay_ms, ret = 0;
cmd_size = dev_conf->cmd_size;
if (cmd_size < 2) {
LCDERR("%s: invalid cmd_size %d\n", __func__, cmd_size);
return -1;
}
if (flag) {
table = dev_conf->init_on;
max_len = dev_conf->init_on_cnt;
} else {
table = dev_conf->init_off;
max_len = dev_conf->init_off_cnt;
}
while ((i + cmd_size) <= max_len) {
type = table[i];
if (type == PER_LCD_CMD_TYPE_END)
break;
if (per_lcd_debug_flag) {
LCDPR("%s: step %d: type=0x%02x, cmd_size=%d\n",
__func__, step, type, cmd_size);
}
if (type == PER_LCD_CMD_TYPE_NONE) {
/* do nothing */
} else if (type == PER_LCD_CMD_TYPE_GPIO) {
if (table[i + 1] < PER_GPIO_MAX) {
#if (CFG_VIRTUL_REG)
if (table[i + 2])
vir_reg_pad_gpio0_o |=
1 << table[i + 1];
else
vir_reg_pad_gpio0_o &=
~(1 << table[i + 1]);
writel(vir_reg_pad_gpio0_o,
vir_io_base);
#else
per_lcd_gpio_set(table[i + 1],
table[i + 2]);
#endif
}
if (cmd_size > 3) {
if (table[i + 3] > 0)
per_lcd_delay_ms(table[i + 3]);
}
} else if (type == PER_LCD_CMD_TYPE_DELAY) {
delay_ms = 0;
for (j = 0; j < (cmd_size - 1); j++)
delay_ms += table[i + 1 + j];
if (delay_ms > 0)
per_lcd_delay_ms(delay_ms);
} else if (type == PER_LCD_CMD_TYPE_CMD) {
intel_8080_wreg_buf(&table[i + 1], (cmd_size - 1));
per_lcd_delay_us(1);
} else if (type == PER_LCD_CMD_TYPE_CMD_DELAY) {
intel_8080_wreg_buf(&table[i + 1], cmd_size);
if (table[i + cmd_size - 1] > 0)
per_lcd_delay_ms(table[i +
cmd_size - 1]);
} else {
LCDERR("%s: type 0x%02x invalid\n", __func__, type);
}
i += cmd_size;
step++;
}
return ret;
}
static void intel_8080_interface_init(void)
{
#if (CFG_VIRTUL_REG)
int i;
/*set all pins input*/
for (i = 0; i < dev_conf->max_gpio_num; i++)
per_lcd_gpio_set(i, 2);
vir_reg_pad_gpio0_o = readl(vir_io_base);
LCDPR("%s: read gpio_reg:0x%x\n", __func__, vir_reg_pad_gpio0_o);
/* set all pins output*/
for (i = 0; i < dev_conf->max_gpio_num; i++)
per_lcd_gpio_set(i, 0);
LCDPR("%s: read gpio_reg:0x%x\n", __func__, vir_reg_pad_gpio0_o);
#endif
}
static int intel_8080_power_on_init(void)
{
int ret = 0;
if (dev_conf->cmd_size < 1) {
LCDERR("%s: cmd_size %d is invalid\n",
__func__, dev_conf->cmd_size);
return -1;
}
if (!dev_conf->init_on) {
LCDERR("%s: init_data is null\n", __func__);
return -1;
}
intel_8080_interface_init();
if (dev_conf->cmd_size == PER_LCD_CMD_SIZE_DYNAMIC)
ret = intel_8080_power_cmd_dynamic_size(1);
else
ret = intel_8080_power_cmd_fixed_size(1);
init_flag = 1;
return ret;
}
static int intel_8080_test(const char *buf)
{
int ret;
unsigned int index;
switch (buf[0]) {
case 'i': /*id*/
intel_8080_power_on_init();
init_flag = 1;
read_ID();
break;
case 'c': /*color fill*/
if (!init_flag)
intel_8080_power_on_init();
ret = sscanf(buf, "color %d", &index);
intel_8080_fill_screen_color(index);
break;
case 'b': /*colorbar*/
if (!init_flag)
intel_8080_power_on_init();
intel_8080_write_color_bars();
break;
case 'r': /*reset*/
reset_display();
break;
default:
LCDPR("unsupport\n");
break;
}
return 0;
}
int intel_8080_clk_test(char *buf)
{
int ret, value, index;
switch (buf[0]) {
case 'r': /*rs*/
ret = sscanf(buf, "rs %d", &value);
if (value)
setRS();
else
clrRS();
LCDPR("set RS value: %d, read_gpio_reg:0x%x\n", value,
vir_reg_pad_gpio0_o);
break;
case 'w': /*WR*/
ret = sscanf(buf, "wr %d", &value);
if (value)
setWR();
else
clrWR();
LCDPR("set WR value: %d, read_gpio_reg:0x%x\n", value,
vir_reg_pad_gpio0_o);
break;
case 'd': /*RD*/
ret = sscanf(buf, "rd %d", &value);
if (value)
setRD();
else
clrRD();
LCDPR("set RD value: %d, read_gpio_reg:0x%x\n", value,
vir_reg_pad_gpio0_o);
break;
case 'c': /*CS*/
ret = sscanf(buf, "cs %d", &value);
if (value)
setCS();
else
clrCS();
LCDPR("set CS value: %d, read_gpio_reg:0x%x\n", value,
vir_reg_pad_gpio0_o);
break;
case 's': /*reset*/
ret = sscanf(buf, "set %d", &value);
if (value)
setRESET();
else
clrRESET();
LCDPR("set CS value: %d, read_gpio_reg:0x%x\n", value,
vir_reg_pad_gpio0_o);
break;
case 'i': /*index*/
ret = sscanf(buf, "index %d %d", &index, &value);
if (value)
vir_reg_pad_gpio0_o |= 1 << index;
else
vir_reg_pad_gpio0_o &= ~(1 << index);
writel(vir_reg_pad_gpio0_o, vir_io_base);
LCDPR("set index: %d value: %d, read_gpio_reg:0x%x\n",
index, value, vir_reg_pad_gpio0_o);
break;
default:
LCDPR("no support\n");
break;
}
return 0;
}
int per_lcd_dev_8080_probe(struct peripheral_lcd_driver_s *per_lcd_drv)
{
int ret;
dev_conf = per_lcd_drv->per_lcd_dev_conf;
per_lcd_drv->frame_post = frame_post;
per_lcd_drv->frame_flush = frame_flush;
per_lcd_drv->set_color_format = set_color_format;
per_lcd_drv->set_gamma = set_gamma;
per_lcd_drv->set_flush_rate = set_flush_rate;
per_lcd_drv->enable = intel_8080_power_on_init;
per_lcd_drv->test = intel_8080_test;
vir_io_base = per_lcd_drv->per_lcd_reg_map->p;
if (!vir_io_base) {
LCDERR("io base err, check reg\n");
return -1;
}
LCDPR("%s: io_base:0x%p", __func__, vir_io_base);
ret = intel_8080_power_on_init();
if (!ret)
intel_8080_fill_screen_color(0);
return 0;
}
int per_lcd_dev_8080_remove(struct peripheral_lcd_driver_s *per_lcd_drv)
{
return 0;
}