Linux 驱动开发5: SPI-LCD

2022-08-08  本文已影响0人  wjundong
#include <linux/module.h>
#include <linux/init.h>
#include <linux/spi/spi.h>
#include <linux/gpio.h>
#include <linux/delay.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 //灰色

MODULE_LICENSE("GPL");

#define DAT 1
#define CMD 0

#define MY_BUS_NUM 1
static struct spi_device *st7789_dev;

// pin 138 (PE10): (MUX UNCLAIMED) 1c20800.pinctrl:138
// pin 139 (PE11): (MUX UNCLAIMED) 1c20800.pinctrl:139
// pin 140 (PE12): (MUX UNCLAIMED) 1c20800.pinctrl:140

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;

#define GPIO_RES 138
#define GPIO_BLK 139
#define GPIO_DC 140

/* 向IPS写入一个字节 com: 1 数据 0:命令 */
void ips_write_byte(uint8_t com, uint8_t dat)
{
    gpio_set_value(GPIO_DC, com ? 1 : 0);

    spi_write(st7789_dev, &dat, 1);
}

static inline void ips_write_dat(uint8_t *dat, int len)
{
    gpio_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));
}

/**
 * @brief This function is called, when the module is loaded into the kernel
 */
static int __init mydev_init(void)
{
    struct spi_master *master;
    int i = 0;

    /* Parameters for SPI device */
    struct spi_board_info spi_device_info = {
        .modalias = "st7789",
        .max_speed_hz = 60*1000*1000,
        .bus_num = MY_BUS_NUM,
        .chip_select = 0,
        .mode = 3,
    };

    /* Get access to spi bus */
    master = spi_busnum_to_master(MY_BUS_NUM);
    /* Check if we could get the master */
    if (!master)
    {
        printk("There is no spi bus with Nr. %d\n", MY_BUS_NUM);
        return -1;
    }

    /* Create new SPI device */
    st7789_dev = spi_new_device(master, &spi_device_info);
    if (!st7789_dev)
    {
        printk("Could not create device!\n");
        return -1;
    }

    st7789_dev->bits_per_word = 8;

    /* Setup the bus for device's parameters */
    if (spi_setup(st7789_dev) != 0)
    {
        printk("Could not change bus setup!\n");
        spi_unregister_device(st7789_dev);
        return -1;
    }

    gpio_request(GPIO_RES, "");
    gpio_direction_output(GPIO_RES, 1);
    mdelay(200);
    gpio_set_value(GPIO_RES, 0);
    mdelay(200);
    gpio_set_value(GPIO_RES, 1);

    gpio_request(GPIO_DC, "");
    gpio_direction_output(GPIO_DC, 0);

    gpio_request(GPIO_BLK, "");
    gpio_direction_output(GPIO_BLK, 1);
    
    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}
    };

    for (; 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 void __exit mydev_exit(void)
{
    if (st7789_dev)
        spi_unregister_device(st7789_dev);

    printk("Goodbye, Kernel\n");
}

module_init(mydev_init);
module_exit(mydev_exit);
上一篇 下一篇

猜你喜欢

热点阅读