linux pwm 调屏_[Linux] pwm设备驱动调试

该博客详细介绍了如何在Linux下使用PWM进行屏幕亮度调节,包括定义的PWM控制宏、结构体、函数以及设备节点操作,通过设备树配置和内核驱动实现PWM的周期、占空比设置以及启用禁用功能。
摘要由CSDN通过智能技术生成

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define PWM_LASER_SET_PERIOD _IOW('A', 0x11, unsigned int)

#define PWM_LASER_GET_PERIOD _IOR('A', 0x12, unsigned int)

#define PWM_LASER_SET_DUTY _IOW('A', 0x13, unsigned int)

#define PWM_LASER_GET_DUTY _IOR('A', 0x14, unsigned int)

#define PWM_LASER_ENABLE _IO('A', 0x15)

#define PWM_LASER_DISABLE _IO('A', 0x16)

struct pwm_para {

int pwm_id;

unsigned int period;

unsigned int level;

unsigned int duty;

struct pwm_device *pwm;

};

struct pwm_para laser;

static void pwm_laser_update(void)

{

laser.duty = laser.level * laser.period / 100;

pwm_config(laser.pwm, laser.duty, laser.period);

}

static void pwm_laser_enable(void)

{

pwm_enable(laser.pwm);

}

static void pwm_laser_disable(void)

{

// 关闭pwm之前将占空比设置为0

laser.level = 0;

pwm_laser_update();

pwm_disable(laser.pwm);

}

static void pwm_laser_set_period(unsigned int period)

{

laser.period = period * 1000000;

pwm_set_period(laser.pwm, laser.period);

}

static unsigned int pwm_laser_get_period(void)

{

return (laser.period / 1000000);

}

static int pwm_laser_open(struct inode *inode, struct file *filp)

{

return 0;

}

static int pwm_laser_release(struct inode *inode, struct file *filp)

{

pwm_laser_disable();

return 0;

}

static ssize_t pwm_laser_read(struct file *filp, char __user *buf, size_t len, loff_t *pos)

{

return 0;

}

static ssize_t pwm_laser_write(struct file *filp, const char __user *buf, size_t len, loff_t *pos)

{

return 0;

}

static long pwm_laser_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)

{

unsigned int period;

unsigned int level;

void __user *argp = (void __user *)arg;

switch (cmd)

{

case PWM_LASER_SET_PERIOD:

if (argp == NULL) {

printk("laser: invalid argument.");

return -EINVAL;

}

if (copy_from_user(&period, argp, sizeof(unsigned int))) {

printk("copy_from_user failed.");

return -EFAULT;

}

pwm_laser_set_period(period);

break;

case PWM_LASER_GET_PERIOD:

period = pwm_laser_get_period();

if (copy_to_user(argp, &period, sizeof(unsigned int))) {

printk("copy_to_user failed.");

return -EFAULT;

}

break;

case PWM_LASER_SET_DUTY :

if (argp == NULL) {

printk("laser: invalid argument.");

return -EINVAL;

}

if (copy_from_user(&level, argp, sizeof(unsigned int))) {

printk("copy_from_user failed.");

return -EFAULT;

}

if ((level < 0) || (level > 100)) {

printk("laser: invalid argument.");

return -EINVAL;

}

laser.level = level;

pwm_laser_update();

break;

case PWM_LASER_GET_DUTY :

if (copy_to_user(argp, &laser.level, sizeof(unsigned int))) {

printk("copy_to_user failed.");

return -EFAULT;

}

break;

case PWM_LASER_ENABLE:

pwm_laser_update();

pwm_laser_enable();

break;

case PWM_LASER_DISABLE:

pwm_laser_disable();

break;

default:

printk("laser: cmd error!\n");

return -EFAULT;

}

return 0;

}

struct file_operations pwm_laser_fops = {

.owner = THIS_MODULE,

.open = pwm_laser_open,

.release = pwm_laser_release,

.write = pwm_laser_write,

.read = pwm_laser_read,

.unlocked_ioctl = pwm_laser_ioctl,

};

struct miscdevice pwm_laser_dev =

{

.minor = MISC_DYNAMIC_MINOR,

.fops = &pwm_laser_fops,

.name = "pwm-laser",

};

static ssize_t pwm_laser_parse_dt(struct platform_device *pdev)

{

struct device_node *node = pdev->dev.of_node;

int ret;

if (!node) {

dev_err(&pdev->dev, "laser: Device Tree node missing\n");

return -EINVAL;

}

ret = of_property_read_u32(node, "pwm-id", &laser.pwm_id);

if (ret < 0) {

dev_err(&pdev->dev, "laser: pwm-id missing\n");

return ret;

}

ret = of_property_read_u32(node, "period", &laser.period);

if (ret < 0) {

dev_err(&pdev->dev, "laser: period missing\n");

return ret;

}

ret = of_property_read_u32(node, "default-level", &laser.level);

if (ret < 0) {

dev_err(&pdev->dev, "laser: default-level missing\n");

return ret;

}

return 0;

}

static void pwm_laser_test(void)

{

int i = 0, dir = 0;

pwm_laser_enable();

while (1)

{

if (dir == 0) {

laser.level = i++;

if (i == 100)

dir = 1;

} else {

laser.level = i--;

if (i == 0)

dir = 0;

}

pwm_laser_update();

msleep(100);

}

pwm_laser_disable();

}

static int pwm_laser_probe(struct platform_device *pdev)

{

int ret;

ret = pwm_laser_parse_dt(pdev);

if (ret < 0) {

dev_err(&pdev->dev, "laser: Device not found\n");

return -ENODEV;

}

laser.pwm = pwm_request(laser.pwm_id, "pwm-laser");

if (IS_ERR(laser.pwm)) {

dev_err(&pdev->dev, "laser: unable to request legacy PWM\n");

ret = PTR_ERR(laser.pwm);

return ret;

}

// 设置pwm参数

pwm_laser_update();

// 设置极性必须在设置参数之后,pwm使能之前,否则会设置失败

ret = pwm_set_polarity(laser.pwm, PWM_POLARITY_NORMAL);

if (ret < 0)

printk("pwm set polarity fail, ret = %d\n", ret);

// 调试完屏蔽使能函数,交由app控制

// pwm_laser_enable();

misc_register(&pwm_laser_dev);

// 调试完屏蔽测试函数

// pwm_laser_test();

return 0;

}

static int pwm_laser_remove(struct platform_device *pdev)

{

pwm_disable(laser.pwm);

pwm_free(laser.pwm);

misc_deregister(&pwm_laser_dev);

return 0;

}

int pwm_laser_suspend(struct device *dev)

{

return 0;

}

int pwm_laser_resume(struct device *dev)

{

return 0;

}

const struct dev_pm_ops pwm_laser_pm_ops = {

.suspend = pwm_laser_suspend,

.resume = pwm_laser_resume,

};

static const struct of_device_id of_pwm_laser_match[] = {

{.compatible = "pwm-laser", },

{},

};

static struct platform_driver pwm_laser = {

.probe = pwm_laser_probe,

.remove = pwm_laser_remove,

.driver = {

.name = "pwm-laser",

.owner = THIS_MODULE,

.pm = &pwm_laser_pm_ops,

.of_match_table = of_match_ptr(of_pwm_laser_match),

},

};

module_platform_driver(pwm_laser);

MODULE_DESCRIPTION("pwm control driver");

MODULE_LICENSE("GPL");

MODULE_AUTHOR("AaronLee");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值