【milkv】st7735 driver

Preface

This article introduces the LCD screen of milkv-duo loading st7735, and the screen display log.

Reference article:
Record configuring spi screen for Linux (st7735s)
https://community.milkv.io/t/milk-v-duo-spi-st7789/131

1. Circuit diagram

Insert image description here
Insert image description here
Insert image description here

1.1 pin setting

Open the pin of spi2
duo-buildroot-sdk\build\boards\cv180x\cv1800b_milkv_duo_sd\u-boot\cvi_board_init.c

	//spi2 -- st7735
	pinmux_config(PINMUX_SPI2);
	PINMUX_CONFIG(SPINOR_MISO, XGPIOA_23);	//DC
	PINMUX_CONFIG(SD0_PWR_EN, XGPIOA_14);	//BL
	PINMUX_CONFIG(SPK_EN, XGPIOA_15);		//RES

Note that the DC here belongs to gpioA

The pinmux_config(PINMUX_SPI2) here; the corresponding configuration can be found in the source code

		case PINMUX_SPI2:
			PINMUX_CONFIG(SD1_CMD, SPI2_SDO);
			PINMUX_CONFIG(SD1_CLK, SPI2_SCK);
			PINMUX_CONFIG(SD1_D0, SPI2_SDI);
			PINMUX_CONFIG(SD1_D3, SPI2_CS_X);
			break;

1.2 dtsi configuration

build\boards\cv180x\cv1800b_milkv_duo_sd\dts_riscv\cv1800b_milkv_duo_sd.dts

&spi2 {
    
    
	status = "okay";

    /delete-node/ spidev@0;

	st7789v: st7789v@0{
    
    
		compatible = "sitronix,st7789v";
		reg = <0>;
		status = "okay";
		spi-max-frequency = <48000000>;
		spi-cpol;
		spi-cpha;
		rotate = <90>;
		fps = <30>;
		rgb;
		buswidth = <8>;

		dc-gpios = <&porta 23 GPIO_ACTIVE_HIGH>;	//DC
		reset-gpios = <&porta 15 GPIO_ACTIVE_HIGH>; //RES
		led-gpios = <&porta 14 GPIO_ACTIVE_HIGH>; //BL

		debug = <0x0>;
	};
};

The gpio here must be implemented in conjunction with your pins.

2. Load the driver

Follow the reference article and use the st7789v code to modify it to st7735.
Documentation to configure spi screen for linux (st7735s)

Compilation conditions
duo-buildroot-sdk\linux_5.10\drivers\staging\fbtft\Makefile

obj-$(CONFIG_FB_TFT_ST7735R)     += fb_st7735r.o
obj-$(CONFIG_FB_TFT_ST7789V)     += fb_st7789v.o

Borrow the code from st7789v

st7735s is consistent with st7735r

引用:https://www.cnblogs.com/milton/p/15614304.html#St7735%E4%BB%8B%E7%BB%8D 
ST7735的配置
因为ST7735存在多个型号, 对于ST7735R和ST7735S, 使用默认的初始化方法

duo-buildroot-sdk\build\boards\cv180x\cv1800b_milkv_duo_sd\linux\ cvitek_cv1800b_milkv_duo_sd_defconfig

# spi lcd -- st7735s
CONFIG_SPI=y
CONFIG_SPI_MASTER=y
CONFIG_SPI_DESIGNWARE=y
CONFIG_SPI_DW_MMIO=y
CONFIG_SPI_SPIDEV=y
CONFIG_FB=y
CONFIG_FB_TFT=y
# CONFIG_FB_TFT_ST7735R=y
CONFIG_FB_TFT_ST7789V=y

Compilation process tips

  CC      drivers/staging/fbtft/fb_st7789v.o

3. Change the driver

3.1 st7789v driver

duo-buildroot-sdk\linux_5.10\drivers\staging\fbtft\fb_st7789v.c

Reference source: https://blog.csdn.net/qq_46604211/article/details/116449891

3.1.2 Interface update

Since the driver is st7789v and my screen is st7735, some initialization interfaces need to be changed.

Note that gamma needs to comment out the for loop.

