TEA5767驱动解析、适配i.MX6ULL

1.TEA5767FM模块

1.1简介

TEA5767是飞利浦公司出的一款集成化的收音机芯片,这是一款低功耗立体声收音IC,广泛应用于手机、MP3、MP4等便携设备,接收频率76MHz~108MHz

1.2 数据格式

1.2.1 写数据格式

位7位6位5位4位3位2位1位0
数据字节1MUTESMPLL13PLL12PLL11PLL10PLL9PLL8
数据字节2PLL7PLL6PLL5PLL4PLL3PLL2PLL1PLL0
数据字节3SUDSSL1SSL0HISIMSMLMRSWP1
数据字节4SWP2STBYBLXTALSMUTEHCCSNCSI
数据字节5PLLREFDTC

1.2.2 写数据格式各符号含义

符号含义
MUTE静音控制:MUTE = 1,左右声道静音;MUTE = 0,左右声道正常
SM搜索模式:SM = 1,处于搜索模式;SM = 0,不处于搜索模式
PLL13-PLL0设定用于搜索和预设的可编程帧率合成器
SUD搜索方向:SUD = 1,向上搜索;SUD = 0,向下搜索
SSL1-0设定搜索标准
HISI高低边带接收:HISI = 1,设定为高边带接收;HISI = 0,设定为低边带接收
MSMS = 1,设定为单声道接收;MS = 0,设定为立体声接收
MLML = 1,左声道静音并设置为立体声;ML = 0,左声道正常
MRMR = 1,右声道静音并设置为立体声;MR = 0,右声道正常
SWP1软件可编程端口:SWP1 = 1,端口1为高电平;SWP1 = 0,端口1为低电平
SWP2软件可编程端口:SWP2 = 1,端口2为高电平;SWP2 = 0,端口2为低电平
STBY待机模式选择:STBY = 1,处于待机模式;STBY = 0,不处于待机模式
BL波段制式:BL =1,日本制式;BL = 0,中国/美国/欧洲调频制式
XTAL振荡器选择:XTAL = 1,使用13MHz晶体振荡器;XTAL = 0,使用32.768KHz晶体振荡器
SMUTE软件静音:SMUTE = 1,软件静音打开;SMUTE = 0,软件静音关闭
HCC高电平切割:HCC =1,高电平切割打开;HCC = 0,高电平切割关闭
SNC立体声噪音去除:SNC = 1,立体声噪音去除打开;SNC = 0,立体声噪音去除关闭
SI搜索标志位:SI = 1,端口1输出准备好信号;SI = 0,端口1做可编程端口用
PLLREFPLLREF = 1,6.5MHz锁相环参考频率使用;PLLREF = 0,6.5MHz锁相环参考频率关闭
DTC去加重时间:DTC = 1,去加重时间为75us;DTC = 0,去加重时间为50us

1.3 读数据格式

位7位6位5位4位3位2位1位0
数据字节1RFBLFPLL13PLL12PLL11PLL10PLL9PLL8
数据字节2PLL7PLL6PLL5PLL4PLL3PLL2PLL1PLL0
数据字节3STEREOIF6IF5IF4IF3IF2IF1IF0
数据字节4LEV3LEV2LEV1LEV0C13C12C11C10
数据字节5

1.3.1 读数据格式各符号含义

符号含义
RF准备好标志:RF = 1,有一个频段被搜到或已到达波段极限;RF = 0,没有频段被搜到
BLF波段极限标志:BLF = 1,已经到达搜索波段的极限
PLL13-0当前频率的PLL值
STEREO立体声标志:STEREO = 1,接收到立体声;STEREO = 0,接收到单声道
IF6-0中频计数器结果,正确调谐时值在31H-3EH之间
LEV3-0RF信号强度ADC输出
C13-0芯片

2.TEA5767设备驱动

根据TEA5767的传输数据格式,编写对应的设备驱动

2.1 所需头文件及宏定义

#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/fs.h>
#include <linux/of.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/spinlock.h>

#define READY_WAIT_TIME 15000	//等待时间
#define HCC_DEFAULT 1			//高电平切割,默认打开		
#define SNC_DEFAULT 1			//立体声噪音去除,默认打开
#define SEARCH_MODE_DEFAULT 2	//搜索模式
#define FORCED_MONO 0			//默认为立体声接收
#define MAX_STATION 50			//存放频率数最大为50个

#define TEA5767_DEBUG 1

2.2 TEA5767设备结构体

/* tea5767设备结构体 */
struct tea5767_dev {
	struct i2c_client *client;
	char name[8]; // tea5767XX

	int frequency;
	int mute;
	int station_list[MAX_STATION];
	int station_count;

