⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mx21_pmp_fm.c

📁 调频收音芯片TEA5767在mx21上的linux驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/************************************************************************ *  File Name : tea5767hn.c *  Description : *	Implementation of fm driver  *  History : *  	14-Sep-04	Aaron Shen		New *    12-Oct-2004  Gary Gao             Modify ************************************************************************ */#include <linux/kernel.h>#include <linux/module.h>#include <linux/delay.h>#include <linux/init.h>#include <asm/uaccess.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/fs.h>#include <linux/mm.h>#include <linux/miscdevice.h>#include <linux/pm.h>#include <linux/types.h>#include <linux/i2c.h>#include <asm/arch/apmc.h>#include "asm/arch/mx2.h"#include "asm/arch/platform.h"#define TEA5767HN_IOC_TEST_I2CRW	12 #define TEA5767HN_IOC_SET_BAND	14 #define TEA5767HN_IOC_STEP_SEARCH_UP		16#define TEA5767HN_IOC_STANDBY	17 /*********************************************************************** * HARDWARE SPECIFIC *********************************************************************** *///Write byte 1#define BIT_MUTE	       0x80#define BIT_SM		       0x40#define BIT_HIGH_PLL	0x3F	//Also used for read mode//Write byte 2#define BIT_LOW_PLL	      0xFF	     //Also used for read mode//Write byte 3#define BIT_SUD		      0x80#define BIT_SSL		      0x60#define BIT_HLSI	             0x10#define BIT_MUTE_STEREO	0x08#define BIT_MUTE_LEFT	0x04#define BIT_MUTE_RIGHT	0x02#define BIT_SWP1	      0x01//Write byte 4#define BIT_SWP2	      0x80#define BIT_STANDBY	      0x40#define BIT_BAND_LIMIT	0x20	// BL=1 then Japanese FM band, =0 then US/Europe FM band, We use US/Europe FM band.#define BIT_XTAL	             0x10#define BIT_SMUTE	      0x08	      // Soft Mute#define BIT_HCC		      0x04	      // High cut control#define BIT_SNC		      0x02	      // Stereo noise canceling#define BIT_SI		      0x01      // Search Indicator//Write byte 5#define BIT_PLLREF	      0x80#define BIT_DTC		      0x40//Read byte 1#define BIT_READY_FLAG	          0x80#define BIT_BAND_LIMIT_FLAG   0x40//Read byte 3#define BIT_STEREO	                 0x80#define BIT_IF_COUNTER	           0x7F//Read byte 4#define BIT_LEV		                 0xF0#define BIT_CI		                 0x0E#define REFERENCE_FREQ	32768#define FM_MINOR      18#define STOP_LEVEL_LOW            1#define STOP_LEVEL_MID             2#define STOP_LEVEL_HIGH           3//#define HLSI_LOW   0//global staticstatic u8 g_tea5767hn_busy = 0;   static struct pm_dev *pmdev;static struct apmc_user *g_tea5767hn_apmc;static u8 val[5];static int tea5767hn_open(struct inode *inode, struct file *filp);static int tea5767hn_release(struct inode *inode, struct file *filp);static int tea5767hn_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);static int tea5767hn_pm_handler(struct pm_dev *pmdev, pm_request_t rqst, void *data);static void tea5767hn_hw_init(void);static void tea5767hn_hw_cleanup(void);static void stop_search(void);static u32 make_display_freq(u32 freq);  static u32 step_search_level_up(u32 freq, u8 level); static u32 step_search_station_up(u32 preset_freq);   static int tea5767hn_reach_band_limit(void);static int tea5767hn_station_detected(void);static void tea5767hn_calculate_pll(u8 *tPLL, u32 freq);static u32 tea5767hn_calculate_frequency(u8 *tPLL);static u32 tea5767hn_search_next_up(u32 preset, u8 flag); static void tea5767hn_hard_standby_control(u8 flag);/************************************************************************ *  * 	i2c related * 	 	 ************************************************************************///The address of the TEA5767 on I2c BUS#define I2C_ADDR_TEA5767HN   0xc0//Define the ID, Need new value, Aaron#define I2C_DRIVERID_I2C_TEA5767HN 0xF000#define I2C_M_READ 0x02          #define I2C_M_WRITE 0x04 #define I2C_NEED_ACK 0x0100static int i2c_fm_write (u8 *data);static int i2c_fm_read (u8 *data);static int i2c_fm_attach_adapter (struct i2c_adapter * adap);static struct i2c_driver i2c_fm_driver = {	name:		"i2c-fm client driver",	id:		      I2C_DRIVERID_I2C_TEA5767HN,	flags:		I2C_DF_DUMMY | I2C_DF_NOTIFY,	attach_adapter:	i2c_fm_attach_adapter,	detach_client:	NULL,	/*i2c_fm_detach_client,*/	command:	NULL};static struct i2c_client i2c_fm_client = {	name:		"i2c-fm client",	id:		      1,	flags:		0,	addr:           -1,	adapter:	      NULL,	driver:		&i2c_fm_driver,	data:		NULL};/** *@brief	This function is called when the associated driver is to install to the I2C system. *		It shall check whether it can handle the adapter. * *@param	adap	point to the adapter structure * *@return	@li	0	Success *		@li	-1	Failure */static int i2c_fm_attach_adapter (struct i2c_adapter * adap){	/* find out the adapter for the I2C module in the DBMX21*/	if (memcmp(adap->name, "DBMX I2C Adapter", 16) != 0 )		return -ENODEV;	/* store the adapter to the client driver */	i2c_fm_client.adapter = adap;	return 0;}/** *@brief	This function initializes the I2C client driver *		It is called when the module is being loaded to the system * *@return	@li	0	Success *		@li	-1	Failure */static void i2c_fm_init (void){	/* 	 * set the address of the FM radio to the client	 */	i2c_fm_client.addr = I2C_ADDR_TEA5767HN;		/* 	 * call the i2c_add_driver() to register the driver to the Linux I2C system	 */	if ((i2c_add_driver( &i2c_fm_driver )))	{		printk("I2C addr driver failed\n");		return;	}		/* 	 * attach the client to the adapter by calling the i2c_attach_client() 	 * function of the Linux I2C system	 */	if ((i2c_attach_client(&i2c_fm_client )) != 0 )	{		printk("I2C attach client failed\n");		i2c_del_driver(&i2c_fm_driver);		return;	}}/** *@brief	This function is to read the data from the I2C slave through the I2C bus. *		Before the access to the I2C bus, the driver should be opened first. * *@param	data	the buffer to store the data *@param	reg	the register number in the I2C slave (SSI sensor) * *@return	@li	number of byte received    Success *		@li	-1	Failure */static int i2c_fm_read(u8 *data){	struct i2c_msg msg;	char buf[5];	int i, ret;	for (i=0; i<5; i++)		buf[i]=0;	 //initialize the message structure	 	msg.addr = 0xc1;   //i2c_fm_client.addr;	msg.flags = I2C_M_READ | I2C_NEED_ACK;	msg.len = 5;	msg.buf = buf;      ret = i2c_transfer( i2c_fm_client.adapter, &msg, 1 );		for (i=0; i<5; i++)		*data++ = buf[i];     //*p++ = buf[i];	return ret;}/** *@brief	This function is to write the data to the I2C slave through the I2C bus. *		Before the access to the I2C bus, the driver should be opened first. * *@param	data	the buffer to store the data *@param	reg	the register number in the I2C slave (FM) * *@return	@li	number of byte received		Success *		@li	-1	Failure */static int i2c_fm_write (u8 *data){	struct i2c_msg msg;	char buf[5];	int i, ret;	/* 	 * store the register value to the first address of the buffer 	 * the adapter/algorithm driver will regard the first byte 	 * as the register value 	 */		for(i=0;i<5;i++)		buf[i] = *data++;   	    	//initialize the message structure		msg.addr = i2c_fm_client.addr;	msg.flags = I2C_M_WRITE | I2C_NEED_ACK;	msg.len = 5;	msg.buf = buf;	ret = i2c_transfer( i2c_fm_client.adapter, &msg, 1 );	return ret;}/*----------------------------------------------------------------------- * SINT16 i2c_fm_cleanup( void ) * This routine is called when the driver is uninstalled. * * Parameters : * 	None * Return : * 	Success		 0 * 	Failure		-1	 *----------------------------------------------------------------------*/static void i2c_fm_cleanup(void){	/*  	* detach the client to the adapter  	*/	i2c_detach_client(&i2c_fm_client);	/*	 * deregister the driver from the Linux I2C system	 */	i2c_del_driver(&i2c_fm_driver);}static int tea5767hn_reach_band_limit(void){	u8 bl_val[5];  	int i;	for(i=0; i<5; i++)		bl_val[i]=0;		i2c_fm_read(bl_val);	if(bl_val[0] & BIT_BAND_LIMIT_FLAG)    	//band limit has been reached	{			//printk("reach band_limit! \n");		return 1;	}	else		return 0;}static int tea5767hn_station_detected(void){      u8 local_val[5];  	int i;	for(i=0; i<5; i++)		local_val[i]=0;	i2c_fm_read(local_val);	if( local_val[0] & BIT_READY_FLAG )               //a station has been found	{		      //printk("station detected! \n");		return 1;	}	else		return 0;}static void tea5767hn_calculate_pll(u8 *tPLL, u32 freq) {	u32	twPLL =0;	//Dec 	u8	tbTmp1;	u8	tbTmp2;		// calcu1ate frequency dataword bits from given station frequency BCD:  	twPLL = (u32)(((freq-225)*4*1000)/REFERENCE_FREQ);  	//convert word to byte f.	tbTmp1 =(u8)(twPLL%256);	//6789=Hex1A85 -->133=Hex85

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -