当前位置: 首页 > news >正文

RK3568平台(背光篇)背光驱动代码分析

一.背光驱动设备树DTS

backlight: backlight {compatible = "pwm-backlight";pwms = <&pwm1 0 5555555 1>;brightness-levels = <77  77  78  78  79  79  80  8182  83  84  85  86  87  87  8888  89  90  90  91  91  92  9394  94  95  95  96  96  97  9798  98  99  99  100 100 101 101102 103 104 104 105 106 107 107108 108 109 109 110 111 112 113114 115 116 116 117 117 118 118119 119 120 121 122 123 124 124125 125 126 126 127 127 128 128129 129 130 130 131 131 132 132133 133 134 134 135 135 136 136137 137 138 138 139 139 140 141142 142 143 144 145 146 146 147147 148 148 149 149 150 151 151152 153 153 154 154 155 156 156157 158 158 159 160 161 162 162163 163 164 164 165 165 166 166167 168 168 169 170 171 172 172173 174 175 175 176 177 178 179 180 181 182 182 183 184 185 186 187 188 189 190 190 191 192 193 194 194 195 196 197 198 199 199 200 201 202 203 204 204 205 206 207 208 209 210 211 211 212 213 214 215 216 216 217 217 218 219 219 220 220 221 222 223 224 224 225 225 226 227 228 229 229 230 231 232 232 233 234 235 236 237 238 239 239 240 240 241 242 242 243 244 245 246 246 247 247 248 249 250 251 251 252 253 254 255>;default-brightness-level = <235>;
};

二.背光驱动代码分析

背光驱动部分代码路径:kernel-5.10\drivers\video\backlight\pwm_bl.c

背光驱动入口部分:

static struct platform_driver pwm_backlight_driver = {.driver		= {.name		= "pwm-backlight",.pm		= &pwm_backlight_pm_ops,.of_match_table	= of_match_ptr(pwm_backlight_of_match),},.probe		= pwm_backlight_probe,.remove		= pwm_backlight_remove,.shutdown	= pwm_backlight_shutdown,
};module_platform_driver(pwm_backlight_driver);MODULE_DESCRIPTION("PWM based Backlight Driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:pwm-backlight");

先看驱动适配函数pwm_backlight_probe:

static int pwm_backlight_probe(struct platform_device *pdev)
{struct platform_pwm_backlight_data *data = dev_get_platdata(&pdev->dev);struct platform_pwm_backlight_data defdata;struct backlight_properties props;struct backlight_device *bl;struct device_node *node = pdev->dev.of_node;struct pwm_bl_data *pb;struct pwm_args pargs;int ret;if (!data) {ret = pwm_backlight_parse_dt(&pdev->dev, &defdata);if (ret < 0) {dev_err(&pdev->dev, "failed to find platform data\n");return ret;}data = &defdata;}if (data->init) {ret = data->init(&pdev->dev);if (ret < 0)return ret;}pb = devm_kzalloc(&pdev->dev, sizeof(*pb), GFP_KERNEL);if (!pb) {ret = -ENOMEM;goto err_alloc;}if (data->levels) {unsigned int i;for (i = 0; i <= data->max_brightness; i++)if (data->levels[i] > pb->scale)pb->scale = data->levels[i];pb->levels = data->levels;} elsepb->scale = data->max_brightness;pb->notify = data->notify;pb->notify_after = data->notify_after;pb->check_fb = data->check_fb;pb->exit = data->exit;pb->dev = &pdev->dev;pb->enabled = false;pb->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable",GPIOD_ASIS);if (IS_ERR(pb->enable_gpio)) {ret = PTR_ERR(pb->enable_gpio);goto err_alloc;}/** Compatibility fallback for drivers still using the integer GPIO* platform data. Must go away soon.*/if (!pb->enable_gpio && gpio_is_valid(data->enable_gpio)) {ret = devm_gpio_request_one(&pdev->dev, data->enable_gpio,GPIOF_OUT_INIT_HIGH, "enable");if (ret < 0) {dev_err(&pdev->dev, "failed to request GPIO#%d: %d\n",data->enable_gpio, ret);goto err_alloc;}pb->enable_gpio = gpio_to_desc(data->enable_gpio);}/** If the GPIO is not known to be already configured as output, that* is, if gpiod_get_direction returns either GPIOF_DIR_IN or -EINVAL,* change the direction to output and set the GPIO as active.* Do not force the GPIO to active when it was already output as it* could cause backlight flickering or we would enable the backlight too* early. Leave the decision of the initial backlight state for later.*/if (pb->enable_gpio &&gpiod_get_direction(pb->enable_gpio) != GPIOF_DIR_OUT)gpiod_direction_output(pb->enable_gpio, 1);pb->power_supply = devm_regulator_get(&pdev->dev, "power");if (IS_ERR(pb->power_supply)) {ret = PTR_ERR(pb->power_supply);goto err_alloc;}pb->pwm = devm_pwm_get(&pdev->dev, NULL);if (IS_ERR(pb->pwm) && PTR_ERR(pb->pwm) != -EPROBE_DEFER && !node) {dev_err(&pdev->dev, "unable to request PWM, trying legacy API\n");pb->legacy = true;pb->pwm = pwm_request(data->pwm_id, "pwm-backlight");}if (IS_ERR(pb->pwm)) {ret = PTR_ERR(pb->pwm);if (ret != -EPROBE_DEFER)dev_err(&pdev->dev, "unable to request PWM\n");goto err_alloc;}dev_dbg(&pdev->dev, "got pwm for backlight\n");/** FIXME: pwm_apply_args() should be removed when switching to* the atomic PWM API.*/pwm_apply_args(pb->pwm);/** The DT case will set the pwm_period_ns field to 0 and store the* period, parsed from the DT, in the PWM device. For the non-DT case,* set the period from platform data if it has not already been set* via the PWM lookup table.*/pwm_get_args(pb->pwm, &pargs);pb->period = pargs.period;if (!pb->period && (data->pwm_period_ns > 0))pb->period = data->pwm_period_ns;pb->lth_brightness = data->lth_brightness * (pb->period / pb->scale);memset(&props, 0, sizeof(struct backlight_properties));props.type = BACKLIGHT_RAW;props.max_brightness = data->max_brightness;bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,&pwm_backlight_ops, &props);if (IS_ERR(bl)) {dev_err(&pdev->dev, "failed to register backlight\n");ret = PTR_ERR(bl);if (pb->legacy)pwm_free(pb->pwm);goto err_alloc;}if (data->dft_brightness > data->max_brightness) {dev_warn(&pdev->dev,"invalid default brightness level: %u, using %u\n",data->dft_brightness, data->max_brightness);data->dft_brightness = data->max_brightness;}bl->props.brightness = data->dft_brightness;bl->props.power = pwm_backlight_initial_power_state(pb);backlight_update_status(bl);platform_set_drvdata(pdev, bl);return 0;err_alloc:if (data->exit)data->exit(&pdev->dev);return ret;
}

probe里有几个重要的函数,这里按照调用顺序,依次进行阐述:

pwm_backlight_probe-> pwm_backlight_parse_dt //拿到dts里定义的brightness-levels和default-brightness-level,前者用来应用层控制不同的背光亮度,后者在初始化时会使能一个默认的背光亮度-> devm_gpiod_get_optional //实际上就是封装了 gpio_request_one-> devm_gpio_request_one   //申请背光使能 gpio-> devm_pwm_get ->     /drivers/pwm/core.c //获得一个pwm-> pwm_request       //申请pwm,防止其他驱动也会使用.-> backlight_device_register -> /drivers/video/baklight/backlight.c  //注册标准背光设备static const struct backlight_ops pwm_backlight_ops = {.update_status	= pwm_backlight_update_status,.check_fb	= pwm_backlight_check_fb,};-> pwm_backlight_update_status-> compute_duty_cycle  //计算占空比-> pwm_backlight_power_on    //enable背光-> backlight_update_status ->   //用默认值更新.

compute_duty_cycle函数计算占空比:

