欢迎扫码关注本人微信公众号:公众号上分享更多嵌入式知识和资料,分享个人学习嵌入式的心得体会。欢迎大家一起来玩呀。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>#include <linux/delay.h>
#include <linux/err.h>#include <linux/spi/spi.h>
#include <linux/timer.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>#include <linux/workqueue.h>
#include <linux/platform_device.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/platform_data/spi-rockchip.h>#include <linux/delay.h>#include <dt-bindings/gpio/gpio.h>#ifdef CONFIG_OF
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#endif#define pga2311_spi_speed 5000000struct pga2311_data_t{struct spi_device *spi;int gpio_mute;int gpio_mute_is_valid;int gpio_mute_output;int gpio_zce; //zero crossing enable pinint gpio_zce_is_valid;int gpio_zce_output;uint8_t right_volume;uint8_t left_volume;
}; static DEFINE_MUTEX(pga2311_global_lock);
static struct pga2311_data_t *p_pga2311_data = NULL;/*
* This function write wk2xxx of Global register:
*/
static int pga2311_write_global_reg(struct spi_device *spi,uint8_t right_volume,uint8_t left_volume) {struct spi_message msg;uint8_t volume[2];int status;struct spi_transfer index_xfer = {.len = 2,.speed_hz = pga2311_spi_speed,};mutex_lock(&pga2311_global_lock);spi_message_init(&msg);/* register index */volume[0] = right_volume;volume[1] = left_volume;_buf = volume;spi_message_add_tail(&index_xfer, &msg);status = spi_sync(spi, &msg);mutex_unlock(&pga2311_global_lock);if (status) {printk(KERN_ERR "%s!!status=%d!---n", __func__,status);}return status;
}static int pga2311_read_global_reg(struct spi_device *spi,uint8_t *right_volume,uint8_t *left_volume) { struct spi_message msg;uint8_t buf_rdat[2];int status;struct spi_transfer index_xfer = {.len = 2,.speed_hz = pga2311_spi_speed,};mutex_lock(&pga2311_global_lock);status =0;spi_message_init(&msg);_buf =(void *) buf_rdat;spi_message_add_tail(&index_xfer, &msg);status = spi_sync(spi, &msg);mutex_unlock(&pga2311_global_lock);if (status) {printk(KERN_ERR "%s!!status=%d!---n", __func__,status);return status;}*right_volume = buf_rdat[0];*left_volume = buf_rdat[1];return 0;
}static ssize_t pga2311_mute_store(struct device *dev, struct device_attribute *attr,const char *buf, size_t count) {struct pga2311_data_t *pdata = p_pga2311_data; printk(KERN_ERR "pga2311_mute_store %s n",buf);if (buf[0] == '0') {pdata->gpio_mute_output = 0;gpio_direction_output(pdata->gpio_mute, pdata->gpio_mute_output);}else if (buf[0] == '1') {pdata->gpio_mute_output = 1;gpio_direction_output(pdata->gpio_mute, pdata->gpio_mute_output);} printk(KERN_ERR "gpio_mute_output %d n",pdata->gpio_mute_output); return count;
}static ssize_t pga2311_zce_store(struct device *dev, struct device_attribute *attr,const char *buf, size_t count) {struct pga2311_data_t *pdata = p_pga2311_data; printk(KERN_ERR "pga2311_zce_store %s n",buf);if (buf[0] == '0') {pdata->gpio_zce_output = 0;gpio_direction_output(pdata->gpio_zce, pdata->gpio_zce_output);}else if (buf[0] == '1') {pdata->gpio_zce_output = 1;gpio_direction_output(pdata->gpio_zce, pdata->gpio_zce_output);}printk(KERN_ERR "gpio_zce_output %d n",pdata->gpio_zce_output); return count;
}static ssize_t pga2311_set_right_volume_store(struct device *dev, struct device_attribute *attr,const char *buf, size_t count) {struct pga2311_data_t *pdata = p_pga2311_data;int num;printk(KERN_ERR "pga2311_set_right_volume_store %s n",buf);num = simple_strtol(buf, NULL, 0);if ( !(num >= 0 && num <= 255))return count;pdata->right_volume = num; pga2311_write_global_reg(pdata->spi,pdata->right_volume,pdata->left_volume); return count;
}static ssize_t pga2311_set_left_volume_store(struct device *dev, struct device_attribute *attr,const char *buf, size_t count) {struct pga2311_data_t *pdata = p_pga2311_data;int num;printk(KERN_ERR "pga2311_set_left_volume_store %s n",buf);num = simple_strtol(buf, NULL, 0);if ( !(num >= 0 && num <= 255))return count;pdata->left_volume = num;pga2311_write_global_reg(pdata->spi,pdata->right_volume,pdata->left_volume);return count;
}static ssize_t pga2311_set_right_volume_show(struct device *dev, struct device_attribute *attr,char *buf) {uint8_t right_volume = 0;uint8_t left_volume = 0; struct pga2311_data_t *pdata = p_pga2311_data;pga2311_read_global_reg(pdata->spi,&right_volume,&left_volume);pga2311_write_global_reg(pdata->spi,pdata->right_volume,pdata->left_volume);return snprintf(buf, PAGE_SIZE, "%dn",right_volume);
}static ssize_t pga2311_set_left_volume_show(struct device *dev, struct device_attribute *attr,char *buf) { uint8_t right_volume = 0;uint8_t left_volume = 0; struct pga2311_data_t *pdata = p_pga2311_data;pga2311_read_global_reg(pdata->spi,&right_volume,&left_volume);pga2311_write_global_reg(pdata->spi,pdata->right_volume,pdata->left_volume);return snprintf(buf, PAGE_SIZE, "%dn",left_volume);
}static struct device_attribute pga2311_attr[] = {__ATTR(set_mute_gpio_direction, 0664, NULL, pga2311_mute_store),__ATTR(set_zce_gpio_direction, 0664, NULL, pga2311_zce_store),__ATTR(right_volume, 0664, pga2311_set_right_volume_show, pga2311_set_right_volume_store),__ATTR(left_volume, 0664, pga2311_set_left_volume_show, pga2311_set_left_volume_store),
};static void pga2311_init_sysfs(struct device *dev)
{int i, ret;for (i = 0; i < ARRAY_SIZE(pga2311_attr); i++) {ret = sysfs_create_file(&dev->kobj,&pga2311_attr[i].attr);if (ret)dev_err(dev, "create charger node(%s) errorn",pga2311_attr[i].attr.name);}
}static int pga2311_parse_dt(struct pga2311_data_t *pdata)
{int gpio;enum of_gpio_flags flags;struct device *dev = &pdata->spi->dev;int ret;struct device_node *node = dev->of_node;if (!node)return -ENODEV;gpio = of_get_named_gpio_flags(node, "gpio_mute", 0, &flags);if (gpio_is_valid(gpio)){pdata->gpio_mute = gpio;pdata->gpio_mute_output = (flags == GPIO_ACTIVE_HIGH)? 1:0; printk(KERN_ERR"gpio_mute: %dn", pdata->gpio_mute);ret = devm_gpio_request(dev,gpio, "gpio_mute");if (ret) {printk("Failed to get gpio_mute gpio.n");}pdata->gpio_mute_is_valid = 1;}gpio = of_get_named_gpio_flags(node, "gpio_zero_crossing_enable", 0,&flags);if (gpio_is_valid(gpio)){pdata->gpio_zce = gpio;pdata->gpio_zce_output = (flags == GPIO_ACTIVE_HIGH)? 1:0;printk(KERN_ERR"gpio_zero_crossing_enable: %dn", pdata->gpio_zce);ret = devm_gpio_request(dev,gpio, "gpio_zero_crossing_enable");if (ret) {printk("Failed to get gpio_zero_crossing_enable gpio.n");}pdata->gpio_zce_is_valid = 1;}if (pdata->gpio_mute_is_valid == 1) { //set mute to defaultgpio_direction_output(pdata->gpio_mute, pdata->gpio_mute_output);}if (pdata->gpio_zce_is_valid == 1) { //set zero crossing enable to defaultgpio_direction_output(pdata->gpio_zce, pdata->gpio_zce_output);}return 0;
}static int pga2311_probe(struct spi_device *spi)
{ int ret = 0; if (!spi)return -ENOMEM;dev_err(&spi->dev, "pga2311_probe: setup mode %d, %s%s%s%s%u bits/w, %u Hz maxn",(int) (spi->mode & (SPI_CPOL | SPI_CPHA)),(spi->mode & SPI_CS_HIGH) ? "cs_high, " : "",(spi->mode & SPI_LSB_FIRST) ? "lsb, " : "",(spi->mode & SPI_3WIRE) ? "3wire, " : "",(spi->mode & SPI_LOOP) ? "loopback, " : "",spi->bits_per_word, spi->max_speed_hz);ret = spi_setup(spi);if (ret < 0) {dev_err(&spi->dev,"ERR: fail to setup spin");return -1;}p_pga2311_data = kmalloc(sizeof(struct pga2311_data_t), GFP_KERNEL);if (p_pga2311_data == NULL) {printk(KERN_ERR"kmalloc pga2311_data_t err n");return -ENOMEM;}memset(p_pga2311_data, 0, sizeof(struct pga2311_data_t));p_pga2311_data->spi = spi;if (pga2311_parse_dt(p_pga2311_data)) {printk(KERN_ERR"pga2311_parse_dt err n");goto err;}pga2311_init_sysfs(&p_pga2311_data->spi->dev);return 0;err:kfree(p_pga2311_data);return -1;
}static const struct of_device_id pga2311_dt_match[] = {{ patible = "ti,pga2311", },{ },
};MODULE_DEVICE_TABLE(of, pga2311_dt_match);static struct spi_driver pga2311_driver = {.driver = {.name = "pga2311",.bus = &spi_bus_type,.owner = THIS_MODULE,.of_match_table = of_match_ptr(pga2311_dt_match),},.probe = pga2311_probe,
};static int __init pga2311_init(void)
{int retval;retval = spi_register_driver(&pga2311_driver);printk(KERN_ALERT "%s,register spi return v = :%dn",__func__,retval);return retval;
}static void __exit pga2311_exit(void)
{printk(KERN_ALERT "%s!!--in--n", __func__);return spi_unregister_driver(&pga2311_driver);
}module_init(pga2311_init);
module_exit(pga2311_exit);MODULE_AUTHOR("System Application Group");
MODULE_DESCRIPTION("pga2311 driver");
MODULE_LICENSE("GPL");···
本文发布于:2024-02-04 19:08:29,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170714397258646.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |