#include <linux/module.h>
#include <linux/init.h>
#include <linux/spi/spi.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#define WIDTH 240
#define HEIGHT 240
//画笔颜色
#define WHITE 0xFFFF
#define BLACK 0x0000
#define BLUE 0x001F
#define BRED 0XF81F
#define GRED 0XFFE0
#define GBLUE 0X07FF
#define RED 0xF800
#define MAGENTA 0xF81F
#define GREEN 0x07E0
#define CYAN 0x7FFF
#define YELLOW 0xFFE0
#define BROWN 0XBC40 //棕色
#define BRRED 0XFC07 //棕红色
#define GRAY 0X8430 //灰色
#define DAT 1
#define CMD 0
#define MY_BUS_NUM 1
static struct spi_device *st7789_dev;
typedef struct
{
uint8_t cmd;
uint8_t data[16];
uint8_t databytes; //The number of data in data[]; bit 7 = delay flag after set; 0xFF = end of cmds.
} lcd_init_cmd_t;
static struct gpio_desc *gpio_reset;
static struct gpio_desc *gpio_dc;
static struct gpio_desc *gpio_blk;
/* 向IPS写入一个字节 com: 1 数据 0:命令 */
void ips_write_byte(uint8_t com, uint8_t dat)
{
gpiod_set_value(gpio_dc, com ? 1 : 0);
spi_write(st7789_dev, &dat, 1);
}
static inline void ips_write_dat(uint8_t *dat, int len)
{
gpiod_set_value(gpio_dc, DAT);
spi_write(st7789_dev, dat, len);
}
void ips_pos_set(uint16_t x0,uint16_t y0,uint16_t x1,uint16_t y1)
{
uint8_t dat1[4] = {
x0>>8, x0, x1>>8, x1
};
uint8_t dat2[4] = {
y0>>8, y0, y1>>8, y1
};
ips_write_byte(CMD,0x2a);
ips_write_dat(dat1, 4);
ips_write_byte(CMD,0x2b);
ips_write_dat(dat2, 4);
ips_write_byte(CMD,0x2C);
}
static uint16_t buffer[WIDTH * HEIGHT];
/* IPS清屏 */
void ips_clear_all(uint16_t color)
{
uint16_t i,j;
ips_pos_set(0,0,WIDTH-1,HEIGHT-1);
for(i=0;i<WIDTH;i++)
for (j=0;j<HEIGHT;j++)
{
buffer[i * WIDTH + j] = color >> 8 | color << 8;
}
ips_write_dat((uint8_t*)buffer, sizeof(buffer));
}
static lcd_init_cmd_t init_cmds[] = {
{0x01, {0x00}, 0x80}, // Power Control 1
{0x11, {0x00}, 0x80}, // Power Control 2
{0x3A, {0x05}, 1}, // VCOM Control 1
{0x36, {0x00}, 1}, // VCOM Control 2 // (C0/00/A0/60)
{0x21, {0x00}, 0x80}, // Display Inversion OFF
{0x13, {0x00}, 0x80}, // Frame Rate Control
{0x2A, {0x00, 0x00, 0x00, 0xEF}, 4}, // Memory Access Control
{0x2B, {0x00, 0x00, 0x00, 0xEF}, 4}, // Pixel Format Set
{0x29, {0x00}, 0x80}, // Display ON
{0, {0}, 0xff}
};
static int st7789v_probe(struct spi_device *spi)
{
int i;
st7789_dev = spi;
st7789_dev->bits_per_word = 8;
gpio_reset = gpiod_get(&spi->dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(gpio_reset)) {
dev_err(&spi->dev, "Couldn't get our reset line\n");
return PTR_ERR(gpio_reset);
}
gpio_dc = gpiod_get(&spi->dev, "dc", GPIOD_OUT_HIGH);
if (IS_ERR(gpio_dc)) {
dev_err(&spi->dev, "Couldn't get our dc line\n");
return PTR_ERR(gpio_dc);
}
gpio_blk = gpiod_get(&spi->dev, "blk", GPIOD_OUT_HIGH);
if (IS_ERR(gpio_blk)) {
dev_err(&spi->dev, "Couldn't get our blk line\n");
return PTR_ERR(gpio_blk);
}
gpiod_set_value(gpio_reset, 1);
mdelay(200);
gpiod_set_value(gpio_reset, 0);
mdelay(200);
gpiod_set_value(gpio_reset, 1);
mdelay(200);
gpiod_set_value(gpio_blk, 1);
for (i = 0; init_cmds[i].databytes != 0xff; i++)
{
ips_write_byte(CMD, init_cmds[i].cmd);
if (init_cmds[i].databytes & 0x1F)
ips_write_dat(init_cmds[i].data, init_cmds[i].databytes & 0x1F);
}
for ( i = 0; i < 100; i++)
{
ips_clear_all(RED);
ips_clear_all(BLUE);
}
printk("Hello, Kernel!\n");
return 0;
}
static int st7789v_remove(struct spi_device *spi) {
return 0;
}
static const struct of_device_id st7789v_of_match[] = {
{ .compatible = "mydev,st7789v" },
{ }
};
MODULE_DEVICE_TABLE(of, st7789v_of_match);
static struct spi_driver st7789v_driver = {
.probe = st7789v_probe,
.remove = st7789v_remove,
.driver = {
.name = "st7789v",
.of_match_table = st7789v_of_match,
},
};
module_spi_driver(st7789v_driver);
MODULE_LICENSE("GPL");
// 在 spi 节点下
mydev@0 {
compatible = "mydev,st7789v";
reg = <0>;
reset-gpios = <&pio 4 5 GPIO_ACTIVE_HIGH>; /* PE5 */
dc-gpios = <&pio 4 4 GPIO_ACTIVE_HIGH>; /* PE4 */
blk-gpios = <&pio 4 3 GPIO_ACTIVE_HIGH>; /* PE3 */
spi-max-frequency = <40000000>;
spi-cpol;
spi-cpha;
};
网友评论