linux4.15内核ILI9341LCD屏并口16线RGB565驱动
设备树配置
spidev3@0x33 {
compatible = "ilitek,ili9341";
spi-max-frequency = <8000000>;
buswidth = <9>;
bgr = <0>;
reg = <0>;
reset = <&gpio5 3 0>;
};
timing3: timing3 {
clock-frequency = <6100000>;
hactive = <240>;
vactive = <320>;
hfront-porch = <10>;
hback-porch = <20>;
hsync-len = <10>;
vback-porch = <2>;
vfront-porch = <4>;
vsync-len = <2>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <1>;
pixelclk-active = <0>;
};
驱动源码
#include <linux/uaccess.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/spi/spi.h>
#include <linux/of_gpio.h>
#include <linux/spi/spidev.h>
#include <linux/device.h>
#define ILI9341_RGB_INTERFACE 0xb0
#define ILI9341_FRC 0xb1
#define ILI9341_DFC 0xb6
#define ILI9341_POWER1 0xc0
#define ILI9341_POWER2 0xc1
#define ILI9341_VCOM1 0xc5
#define ILI9341_VCOM2 0xc7
#define ILI9341_POWERA 0xcb
#define ILI9341_POWERB 0xcf
#define ILI9341_PGAMMA 0xe0
#define ILI9341_NGAMMA 0xe1
#define ILI9341_DTCA 0xe8
#define ILI9341_DTCB 0xea
#define ILI9341_POWER_SEQ 0xed
#define ILI9341_3GAMMA_EN 0xf2
#define ILI9341_INTERFACE 0xf6
#define ILI9341_PRC 0xf7
#define ILI9341_ETMOD 0xb7
#define ILI9341_MADCTL_BGR BIT(3)
#define ILI9341_MADCTL_MV BIT(5)
#define ILI9341_MADCTL_MX BIT(6)
#define ILI9341_MADCTL_MY BIT(7)
#define ILI9341_POWER_B_LEN 3
#define ILI9341_POWER_SEQ_LEN 4
#define ILI9341_DTCA_LEN 3
#define ILI9341_DTCB_LEN 2
#define ILI9341_POWER_A_LEN 5
#define ILI9341_DFC_1_LEN 2
#define ILI9341_FRC_LEN 2
#define ILI9341_VCOM_1_LEN 2
#define ILI9341_DFC_2_LEN 4
#define ILI9341_COLUMN_ADDR_LEN 4
#define ILI9341_PAGE_ADDR_LEN 4
#define ILI9341_INTERFACE_LEN 3
#define ILI9341_PGAMMA_LEN 15
#define ILI9341_NGAMMA_LEN 15
#define ILI9341_CA_LEN 3
#define ILI9341_PIXEL_DPI_16_BITS (BIT(6) | BIT(4))
#define ILI9341_PIXEL_DPI_18_BITS (BIT(6) | BIT(5))
#define ILI9341_GAMMA_CURVE_1 BIT(0)
#define ILI9341_IF_WE_MODE BIT(0)
#define ILI9341_IF_BIG_ENDIAN 0x00
#define ILI9341_IF_DM_RGB BIT(2)
#define ILI9341_IF_DM_INTERNAL 0x00
#define ILI9341_IF_DM_VSYNC BIT(3)
#define ILI9341_IF_RM_RGB BIT(1)
#define ILI9341_IF_RIM_RGB 0x00
#define ILI9341_COLUMN_ADDR 0x00ef
#define ILI9341_PAGE_ADDR 0x013f
#define ILI9341_RGB_EPL BIT(0)
#define ILI9341_RGB_DPL BIT(1)
#define ILI9341_RGB_HSPL BIT(2)
#define ILI9341_RGB_VSPL BIT(3)
#define ILI9341_RGB_DE_MODE BIT(6)
#define ILI9341_RGB_DISP_PATH_MEM BIT(7)
#define ILI9341_DBI_VCOMH_4P6V 0x23
#define ILI9341_DBI_PWR_2_DEFAULT 0x10
#define ILI9341_DBI_PRC_NORMAL 0x20
#define ILI9341_DBI_VCOM_1_VMH_4P25V 0x3e
#define ILI9341_DBI_VCOM_1_VML_1P5V 0x28
#define ILI9341_DBI_VCOM_2_DEC_58 0x86
#define ILI9341_DBI_FRC_DIVA 0x00
#define ILI9341_DBI_FRC_RTNA 0x1b
#define ILI9341_DBI_EMS_GAS BIT(0)
#define ILI9341_DBI_EMS_DTS BIT(1)
#define ILI9341_DBI_EMS_GON BIT(2)
#define NUMARGS(...) (sizeof((int[]){__VA_ARGS__})/sizeof(int))
#define ili9341_spi_write(spidev, ...) \
__ili9341_spi_write(spidev, NUMARGS(__VA_ARGS__), __VA_ARGS__)
static void __ili9341_spi_write(struct spi_device *spi, int len, ...)
{
va_list args;
unsigned short tmp[256] = {0};
unsigned short *buf = tmp;
struct spi_message m;
struct spi_transfer t = {
.tx_buf = tmp,
.len = len*2,
};
int i,ret;
if(len <= 0 )
return;
va_start(args, len);
*buf++ = (u8)va_arg(args, unsigned int);
i = len - 1;
while (i--) {
*buf = (u8)va_arg(args, unsigned int);
*buf++ |= 0x100;
}
va_end(args);
spi_message_init(&m);
spi_message_add_tail(&t,&m);
ret = spi_sync(spi, &m);
if(ret)
printk("%s ret=%d\n",__func__,ret);
}
static int ili9341_probe(struct spi_device *spi)
{
struct spi_device *spidev;
struct device_node *np = spi->dev.of_node;
int reset;
int err = -1;
spidev = spi;
spidev->bits_per_word = 9;
err = spi_setup(spidev);
reset = of_get_named_gpio(np, "reset", 0);
if (reset < 0)
{
printk("reset gpio error\n");
return -1;
}
if(gpio_request(reset, "reset") < 0)
{
printk("lcd gpio_request error\n");
return -1;
}
if(gpio_direction_output(reset, 1) < 0)
{
printk("lcd gpio_direction_output error\n");
gpio_free(reset);
return -1;
}
gpio_set_value(reset, 0);
udelay(10);
gpio_set_value(reset, 1);
mdelay(1);
gpio_set_value(reset, 0);
mdelay(1);
gpio_set_value(reset, 1);
ili9341_spi_write(spidev, 0x01);
mdelay(5);
ili9341_spi_write(spidev, 0x28);
ili9341_spi_write(spidev, 0xca, 0xc3, 0x08, 0x50);
ili9341_spi_write(spidev, ILI9341_POWERB, 0x00, 0xc1, 0x30);
ili9341_spi_write(spidev, ILI9341_POWER_SEQ, 0x64, 0x03, 0x12, 0x81);
ili9341_spi_write(spidev, ILI9341_DTCA, 0x85, 0x00, 0x78);
ili9341_spi_write(spidev, ILI9341_POWERA, 0x39, 0x2c, 0x00, 0x34, 0x02);
ili9341_spi_write(spidev, ILI9341_PRC, 0x20);
ili9341_spi_write(spidev, ILI9341_DTCB, 0x00, 0x00);
ili9341_spi_write(spidev, ILI9341_FRC, 0x00, 0x1b);
ili9341_spi_write(spidev, ILI9341_DFC, 0x0a, 0xa2);
ili9341_spi_write(spidev, ILI9341_POWER1, 0x10);
ili9341_spi_write(spidev, ILI9341_POWER2, 0x10);
ili9341_spi_write(spidev, ILI9341_VCOM1, 0x45, 0x15);
ili9341_spi_write(spidev, ILI9341_VCOM2, 0x90);
ili9341_spi_write(spidev, 0x36, 0xc8);
ili9341_spi_write(spidev, ILI9341_3GAMMA_EN, 0x00);
ili9341_spi_write(spidev, ILI9341_RGB_INTERFACE, ILI9341_RGB_DISP_PATH_MEM | ILI9341_RGB_DE_MODE | ILI9341_RGB_DPL);
ili9341_spi_write(spidev, ILI9341_DFC, 0x0a, 0xa7, 0x27, 0x04);
ili9341_spi_write(spidev, 0x2a, 0x00, 0x00, (ILI9341_COLUMN_ADDR >> 4) & 0xff, ILI9341_COLUMN_ADDR & 0xff);
ili9341_spi_write(spidev, 0x2b, 0x00, 0x00, (ILI9341_PAGE_ADDR >> 4) & 0xff, ILI9341_PAGE_ADDR & 0xff);
ili9341_spi_write(spidev, ILI9341_INTERFACE, ILI9341_IF_WE_MODE, 0x00, ILI9341_IF_DM_RGB | ILI9341_IF_RM_RGB);
ili9341_spi_write(spidev, 0x3a, ILI9341_PIXEL_DPI_16_BITS);
ili9341_spi_write(spidev, 0x2c);
ili9341_spi_write(spidev, 0x26, ILI9341_GAMMA_CURVE_1);
ili9341_spi_write(spidev, ILI9341_PGAMMA, 0x0f, 0x29, 0x24, 0x0c, 0x0e,0x09, 0x4e, 0x78, 0x3c, 0x09,0x13, 0x05, 0x17, 0x11, 0x00);
ili9341_spi_write(spidev, ILI9341_NGAMMA, 0x00, 0x16, 0x1b, 0x04, 0x11, 0x07, 0x31, 0x33, 0x42, 0x05, 0x0c, 0x0a, 0x28, 0x2f, 0x0f);
ili9341_spi_write(spidev, 0x11);
mdelay(20);
ili9341_spi_write(spidev, 0x29);
ili9341_spi_write(spidev, 0x2c);
return 0;
}
static int ili9341_remove(struct spi_device *spi)
{
return 0;
}
static const struct of_device_id ili9341_of_match[] = {
{ .compatible = "ilitek,ili9341" },
{ }
};
MODULE_DEVICE_TABLE(of, ili9341_of_match);
static struct spi_driver ili9341_driver = {
.probe = ili9341_probe,
.remove = ili9341_remove,
.driver = {
.name = "ili9341",
.owner = THIS_MODULE,
.of_match_table = ili9341_of_match,
},
};
module_spi_driver(ili9341_driver);
MODULE_DESCRIPTION("ILITEK ILI9341 Init");
MODULE_LICENSE("GPL v2");
参考资料
资料