首页 > 系统相关 >嵌入式Linux ------ 一次简单的FrameBuffer驱动开发

嵌入式Linux ------ 一次简单的FrameBuffer驱动开发

时间:2023-08-10 15:47:31浏览次数:41  
标签:info fbops fix var fb ssd1327 Linux ------ FrameBuffer

Linux 一次简单的FrameBuffer驱动开发

设施 版本
CPU Allwinner F1C200s
linux 6.4.0-rc4
显示器 1.28 inch 16-grayscale OLED 128x128 驱动IC SSD1327
Orangepi 5

声明

本驱动仓库位于:https://github.com/AllwinnerSuniv/suniv-epd/tree/main/ssd1327

本驱动代码采样自 fbtft(linux/drivers/staging/fbtft) 项目

本案例用到的显示器可从如下链接购买:

模组:
https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-24706531953.9.7b7d6a4bKhv5j9&id=665635617961

面板:
https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-24706531953.15.7b7d6a4bKhv5j9&id=666352035372

思路

这块显示屏是16灰度格式的,这意味着一个像素点需要用4bit来表示,同理1byte表示2像素

我们在fb驱动中获取 rgb565 数据 转成16灰度 发给显示屏即可,转换函数如下:

#define RED(a)      ((((a) & 0xf800) >> 11) << 3)
#define GREEN(a)    ((((a) & 0x07e0) >> 5) << 2)
#define BLUE(a)     (((a) & 0x001f) << 3)
static inline u8 rgb565_to_4bit_grayscale(u16 rgb565)
{
        int r, g, b;
        __maybe_unused int level;
        u16 gray;

        /* get each channel and expand them to 8 bit */
        r = RED(rgb565);
        g = GREEN(rgb565);
        b = BLUE(rgb565);

        /* convert rgb888 to grayscale */
        gray = ((r * 77 + g * 151 + b * 28) >> 8); // 0 ~ 255
        if (gray == 0)
                return gray;

        /*
         * so 4-bit grayscale like:
         * B3  B2  B1  B0
         * 0   0   0   0
         * which means have 16 kind of gray
         */
        gray /= 16;

        return gray;
}

驱动流程如下

  1. 根据显示器宽高、bpp申请 vmem
  2. 申请 fbops fbinfo 结构体
  3. 配置 fbops 中的函数
        fbops->fb_read      = fb_sys_read;
        fbops->fb_write     = ssd1327_fb_write;
        fbops->fb_fillrect  = ssd1327_fb_fillrect;
        fbops->fb_copyarea  = ssd1327_fb_copyarea;
        fbops->fb_imageblit = ssd1327_fb_imageblit;
        fbops->fb_setcolreg = ssd1327_fb_setcolreg;
        fbops->fb_blank     = ssd1327_fb_blank;
  1. 配置 fbinfo 结构体
        snprintf(info->fix.id, sizeof(info->fix.id), "%s", dev->driver->name);
        info->fix.type            =       FB_TYPE_PACKED_PIXELS;
        info->fix.visual          =       FB_VISUAL_TRUECOLOR;
        // info->fix.visual          =       FB_VISUAL_MONO10;
        info->fix.xpanstep        =       0;
        info->fix.ypanstep        =       0;
        info->fix.ywrapstep       =       0;
        info->fix.line_length     =       width * bpp / BITS_PER_BYTE;
        info->fix.accel           =       FB_ACCEL_NONE;                                       
        info->fix.smem_len        =       vmem_size;

        info->var.rotate          =       rotate;
        info->var.xres            =       width;
        info->var.yres            =       height;
        info->var.xres_virtual    =       info->var.xres;
        info->var.yres_virtual    =       info->var.yres;

        info->var.bits_per_pixel  =       bpp;
        info->var.nonstd          =       1;
        info->var.grayscale       =       1;

        switch (info->var.bits_per_pixel) {
        case 1:
        case 2:
        case 4:
        case 8:
                info->var.red.offset = info->var.green.offset = info->var.blue.offset = 0;
                info->var.red.length = info->var.green.length = info->var.blue.length = 8;
                break;

        case 16:
                info->var.red.offset      =       11;
                info->var.red.length      =       5;
                info->var.green.offset    =       5;
                info->var.green.length    =       6;
                info->var.blue.offset     =       0;
                info->var.blue.length     =       5;
                info->var.transp.offset   =       0;
                info->var.transp.length   =       0;
                break;
        default:
                dev_err(dev, "color depth %d not supported\n",
                        info->var.bits_per_pixel);
                break;
        }

        info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;

  1. 我们用到了fbdeferred_io 机制,配置如下
        fbdefio->delay = HZ / display.fps;
        fbdefio->deferred_io = ssd1327_deferred_io;
        fb_deferred_io_init(info);
  1. 调色板的配置,对于rgb565
info->pseudo_palette = &par->pseudo_palette;

/* from pxafb.c */
static unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
{
        chan &= 0xffff;
        chan >>= 16 - bf->length;
        return chan << bf->offset;
}

