ODROID-XU4: add fbtft_device(ODROID TFT35 driver)

Change-Id: I5acded855e96b83eeae7d98a30c789a07c1d8044
This commit is contained in:
charles.park
2017-01-19 17:18:35 +09:00
parent b2bc11d8fb
commit 2147eecf3f
2 changed files with 164 additions and 13 deletions

View File

@@ -549,20 +549,22 @@ static struct fbtft_device_display displays[] = {
.dev = {
.release = fbtft_device_pdev_release,
.platform_data = &(struct fbtft_platform_data) {
/* for ODROID TFT35(ili9488) */
.bgr = true,
.gpios = (const struct fbtft_gpio []) {
{ "reset", 17 },
{ "dc", 1 },
{ "wr", 0 },
{ "cs", 21 },
{ "db00", 9 },
{ "db01", 11 },
{ "db02", 18 },
{ "db03", 23 },
{ "db04", 24 },
{ "db05", 25 },
{ "db06", 8 },
{ "db07", 7 },
{ "led", 4 },
{ "reset", 174 }, /* GPA0.3 */
{ "dc", 28 }, /* GPX2.4 */
{ "wr", 190 }, /* GPA2.5 */
{ "cs", 173 }, /* GPA0.2 */
{ "db00", 23 }, /* GPX1.7 */
{ "db01", 24 }, /* GPX2.0 */
{ "db02", 19 }, /* GPX1.3 */
{ "db03", 189 }, /* GPA2.4 */
{ "db04", 191 }, /* GPA2.6 */
{ "db05", 192 }, /* GPA2.7 */
{ "db06", 22 }, /* GPX1.6 */
{ "db07", 21 }, /* GPX1.5 */
{ "led", 31 }, /* GPX2.7 */
{},
},
},

149
drivers/staging/fbtft/flexfb.c Normal file → Executable file
View File

@@ -126,6 +126,23 @@ static int ssd1351_init[] = { -1, 0xfd, 0x12, -1, 0xfd, 0xb1, -1, 0xae, -1, 0xb3
-1, 0xab, 0x01, -1, 0xb1, 0x32, -1, 0xb4, 0xa0, 0xb5, 0x55, -1, 0xbb, 0x17, -1, 0xbe, 0x05,
-1, 0xc1, 0xc8, 0x80, 0xc8, -1, 0xc7, 0x0f, -1, 0xb6, 0x01, -1, 0xa6, -1, 0xaf, -3 };
/* for ODROID TFT35 LCD */
static int ili9488_init[] = {
-1, 0xB0,0x00,
-1, 0x11,
-2, 120,
-1, 0x3A,0x55,
-1, 0xC2,0x33,
-1, 0xC5,0x00,0x1E,0x80,
-1, 0x36,0x28,
-1, 0xB1,0xB0,
-1, 0xE0,0x00,0x04,0x0E,0x08,0x17,0x0A,0x40,0x79,0x4D,0x07,0x0E,0x0A,0x1A,0x1D,0x0F,
-1, 0xE1,0x00,0x1B,0x1F,0x02,0x10,0x05,0x32,0x34,0x43,0x02,0x0A,0x09,0x33,0x37,0x0F,
-1, 0x11,
-1, 0x29,
-3
};
/**
* struct flexfb_lcd_controller - Describes the LCD controller properties
* @name: Model name of the chip
@@ -227,8 +244,118 @@ static const struct flexfb_lcd_controller flexfb_chip_table[] = {
.init_seq = ssd1351_init,
.init_seq_sz = ARRAY_SIZE(ssd1351_init),
},
/* for ODROID TFT35 LCD */
{
.name = "ili9488",
.width = 320,
.height = 480,
.setaddrwin = 0,
.init_seq = ili9488_init,
.init_seq_sz = ARRAY_SIZE(ili9488_init),
},
};
/* for ODROID TFT32 LCD(ili9488) */
#define ODROIDXU3_GPX1_REG 0x13400C24
#define ODROIDXU3_GPX2_REG 0x13400C44
#define ODROIDXU3_GPA2_REG 0x14010044
union reg_bitfield {
unsigned int wvalue;
struct {
unsigned int bit0 : 1;
unsigned int bit1 : 1;
unsigned int bit2 : 1;
unsigned int bit3 : 1;
unsigned int bit4 : 1;
unsigned int bit5 : 1;
unsigned int bit6 : 1;
unsigned int bit7 : 1;
unsigned int bit8_bit31 : 24;
} bits;
};
volatile void __iomem *reg_gpx1;
volatile void __iomem *reg_gpx2;
volatile void __iomem *reg_gpa2;
static int write_reg_wr_ili9488(struct fbtft_par *par, void *buf, size_t len)
{
u8 data;
union reg_bitfield gpx1, gpx2, gpa2;
if ((reg_gpx1 == NULL) || (reg_gpx2 == NULL) || (reg_gpa2 == NULL)) {
pr_err("%s : ioremap gpio register fail!\n", __func__);
return 0;
}
gpx1.wvalue = ioread32(reg_gpx1);
gpx2.wvalue = ioread32(reg_gpx2);
gpa2.wvalue = ioread32(reg_gpa2);
while (len--) {
data = *(u8 *) buf;
gpx1.bits.bit7 = (data & 0x01) ? 1 : 0;
gpx2.bits.bit0 = (data & 0x02) ? 1 : 0;
gpx1.bits.bit3 = (data & 0x04) ? 1 : 0;
gpa2.bits.bit4 = (data & 0x08) ? 1 : 0;
gpa2.bits.bit6 = (data & 0x10) ? 1 : 0;
gpa2.bits.bit7 = (data & 0x20) ? 1 : 0;
gpx1.bits.bit6 = (data & 0x40) ? 1 : 0;
gpx1.bits.bit5 = (data & 0x80) ? 1 : 0;
/* Start writing by pulling down /WR */
gpa2.bits.bit5 = 0;
iowrite32(gpx1.wvalue, reg_gpx1);
iowrite32(gpx2.wvalue, reg_gpx2);
iowrite32(gpa2.wvalue, reg_gpa2);
gpa2.bits.bit5 = 1;
iowrite32(gpa2.wvalue, reg_gpa2);
buf++;
}
return 0;
}
static void set_addr_win_ili9488(struct fbtft_par *par, int xs, int ys, int xe, int ye)
{
/* Column address */
write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF);
/* Row adress */
write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF);
/* Memory write */
write_reg(par, 0x2C);
}
#define ODROID_TFT35_MACTL_MV 0x20
#define ODROID_TFT35_MACTL_MX 0x40
#define ODROID_TFT35_MACTL_MY 0x80
static int set_var_ili9488(struct fbtft_par *par)
{
u8 val;
switch (par->info->var.rotate) {
case 270:
val = ODROID_TFT35_MACTL_MV;
break;
case 180:
val = ODROID_TFT35_MACTL_MY;
break;
case 90:
val = ODROID_TFT35_MACTL_MV | ODROID_TFT35_MACTL_MX | ODROID_TFT35_MACTL_MY;
break;
default:
val = ODROID_TFT35_MACTL_MX;
break;
}
/* Memory Access Control */
write_reg(par, 0x36, val | (par->bgr << 3));
return 0;
}
/* ili9320, ili9325 */
static void flexfb_set_addr_win_1(struct fbtft_par *par,
int xs, int ys, int xe, int ye)
@@ -518,6 +645,21 @@ static int flexfb_probe_common(struct spi_device *sdev,
if (!nobacklight)
par->fbtftops.register_backlight = fbtft_register_backlight;
/* for ODROID TFT35 LCD(ili9488) */
if (!strcmp(chip, "ili9488")) {
reg_gpx1 = ioremap(ODROIDXU3_GPX1_REG, 4);
reg_gpx2 = ioremap(ODROIDXU3_GPX2_REG, 4);
reg_gpa2 = ioremap(ODROIDXU3_GPA2_REG, 4);
if ((reg_gpx1 == NULL) || (reg_gpx2 == NULL) || (reg_gpa2 == NULL))
pr_err("%s : ioremap gpiox register error!\n", __func__);
else {
pr_err("%s : ioremap gpiox register success!\n", __func__);
par->fbtftops.write = write_reg_wr_ili9488;
par->fbtftops.set_addr_win = set_addr_win_ili9488;
par->fbtftops.set_var = set_var_ili9488;
}
}
ret = fbtft_register_framebuffer(info);
if (ret < 0)
goto out_release;
@@ -540,6 +682,13 @@ static int flexfb_remove_common(struct device *dev, struct fb_info *info)
if (par)
fbtft_par_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, par, "%s()\n",
__func__);
if (!strcmp(chip, "ili9488")) {
if (reg_gpx1) iounmap(reg_gpx1);
if (reg_gpx2) iounmap(reg_gpx2);
if (reg_gpa2) iounmap(reg_gpa2);
}
fbtft_unregister_framebuffer(info);
fbtft_framebuffer_release(info);