linux的lcd驱动(framebuffer)---点屏

一.设定屏幕参数

1.更改设备树下的lcd节点参数
目录:arch/arm/boot/dts/imx6ull-14x14-nand-7-1024x600-c.dts

点击查看代码
&i2c2 {
	goodix_ts@5d {
		reg = <0x5d>;
	};
};

&lcdif {
	display0: display {
		bits-per-pixel = <32>;//16
		bus-width = <24>;

		display-timings {
			native-mode = <&timing0>;
			timing0: timing0 {
			clock-frequency = <35000000>;/*35000000*/
			hactive = <720>;
			vactive = <720>;
			hfront-porch = <46>;
			hback-porch = <44>;
			hsync-len = <2>;
			vback-porch = <16>;//min: 12   zsq_normal:16       18
			vfront-porch = <50>;//zsq_normal: 50        16
			vsync-len = <5>;//zsq_normal 5				2

			hsync-active = <0>;
			vsync-active = <0>;
			de-active = <1>;
			pixelclk-active = <1>;
			};
		};
	};
};

2.在设备树下增加模拟spi的设备节点
目录:arch/arm/boot/dts/imx6ull-14x14-evk.dts

点击查看代码
gpiomnspis {
 			#address-cells = <1>;
 			#size-cells = <1>;
 			compatible = "atkalpha-gpiomnspis";
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_gpio_mnspis>;
 			cs-gpio = <&gpio1 20 GPIO_ACTIVE_LOW>;			//uart2-tx
			gpio-sck = <&gpio1 21 0>;						//uart2-rx
			gpio-mosi = <&gpio1 23 0>;						//rts
 			status = "okay";
 	};

3.在屏幕驱动的probe函数下,对屏幕进行初始化
目录:/drivers/video/fbdev/mxsfb.c

3.1首先找到"mxsfb_probe"函数,做如下处理

点击查看代码
static int mxsfb_probe(struct platform_device *pdev)
{
	const struct of_device_id *of_id =
			of_match_device(mxsfb_dt_ids, &pdev->dev);
	struct resource *res;
	struct mxsfb_info *host;
	struct fb_info *fb_info;
	struct pinctrl *pinctrl;
	int irq = platform_get_irq(pdev, 0);
	int gpio, ret;
	lcd_spiinit();        //add lcd_spiinit() by me
	if (of_id)
		pdev->id_entry = of_id->data;

	gpio = of_get_named_gpio(pdev->dev.of_node, "enable-gpio", 0);
	if (gpio == -EPROBE_DEFER)
		return -EPROBE_DEFER;
    ...
}

3.2lcd初始化代码如下

点击查看代码
void lcd_spiinit(void)
{
	gpio_lcd_spi.nd = of_find_node_by_path("/gpiomnspis");
	gpio_lcd_spi.cs_gpio = of_get_named_gpio(gpio_lcd_spi.nd, "cs-gpio", 0);
	gpio_lcd_spi.gpio_mosi = of_get_named_gpio(gpio_lcd_spi.nd, "gpio-mosi", 0);
	gpio_lcd_spi.gpio_sck = of_get_named_gpio(gpio_lcd_spi.nd, "gpio-sck", 0);
	gpio_direction_output(gpio_lcd_spi.cs_gpio, 1);
	gpio_direction_output(gpio_lcd_spi.gpio_mosi, 1);
	gpio_direction_output(gpio_lcd_spi.gpio_sck, 1);
		  
    Wrt_Reg_3052(0xFF,0x30);
	Wrt_Reg_3052(0xFF,0x52);
	Wrt_Reg_3052(0xFF,0x01);
	Wrt_Reg_3052(0xE3,0x00);
	Wrt_Reg_3052(0x0A,0x01);
	Wrt_Reg_3052(0x23,0xA0);//A2
    ...
}
点击查看代码
struct gpio_lcd_spi_dev{
	dev_t devids; /* 设备号 */
	//struct cdev cdev; /* cdev */
	struct class *class; /* 类 */
	struct device *device; /* 设备 */
	int major; /* 主设备号 */
	int minor; /* 次设备号 */
	struct device_node *nd; /* 设备节点 */
	int cs_gpio; /* led 所使用的 GPIO 编号 */
	int gpio_mosi;
	int gpio_sck;
};
static	struct gpio_lcd_spi_dev gpio_lcd_spi;

#define	OLED_MOSI_SET()  gpio_set_value(gpio_lcd_spi.gpio_mosi, 1);	 
#define	OLED_MOSI_CLR()  gpio_set_value(gpio_lcd_spi.gpio_mosi, 0);
#define	OLED_CLK_SET()   gpio_set_value(gpio_lcd_spi.gpio_sck, 1);
#define	OLED_CLK_CLR()   gpio_set_value(gpio_lcd_spi.gpio_sck, 0);
#define OLED_CS_Clr()  	 gpio_set_value(gpio_lcd_spi.cs_gpio, 0);
#define OLED_CS_Set()  	 gpio_set_value(gpio_lcd_spi.cs_gpio, 1);

static void SPI_WriteByte1(uint8_t Data)
{
	unsigned char i=0;
	for(i=8;i>0;i--)
	{
		OLED_CLK_CLR();    //将时钟拉低拉高  
	  	if(Data&0x80)	
		{
			OLED_MOSI_SET(); //写数据1
    	}
		else
		{
			OLED_MOSI_CLR(); //写数据0
	  	}
    	OLED_CLK_SET();    //发送1bit数据
    	Data<<=1;
		//usleep(1000);
		//mdelay(1); 
	}
}
void Wrt_Reg_3052(uint8_t dat,uint8_t cmd)
{
	
	OLED_CS_Clr();
	OLED_CLK_CLR();    //将时钟拉低拉高  
	OLED_MOSI_CLR();   
    OLED_CLK_SET();    //发送1bit数据
	SPI_WriteByte1(dat);
	OLED_CLK_CLR();    //将时钟拉低拉高  
	OLED_MOSI_SET();
	OLED_CLK_SET();
	SPI_WriteByte1(cmd);
	OLED_CS_Set();
}

void lcd_spiinit(void)
{
	gpio_lcd_spi.nd = of_find_node_by_path("/gpiomnspis");
posted @   Charles_hui  阅读(222)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示