static int ssd1327_fb_setcolreg(unsigned int regno, unsigned int red,
                                unsigned int green, unsigned int blue,
                                unsigned int transp, struct fb_info *info)
{
		...
		
        switch (info->fix.visual) {
        case FB_VISUAL_TRUECOLOR:
                if (regno < 16) {
                        val  = chan_to_field(red, &info->var.red);
                        val |= chan_to_field(green, &info->var.green);
                        val |= chan_to_field(blue, &info->var.blue);

                        ((u32 *)(info->pseudo_palette))[regno] = val;
                        ret = 0;
                }
                break;
        default:
                dev_err(info->dev, "unsupported color format!");
                ret = -1;
                break;
        }
		
		...
}
  1. 其他接口的初始化,例如锁等
  2. 初始化显示屏硬件,init_display 序列等
  3. 注册 fbinfo 结构体
  4. sysfs的管理

fbtft驱动的显示刷新流程

        fbops->fb_write     = ssd1327_fb_write;
        fbops->fb_fillrect  = ssd1327_fb_fillrect;
        fbops->fb_copyarea  = ssd1327_fb_copyarea;
        fbops->fb_imageblit = ssd1327_fb_imageblit;

上述接口会根据传入的宽高调用mk_dirty标记脏数据,然后通过schdule deferred_io work调用 update_display 完成区域更新

标签:info,fbops,fix,var,fb,ssd1327,Linux,------,FrameBuffer
From: https://www.cnblogs.com/hfwz/p/17581764.html

相关文章

  • Eolink 出席 QECon 大会,引领「AI+API」技术的革新浪潮
    7月28日-29日,第八届QECon质量效能大会在北京成功召开。大会聚焦“数生智慧,高质量发展新引擎”,深入探讨如何利用数字化和智能化技术推动软件质量的发展,进而为高质量的经济发展提供新的引擎。作为国内API全生命周期解决方案的领军者,Eolink受邀出席本次大会。会上,EolinkCEO......
  • Windows 10的IIS中设置虚拟目录后无法打开浏览
    问题使用Windows10的IIS架设服务器,配置中设置了虚拟目录后,浏览时出现以下服务器报错内容:点击“编辑虚拟目录”窗口中的“测试设置”,发现“授权”报错:服务器配置为将传递身份验证和内置帐户一起使用,以访问指定的物理路径。但是,IIS管理器无法验证此内置帐户是否有访问权。请......
  • linux连接Windows上的数据库
    /*定义一些数据库连接需要的宏*/#include<stdio.h>#include<string.h>#include<stdlib.h>/*引入连接Mysql的头文件*/#include<mysql/mysql.h>#defineHOST"Linux的IP地址"/*MySql服务器地址*/#defineUSERNAME"root"/*用户名*/#definePASSWORD&......
  • manacher(马拉车)算法C++详解
    马拉车的定义马拉车本质是对中心扩展法(暴力算法)的优化。马拉车是干什么的Manacher算法帮助我们在给定的字符串中找到最长的回文子串。为了简单起见,我们先只处理有奇数个字符的字符串,关于偶数个字符的字符串,在文章最后会给出解法。我们的处理思路和暴力算法基本一致,那就是从左......
  • ESLint和Prettier冲突
    问题:同时使用ESLint和Prettier时,在某行代码到达某长度时候出现警告线。ESLint推荐换行(手动换行警告消除)但保存(自动格式化后)被Prettier强制拉到同一行(貌似是本行代码长度已经碰到ESLint的逆鳞但未触及Prettier?) 解决: 默认vscode里设置了Prettier的PrintWidth为80 而默认......
  • RedHat:安装Python3.7
    学习自:rhel安装python3.7_redhat安装python3_weixin_44282127的博客-CSDN博客1、准备工作以下过程需要以用户角度开展:su-用户1)创建存放安装包的文件夹mkdir/opt/python2)去Python官网下载所需的python版本(这里以3.7.16为例)①选择Linux ②找到对应版本的python......
  • Qt CUDA混合编程BUG(一)
    在QT中进行CUDA编程,CUDA库与其他外部库冲突,debug失败问题描述在QT中进行CUDA编程,单独使用CUDA编程时并未出现难以解决的问题,但当我讲CUDA处理的部分,加入已搭建完毕一项较大的QT项目工程时,CUDA的lib库与项目使用到的其他外部lib库文件出现冲突,导致debug失败。可能出现多种错......
  • 微信的 h5 支付和 jsapi 支付
    目录......
  • 基于RiceQuant的期货多因子策略实现(二)
    前言介绍期货交易经典理论介绍期货因子大类分类通过构建时序与截面因子,构建多空组合。交易理论现货溢价理论(套保者影响)对冲压力假说(期货价格由现货价格和对冲需求共同决定)存储理论(商品的存储影响现货和期货之间的价格关系,存储成本低,市场预期未来价格上涨时,商人会选择购......
  • Linux下发现一个高安全性的系统管理工具
     软件AnySetup主要功能主要功能是对Linux操作系统下的基本配置进行管理、多种服务配置进行管理、安全配置进行管理等。如:操作系统的升级管理,软件包的安装、更新和卸载管理,软件仓库源的管理,系统时间和时区的管理,系统语言环境的管理,网络环境的配置管理,系统服务的启动、关闭、......