// st7735
static int init_display(struct fbtft_par *par)
{
    
    
	par->fbtftops.reset(par);//硬复位

	mdelay(50);
	write_reg(par,0x11);//软复位
	mdelay(100);
	//下面添加初始化函数write_reg 参数分别为:结构体指针,写命令,写数据....(后都为数据)
	//ST7735s Frame Rate
	write_reg(par,0xB1,0x05,0x3c,0x3c); 

	write_reg(par,0xB2,0x05,0x3c,0x3c);  

	write_reg(par,0xB3,0x05,0x3c,0x3c,0x05,0x3c,0x3c); 
 
	
	write_reg(par,0xB4,0x03); //Column inversion 
	
	//ST7735s Power Sequence
	write_reg(par,0xC0,0x28,0x08,0x04); 

	write_reg(par,0xC1,0xc0); 

	write_reg(par,0xC2,0x0d,0x00); 
	
	write_reg(par,0xC3,0x8d,0x2a); //VCOM 
	
	write_reg(par,0xc4,0x8d,0xee); //MX, MY, RGB mode  
	write_reg(par,0xc5,0x1a);
	write_reg(par,0x36,0xc0);
	//ST7735s Gamma Sequence
	write_reg(par,0xe0,0x04,0x22,0x07,0x0a,0x2e,0x30,0x25,0x2a,0x28,0x26,0x2e,0x3a,0x00,0x01,0x03,0x13); 

	write_reg(par,0xe1,0x04,0x16,0x06,0x0d,0x2d,0x26,0x23,0x27,0x27,0x25,0x2d,0x3b,0x00,0x01,0x04,0x13);  
	
	write_reg(par,0x3A,0x05); //65k mode  
	
	write_reg(par,0x29);//Display on
	mdelay(100);

	return 0;
}

static int set_gamma(struct fbtft_par *par, u32 *curves)
{
    
    
	int i;
	int j;
	int c; /* curve index offset */

	/*
	 * Bitmasks for gamma curve command parameters.
	 * The masks are the same for both positive and negative voltage
	 * gamma curves.
	 */
	static const u8 gamma_par_mask[] = {
    
    
		0xFF, /* V63[3:0], V0[3:0]*/
		0x3F, /* V1[5:0] */
		0x3F, /* V2[5:0] */
		0x1F, /* V4[4:0] */
		0x1F, /* V6[4:0] */
		0x3F, /* J0[1:0], V13[3:0] */
		0x7F, /* V20[6:0] */
		0x77, /* V36[2:0], V27[2:0] */
		0x7F, /* V43[6:0] */
		0x3F, /* J1[1:0], V50[3:0] */
		0x1F, /* V57[4:0] */
		0x1F, /* V59[4:0] */
		0x3F, /* V61[5:0] */
		0x3F, /* V62[5:0] */
	};

	for (i = 0; i < par->gamma.num_curves; i++) {
    
    
		c = i * par->gamma.num_values;
		// for (j = 0; j < par->gamma.num_values; j++)
		// 	curves[c + j] &= gamma_par_mask[j];
		write_reg(par, PVGAMCTRL + i,
			  curves[c + 0],  curves[c + 1],  curves[c + 2],
			  curves[c + 3],  curves[c + 4],  curves[c + 5],
			  curves[c + 6],  curves[c + 7],  curves[c + 8],
			  curves[c + 9],  curves[c + 10], curves[c + 11],
			  curves[c + 12], curves[c + 13]);
	}
	return 0;
}

3.1.3 Change width and height

The screen width and height of st7735 is 128*160.

duo-buildroot-sdk\linux_5.10\drivers\staging\fbtft\fb_st7789v.c

static struct fbtft_display display = {
    
    
	.regwidth = 8,
	.width = 128,//240,
	.height = 160,//320,
	.gamma_num = 2,
	.gamma_len = 14,
	.gamma = HSD20_IPS_GAMMA,
	.fbtftops = {
    
    
		.init_display = init_display,
		.set_var = set_var,
		.set_gamma = set_gamma,
		.blank = blank,
	},
};

3.2 fbtft-core

duo-buildroot-sdk\linux_5.10\drivers\staging\fbtft\fbtft-core.c

3.2.1 Add header file

#include <linux/gpio.h> //add
#include <linux/of_gpio.h> //add

3.2.2 Change interface

This is caused by the kernel version update, and some interfaces may need to be changed.
The attributes in dtsi plus -gpio can be selected by yourself.
reset is reimplemented.

