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() # 输入验证,拆分并转换为整数 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,导入 org.mybatis.spring.boot 依赖: <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.3</version></dependency…...
shell综合小实验1-----查看系统硬件信息
echo命令的使用 1:echo -n 不换行 echo -n “我是个大聪明” #不换行输入我是大聪明 2:echo -e 开启颜色 echo -e "\03335m我是大聪明\033[0m" #用35m这种颜色输出我是大聪明然后关闭颜色显示, 30多是字体颜色,40多是…...
【过程管理】项目需求管理规程(Word原件)
在软件开发的过程中,开发人员与用户之间往往忽视有效的信息沟通,这常常导致开发出的软件无法满足用户的实际需求,进而引发不必要的返工。返工不仅为开发人员带来技术上的困扰,增加了人力和物力的消耗,还会对软件的整体…...
C# 不使用 `async` 和 `await` 的常见场景
虽然 async 和 await 是强大的异步编程工具,但在某些情况下,不使用它们可能更合适。以下是一些不使用 async 和 await 的常见场景: 方法是完全同步的: 如果方法中的所有操作都是同步的,并且没有异步调用,则…...
adb目录笔记《adb更新、进入开发者模式,adb查询packages、adb开启应用,查询进程、强制删除进程》
1.sideload模式 在需要安卓没有root权限的时候,可以使用adb reboot sideload命令进入sideload模式,之后运行对应文件 adb reboot sideload adb sideload <root.zip> 2.packages包查询、运行、删除 在需要查看安卓中packages包的名称时…...
VS2022 C++ EasyX EGE 吃豆人升级版
我是可爱的C小盆友(不要脸了),嘻嘻,等了这么久,吃豆人终于升级啦! 更新日志: 1.修复奇奇怪怪的bug 2.把敌人AI增强了一(hen)点(duo) 3.加入了…...
计算机图形学 | 动画模拟
动画模拟 布料模拟 质点弹簧系统: 红色部分很弱地阻挡对折 Steep connection FEM:有限元方法 粒子系统 粒子系统本质上就是在定义个体和群体的关系。 动画帧率 VR游戏要不晕需要达到90fps Forward Kinematics Inverse Kinematics 只告诉末端p点,中间…...
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手游开放大世界解决方案
开个新坑了,分享一个手游开放大世界的解决方案,也算是我开发研究了一年多的结果吧。之前项目需要,做了一整套的手游开放大世界解决方案,这里做一个总结归纳,将所需要的技术栈和解决方案等汇总。 这篇文章只是起头一个目…...
mysql B+ 树
问题: mysql innodb引擎 B树主键自增,插入数据时是从中间分裂,还是使用页尾部元素作为父节点的值然后添加一个新页,或者说主键连续自增,mysql有没有做这样的优化? 以下是Chat GPT给出的回答:...
Sublime Text常用快捷键大全
Sublime Text 是一款功能强大且广受欢迎的文本编辑器,其丰富的快捷键支持使得开发者能够更高效地编写和编辑代码。以下是 Sublime Text 中一些常用的快捷键,帮助你更加高效地使用这款工具: 功能分类快捷键 (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) 是面向对象设计的核心原则之一,由罗伯特马丁(Robert C. Martin)提出,旨在降低类间的依赖度,使之更易于维护和扩展。该原则主张高层模块不应该依赖于底层模块&#x…...
06_Linux中如何让程序重启后自动启动
Linux中如何让程序重启后自动启动 systemd单元文件1.创建服务文件!!!服务配置文件的介绍 2.需要配置服务的状态(加载和启用服务)3.验证服务程序的运行状态4.打印程序的标准输出 systemd单元文件 Systemd 是现代 Linux…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...
日常一水C
多态 言简意赅:就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过,当子类和父类的函数名相同时,会隐藏父类的同名函数转而调用子类的同名函数,如果要调用父类的同名函数,那么就需要对父类进行引用&#…...
Ubuntu系统复制(U盘-电脑硬盘)
所需环境 电脑自带硬盘:1块 (1T) U盘1:Ubuntu系统引导盘(用于“U盘2”复制到“电脑自带硬盘”) U盘2:Ubuntu系统盘(1T,用于被复制) !!!建议“电脑…...
LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)
在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...
消防一体化安全管控平台:构建消防“一张图”和APP统一管理
在城市的某个角落,一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延,滚滚浓烟弥漫开来,周围群众的生命财产安全受到严重威胁。就在这千钧一发之际,消防救援队伍迅速行动,而豪越科技消防一体化安全管控平台构建的消防“…...
