RK3368 QN8027 FM发射驱动
之前在做车机相关项目,有FM发射需求,8027这颗芯片,之前大部分都是在单片机使用,很少在linux系统使用,我把他移植成了linux驱动,以下为参考:
#include <linux/hrtimer.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/async.h>
#include <linux/irq.h>
#include <linux/workqueue.h>
#include <linux/proc_fs.h>
#include <linux/version.h>
#include <linux/of_gpio.h>
#include <linux/miscdevice.h>
#include <asm/setup.h>
#include <linux/regulator/machine.h>
#include <linux/sensor-dev.h>
#include <linux/cdev.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/kdev_t.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include<linux/fs.h>
#include<linux/string.h>
#include<asm/uaccess.h>
#include <dt-bindings/gpio/gpio.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/termios.h>
#include "QN8027.h"
#define QN8027_I2C_NAME "QN8027"
#define QN8027_I2C_ADDR 0x58
#define QN8027_DEV_NAME "QN8027"
static int qn8027_fm_write(struct i2c_client *client, u8 addr, u8 *pdata, int datalen);
static int qn8027_fm_read(struct i2c_client *client, u8 addr, u8 *pdata, unsigned int datalen);
void QNF_SetRegBit(struct i2c_client *client,u8 reg, u8 bitMask, u8 data_val) ;
u16 QNF_GetCh(struct i2c_client *client) ;
void QN_ChipInitialization(struct i2c_client *client);
UINT8 QNF_SetCh(struct i2c_client *client,u16 freq) ;
void QN_ChipInitialization(struct i2c_client *client);
static struct i2c_client *Gol_client;
struct proc_dir_entry *qn8027_extend_dir;
extern void es8316_spk_ctrl(int level);
static int qn8027_fm_write(struct i2c_client *client, u8 addr, u8 *pdata, int datalen)
{
int ret = 0;
u8 tmp_buf[128];
unsigned int bytelen = 0;
if (datalen > 125)
{
printk("%s too big datalen = %d!\n", __func__, datalen);
return -1;
}
tmp_buf[0] = addr;
bytelen++;
if (datalen != 0 && pdata != NULL)
{
memcpy(&tmp_buf[bytelen], pdata, datalen);
bytelen += datalen;
}
ret = i2c_master_send(client, tmp_buf, bytelen);
return ret;
}
static int qn8027_fm_read(struct i2c_client *client, u8 addr, u8 *pdata, unsigned int datalen)
{
int ret = 0;
if (datalen > 126)
{
printk("%s too big datalen = %d!\n", __func__, datalen);
return -1;
}
ret = qn8027_fm_write(client, addr, NULL, 0);
if (ret < 0)
{
printk("%s set data address fail!\n", __func__);
return ret;
}
return i2c_master_recv(client, pdata, datalen);
}
void QNF_SetRegBit(struct i2c_client *client,u8 reg, u8 bitMask, u8 data_val)
{
u8 temp;
int ret;
ret= qn8027_fm_read(client,reg,&temp,sizeof(temp));
temp &= (u8)(~bitMask);
temp |= data_val & bitMask;
qn8027_fm_write(client, reg, &temp, 1);
}
UINT8 QNF_SetCh(struct i2c_client *client,u16 freq)
{
// calculate ch parameter used for register setting
UINT8 tStep;
UINT8 tCh;
UINT16 f;
f = FREQ2CHREG(freq);
// set to reg: CH
tCh = (UINT8) f;
qn8027_fm_write(client,CH, &tCh,1);
// set to reg: CH_STEP
qn8027_fm_read(client,CH_STEP,&tStep,1);
tStep &= ~CH_CH;
tStep |= ((UINT8) (f >> 8) & CH_CH);
qn8027_fm_write(client,CH_STEP, &tStep,1);
return 1;
}
u16 QNF_GetCh(struct i2c_client *client)
{
u8 tCh;
u8 tStep;
u16 ch = 0;
// set to reg: CH_STEP
qn8027_fm_read(client,CH_STEP,&tStep,1);
tStep &= CH_CH;
printk("Step &= CH_CH; ==== %d\n",tStep);
ch = tStep ;
printk(" ch = tStep ; ==== %d\n",ch);
qn8027_fm_read(client,CH,&tCh,1);
printk(" ch = tCh ; ==== %d\n",tCh);
ch = (ch<<8)+tCh;
printk("(ch<<8)+tCh; ==== %d\n",ch);
return CHREG2FREQ(ch);
}
void QN_ChipInitialization(struct i2c_client *client)
{
u8 write_buf;
u8 read_buf;
int ret = 0;
//write_buf = 0x81;
//ret = qn8027_fm_write(client, 0x00, &write_buf, 1);
//msleep(200);
write_buf = 0x20;
ret = qn8027_fm_write(client, 0x03, &write_buf, 1);
msleep(200);
write_buf = 0x21;
ret = qn8027_fm_write(client, 0x04, &write_buf, 1);
msleep(200);
QNF_SetRegBit(client,0x00,0x40,0x40);
msleep(200); //delay 20 ms
write_buf = 0xe4;
ret = qn8027_fm_write(client, 0x18, &write_buf, 1);
msleep(200);
write_buf = 0xf0;
qn8027_fm_write(client, 0x1b, &write_buf, 1);
msleep(200);
write_buf = 0xB9;
ret = qn8027_fm_write(client, 0x02, &write_buf, 1);
msleep(200);
write_buf = 0x20;
ret = qn8027_fm_write(client, 0x00, &write_buf, 1);
ret= qn8027_fm_read(client,0x00,&read_buf,sizeof(read_buf));
printk("intqn8027_fm_read ===================== %x\n",read_buf);
}
static int qn8027_fm_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ch;
int ret = 0;
u8 write_buf;
QN_ChipInitialization(client);
ch = QNF_GetCh(client);
Gol_client = client;
printk("qn8027 ch ========================= %d\n",ch);
return 0;
}
static int qn8027_fm_remove(struct i2c_client *client)
{
printk("qn8027_fm_remove ========================= \n");
return 0;
}
static int qn8027_open(struct inode *inode, struct file *file)
{
return nonseekable_open(inode, file);
}
static int qn8027_release(struct inode *inode, struct file *file)
{
return 0;
}
static ssize_t qn8027_read(struct file *file, char __user * usr_buf, size_t len, loff_t * f_pos)
{
int ch = 0;
ch = QNF_GetCh(Gol_client);
copy_to_user(usr_buf,&ch,1);
printk("qn8027_read =================== %d\n",ch);
return 0;
}
static ssize_t qn8027_write(struct file *file, const char __user * usr_buf, size_t len, loff_t * f_pos){
char fm_buf[40];
copy_from_user(&fm_buf,usr_buf,len);
QNF_SetCh(Gol_client,10000);
printk("qn8027_write ===================\n");
return len;
}
static ssize_t qn8027_proc_write(struct file *file, const char __user *usr_buf,
size_t count, loff_t *pos){
char fm_buf[40];
int value;
char write_buf;
copy_from_user(&fm_buf,usr_buf,count);
fm_buf[count] = '\0';
value = simple_strtol(fm_buf,NULL,10);
printk("qn8027_write =================== fm_buf %s,count = %d,value = %d\n",fm_buf,count,value);
if(value > 0)// set fm rate
{
es8316_spk_ctrl(0);// trun off spk
write_buf = 0x10;
qn8027_fm_write(Gol_client, 0x03, &write_buf, 1);
msleep(200);
write_buf = 0x11;
qn8027_fm_write(Gol_client, 0x04, &write_buf, 1);
msleep(200);
printk("hxl ===============turn off fm\n");
QNF_SetCh(Gol_client,value);
}
else // turn off fm
{
es8316_spk_ctrl(1);// trun on spk
write_buf = 0x00;
qn8027_fm_write(Gol_client, 0x03, &write_buf, 1);
msleep(200);
write_buf = 0x00;
qn8027_fm_write(Gol_client, 0x04, &write_buf, 1);
msleep(200);
printk("hxl ===============turn off fm\n");
}
return count;
}
static int qn8027_proc_read(struct file *file, char *usr_buf,
size_t count, loff_t *pos){
printk("qn8027_read =================== \n");
return 0;
}
static int qn8027_proc_show(struct seq_file *m, void *v)
{
int val = 0;
val = QNF_GetCh(Gol_client);
seq_printf(m, "%d\n",val);
printk("qn8027_proc_show ......\n");
return 0;
}
static int qn8027_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, qn8027_proc_show, NULL);
}
static struct file_operations qn8027_fops = {
.owner = THIS_MODULE,
.open = qn8027_open,
.release = qn8027_release,
//.unlocked_ioctl = qn8027_ioctl,
.write = qn8027_write,
.read = seq_read,
};
static const struct i2c_device_id qn8027_id[] = {
{QN8027_I2C_NAME, 0},
{}
};
MODULE_DEVICE_TABLE(i2c, qn8027_id);
static struct i2c_driver qn8027_fm_driver = {
.driver = {
.name = QN8027_I2C_NAME,
.owner = THIS_MODULE,
},
.probe = qn8027_fm_probe,
.remove = qn8027_fm_remove,
.id_table = qn8027_id,
};
static const struct file_operations qn8027_extend_fops = {
.owner = THIS_MODULE,
.open = qn8027_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = qn8027_proc_write,
};
static int __init qn8027_fm_init(void)
{
int ret;
int ent;
printk("==qn8027_fm_init==\n");
qn8027_extend_dir = proc_mkdir("QN8027", NULL);
if(qn8027_extend_dir == NULL)
{
printk("unable to creat /proc/QN8027 directory\n");
return -ENOMEM;
}
ent = proc_create("rw_data", 0666, qn8027_extend_dir, &qn8027_extend_fops);
if(ent == NULL)
{
printk("unable to create /proc/QN8027/rw_data entry");
//goto fail;
}
ret = i2c_add_driver(&qn8027_fm_driver);
printk("ret=%d\n",ret);
return ret;
}
static void __exit qn8027_fm_exit(void)
{
printk("==qn8027_fm_exit==\n");
i2c_del_driver(&qn8027_fm_driver);
return;
}
module_init(qn8027_fm_init);
module_exit(qn8027_fm_exit);
RK3368 QN8027 FM发射驱动相关推荐
- 杰理之FM发射【篇】
FM发射功能的驱动代码在路径-\apps\common\device\fm_emitter,该文件夹下包含了驱动代码. FM数据编码发射源代码在路径-\cpu\br23\audio_common,au ...
- 国产荔枝糖FPGA开发板实现FM发射
之前在ZEDBOARD上实现了FM发射,移植到荔枝糖FPGA开发板上,运行异常,抓波形看,波形紊乱,由于最高时钟为450M,估计是荔枝糖FPGA开发板跑不了这么高,那就降频吧,降到18M果然可以发射了 ...
- 基于mtk平台调试FM发射芯片KT0805
一个比较简单的i2c设备,原理图如下, 主要是供电,硬件连接好了,软件不需要处理,音频数据是接在耳机模式上AU_HPL,AU_HPR,数据芯片自己接受发射, 软件需要处理的是SW1或者SW2,连接的G ...
- GNURadio+HackRF小实验(FM发射与接收)
引言:初次接触HackRF,做了些小实验,记录一下. 运行环境:Ubuntu 16.04,HackRF One 1 运行环境搭建 百度上说虚拟机不好用,为了方便我直接做了个U盘系统(不是U盘启动盘), ...
- FM 发射模块QN8027软件android 5.1实现分析
FM 发射模块QN8027软件android 5.1实现分析 一,kernel层中的驱动:(主要为厂家提供,主要配置对应的I2C口线) 由三个文件组成: 1, Makefile /*驱动的编译文 ...
- c++驱动键鼠源码_Android移植FM芯片RDA5807M驱动指导
文档说明 本文档以SC826为例(MSM8953平台,Android 7),描述如何移植FM芯片RDA5807M驱动. 移植修改 1):rdafm_drv.c rdafm_drv.h 放到kernel ...
- FM收音机ic FM发射模块SX6116
原文地址::http://china.coovee.net/business1/detail/12753421.html 相关文章 1.HS6760 FM调频发射端芯片 SSOP-10封装----ht ...
- tl494组成的超声波发射电路_最简单无线发射电路图大全(超声波发射/射频收发电路/调频发射器) - 全文...
最简单无线发射电路图(一):555构成的超声波发射电路 从555的3脚输出的40kHz的振荡脉冲驱动T-40-16工作,使之发射出40kHz的超声波信号.电路工作电压为9V,工作电流为40-45mA, ...
- Android FM模块学习之一 FM启动流程
转自:http://blog.csdn.net/tfslovexizi/article/details/41283743 最近在学习FM模块,FM是一个值得学习的模块,可以从上层看到底层.上层就是FM ...
最新文章
- 【深度学习】CornerNet: 将目标检测问题视作关键点检测与配对
- rabbitmq 入门demo
- java经典程序_java经典程序编程知识(二)
- P3258 [JLOI2014]松鼠的新家
- wordpress绿色小清新运营笔记博客主题模板
- 校招对项目实战要求分析
- 最速下降法极小化rosenbrock函数 代码_典型算法思想与应用9|分支限界法与电路布线问题
- 你的灯还亮着吗阅读笔记之二
- 虚拟机安装JDK1.8
- C# 大华相机图像采集
- 网页分享接口代码格式
- JS逻辑运算符的与,或,非
- 百度竞价推广之关键词的选择策略
- 计算机主板 也叫系统板或母版,电脑主板与CPU常见故障维修
- 您可以在Windows PC或Android手机上使用iMessage吗?
- wo de wen jian
- 细胞穿透肽八精氨酸、 H2N-RRRRRRRR-OH、 148796-86-5
- 2017百度实习生招聘编程题
- EO.Web浏览器 v2023.0.18.0 for .NET -- EO.WebBrowser
- float型float f=3.4是否正确?