环境:ubuntu18.04虚拟机和imx6q开发平台

目录

  • 前言
  • 1.添加ssd1363驱动到fbtft
  • 2.亮度调节

前言

手里有一块ssd1363芯片的屏幕,查了很多关于framebuffer驱动的资料,在linux里面有个fbtft驱动部分专门针对这种tftf屏幕做的驱动,于是照着fbtft里面的驱动添加ssd1363并编写应用程序修改亮度值


1.添加ssd1363驱动到fbtft

路径如下:

/drivers/staging/fbtft

在这里直接复制fb_ssd1306.c一份文件为fb_ssd1363.c,修改内容如下

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include "fbtft.h"
#define DRVNAME     "fb_ssd1363"
#define WIDTH       320
#define HEIGHT      160
#define CMD         0
#define DATA        1
#define DEFAULT_GAMMA   "f"
static uint8_t GRAY_LEVEL = 10;    //0-15
static uint8_t OLED_GRAM[160][160]={0};static int init_display(struct fbtft_par *par)
{fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);par->fbtftops.reset(par);/* Write CMD */gpio_set_value(par->gpio.dc, CMD);write_reg(par, 0xAE);write_reg(par, 0xFD);gpio_set_value(par->gpio.dc, DATA);write_reg(par, 0x12);gpio_set_value(par->gpio.dc, CMD);write_reg(par, 0xA0);gpio_set_value(par->gpio.dc, DATA);write_reg(par, 0x22);gpio_set_value(par->gpio.dc, DATA);write_reg(par, 0x00);gpio_set_value(par->gpio.dc, CMD);write_reg(par, 0xA1);gpio_set_value(par->gpio.dc, DATA);write_reg(par, 0x00);gpio_set_value(par->gpio.dc, CMD);write_reg(par, 0xA2);gpio_set_value(par->gpio.dc, DATA);write_reg(par, 0x00);gpio_set_value(par->gpio.dc, CMD);write_reg(par, 0xA6);write_reg(par, 0xAD);gpio_set_value(par->gpio.dc, DATA);write_reg(par, 0x80);gpio_set_value(par->gpio.dc, CMD);write_reg(par, 0xB1);gpio_set_value(par->gpio.dc, DATA);write_reg(par, 0x92);gpio_set_value(par->gpio.dc, CMD);write_reg(par, 0xB3);gpio_set_value(par->gpio.dc, DATA);write_reg(par, 0x70);gpio_set_value(par->gpio.dc, CMD);write_reg(par, 0xB4);gpio_set_value(par->gpio.dc, DATA);write_reg(par, 0x11);gpio_set_value(par->gpio.dc, DATA);write_reg(par, 0xC0);   gpio_set_value(par->gpio.dc, CMD);write_reg(par, 0xB6);gpio_set_value(par->gpio.dc, DATA);write_reg(par, 0xC8);   gpio_set_value(par->gpio.dc, CMD);write_reg(par, 0xB9);write_reg(par, 0xBA);gpio_set_value(par->gpio.dc, DATA);write_reg(par, 0x02);      gpio_set_value(par->gpio.dc, CMD);write_reg(par, 0xBB);gpio_set_value(par->gpio.dc, DATA);write_reg(par, 0x07);   gpio_set_value(par->gpio.dc, CMD);write_reg(par, 0xBE);gpio_set_value(par->gpio.dc, DATA);write_reg(par, 0x07);   gpio_set_value(par->gpio.dc, CMD);write_reg(par, 0xC1);gpio_set_value(par->gpio.dc, DATA);write_reg(par, 0x50);   gpio_set_value(par->gpio.dc, CMD);write_reg(par, 0xCA);gpio_set_value(par->gpio.dc, DATA);write_reg(par, 0x9F);   gpio_set_value(par->gpio.dc, CMD);write_reg(par, 0xAF);//开启显示     return 0;
}
//设置每一页起始地址0-8
static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
{fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par,"%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye);/* Set Lower Column Start Address for Page Addressing Mode */gpio_set_value(par->gpio.dc, CMD);write_reg(par, 0x15);gpio_set_value(par->gpio.dc, DATA);write_reg(par, 0x00);   gpio_set_value(par->gpio.dc, DATA);write_reg(par, 0x4F); /* Set Higher Column Start Address for Page Addressing Mode */gpio_set_value(par->gpio.dc, CMD);write_reg(par, 0x75);gpio_set_value(par->gpio.dc, DATA);write_reg(par, 0x00); gpio_set_value(par->gpio.dc, DATA);write_reg(par, 0x9F);
}
static int blank(struct fbtft_par *par, bool on)
{fbtft_par_dbg(DEBUG_BLANK, par, "%s(blank=%s)\n",__func__, on ? "true" : "false");if (on)write_reg(par, 0xAE);elsewrite_reg(par, 0xAF);return 0;
}
/* Gamma is used to control Contrast */
static int set_gamma(struct fbtft_par *par, unsigned long *curves)
{fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);/* apply mask */curves[0] &= 0x0F;if(curves[0]<16)GRAY_LEVEL = curves[0];printk("\r\nset_gamma:%d\r\n",curves[0]);return 0;
}
//画点
//x:0~319
//y:0~159
//gray:light
void OLED_DrawPoint(u16 x,u16 y,u8 gray)
{u8 pos,temp=0;if(x>319||y>159)return;//超出范围了pos=x/2;if((pos%2)==0){pos+=1;}else{pos-=1;}temp = OLED_GRAM[y][pos];if((x%2)==0){temp&=0xf0;temp|=gray;}else{temp&=0x0f;temp|=(gray<<4);    }OLED_GRAM[y][pos]=temp;
}
static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
{u16 *vmem16 = (u16 *)par->info->screen_base;u8 *buf = par->txbuf.buf;int x, y, i;int ret = 0;fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__);//Data packagesfor (x = 0; x < par->info->var.xres; x++) {for (y = 0; y < par->info->var.yres/8; y++) {for (i = 0; i < 8; i++){if(vmem16[(y*8+i)*par->info->var.xres+x]){OLED_DrawPoint(x,y*8+i,GRAY_LEVEL);}else{OLED_DrawPoint(x,y*8+i,0);/* code */}                    }}}gpio_set_value(par->gpio.dc, CMD);write_reg(par, 0x5C);/* Write data */gpio_set_value(par->gpio.dc, DATA);ret = par->fbtftops.write(par, OLED_GRAM,sizeof(OLED_GRAM));if (ret < 0)dev_err(par->info->device, "write failed and returned: %d\n",ret);return ret;
}
static struct fbtft_display display = {.regwidth = 8,.width = WIDTH,.height = HEIGHT,.gamma_num = 1,.gamma_len = 1,.gamma = DEFAULT_GAMMA,.fbtftops = {.write_vmem = write_vmem,.init_display = init_display,.set_addr_win = set_addr_win,.blank = blank,.set_gamma = set_gamma,},
};
FBTFT_REGISTER_DRIVER(DRVNAME, "solomon,ssd1363", &display);
MODULE_ALIAS("spi:" DRVNAME);
MODULE_ALIAS("platform:" DRVNAME);
MODULE_ALIAS("spi:ssd1363");
MODULE_ALIAS("platform:ssd1363");
MODULE_DESCRIPTION("ssd1363 OLED Driver");
MODULE_AUTHOR("Noralf Tronnes");
MODULE_LICENSE("GPL");

