NanoPi NEO Air使用十二:使用自带的fbtft驱动点亮SPI接口TFT屏幕,ST7789V

Posted 丘木木

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NanoPi NEO Air使用十二:使用自带的fbtft驱动点亮SPI接口TFT屏幕,ST7789V相关的知识,希望对你有一定的参考价值。

本节为手中SPI接口的屏幕移植驱动,屏幕如下:


240x240分辨率,1.3寸,主控为ST7789V。

与开发板的引脚连接确定如下:

功能IO
GNDPin6
5VPin2
LCD_RESETPin7-PG11
LCD_DCPin22-PA1
SPICLKPin23-PC2
SPIMOSIPin19-PC0

从开发板的引脚图发现,开发板使用的SPI0。

引脚连接确定如下:

功能IO
GNDPin6
5VPin2
LED_EN(BLK)Pin11-PA0
LCD_RESETPin7-PG11
LCD_DCPin22-PA1
SPICLKPin23-PC2
SPIMOSIPin19-PC0

修改设备树

打开/home/ql/linux/H3/linux/arch/arm/boot/dts/sun8i-h3-nanopi.dtsi,找到spi0节点,修改为如下:


&spi0 
	/* needed to avoid dtc warning */
	#address-cells = <1>;
	#size-cells = <0>;

	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&spi0_pins &spi0_cs_pins>;
	cs-gpios = <&pio 2 3 GPIO_ACTIVE_HIGH>, <&pio 0 6 GPIO_ACTIVE_HIGH>; /*SPI-CS:PC3 and PA6*/

	pitft: pitft@0
		compatible = "sitronix,st7789v";
		reg = <0>;
		status = "okay";

		spi-max-frequency = <50000000>;
		rotate = <90>;
		fps = <33>;
		buswidth = <8>;
		dc-gpios = <&pio 0 1 GPIO_ACTIVE_HIGH>;	 /* PA1 */
		reset-gpios = <&pio 6 11 GPIO_ACTIVE_HIGH>; /* PG11 */
		led-gpios = <&pio 0 0 GPIO_ACTIVE_LOW>;	 /* PA0 */		
		debug = <0x0>;
	;
;

关闭HDMI,否则设备默认HDMI输出,tft黑屏

&hdmi 
	//status = "okay";
	status = "disable";
;

&hdmi_out 
	hdmi_out_con: endpoint 
		remote-endpoint = <&hdmi_con_in>;
	;
;

&sound_hdmi 
	//status = "okay";
	status = "disable";
;

修改驱动文件

上面设备树中节点pitft的compatible 属性为“st7789v”,在内核源码工程中搜索“st7789v”,找到/home/ql/linux/H3/linux/drivers/staging/fbtft/fb_st7789v.c

也可以使用另一种方法,打开.config文件,搜索“st7789”

说明内核中编译进了st7789的驱动,继续搜索“CONFIG_FB_TFT_ST7789V”,找到linux\\drivers\\staging\\fbtft\\Makefile

得知源文件名为fb_st7789v.c

/*
 * FB driver for the ST7789V LCD Controller
 *
 * Copyright (C) 2015 Dennis Menschel
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <video/mipi_display.h>
#include <linux/gpio.h>

#include "fbtft.h"

#define DRVNAME "fb_st7789v"

#define DEFAULT_GAMMA \\
	"70 2C 2E 15 10 09 48 33 53 0B 19 18 20 25\\n" \\
	"70 2C 2E 15 10 09 48 33 53 0B 19 18 20 25"

/**
 * enum st7789v_command - ST7789V display controller commands
 *
 * @PORCTRL: porch setting
 * @GCTRL: gate control
 * @VCOMS: VCOM setting
 * @VDVVRHEN: VDV and VRH command enable
 * @VRHS: VRH set
 * @VDVS: VDV set
 * @VCMOFSET: VCOM offset set
 * @PWCTRL1: power control 1
 * @PVGAMCTRL: positive voltage gamma control
 * @NVGAMCTRL: negative voltage gamma control
 *
 * The command names are the same as those found in the datasheet to ease
 * looking up their semantics and usage.
 *
 * Note that the ST7789V display controller offers quite a few more commands
 * which have been omitted from this list as they are not used at the moment.
 * Furthermore, commands that are compliant with the MIPI DCS have been left
 * out as well to avoid duplicate entries.
 */
enum st7789v_command 
	PORCTRL = 0xB2,
	GCTRL = 0xB7,
	VCOMS = 0xBB,
	VDVVRHEN = 0xC2,
	VRHS = 0xC3,
	VDVS = 0xC4,
	VCMOFSET = 0xC5,
	PWCTRL1 = 0xD0,
	PVGAMCTRL = 0xE0,
	NVGAMCTRL = 0xE1,
;

#define MADCTL_BGR BIT(3) /* bitmask for RGB/BGR order */
#define MADCTL_MV BIT(5) /* bitmask for page/column order */
#define MADCTL_MX BIT(6) /* bitmask for column address order */
#define MADCTL_MY BIT(7) /* bitmask for page address order */