//https://blog.csdn.net/qq_46604211/article/details/116449891
static int fbtft_request_one_gpio(struct fbtft_par *par,
                  const char *name, int index,
                  struct gpio_desc **gpiop)
{
    
    
    struct device *dev = par->info->device;
    struct device_node *node = dev->of_node;
    int gpio, flags, ret = 0;
    enum of_gpio_flags of_flags;
    if (of_find_property(node, name, NULL)) {
    
    
        gpio = of_get_named_gpio_flags(node, name, index, &of_flags);
        if (gpio == -ENOENT)
            return 0;
        if (gpio == -EPROBE_DEFER)
            return gpio;
        if (gpio < 0) {
    
    
            dev_err(dev,
                "failed to get '%s' from DT\n", name);
            return gpio;
        }
         //active low translates to initially low
        flags = (of_flags & OF_GPIO_ACTIVE_LOW) ? GPIOF_OUT_INIT_LOW :
                            GPIOF_OUT_INIT_HIGH;
        ret = devm_gpio_request_one(dev, gpio, flags,
                        dev->driver->name);
        if (ret) {
    
    
            dev_err(dev,
                "gpio_request_one('%s'=%d) failed with %d\n",
                name, gpio, ret);
            return ret;
        }

        *gpiop = gpio_to_desc(gpio);
        fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, "%s: '%s' = GPIO%d\n",
                            __func__, name, gpio);
    }

    return ret;
}

static int fbtft_request_gpios(struct fbtft_par *par)
{
    
    
    int i;
    int ret;

    ret = fbtft_request_one_gpio(par, "reset-gpios", 0, &par->gpio.reset);
    if (ret)
        return ret;
    ret = fbtft_request_one_gpio(par, "dc-gpios", 0, &par->gpio.dc);
    if (ret)
        return ret;
    ret = fbtft_request_one_gpio(par, "rd-gpios", 0, &par->gpio.rd);
    if (ret)
        return ret;
    ret = fbtft_request_one_gpio(par, "wr-gpios", 0, &par->gpio.wr);
    if (ret)
        return ret;
    ret = fbtft_request_one_gpio(par, "cs-gpios", 0, &par->gpio.cs);
    if (ret)
        return ret;
    ret = fbtft_request_one_gpio(par, "latch-gpios", 0, &par->gpio.latch);
    if (ret)
        return ret;
    for (i = 0; i < 16; i++) {
    
    
        ret = fbtft_request_one_gpio(par, "db-gpios", i,
                         &par->gpio.db[i]);
        if (ret)
            return ret;
        ret = fbtft_request_one_gpio(par, "led-gpios", i,
                         &par->gpio.led[i]);
        if (ret)
            return ret;
        ret = fbtft_request_one_gpio(par, "aux-gpios", i,
                         &par->gpio.aux[i]);
        if (ret)
            return ret;
    }

    return 0;
}

//作者:Leesans https://www.bilibili.com/read/cv9947785/ 出处:bilibili
static void fbtft_reset(struct fbtft_par *par)
{
    
    
    if (!par->gpio.reset)
        return;
    fbtft_par_dbg(DEBUG_RESET, par, "%s()\n", __func__);
    gpiod_set_value_cansleep(par->gpio.reset, 1);
    msleep(10);
    gpiod_set_value_cansleep(par->gpio.reset, 0);
    msleep(200);
    gpiod_set_value_cansleep(par->gpio.reset, 1);
    msleep(10);
}

4. Screen display results

Insert image description here
The driver loads normally.

You can test the screen function through the following two commands.

cat /dev/urandom > /dev/fb0 	//显示花屏
cat /dev/zero > /dev/fb0  		//清空屏幕
echo xxxx > /dev/fb0 				//显示点个数

Look carefully at the upper right corner. There is a line of different colors. It is very short. You can echo followed by a long x. The more x, the longer the line.
This is manually assigned to the pixels.

Insert image description here

5. Display the log on the screen

Reference source:
https://community.milkv.io/t/milk-v-duo-spi-st7789/131

5.1 Add compilation module

duo-buildroot-sdk\build\boards\cv180x\cv1800b_milkv_duo_sd\linux\cvitek_cv1800b_milkv_duo_sd_defconfig

# lcd display kernel log
CONFIG_TTY=y
CONFIG_VT=y
CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
CONFIG_FB=y
CONFIG_FB_CMDLINE=y
CONFIG_FB_NOTIFY=y
CONFIG_FONT_SUPPORT=y
CONFIG_FONTS=y
CONFIG_FONT_8x16=y
CONFIG_VGA_CONSOLE=y
CONFIG_DUMMY_CONSOLE=y
CONFIG_DUMMY_CONSOLE_COLUMNS=80
CONFIG_DUMMY_CONSOLE_ROWS=25
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y

5.2 Add tty0 to display log

duo-buildroot-sdk\u-boot-2021.10\include\configs\cv180x-asic.h

#define SET_BOOTARGS "setenv bootargs ${root} ${mtdparts} " \
		"console=tty0 console=$consoledev,$baudrate $othbootargs;"

5.3 Display

Insert image description here

Guess you like

Origin blog.csdn.net/qq_38091632/article/details/132984570