?? kernel-2.6.19_mx-modular_rel1_1-5_update.patch
字號:
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 + -