/**
 * init_display() - initialize the display controller
 *
 * @par: FBTFT parameter object
 *
 * Most of the commands in this init function set their parameters to the
 * same default values which are already in place after the display has been
 * powered up. (The main exception to this rule is the pixel format which
 * would default to 18 instead of 16 bit per pixel.)
 * Nonetheless, this sequence can be used as a template for concrete
 * displays which usually need some adjustments.
 *
 * Return: 0 on success, < 0 if error occurred.
 */
static int init_display(struct fbtft_par *par)

	/* turn off sleep mode */
	write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE);
	mdelay(120);

	/* set pixel format to RGB-565 */
	write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT);

	write_reg(par, PORCTRL, 0x08, 0x08, 0x00, 0x22, 0x22);

	/*
	 * VGH = 13.26V
	 * VGL = -10.43V
	 */
	write_reg(par, GCTRL, 0x35);

	/*
	 * VDV and VRH register values come from command write
	 * (instead of NVM)
	 */
	write_reg(par, VDVVRHEN, 0x01, 0xFF);

	/*
	 * VAP =  4.1V + (VCOM + VCOM offset + 0.5 * VDV)
	 * VAN = -4.1V + (VCOM + VCOM offset + 0.5 * VDV)
	 */
	write_reg(par, VRHS, 0x0B);

	/* VDV = 0V */
	write_reg(par, VDVS, 0x20);

	/* VCOM = 0.9V */
	write_reg(par, VCOMS, 0x20);

	/* VCOM offset = 0V */
	write_reg(par, VCMOFSET, 0x20);

	/*
	 * AVDD = 6.8V
	 * AVCL = -4.8V
	 * VDS = 2.3V
	 */
	write_reg(par, PWCTRL1, 0xA4, 0xA1);

	write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
	return 0;


/**
 * set_var() - apply LCD properties like rotation and BGR mode
 *
 * @par: FBTFT parameter object
 *
 * Return: 0 on success, < 0 if error occurred.
 */
static int set_var(struct fbtft_par *par)

	u8 madctl_par = 0;

	if (par->bgr)
		madctl_par |= MADCTL_BGR;
	switch (par->info->var.rotate) 
	case 0:
		break;
	case 90:
		madctl_par |= (MADCTL_MV | MADCTL_MY);
		break;
	case 180:
		madctl_par |= (MADCTL_MX | MADCTL_MY);
		break;
	case 270:
		madctl_par |= (MADCTL_MV | MADCTL_MX);
		break;
	default:
		return -EINVAL;
	
	write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, madctl_par);
	return 0;


/**
 * set_gamma() - set gamma curves
 *
 * @par: FBTFT parameter object
 * @curves: gamma curves
 *
 * Before the gamma curves are applied, they are preprocessed with a bitmask
 * to ensure syntactically correct input for the display controller.
 * This implies that the curves input parameter might be changed by this
 * function and that illegal gamma values are auto-corrected and not
 * reported as errors.
 *
 * Return: 0 on success, < 0 if error occurred.
 */
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;


/**
 * blank() - blank the display
 *
 * @par: FBTFT parameter object
 * @on: whether to enable or disable blanking the display
 *
 * Return: 0 on success, < 0 if error occurred.
 */
static int blank(struct fbtft_par *par, bool on)

	if (on)
		write_reg(par, MIPI_DCS_SET_DISPLAY_OFF);
	else
		write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
	return 0;


static struct fbtft_display display = 
	.regwidth = 8,
	.width = 240,
	.height = 240,
	.gamma_num = 2,
	.gamma_len = 14,
	.gamma = DEFAULT_GAMMA,
	.fbtftops = 
		.init_display = init_display,
		.set_var = set_var,
		.set_gamma = set_gamma,
		.blank = blank,
	,
;

FBTFT_REGISTER_DRIVER(DRVNAME, "sitronix,st7789v", &display);

MODULE_ALIAS("spi:" DRVNAME);
MODULE_ALIAS("platform:" DRVNAME);
MODULE_ALIAS("spi:st7789v");
MODULE_ALIAS("platform:st7789v");

MODULE_DESCRIPTION("FB driver for the ST7789V LCD Controller");
MODULE_AUTHOR("Dennis Menschel");
MODULE_LICENSE("GPL");

以上是关于NanoPi NEO Air使用十二:使用自带的fbtft驱动点亮SPI接口TFT屏幕,ST7789V的主要内容,如果未能解决你的问题,请参考以下文章

NanoPi NEO Air使用九:使用Linux内核自带的LED驱动

NanoPi NEO Air使用十三:使用自带的fbtft驱动点亮SPI接口TFT屏幕,ST7789V,模块加载的方式

NanoPi NEO Air使用十三:使用自带的fbtft驱动点亮SPI接口TFT屏幕,ST7789V,模块加载的方式

NanoPi NEO Air使用二:固件烧录

NanoPi NEO Air使用一:介绍

NanoPi NEO Air使用四:操作GPIO