另外还要修改Kconfig和Makefile文件

config FB_TFT_SSD1363tristate "FB driver for the SSD1363 OLED Controller"depends on FB_TFThelpFramebuffer support for SSD1363
obj-$(CONFIG_FB_TFT_SSD1363)     += fb_ssd1363.o

添加完成后就可以在make menuconfig中配置fbtft了


接下来还要修改设备树,我这里用的是ecspi2

&ecspi2 {fsl,spi-num-chipselects = <1>;cs-gpios = <&gpio2 27 0>;pinctrl-names = "default";pinctrl-0 = <&pinctrl_ecspi2>;status = "okay";ssd1363@0{ compatible = "solomon,ssd1363";dc-gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>;reset-gpios = <&gpio3 20 GPIO_ACTIVE_HIGH>;buswidth = <8>;spi-max-frequency = <10000000>;reg = <0>;};
};

这里离成功更近一步了,编译内核和设备树,通过tftp传输到板子上,nfs挂载文件系统,系统启动后会有如下日志打印

set_gamma:15
Console: switching to colour frame buffer device 40x20
graphics fb0: fb_ssd1363 frame buffer, 320x160, 100 KiB video memory, 4 KiB DMA buffer memory, fps=20, spi1.0 at 10 MHz

如果在uboot的bootargs中设置了console=tty1的话,这是屏幕上就会显示了,虽然屏幕正常显示了,但是ssd1363是有灰度调节的,这里我准备把它当成屏幕亮度来调节。