	u32 minstation; //最小频率,默认值为87500
	u32 maxstation; //最大频率,默认值为10800

	struct task_struct *scan_task; /* 进程控制 */
	u8 scan_task_flag;
	spinlock_t station_list_lock; /*自旋锁*/
};

2.3 主要函数

/*设置频率*/
static int tea5767_set_freq(struct i2c_client *client, int freq, int hcc,
			    int snc, unsigned char forcd_mono, int mute,
			    int standby)
{
#ifdef TEA5767_DEBUG
	dev_info(&client->dev, "tea5767_set_freq is entered \n");
#endif
	/* 计算寄存器内容*/
	unsigned char radio[5]; // 寄存器 5个字节
	unsigned char frequencyH; // 频率高字节
	unsigned char frequencyL; // 频率低字节
	unsigned int frequencyB;
	frequencyH = 0;
	frequencyL = 0;
	frequencyB = 0;

	frequencyB = 4 * (freq * 1000 + 225000) / 32768; //计算PLL
	frequencyH = frequencyB >> 8;
	frequencyL = frequencyB & 0xFF;

	radio[0] = frequencyH;
	if (mute)
		radio[0] |= 0x80;
	radio[1] = frequencyL;
	radio[2] = 0xB0; //搜索设置
	if (forcd_mono)
		radio[2] |= 0x08;
	radio[3] = 0x10; // 振荡器32.768 kHz
	if (freq < 87500)
		radio[3] |= 0x20;
	if (hcc)
		radio[3] |= 0x04;
	if (snc)
		radio[3] |= 0x02;
	if (standby)
		radio[3] |= 0x40;
	radio[4] = 0x40; // 去加重时间为75us

	/* i2c写入 */
	if (-1 == i2c_master_send(client, radio, 5)) {
		return -1;
	}

#ifdef TEA5767_DEBUG
	dev_info(&client->dev, "tea5767_set_freq is exited.\n");
#endif
	return 0;
}

2.4 辅助函数(仅声明)

static int tea5767_get_wrapped_frequency(struct i2c_client *client, int freq);
static int tea5767_get_device_frequency(struct i2c_client *client);
static int tea5767_search(struct i2c_client *client, int dir, int mode,
			  int forced_mono);
static int tea5767_wait_ready(struct i2c_client *client);
static int tea5767_get_status(struct i2c_client *client, int *freq,
			      unsigned char *mode, unsigned char *level_adc);
static int tea5767_scan_frequencies(struct i2c_client *client, int mode,
				    int forced_mono);

2.5 读写sysfs设备节点方法

在/sys中生成节点,可用于应用层从驱动中获取数据,也可以直接将数据写入到驱动中

2.5.1 DEVICE_ATTR()宏定义

DEVICE_ATTR的功能就是定义一个device_attribute结构体对象

该定义为位于include/linux/device.h

#define DEVICE_ATTR(_name, _mode, _show, _store) \
	struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)

_name : 节点名字,在sys路径下可以搜索的到
_mode : 节点权限

权限含义
400拥有者可读,其他任何人不能进行任何操作
644拥有者可读,但只有拥有者可以编辑
660拥有者和组用户都可读写,其他人不能进行任何操作
664所有人都可读,但只有拥有者和组用户可编辑
700拥有者能够读、写和执行,其他用户不能进行任何操作
744所有人都能读,但只有拥有者才能进行编辑和执行
755所有人都能读和执行,但只有拥有者才能编辑
777所有人都能读、写和执行

_show : 当cat命令作用于该文件时调用该函数

_store : 当echo数据到该文件时调用该函数

2.5.2驱动中的具体实现

static DEVICE_ATTR(
	station, S_IWUSR | S_IRUGO, sysfs_show_station_callback,
	sysfs_store_station_callback); // Create sysfs attribute "station"

static DEVICE_ATTR(mute, S_IWUSR | S_IRUGO, sysfs_show_mute_callback,
		   sysfs_store_mute_callback); // Create sysfs attribute "mute"

static DEVICE_ATTR(stationlist, S_IRUGO, sysfs_show_stationlist_callback,
		   NULL); // Create sysfs attribute "stationlist"

static DEVICE_ATTR(autoscan, S_IWUSR | S_IRUGO, NULL,
		   sysfs_store_autoscan_callback);

static struct attribute *tea5767_sysfs_attrs[] = {
	&dev_attr_station.attr,
	&dev_attr_mute.attr,
	&dev_attr_stationlist.attr,
	&dev_attr_autoscan.attr,
	NULL,
};

/* Following creates sysfs group that will be registered and deregistered in module enter and exit. */
static struct attribute_group tea5767_sysfs_group = {
	.name = "tea5767",
	.attrs = tea5767_sysfs_attrs,
};

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值