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

📄 kernel-2.6.19_mx-modular_rel1_1-5_update.patch

📁 si4702 linux patch,this is FM chip si4702 driver,based on iMX31 platform
💻 PATCH
📖 第 1 页 / 共 3 页
字号:
diff --exclude CVS -uNr linux-2.6.19.2/drivers/char/si4702.c linux-2.6.19.2.modified/drivers/char/si4702.c
--- linux-2.6.19.2/drivers/char/si4702.c	1970-01-01 07:00:00.000000000 +0700
+++ linux-2.6.19.2.modified/drivers/char/si4702.c	2007-10-26 13:10:09.000000000 +0800
@@ -0,0 +1,1122 @@
+/*
+ * linux/drivers/char/si4702.c
+ *
+ * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*!
+ * @defgroup Character device driver for si4702 FM radio
+ */
+
+/*
+ * @file si4702.c
+ *
+ * @brief si4702 Radio FM driver
+ *
+ * @ingroup Character
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/fcntl.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <asm/arch/mxc_i2c.h>
+#include <asm/arch/pmic_power.h>
+#include <asm/arch/pmic_audio.h>
+
+#include <asm/uaccess.h>
+
+#include "si4702.h"
+
+#define DEBUG_SI4702
+#ifdef DEBUG_SI4702
+#define DPRINTK(format,args...) printk("SI4702: "format,##args)
+#else
+#define DPRINTK(format,args...)
+#endif
+
+/* major number of this device */
+static int major;
+static int count = 0;	/* open count */
+static spinlock_t count_lock; 	/* spin lock for count */
+static struct si4702_device si4702_dev = {0};
+static struct class *radio_class = NULL; /* class struct */
+
+static char si4702_reg_buf[SI4702_REG_BYTE];
+
+static void dump_reg(void);
+static int si4702_read_reg(u8 reg, u16 *word);
+static int si4702_write_reg(u8 reg, u16 word);
+static int fm_sys_init(void);
+static int fm_sys_exit(void);
+
+/*!
+  * si4702_gpio_active
+  *
+  * audio line selection for FM and
+  * power on for FM 
+  */
+static void si4702_gpio_active(void)
+{
+	/* reset pin */
+	mxc_request_iomux(MX31_PIN_SRST0, OUTPUTCONFIG_GPIO, 
+				INPUTCONFIG_NONE);
+	mxc_set_gpio_direction(MX31_PIN_SRST0, 0);
+
+	mxc_request_iomux(MX31_PIN_SIMPD0, OUTPUTCONFIG_GPIO, 
+				INPUTCONFIG_NONE);
+	mxc_set_gpio_direction(MX31_PIN_SIMPD0, 0);
+
+}
+
+/*!
+  * si4702_gpio_inactive
+  *
+  * power off for FM 
+  * free the GPIOs
+  */
+static void si4702_gpio_inactive(void)
+{
+	mxc_free_iomux(MX31_PIN_SRST0, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
+	mxc_free_iomux(MX31_PIN_SIMPD0, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
+}
+
+//extern int pmic_read(int reg_num, unsigned int *reg_val);
+//extern int pmic_write(int reg_num, const unsigned int reg_val);
+/*!
+  * si4702_gpio_reset
+  *
+  * Reset the si4702
+  */
+static void si4702_gpio_reset(void)
+{
+	DPRINTK("reset si4702\n");
+
+	//DPRINTK("reset reg 34 to 0\n");
+	//pmic_write(REG_POWER_MISCELLANEOUS, 0);
+	//ndelay(DURATION_INIT_1);
+	//DPRINTK("set reg 34 to 0x%x\n", 0x1 << 6 | 0x1 << 10);
+	//pmic_write(REG_POWER_MISCELLANEOUS, 0x1 << 6 | 0x1 << 10);
+	//ndelay(DURATION_INIT_1);
+	
+	/* reset FM */
+	mxc_set_gpio_dataout(MX31_PIN_SRST0, 0);
+	mdelay(100);
+	
+	/* set sdio direction for output */
+	mxc_set_gpio_dataout(MX31_PIN_SRST0, 1);
+	mdelay(100);
+}
+
+/*!
+  * si4702_startup
+  * Startup and initial the si4702
+  * @param 
+  * @return
+  * 	0 successful
+  */
+static int si4702_startup(void)
+{
+	u16 magic = 0, count = 0, id;
+
+#ifdef MORE_TIME
+	si4702_read_reg(SI4702_DEVICEID, &id);
+	printk(KERN_ERR "si4702: DEVICEID: 0x%x\n", id);
+#endif	
+		
+	mxc_set_gpio_dataout(MX31_PIN_SIMPD0, 1);
+	mdelay(100);
+
+	si4702_write_reg(SI4702_POWERCFG, 0x4001); /* disable mute, stereo, seek down, powerup */
+	mdelay(500);
+	si4702_read_reg(SI4702_TEST1, &magic);
+	if(magic != 0x3C04) // this means the chip power on normally
+		DPRINTK("magic number 0x%x.\n", magic);
+	si4702_write_reg(SI4702_CHANNEL, 0); /* close tune, set channel to 0 */
+	si4702_write_reg(SI4702_SYSCONFIG1, 0); /* disable interrupt, disable GPIO */
+	si4702_write_reg(SI4702_SYSCONFIG2, 0x0f13); /* seek threshold, band, space select to Europe, volume to max */
+	si4702_write_reg(SI4702_SYSCONFIG3, 0x48); 
+	
+	return 0;
+}
+
+/*!
+  * si4702_shutdown
+  * Shutdown the si4702
+  */
+static void si4702_shutdown(void)
+{
+#if 0
+	u8 si4702_shutdown_regs[] = {
+		0x40,	/* disable mute, stereo, seek down */
+		0x40	/* power down */
+	};
+#endif
+	
+	//si4702_operation(SD_WRITE, &(si4702_shutdown_regs[0]), 2);
+	si4702_write_reg(SI4702_POWERCFG, 0x4041);
+
+	mxc_set_gpio_dataout(MX31_PIN_SIMPD0, 0);
+}
+
+/*!
+  * si4702_channel_select
+  *
+  * Select a channel
+  * @param
+  * 	freq	frequence to select in KHz unit
+  * @return
+  * 	0 successful
+  *
+  */
+static u8 si4702_channel_select(u32 freq)
+{
+	u16 loop_counter = 0;
+	s16 channel;
+	u16 si4702_read_data, si4702_write_data;
+	u8 error_ind = 0;
+	u8 si4702_channel_start_tune[] = {0x40,0x01,0x80,0x00};
+	u8 si4702_channel_stop_tune[] = {0x40,0x01,0x00};	
+
+	if (si4702_dev.mute) {
+		/* enable mute */
+		si4702_channel_start_tune[0] = 0;
+		si4702_channel_stop_tune[0] = 0;
+	}
+	DPRINTK("Input frequnce is %d\n", freq);
+	/* convert freq to channel */
+	channel = (freq - BAND) / SPACING;
+	//channel = freq;
+	if (channel < 0 || channel > 1023) {
+		DPRINTK("Input frequnce is invalid\n");
+		return -1;
+	}
+	/* fill channel bits */
+	si4702_channel_start_tune[2] |= channel >> 8;
+	si4702_channel_start_tune[3] |= channel & 0xFF;
+
+	/* set tune bit */
+ 	//error_ind = si4702_operation(SD_WRITE, &(si4702_channel_start_tune[0]), 4);
+ 	si4702_write_data = BYTE_TO_WORD(si4702_channel_start_tune[0], si4702_channel_start_tune[1]);
+	error_ind = si4702_write_reg(SI4702_POWERCFG, si4702_write_data);
+
+	si4702_write_data = BYTE_TO_WORD(si4702_channel_start_tune[2], si4702_channel_start_tune[3]);
+	error_ind = si4702_write_reg(SI4702_CHANNEL, si4702_write_data);
+
+	if (error_ind) {
+		DPRINTK("Failed to set start tune\n");
+		return -1;
+	}
+
+	//si4702_read_reg(SI4702_POWERCFG, &si4702_read_data);
+	//si4702_read_reg(SI4702_CHANNEL, &si4702_read_data);
+	/* wait for STC == 1 */
+	do {	
+		//error_ind = si4702_operation(SD_READ, &(si4702_reg_data[0]), 1);
+		error_ind = si4702_read_reg(SI4702_STATUSRSSI, &si4702_read_data);
+		
+		if(error_ind) {
+			DPRINTK("Failed to read setted STC\n");
+			return -1;	
+		}
+		if ((si4702_read_data & 0x4000) != 0)
+			break;
+		/* sleep to wait */
+		msleep(200);
+		
+	} while(++loop_counter < DELAY_WAIT);
+
+	/* check loop_counter */
+	if (loop_counter >= DELAY_WAIT) {
+		DPRINTK("Can't wait for STC bit set");
+		return -1;
+	}
+	loop_counter = 0;
+
+	/* clear tune bit */
+	//error_ind = si4702_operation(SD_WRITE, &(si4702_channel_stop_tune[0]), 2);
+	error_ind = si4702_write_reg(SI4702_CHANNEL, 0);
+	
+	if (error_ind) {
+		DPRINTK("Failed to set stop tune\n");
+		return -1;
+	}	
+
+	/* wait for STC == 0 */
+	do {	
+		//error_ind = si4702_operation(SD_READ, &(si4702_reg_data[0]), 1);
+		error_ind = si4702_read_reg(SI4702_STATUSRSSI, &si4702_read_data);
+		
+		if(error_ind) {
+			DPRINTK("Failed to set read STC\n");
+			return -1;	
+		}
+		if ((si4702_read_data & 0x4000) == 0)
+			break;
+		/* sleep to wait */
+		msleep(200);
+		
+	} while(++loop_counter < DELAY_WAIT);	
+		
+	/* check loop_counter */
+	if (loop_counter >= DELAY_WAIT) {
+		DPRINTK("Can't wait for STC bit set");
+		return -1;
+	}
+#if 1
+	/* read RSSI */
+	//error_ind = si4702_operation(SD_READ, &(si4702_reg_data[0]), 4);	
+	error_ind = si4702_read_reg(SI4702_READCHAN, &si4702_read_data);
+	
+	if(error_ind) {
+		DPRINTK("Failed to read RSSI\n");
+		return -1;
+	}
+	
+	channel = si4702_read_data & 0x03ff;
+	DPRINTK("seek finish: channel(%d)\n", channel);
+#endif
+	return 0;
+}
+
+/*!
+  * si4702_channel_seek
+  * @param	seek info, direction. 1 seekup
+  * @return 
+  * 	frequnce been seeked
+  * 	-1 	I2C error 
+  * 	-2	seek fail
+  */
+static s32 si4702_channel_seek(s16 dir)
+{
+	u16 loop_counter = 0;
+	u16 si4702_reg_data;
+	u8 error_ind = 0;
+	s32 seek_error = 0;
+	u8 si4702_channel_seek_start[] = {0x41};
+	u8 si4702_channel_seek_stop[] = {0x40};
+	u32 channel;
+
+	if (si4702_dev.mute) {
+		/* check disable mute */
+		si4702_channel_seek_start[0] = 0x01;
+		si4702_channel_seek_stop[0] = 0x00;
+	}
+	if (dir) {
+		DPRINTK("Change to SEEKUP\n");
+		si4702_channel_seek_start[0] |= 0x02;
+		si4702_channel_seek_stop[0] |= 0x02;
+	}
+	/* set seek bit */
+ 	//error_ind = si4702_operation(SD_WRITE, &(si4702_channel_seek_start[0]), 1);
+
+	error_ind = si4702_read_reg(SI4702_POWERCFG, &si4702_reg_data);
+	si4702_reg_data &= 0x0F;
+	si4702_reg_data |= si4702_channel_seek_start[0] << 8;
+	error_ind = si4702_write_reg(SI4702_POWERCFG, si4702_reg_data);
+	
+	if (error_ind) {
+		DPRINTK("Failed to set seek start bit\n");
+		return -1;
+	}
+
+	/* wait STC == 1 */
+	do {	
+		//error_ind = si4702_operation(SD_READ, &(si4702_reg_data[0]), 1);
+		error_ind = si4702_read_reg(SI4702_STATUSRSSI, &si4702_reg_data);
+		if(error_ind) {
+			DPRINTK("Failed to read STC bit\n");
+			return -1;	
+		}
+
+		if ((si4702_reg_data & 0x4000) != 0) 
+			break;
+		/* sleep to wait */
+		msleep(200);
+
+	} while (++loop_counter < DELAY_WAIT);		
+
+	if (loop_counter >= DELAY_WAIT) {
+		DPRINTK("Can't wait for STC bit set");
+		return -1;
+	}
+	loop_counter = 0;
+
+	/* check whether SF==1 (seek failed bit) */
+	if ((si4702_reg_data & 0x2000) != 0) {
+		DPRINTK("Failed to seek any channel\n");
+		seek_error = -2;
+	}
+
+	/* clear seek bit */
+	//error_ind = si4702_operation(SD_WRITE, &(si4702_channel_seek_stop[0]), 1);
+	error_ind = si4702_read_reg(SI4702_POWERCFG, &si4702_reg_data);
+	si4702_reg_data &= 0x0F;
+	si4702_reg_data |= si4702_channel_seek_stop[0] << 8;
+	error_ind = si4702_write_reg(SI4702_POWERCFG, si4702_reg_data);
+	
+	if (error_ind) {
+		DPRINTK("Failed to stop seek\n");
+		return -1;	
+	}
+	/* wait STC == 0 */
+	do {	
+		//error_ind = si4702_operation(SD_READ, &(si4702_reg_data[0]), 1);
+		error_ind = si4702_read_reg(SI4702_STATUSRSSI, &si4702_reg_data);
+		
+		if (error_ind) {
+			DPRINTK("Failed to wait STC bit to clear\n");
+			return -1;	
+		}
+		if ((si4702_reg_data & 0x40) == 0)
+			break;
+		/* sleep to wait */
+		msleep(200);
+	} while (++loop_counter < DELAY_WAIT);
+
+	/* check loop_counter */
+	if (loop_counter >= DELAY_WAIT) {
+		DPRINTK("Can't wait for STC bit set");
+		return -1;
+	}
+
+	error_ind = si4702_read_reg(SI4702_READCHAN, &si4702_reg_data);
+	
+	if (error_ind) {
+		DPRINTK("I2C simulate failed\n");

⌨️ 快捷键说明

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