2.亮度调节

亮度调节比较麻烦,因为要从应用层去修改驱动层,不能直接去修改驱动层的变量,要通过内核层来修改,于是开始研究framebuffer的整个初始化注册过程,发现注册过程大概如下
在fbtft-core.c文件中
fbtft采用fbtft_register_framebuffer函数注册fb驱动
这里调用ret = register_framebuffer(fb_info);函数完成注册
发现内核注册的时候fb_info传递给了内核,于是在内核里面去查看
应用层一般可以通过ioctl函数操作读取fb的信息,我就想能不能通过ioctl函数来操作驱动修改亮度值
在fbmem.c文件中

static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,unsigned long arg)

这个函数就是ioctl最终实际调用的函数
在fb.h中添加一个宏定义用来改变亮度值

#define FBIOSET_DISPLIGHT        0x4619

修改do_fb_ioctl内容

1.添加头文件
#include "../drivers/staging/fbtft/fbtft.h"
2.添加指针初始化
struct fbtft_par *par = info->par;
unsigned long gamma=arg;
3.添加 FBIOSET_DISPLIGHT 的 case
case FBIOSET_DISPLIGHT:if (!lock_fb_info(info))return -ENODEV;ret = par->fbtftops.set_gamma(par, &gamma);  unlock_fb_info(info);
break;

这样一来就可以通过应用层调用set_gamma函数了,在fb_ssd1363.c中写好了set_gamma函数,这个本来是修改伽马值的,被我用来修改亮度用,算是投机取巧吧

static int set_gamma(struct fbtft_par *par, unsigned long *curves)
{fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);/* apply mask */curves[0] &= 0x0F;if(curves[0]<16)GRAY_LEVEL = curves[0];printk("\r\nset_gamma:%d\r\n",curves[0]);return 0;
}

接下来编写应用程序如下

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>#define FBIOSET_DISPLIGHT        0x4619static char *fbp = 0;
int main ( int argc, char *argv[] )
{int fbfd = 0;unsigned long light ;printf("argc:%d argv0:%s argv1:%s\n",argc,argv[0],argv[1]);if(argc != 2){printf("Error Usage!\r\n");return -1;}light = atoi(argv[1]);printf("light:%d\r\n",light);//打开显示设备fbfd = open("/dev/fb0", O_RDWR);if (ioctl(fbfd, FBIOSET_DISPLIGHT, light)){printf("Error: reading light information.\n");exit(1);}close(fbfd);return 0;
}

然后编译生成文件

arm-linux-gnueabihf-gcc ssd1363_app.c -o ssd1363_app

把文件放到挂载的nfs系统里面,运行如下

/app # ./ssd1363_app 10
argc:2 argv0:./ssd1363_app argv1:
set_gamma:10
10
light:10

屏幕亮度成功修改,大功告成,哈哈

linux:framebuffer驱动之ssd1363驱动和fbtft驱动修改相关推荐

  1. Linux Framebuffer驱动剖析之中的一个—软件需求

    嵌入式企鹅圈将以本文作为2015年的终结篇,以回应第一篇<Linux字符设备驱动剖析>.嵌入式企鹅圈一直专注于嵌入式Linux和物联网IOT双方面的原创技术分享,稍后会公布嵌入式企鹅圈的2 ...

  2. Linux Framebuffer驱动剖析之一—软件需求

    本系列文章将分析Linux Framebuffer驱动的作用(需求).框架.接口实现和使用.按笔者一直倡导的Linux学习理念-从软件需求的角度去理解Linux,对于Linux各个子系统,我们首先要理 ...

  3. Linux 驱动 – Frame Buffer (帧缓冲)显示驱动

    Linux 驱动 – Frame Buffer (帧缓冲)显示驱动 一.Frame Buffer Frame Buffer 翻译过来是帧缓冲的意思,帧指的是一帧图像,缓冲是暂时存放的意思,连起来就是暂 ...

  4. 嵌入式Linux设备驱动程序:在运行时读取驱动程序状态

    嵌入式Linux设备驱动程序:在运行时读取驱动程序状态 Embedded Linux device drivers: Reading driver state at runtime 在运行时了解驱动程 ...

  5. linux驱动之i2c子系统mpu6050设备驱动

    以下是mpu6050简单的驱动实现,mpu6050是I2C接口的6轴传感器,可以作为字符设备注册到内核,本代码运行环境是3.4.2内核,4.3.2版本的编译链,12.04版本的Ubuntu,硬件环境是 ...

  6. linux主设备编号从0到多少,Linux驱动开发之主设备号找驱动,次设备号找设备

    一.引言 很久前接触linux驱动就知道主设备号找驱动,次设备号找设备.这句到底怎么理解呢,如何在驱动中实现呢,在介绍该实现之前先看下内核中主次设备号的管理: 二.Linux内核主次设备号的管理 Li ...

  7. linux设备驱动之总线、设备、驱动

    文章转载至多个地方,网上拼凑的一篇文章,说的好听一些的话那就叫自己总结的文章,只 是多次引用啊,哈哈,哎,不管了,反正这个有利用学习进步就好,这是重要的,文章转载过来要经过一篇大脑才能成为自己的,以后 ...

  8. Linux SPI总线和设备驱动架构之三:SPI控制器驱动

    通过第一篇文章,我们已经知道,整个SPI驱动架构可以分为协议驱动.通用接口层和控制器驱动三大部分.其中,控制器驱动负责最底层的数据收发工作,为了完成数据的收发工作,控制器驱动需要完成以下这些功能: 1 ...

  9. linux 块设备驱动 (三)块设备驱动开发

    linux 块设备驱动 (三)块设备驱动开发 一: 块设备驱动注册与注销 块设备驱动中的第1个工作通常是注册它们自己到内核,完成这个任务的函数是 register_blkdev(),其原型为: int ...

最新文章

  1. Hyperopt中文文档:Home
  2. ubuntu16.04 关闭防火墙的方法
  3. 被边缘化的“卓越亚马逊”
  4. 沃尔玛尝到了推行InnerSource的甜头
  5. 洛谷 - P4721 【模板】分治 FFT(分治NTT)
  6. 通过IDE生成和手动call调用webservice
  7. 促销方式,各位自己马克,留着用就好
  8. 图片懒加载、ajax异步调用数据、lazyload插件的使用
  9. 重定位代码Repair
  10. 还在用Json-lib?面对疾风吧!
  11. redis 正则匹配value_Java-19-Redis
  12. 算法:回溯十七 Combination Sum III挑选数组中规定个数元素的和为指定数
  13. javaWeb发展历史
  14. ERStudio逆向工程生成ER模型
  15. 简洁高效的JQuery
  16. 斗破苍穹hd和java版区别_《斗罗大陆》和《斗破苍穹》的区别有哪些?
  17. 行人属性识别 PETA数据集
  18. Android P 正式到来
  19. [附源码]计算机毕业设计JAVA中学学生学籍管理
  20. 《Windows 8 权威指南》——1.2 Windows 8平板模式下IE浏览器网页

热门文章

  1. SQL Server 还原数据库
  2. 网络硬盘 excel服务器,Excel Server Tutorial
  3. 达梦数据库的替代(instead of )触发器使用一例
  4. python 写入excel数据xlwt_用python包xlwt将数据写入Excel中
  5. NVME Reset
  6. 为何美团、抖音都潜入社群团购?毫无疑问社群团购是大趋势。
  7. 微星 MSI GF63 i5-8300H+8G+128G+UHD630 基本完美黑苹果,把EFI分享给各位(2021.8.11 更新)
  8. 深度操作系统 15.7 —— 性能好才是真的好
  9. 电脑安卓手机模拟器怎么修改IP地址
  10. Himall商城ExpressDaDaHelper订单预发布 查询运费后发单接口