static int compute_duty_cycle(struct pwm_bl_data *pb, int brightness)
{/*一般情况下这个值都为0*/unsigned int lth = pb->lth_brightness;/*占空比*/int duty_cycle;/*pb->levels这个表格就是从dts节点brightness-levels中获取的,假设进来的参数brightness是254,那么得到的duty_cycle就是1,如果没有这个表格,那么就直接是进来的亮度值.*/if (pb->levels)duty_cycle = pb->levels[brightness];elseduty_cycle = brightness;/*假设这里lth是0,那么公式就是duty_cycle * pb->period / pb->scalepb->period也就是dts节点 pwms 的第三个参数周期值为 25000pb->scale为pb->levels数组中的最大值所以这个公式就是按照将Android的纯数值转换成事件周期值对应的占空比.*/return (duty_cycle * (pb->period - lth) / pb->scale) + lth;
}

pwm_backlight_power_on 函数通过去拉背光的gpio enable背光

static void pwm_backlight_power_on(struct pwm_bl_data *pb)
{struct pwm_state state;int err;pwm_get_state(pb->pwm, &state);if (pb->enabled)return;err = regulator_enable(pb->power_supply);if (err < 0)dev_err(pb->dev, "failed to enable power supply\n");state.enabled = true;pwm_apply_state(pb->pwm, &state);if (pb->post_pwm_on_delay)msleep(pb->post_pwm_on_delay);if (pb->enable_gpio)gpiod_set_value(pb->enable_gpio, 1);  pb->enabled = true;
}

LCD背光驱动,导出给应用层控制背光的brightness、bl_power、actual_brightness等节点

路径:kernel-5.10\drivers\video\backlight\backlight.c

再backlight.c文件里面会给应用层控制背光的brightness、bl_power、actual_brightness等节点

 对应于/sys/class/backlight,提供属性和操作函数。

/sys/class/backlight/lcd_backlight@0
cat max_brightness		//获取最大的亮度:100
cat actual_brightness	//获取实际的亮度:80
echo 100 > brightness	//设置亮度为100
echo 80 > brightness	//设置亮度为80
static ssize_t bl_power_show(struct device *dev, struct device_attribute *attr,char *buf)
{struct backlight_device *bd = to_backlight_device(dev);return sprintf(buf, "%d\n", bd->props.power);
}static ssize_t bl_power_store(struct device *dev, struct device_attribute *attr,const char *buf, size_t count)
{int rc;struct backlight_device *bd = to_backlight_device(dev);unsigned long power, old_power;rc = kstrtoul(buf, 0, &power);if (rc)return rc;rc = -ENXIO;mutex_lock(&bd->ops_lock);if (bd->ops) {pr_debug("set power to %lu\n", power);if (bd->props.power != power) {old_power = bd->props.power;bd->props.power = power;rc = backlight_update_status(bd);if (rc)bd->props.power = old_power;elserc = count;} else {rc = count;}}mutex_unlock(&bd->ops_lock);return rc;
}
static DEVICE_ATTR_RW(bl_power);static struct attribute *bl_device_attrs[] = {&dev_attr_bl_power.attr,&dev_attr_brightness.attr,&dev_attr_actual_brightness.attr,&dev_attr_max_brightness.attr,&dev_attr_scale.attr,&dev_attr_type.attr,NULL,
};
ATTRIBUTE_GROUPS(bl_device);

以bl_power为例:最终调用backlight_update_status()来调节背光。

三.应用程序调节背光

下面的两种方式都可以使用backlight节点来控制背光。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>#define LCD_BACKLIGHT "/sys/class/backlight/lcd_backlight@0/brightness"int main(int argc, char *argv[])
{
#if 0int fd;char *testwrite = "/sys/class/backlight/lcd_backlight@0/brightness";ssize_t len_w;char buf_w[] = "10";//if((fd = open("/sys/class/backlight/lcd_backlight@0/brightness", O_RDWR))<0){/* open()可以带2/3个参数 *///if((fd = open(testwrite,O_RDWR,0777))<0){if((fd = open(LCD_BACKLIGHT, O_RDWR, 0777)) <0 ){printf("open %s failed!\n",testwrite);}//len_w = write(fd, "99", 2);len_w = write(fd, buf_w, strlen(buf_w));if(len_w == -1){perror("write");}  else{printf("write function ok!\n");}close(fd);#elseFILE * fp =fopen("/sys/class/backlight/lcd_backlight@0/brightness","w");if (fp == NULL)perror("export open filed");elsefprintf(fp,"%d",100);fclose(fp);
#endifreturn 0;
}

相关文章:

RK3568平台(背光篇)背光驱动代码分析

一.背光驱动设备树DTS backlight: backlight {compatible "pwm-backlight";pwms <&pwm1 0 5555555 1>;brightness-levels <77 77 78 78 79 79 80 8182 83 84 85 86 87 87 8888 89 90 90 91 91 92 9394 94 95 95 96 96 9…...

华为od统一考试B卷【比赛】python实现

def split_params(param_str): return list(map(int, param_str.split(,))) def main(): # 获取输入 target_str input().strip() # 输入验证&#xff0c;拆分并转换为整数 try: m, n split_params(target_str) except ValueError: print(-1) return # 检查 M 和 …...

Prometheus 监控接入规范

目录 一、目的 二、自定义监控指标定义规范 2.1 基本命名规范 2.1.1 指标命名规范 2.1.2 标签名称 2.2 控制基数 2.2.1 避免高基数标签 2.2.2 预定义标签集 2.2.3 动态数据的处理 2.2.4 评估与监控基数 2.2.5 降低历史数据的保留 2.2.6 适当使用 Histogram 和 Summa…...

优化 SQL 查询性能:深入理解 EXPLAIN 命令

优化 SQL 查询性能:深入理解 EXPLAIN 命令 在 MySQL 数据库管理中,优化 SQL 查询性能是确保高效数据处理的关键。EXPLAIN 命令是分析和优化 SQL 查询的强大工具,它帮助我们理解查询执行计划,从而找到性能瓶颈并进行优化。本文将详细解释 EXPLAIN 命令返回的各个列的含义,…...

@Mapper报红

检查pom.xml&#xff0c;导入 org.mybatis.spring.boot 依赖&#xff1a; <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.3</version></dependency…...

shell综合小实验1-----查看系统硬件信息

echo命令的使用 1&#xff1a;echo -n 不换行 echo -n “我是个大聪明” #不换行输入我是大聪明 2&#xff1a;echo -e 开启颜色 echo -e "\03335m我是大聪明\033[0m" #用35m这种颜色输出我是大聪明然后关闭颜色显示&#xff0c; 30多是字体颜色&#xff0c;40多是…...

【过程管理】项目需求管理规程(Word原件)

在软件开发的过程中&#xff0c;开发人员与用户之间往往忽视有效的信息沟通&#xff0c;这常常导致开发出的软件无法满足用户的实际需求&#xff0c;进而引发不必要的返工。返工不仅为开发人员带来技术上的困扰&#xff0c;增加了人力和物力的消耗&#xff0c;还会对软件的整体…...

C# 不使用 `async` 和 `await` 的常见场景

虽然 async 和 await 是强大的异步编程工具&#xff0c;但在某些情况下&#xff0c;不使用它们可能更合适。以下是一些不使用 async 和 await 的常见场景&#xff1a; 方法是完全同步的&#xff1a; 如果方法中的所有操作都是同步的&#xff0c;并且没有异步调用&#xff0c;则…...

adb目录笔记《adb更新、进入开发者模式,adb查询packages、adb开启应用,查询进程、强制删除进程》

1.sideload模式 在需要安卓没有root权限的时候&#xff0c;可以使用adb reboot sideload命令进入sideload模式&#xff0c;之后运行对应文件 adb reboot sideload adb sideload <root.zip> 2.packages包查询、运行、删除 在需要查看安卓中packages包的名称时&#xf…...

VS2022 C++ EasyX EGE 吃豆人升级版

我是可爱的C小盆友&#xff08;不要脸了&#xff09;&#xff0c;嘻嘻&#xff0c;等了这么久&#xff0c;吃豆人终于升级啦&#xff01; 更新日志&#xff1a; 1.修复奇奇怪怪的bug 2.把敌人AI增强了一&#xff08;hen&#xff09;点&#xff08;duo&#xff09; 3.加入了…...

计算机图形学 | 动画模拟

动画模拟 布料模拟 质点弹簧系统&#xff1a; 红色部分很弱地阻挡对折 Steep connection FEM:有限元方法 粒子系统 粒子系统本质上就是在定义个体和群体的关系。 动画帧率 VR游戏要不晕需要达到90fps Forward Kinematics Inverse Kinematics 只告诉末端p点&#xff0c;中间…...

B2.3 Arm 内存模型定义

B2.3 Arm 内存模型定义 Arm 内存模型引入了以下几种关系: 内在关系 :例如,内在数据/控制/顺序依赖关系和内在翻译之前的关系,这些是源自指令语义的硬件要求。 之后关系 :例如,之后的连贯性和 TLB 之后的关系,这些关系在特定执行中发生这种方式,但在不同的执行中可以以…...

(javaweb)SpringBootWeb案例(毕业设计)案例--部门管理

目录 1.准备工作 2.部门管理--查询功能 3.前后端联调 3.部门管理--新增功能 1.准备工作 mapper数据访问层相当于dao层 根据页面原型和需求分析出接口文档--前后端必须遵循这种规范 大部分情况下 接口文档由后端人员来编写 前后端进行交互基于restful风格接口 http的请求方式…...

PCL 采样一致性模型介绍

采样一致性可以简单高效的检测出一些具有数学表达式的目标模型。PCL中的sample consensus模块中不仅包含各种的采样一致性估计方法,也包含一些已经编写好的数学模型,下面主要介绍一下PCL中的采样一致性模型。 1. 二维圆模型 pcl::SampleConsensusModelCircle2D< PointT …...

Unity手游开放大世界解决方案

开个新坑了&#xff0c;分享一个手游开放大世界的解决方案&#xff0c;也算是我开发研究了一年多的结果吧。之前项目需要&#xff0c;做了一整套的手游开放大世界解决方案&#xff0c;这里做一个总结归纳&#xff0c;将所需要的技术栈和解决方案等汇总。 这篇文章只是起头一个目…...

mysql B+ 树

问题&#xff1a; mysql innodb引擎 B树主键自增&#xff0c;插入数据时是从中间分裂&#xff0c;还是使用页尾部元素作为父节点的值然后添加一个新页&#xff0c;或者说主键连续自增&#xff0c;mysql有没有做这样的优化&#xff1f; 以下是Chat GPT给出的回答&#xff1a;...

Sublime Text常用快捷键大全

Sublime Text 是一款功能强大且广受欢迎的文本编辑器&#xff0c;其丰富的快捷键支持使得开发者能够更高效地编写和编辑代码。以下是 Sublime Text 中一些常用的快捷键&#xff0c;帮助你更加高效地使用这款工具&#xff1a; 功能分类快捷键 (Windows)快捷键 (Mac)新建文件Ctr…...

中成科信票务管理系统 TicketManager.ashx接口SQL注入漏洞复现 [附POC]

文章目录 中成科信票务管理系统 TicketManager.ashx接口SQL注入漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现0x06 修复建议中成科信票务管理系统 TicketManager.ashx接口SQL注入漏洞复现 [附POC] 0x01 前言 …...

设计模式六大原则之:依赖倒置原则

1. 依赖倒置原则简介 依赖倒置原则(Dependency Inversion Principle, DIP) 是面向对象设计的核心原则之一&#xff0c;由罗伯特马丁(Robert C. Martin)提出&#xff0c;旨在降低类间的依赖度&#xff0c;使之更易于维护和扩展。该原则主张高层模块不应该依赖于底层模块&#x…...

06_Linux中如何让程序重启后自动启动

Linux中如何让程序重启后自动启动 systemd单元文件1.创建服务文件&#xff01;&#xff01;&#xff01;服务配置文件的介绍 2.需要配置服务的状态&#xff08;加载和启用服务&#xff09;3.验证服务程序的运行状态4.打印程序的标准输出 systemd单元文件 Systemd 是现代 Linux…...

优化业务流程的关键:深入探讨BPA流程设计

在当前竞争激烈的商业环境中&#xff0c;业务流程自动化&#xff08;BPA&#xff09;已经成为企业提升效率、减少成本和提高业务灵活性的关键工具。今天&#xff0c;我们将深入探讨BPA流程设计的重要性及其实施步骤&#xff0c;为企业提供实用的指南。 什么是BPA&#xff1f; …...

qt工程中调用sdl的流程

配置 Qt 工程 在你的 Qt 工程中&#xff0c;需要对项目文件&#xff08;.pro 文件&#xff09;进行配置&#xff0c;以包含 SDL 库的路径和链接选项。 # Qt Project File (.pro)# 设置 SDL 库的路径 INCLUDEPATH /path/to/SDL/include LIBS -L/path/to/SDL/lib -lSDL2初始化…...

ECMAScript性能优化技巧与陷阱

​ 大家好&#xff0c;我是程序员小羊&#xff01; 前言 ECMAScript&#xff0c;即JavaScript&#xff0c;是一种广泛应用于Web开发中的脚本语言。随着现代Web应用的复杂度日益增加&#xff0c;如何优化JavaScript的性能变得至关重要。性能优化不仅能提高应用的响应速度&#x…...

c++实现B树(上)

哈喽啊&#xff01;好久不见&#xff0c;甚是想念&#xff01;失踪人口要回归了&#xff0c;时隔一个多月小吉我终于要更新blog了&#x1f389;。在停更的一个多月中&#xff0c;小吉也有在好好学习提升自己&#xff0c;立志给大家呈现好文章。  现在让我们进入正题吧&#xf…...

【机器学习】深度强化学习–RL的基本概念、经典场景以及算法分类

引言 深度强化学习&#xff08;Deep Reinforcement Learning, DRL&#xff09;是机器学习的一个分支&#xff0c;它结合了深度学习&#xff08;Deep Learning&#xff09;和强化学习&#xff08;Reinforcement Learning, RL&#xff09;的技术 文章目录 引言一、深度强化学习–…...

【git】将本地文件上传到github

安装git 选择一个文件夹作为git仓库&#xff0c;cd到文件夹输入 git init文件夹出现.git文件夹&#xff0c;该文件夹默认为隐藏文件夹&#xff0c;设置为不隐藏 在cmd中输入 ssh-keygen -t rsa -C "xxxxxx.com"该邮箱为github邮箱&#xff0c;然后一路enter出现以…...

安卓应用开发学习:手机摇一摇功能应用尝试--摇骰子和摇红包

一、引言 前几天&#xff0c;我发布的日志《安卓应用开发学习&#xff1a;查看手机传感器信息》记录了如何查看手机传感器的信息&#xff0c;通过上述的方法&#xff0c;可以看到我的OPPO手机支持19种传感器。本篇日志就记录一下常见的加速度传感器的典型应用——“摇一摇”功…...

HTML中的<fieldset>标签元素框的使用

HTML 提供的 <fieldset> 标签用于在表单中分组相关元素。 <fieldset> 标签会在相关元素周围绘制一个框。 <legend> 标签为 fieldset 元素定义标题。 语法如下&#xff1a; <fieldset><legend>标题</legend><!-- 元素内容... -->…...

Linux驱动入门实验班——SR501红外模块驱动(附百问网视频链接)

目录 一、工作方式 二、接口图 三、编写思路 1.构造file_operations结构体 2.实现read函数 3.编写入口函数 4.编写中断处理函数 5.编写出口函数 6.声明出入口函数以及协议 四、源码 五、课程链接 一、工作方式 SR501人体红外感应模块有两种工作模式&#xff1a; …...

windows C++- Com技术简介(上)

在介绍C和winrt与COM组件技术的关系之前&#xff0c;有必要介绍一下com组件技术&#xff0c;这项技术比较古老&#xff0c;但是它一直作为windows的基石存在。COM 是一类独立于平台且面向对象的分布式系统&#xff0c;用于创建可交互的二进制软件组件。 COM 技术是 Microsoft O…...