aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/radio')
-rw-r--r--drivers/media/radio/Kconfig12
-rw-r--r--drivers/media/radio/Makefile1
-rw-r--r--drivers/media/radio/si4709/Makefile6
-rwxr-xr-xdrivers/media/radio/si4709/radio-si4709_common.h41
-rw-r--r--drivers/media/radio/si4709/radio-si4709_dev.c2563
-rw-r--r--drivers/media/radio/si4709/radio-si4709_dev.h181
-rw-r--r--drivers/media/radio/si4709/radio-si4709_i2c_drv.c196
-rw-r--r--drivers/media/radio/si4709/radio-si4709_i2c_drv.h8
-rw-r--r--drivers/media/radio/si4709/radio-si4709_ioctl.h104
-rw-r--r--drivers/media/radio/si4709/radio-si4709_main.c799
-rw-r--r--drivers/media/radio/si4709/radio-si4709_main.h9
-rw-r--r--drivers/media/radio/si4709/radio-si4709_regs.h859
12 files changed, 4779 insertions, 0 deletions
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index 52798a1..a7ab498 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -357,6 +357,18 @@ config RADIO_SI470X
source "drivers/media/radio/si470x/Kconfig"
+config RADIO_SI4709
+ bool "Silicon Labs Si4709 FM Radio Receiver support"
+ ---help---
+ This is a driver for I2C devices with the Silicon Labs SI4709
+ chip.
+
+ Say Y here if you want to connect this type of radio to your
+ computer's I2C port.
+
+ To compile this driver as a module, choose M here: the
+ module will be called radio-i2c-si470x.
+
config USB_MR800
tristate "AverMedia MR 800 USB FM radio support"
depends on USB && VIDEO_V4L2
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile
index f484a6e..5d0e62f 100644
--- a/drivers/media/radio/Makefile
+++ b/drivers/media/radio/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_RADIO_SI4713) += radio-si4713.o
obj-$(CONFIG_RADIO_MIROPCM20) += radio-miropcm20.o
obj-$(CONFIG_USB_DSBR) += dsbr100.o
obj-$(CONFIG_RADIO_SI470X) += si470x/
+obj-$(CONFIG_RADIO_SI4709) += si4709/
obj-$(CONFIG_USB_MR800) += radio-mr800.o
obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o
obj-$(CONFIG_RADIO_SAA7706H) += saa7706h.o
diff --git a/drivers/media/radio/si4709/Makefile b/drivers/media/radio/si4709/Makefile
new file mode 100644
index 0000000..d110423
--- /dev/null
+++ b/drivers/media/radio/si4709/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for Silicon Labs Si4709 FM Radio Receiver
+#
+
+radio-si4709-i2c-objs := radio-si4709_dev.o radio-si4709_i2c_drv.o radio-si4709_main.o
+obj-$(CONFIG_RADIO_SI4709) += radio-si4709-i2c.o
diff --git a/drivers/media/radio/si4709/radio-si4709_common.h b/drivers/media/radio/si4709/radio-si4709_common.h
new file mode 100755
index 0000000..c81ed92
--- /dev/null
+++ b/drivers/media/radio/si4709/radio-si4709_common.h
@@ -0,0 +1,41 @@
+#ifndef _COMMON_H
+#define _COMMON_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <mach/gpio.h>
+
+//#define Si4709_DEBUG
+
+#define error(fmt,arg...) printk(KERN_CRIT fmt "\n",## arg)
+
+#ifdef Si4709_DEBUG
+#define debug(fmt,arg...) printk(KERN_CRIT "--------" fmt "\n",## arg)
+#else
+#define debug(fmt,arg...)
+#endif
+
+#define FM_RESET GPIO_FM_RST
+
+/*VNVS:28-OCT'09---- For testing FM tune and seek operation status*/
+#define TEST_FM
+
+/*VNVS:7-JUNE'10 ---- RDS Interrupt ON Always (Enabling interrupt when RDS is enabled)*/
+#define RDS_INTERRUPT_ON_ALWAYS
+
+/*VNVS:18-JUN'10---- For testing RDS*/
+/*Enable only for debugging RDS*/
+//#define RDS_TESTING
+#ifdef RDS_TESTING
+#define debug_rds(fmt,arg...) printk(KERN_CRIT "--------" fmt "\n",## arg)
+#define GROUP_TYPE_2A ( 2 * 2 + 0)
+#define GROUP_TYPE_2B ( 2 * 2 + 1)
+#else
+#define debug_rds(fmt,arg...)
+#endif
+
+#define YES 1
+#define NO 0
+
+#endif
+
diff --git a/drivers/media/radio/si4709/radio-si4709_dev.c b/drivers/media/radio/si4709/radio-si4709_dev.c
new file mode 100644
index 0000000..6a65da9
--- /dev/null
+++ b/drivers/media/radio/si4709/radio-si4709_dev.c
@@ -0,0 +1,2563 @@
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+#include <linux/workqueue.h>
+
+#include <mach/gpio.h>
+#include <plat/gpio-cfg.h>
+#include <../../../arch/arm/mach-s5pv210/include/mach/gpio-aries.h>
+
+#include "radio-si4709_regs.h"
+#include "radio-si4709_main.h"
+#include "radio-si4709_dev.h"
+#include "radio-si4709_common.h"
+
+enum
+{
+ eTRUE,
+ eFALSE,
+}dev_struct_status_t;
+
+/*dev_state*/
+/*power_state*/
+#define RADIO_ON 1
+#define RADIO_POWERDOWN 0
+/*seek_state*/
+#define RADIO_SEEK_ON 1
+#define RADIO_SEEK_OFF 0
+
+#define FREQ_87500_kHz 8750
+#define FREQ_76000_kHz 7600
+
+#define RSSI_seek_th_MAX 0x7F
+#define RSSI_seek_th_MIN 0x00
+
+#define seek_SNR_th_DISB 0x00
+#define seek_SNR_th_MIN 0x01 /*most stops*/
+#define seek_SNR_th_MAX 0x0F /*fewest stops*/
+
+#define seek_FM_ID_th_DISB 0x00
+#define seek_FM_ID_th_MAX 0x01 /*most stops*/
+#define seek_FM_ID_th_MIN 0x0F /*fewest stops*/
+
+#define TUNE_RSSI_THRESHOLD 0x00
+#define TUNE_SNR_THRESHOLD 0x01
+#define TUNE_CNT_THRESHOLD 0x00
+
+typedef struct
+{
+ u32 frequency;
+ u8 rsssi_val;
+}channel_into_t;
+
+typedef struct
+{
+ u16 band;
+ u32 bottom_of_band;
+ u16 channel_spacing;
+ u32 timeout_RDS; /****For storing the jiffy value****/
+ u32 seek_preset[NUM_SEEK_PRESETS];
+ u8 curr_snr;
+ u8 curr_rssi_th;
+}dev_settings_t;
+
+typedef struct
+{
+ /*Any function which
+ - views/modifies the fields of this structure
+ - does i2c communication
+ should lock the mutex before doing so.
+ Recursive locking should not be done.
+ In this file all the exported functions will take care
+ of this. The static functions will not deal with the
+ mutex*/
+ struct mutex lock;
+
+ struct i2c_client const *client;
+
+ dev_state_t state;
+
+ dev_settings_t settings;
+
+ channel_into_t rssi_freq[50];
+
+ u16 registers[NUM_OF_REGISTERS];
+
+ /* This field will be checked by all the functions
+ exported by this file (except the init function),
+ to validate the the fields of this structure.
+ if eTRUE: the fileds are valid
+ if eFALSE: do not trust the values of the fields
+ of this structure*/
+ unsigned short valid;
+
+ /*will be true is the client ans state fields are correct*/
+ unsigned short valid_client_state;
+}Si4709_device_t;
+
+
+/*extern functions*/
+/**********************************************/
+/*All the exported functions which view or modify the device
+ state/data, do i2c com will have to lock the mutex before
+ doing so*/
+/**********************************************/
+int Si4709_dev_init(struct i2c_client *);
+int Si4709_dev_exit(void);
+
+void Si4709_dev_mutex_init(void);
+
+int Si4709_dev_suspend(void);
+int Si4709_dev_resume(void);
+
+int Si4709_dev_powerup(void);
+int Si4709_dev_powerdown(void);
+
+int Si4709_dev_band_set(int);
+int Si4709_dev_ch_spacing_set(int);
+
+int Si4709_dev_chan_select(u32);
+int Si4709_dev_chan_get(u32*);
+
+int Si4709_dev_seek_up(u32*);
+int Si4709_dev_seek_down(u32*);
+int Si4709_dev_seek_auto(u32*);
+
+int Si4709_dev_RSSI_seek_th_set(u8);
+int Si4709_dev_seek_SNR_th_set(u8);
+int Si4709_dev_seek_FM_ID_th_set(u8);
+int Si4709_dev_cur_RSSI_get(rssi_snr_t*);
+int Si4709_dev_VOLEXT_ENB(void);
+int Si4709_dev_VOLEXT_DISB(void);
+int Si4709_dev_volume_set(u8);
+int Si4709_dev_volume_get(u8 *);
+int Si4709_dev_DSMUTE_ON(void);
+int Si4709_dev_DSMUTE_OFF(void);
+int Si4709_dev_MUTE_ON(void);
+int Si4709_dev_MUTE_OFF(void);
+int Si4709_dev_MONO_SET(void);
+int Si4709_dev_STEREO_SET(void);
+int Si4709_dev_RDS_ENABLE(void);
+int Si4709_dev_RDS_DISABLE(void);
+int Si4709_dev_RDS_timeout_set(u32);
+int Si4709_dev_rstate_get(dev_state_t*);
+int Si4709_dev_RDS_data_get(radio_data_t*);
+int Si4709_dev_device_id(device_id *);
+int Si4709_dev_chip_id(chip_id *);
+int Si4709_dev_sys_config2(sys_config2 *);
+int Si4709_dev_power_config(power_config *);
+int Si4709_dev_AFCRL_get(u8*);
+int Si4709_dev_DE_set(u8);
+/***********************************************/
+
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+#define RDS_BUFFER_LENGTH 50
+static u16 *RDS_Block_Data_buffer;
+static u8 *RDS_Block_Error_buffer;
+static u8 RDS_Buffer_Index_read; //index number for last read data
+static u8 RDS_Buffer_Index_write; //index number for last written data
+
+int Si4709_RDS_flag;
+int RDS_Data_Available;
+int RDS_Data_Lost;
+int RDS_Groups_Available_till_now;
+struct workqueue_struct *Si4709_wq;
+struct work_struct Si4709_work;
+#endif
+
+/*static functions*/
+/**********************************************/
+static void wait(void);
+
+static void wait_RDS(void );
+
+static int powerup(void);
+static int powerdown(void);
+
+static int seek(u32*, int);
+static int tune_freq(u32);
+
+static void get_cur_chan_freq(u32 *, u16);
+
+static u16 freq_to_channel(u32);
+static u32 channel_to_freq(u16);
+
+static int insert_preset(u32,u8,u8*);
+
+static int i2c_read(u8);
+static int i2c_write(u8);
+/**********************************************/
+
+/*Si4709 device structure*/
+static Si4709_device_t Si4709_dev =
+{
+ .client = NULL,
+ .valid = eFALSE,
+ .valid_client_state = eFALSE,
+};
+
+/*Wait flag*/
+/*WAITING or WAIT_OVER or NO_WAIT*/
+int Si4709_dev_wait_flag = NO_WAIT;
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+int Si4709_RDS_flag = NO_WAIT;
+#endif
+
+int Si4709_dev_init(struct i2c_client *client)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_init called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ Si4709_dev.client = client;
+
+ /***reset the device here****/
+ gpio_set_value(FM_RESET, GPIO_LEVEL_LOW);
+ mdelay(1);
+ gpio_set_value(FM_RESET, GPIO_LEVEL_HIGH);
+ mdelay(2);
+
+ s3c_gpio_setpull(GPIO_FM_INT, S3C_GPIO_PULL_UP);
+ s3c_gpio_slp_setpull_updown(GPIO_FM_INT, S3C_GPIO_PULL_UP);
+
+ Si4709_dev.state.power_state = RADIO_POWERDOWN;
+ Si4709_dev.state.seek_state = RADIO_SEEK_OFF;
+
+ if( (ret = i2c_read(BOOTCONFIG) ) < 0 )
+ {
+ debug("i2c_read failed");
+ }
+ else
+ {
+ Si4709_dev.valid_client_state = eTRUE;
+ }
+
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+ /*Creating Circular Buffer*/
+ /*Single RDS_Block_Data buffer size is 4x16 bits*/
+ RDS_Block_Data_buffer = kzalloc(RDS_BUFFER_LENGTH*8,GFP_KERNEL);
+ if(!RDS_Block_Data_buffer)
+ {
+ error("Not sufficient memory for creating RDS_Block_Data_buffer");
+ ret = -ENOMEM;
+ goto EXIT;
+ }
+
+ /*Single RDS_Block_Error buffer size is 4x8 bits*/
+ RDS_Block_Error_buffer = kzalloc(RDS_BUFFER_LENGTH*4,GFP_KERNEL);
+ if(!RDS_Block_Error_buffer)
+ {
+ error("Not sufficient memory for creating RDS_Block_Error_buffer");
+ ret = -ENOMEM;
+ kfree(RDS_Block_Data_buffer);
+ goto EXIT;
+ }
+
+ /*Initialising read and write indices*/
+ RDS_Buffer_Index_read= 0;
+ RDS_Buffer_Index_write= 0;
+
+ /*Creating work-queue*/
+ Si4709_wq = create_singlethread_workqueue("Si4709_wq");
+ if(!Si4709_wq)
+ {
+ error("Not sufficient memory for Si4709_wq, work-queue");
+ ret = -ENOMEM;
+ kfree(RDS_Block_Error_buffer);
+ kfree(RDS_Block_Data_buffer);
+ goto EXIT;
+ }
+
+ /*Initialising work_queue*/
+ INIT_WORK(&Si4709_work, Si4709_work_func);
+
+ RDS_Data_Available = 0;
+ RDS_Data_Lost =0;
+ RDS_Groups_Available_till_now = 0;
+EXIT:
+#endif
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ debug("Si4709_dev_init call over");
+
+ return ret;
+}
+
+int Si4709_dev_exit(void)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_exit called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ // Temporary blocked by abnormal function call(E-CIM 2657654) - DW Shim. 2010.03.04
+ printk(KERN_ERR "Si4709_dev_exit() is called!!");
+// Si4709_dev.client = NULL;
+
+// Si4709_dev.valid_client_state = eFALSE;
+// Si4709_dev.valid = eFALSE;
+
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+ if(Si4709_wq)
+ destroy_workqueue(Si4709_wq);
+
+ if(RDS_Block_Error_buffer)
+ kfree(RDS_Block_Error_buffer);
+
+ if(RDS_Block_Data_buffer)
+ kfree(RDS_Block_Data_buffer);
+#endif
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ debug("Si4709_dev_exit call over");
+
+ return ret;
+}
+
+void Si4709_dev_mutex_init(void)
+{
+ mutex_init(&(Si4709_dev.lock));
+}
+
+int Si4709_dev_powerup(void)
+{
+ int ret = 0;
+ u32 value = 100;
+
+ debug("Si4709_dev_powerup called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if(!(RADIO_ON==Si4709_dev.state.power_state))
+ {
+ if( (ret = powerup()) < 0 )
+ {
+ debug("powerup failed");
+ }
+ else if( Si4709_dev.valid_client_state == eFALSE )
+ {
+ debug("Si4709_dev_powerup called when DS (state, client) is invalid");
+ ret = -1;
+ }
+ else
+ {
+ /*initial settings*/
+#if 0
+ POWERCFG_BITSET_RDSM_LOW(&Si4709_dev.registers[POWERCFG]);
+#else
+ POWERCFG_BITSET_RDSM_HIGH(&Si4709_dev.registers[POWERCFG]);
+#endif
+ // POWERCFG_BITSET_SKMODE_HIGH(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_SKMODE_LOW(&Si4709_dev.registers[POWERCFG]); /*VNVS:18-NOV'09---- wrap at the upper and lower band limit and continue seeking*/
+ SYSCONFIG1_BITSET_STCIEN_HIGH(&Si4709_dev.registers[SYSCONFIG1]);
+ SYSCONFIG1_BITSET_RDSIEN_LOW(&Si4709_dev.registers[SYSCONFIG1]);
+ SYSCONFIG1_BITSET_RDS_HIGH(&Si4709_dev.registers[SYSCONFIG1]);
+ SYSCONFIG1_BITSET_DE_50(&Si4709_dev.registers[SYSCONFIG1]); /*VNVS:18-NOV'09--- Setting DE-Time Constant as 50us(Europe,Japan,Australia)*/
+ SYSCONFIG1_BITSET_GPIO_STC_RDS_INT(&Si4709_dev.registers[SYSCONFIG1]);
+ SYSCONFIG1_BITSET_RESERVED(&Si4709_dev.registers[SYSCONFIG1]);
+
+ // SYSCONFIG2_BITSET_SEEKTH(&Si4709_dev.registers[SYSCONFIG2],2);
+ SYSCONFIG2_BITSET_SEEKTH(&Si4709_dev.registers[SYSCONFIG2], TUNE_RSSI_THRESHOLD); /*VNVS:18-NOV'09---- modified for detecting more stations of good quality*/
+ SYSCONFIG2_BITSET_VOLUME(&Si4709_dev.registers[SYSCONFIG2],0x0F);
+ SYSCONFIG2_BITSET_BAND_87p5_108_MHz(&Si4709_dev.registers[SYSCONFIG2]);
+ Si4709_dev.settings.band = BAND_87500_108000_kHz;
+ Si4709_dev.settings.bottom_of_band = FREQ_87500_kHz;
+
+ SYSCONFIG2_BITSET_SPACE_100_KHz(&Si4709_dev.registers[SYSCONFIG2]);
+ Si4709_dev.settings.channel_spacing = CHAN_SPACING_100_kHz;
+
+
+ // SYSCONFIG3_BITSET_SKSNR(&Si4709_dev.registers[SYSCONFIG3],3);
+ SYSCONFIG3_BITSET_SKSNR(&Si4709_dev.registers[SYSCONFIG3], TUNE_SNR_THRESHOLD);/*VNVS:18-NOV'09---- modified for detecting more stations of good quality*/
+ SYSCONFIG3_BITSET_SKCNT(&Si4709_dev.registers[SYSCONFIG3], TUNE_CNT_THRESHOLD);
+
+ SYSCONFIG3_BITSET_RESERVED(&Si4709_dev.registers[SYSCONFIG3]);
+
+ Si4709_dev.settings.timeout_RDS = msecs_to_jiffies(value);
+ Si4709_dev.settings.curr_snr = TUNE_SNR_THRESHOLD;
+ Si4709_dev.settings.curr_rssi_th = TUNE_RSSI_THRESHOLD;
+
+ /*this will write all the above registers*/
+ if( (ret = i2c_write(SYSCONFIG3)) < 0 )
+ {
+ debug("Si4709_dev_powerup i2c_write 1 failed");
+ }
+ else
+ {
+ Si4709_dev.valid = eTRUE;
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+ /*Initialising read and write indices*/
+ RDS_Buffer_Index_read= 0;
+ RDS_Buffer_Index_write= 0;
+
+ RDS_Data_Available = 0;
+ RDS_Data_Lost =0;
+ RDS_Groups_Available_till_now = 0;
+#endif
+ }
+
+ }
+ }
+ else
+ debug("Device already Powered-ON");
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+
+int Si4709_dev_powerdown(void)
+{
+ int ret = 0;
+
+ msleep(500); // For avoiding turned off pop noise
+ debug("Si4709_dev_powerdown called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_powerdown called when DS is invalid");
+ ret = -1;
+ }
+ else if ( ( ret = powerdown()) < 0 )
+ {
+ debug("powerdown failed");
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_suspend(void)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_suspend called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid_client_state== eFALSE )
+ {
+ debug("Si4709_dev_suspend called when DS (state, client) is invalid");
+ ret = -1;
+ }
+#if 0
+ else if( Si4709_dev.state.power_state == RADIO_ON )
+ {
+ ret = powerdown();
+ }
+#endif
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ debug("Si4709_dev_enable call over");
+
+ return ret;
+}
+
+int Si4709_dev_resume(void)
+{
+ int ret = 0;
+
+// debug("Si4709_dev_resume called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid_client_state == eFALSE )
+ {
+ debug("Si4709_dev_resume called when DS (state, client) is invalid");
+ ret = -1;
+ }
+#if 0
+ else if( Si4709_dev.state.power_state == RADIO_POWERDOWN )
+ {
+ if( (ret = powerup()) < 0 )
+ {
+ debug("powerup failed");
+ }
+ }
+#endif
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+// debug("Si4709_dev_disable call over");
+
+ return ret;
+}
+
+int Si4709_dev_band_set(int band)
+{
+ int ret = 0;
+ u16 sysconfig2 =0;
+ u16 prev_band = 0;
+ u32 prev_bottom_of_band = 0;
+
+ debug("Si4709_dev_band_set called");
+
+ mutex_lock(&(Si4709_dev.lock));
+ sysconfig2 = Si4709_dev.registers[SYSCONFIG2];
+ prev_band = Si4709_dev.settings.band;
+ prev_bottom_of_band = Si4709_dev.settings.bottom_of_band;
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_band_set called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ switch (band)
+ {
+ case BAND_87500_108000_kHz:
+ SYSCONFIG2_BITSET_BAND_87p5_108_MHz(&Si4709_dev.registers[SYSCONFIG2]);
+ Si4709_dev.settings.band = BAND_87500_108000_kHz;
+ Si4709_dev.settings.bottom_of_band = FREQ_87500_kHz;
+ break;
+
+ case BAND_76000_108000_kHz:
+ SYSCONFIG2_BITSET_BAND_76_108_MHz(&Si4709_dev.registers[SYSCONFIG2]);
+ Si4709_dev.settings.band = BAND_76000_108000_kHz;
+ Si4709_dev.settings.bottom_of_band = FREQ_76000_kHz;
+ break;
+
+ case BAND_76000_90000_kHz:
+ SYSCONFIG2_BITSET_BAND_76_90_MHz(&Si4709_dev.registers[SYSCONFIG2]);
+ Si4709_dev.settings.band = BAND_76000_90000_kHz;
+ Si4709_dev.settings.bottom_of_band = FREQ_76000_kHz;
+ break;
+
+ default:
+ ret = -1;
+ }
+
+ if(ret == 0)
+ {
+ if( (ret = i2c_write(SYSCONFIG2)) < 0 )
+ {
+ debug("Si4709_dev_band_set i2c_write 1 failed");
+ Si4709_dev.settings.band = prev_band;
+ Si4709_dev.settings.bottom_of_band = prev_bottom_of_band;
+ Si4709_dev.registers[SYSCONFIG2] = sysconfig2;
+ }
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_ch_spacing_set(int ch_spacing)
+{
+ int ret = 0;
+ u16 sysconfig2 = 0;
+ u16 prev_ch_spacing = 0;
+
+ debug("Si4709_dev_ch_spacing_set called");
+
+ mutex_lock(&(Si4709_dev.lock));
+ sysconfig2 = Si4709_dev.registers[SYSCONFIG2];
+ prev_ch_spacing = Si4709_dev.settings.channel_spacing;
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_ch_spacing_set called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ switch (ch_spacing)
+ {
+ case CHAN_SPACING_200_kHz:
+ SYSCONFIG2_BITSET_SPACE_200_KHz(&Si4709_dev.registers[SYSCONFIG2]);
+ Si4709_dev.settings.channel_spacing = CHAN_SPACING_200_kHz;
+ break;
+
+ case CHAN_SPACING_100_kHz:
+ SYSCONFIG2_BITSET_SPACE_100_KHz(&Si4709_dev.registers[SYSCONFIG2]);
+ Si4709_dev.settings.channel_spacing = CHAN_SPACING_100_kHz;
+ break;
+
+ case CHAN_SPACING_50_kHz:
+ SYSCONFIG2_BITSET_SPACE_50_KHz(&Si4709_dev.registers[SYSCONFIG2]);
+ Si4709_dev.settings.channel_spacing = CHAN_SPACING_50_kHz;
+ break;
+
+ default:
+ ret = -1;
+ }
+
+ if(ret == 0)
+ {
+ if( (ret = i2c_write(SYSCONFIG2)) < 0 )
+ {
+ debug("Si4709_dev_ch_spacing_set i2c_write 1 failed");
+ Si4709_dev.settings.channel_spacing = prev_ch_spacing;
+ Si4709_dev.registers[SYSCONFIG2] = sysconfig2;
+ }
+
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_chan_select(u32 frequency)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_chan_select called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_chan_select called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ Si4709_dev.state.seek_state = RADIO_SEEK_ON;
+
+ ret = tune_freq(frequency);
+ debug("Si4709_dev_chan_select called1");
+ Si4709_dev.state.seek_state = RADIO_SEEK_OFF;
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_chan_get(u32 *frequency)
+{
+ int ret = 0;
+
+
+ debug("Si4709_dev_chan_get called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_chan_get called when DS is invalid");
+ ret = -1;
+ }
+ else if( (ret = i2c_read(READCHAN)) < 0 )
+ {
+ debug("Si4709_dev_chan_get i2c_read failed");
+ }
+ else
+ {
+ get_cur_chan_freq(frequency, Si4709_dev.registers[READCHAN]);
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_seek_up(u32 *frequency)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_seek_up called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_seek_up called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ Si4709_dev.state.seek_state = RADIO_SEEK_ON;
+
+ ret = seek(frequency, 1);
+
+ Si4709_dev.state.seek_state = RADIO_SEEK_OFF;
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_seek_down(u32 *frequency)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_seek_down called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_seek_down called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ Si4709_dev.state.seek_state = RADIO_SEEK_ON;
+
+ ret = seek(frequency, 0);
+
+ Si4709_dev.state.seek_state = RADIO_SEEK_OFF;
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+
+#if 0
+int Si4709_dev_seek_auto(u32 *seek_preset_user)
+{
+ u8 *rssi_seek;
+ int ret = 0;
+ int i =0;
+ int j = 0;
+ channel_into_t temp;
+
+ debug("Si4709_dev_seek_auto called");
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_seek_auto called when DS is invalid");
+ ret = -1;
+ }
+
+ else if( (rssi_seek = (u8 *)kzalloc(sizeof(u8) * NUM_SEEK_PRESETS, GFP_KERNEL)) == NULL )
+ {
+ debug("Si4709_ioctl: no memory");
+ ret = -ENOMEM;
+ }
+
+ else
+ {
+
+ if( (ret = tune_freq(FREQ_87500_kHz)) == 0 )
+ {
+ debug("Si4709_dev_seek_auto tune_freq success");
+ get_cur_chan_freq(&(Si4709_dev.rssi_freq[0].frequency), Si4709_dev.registers[READCHAN]);
+ Si4709_dev_cur_RSSI_get(&(Si4709_dev.rssi_freq[0].rsssi_val));
+
+ }
+ else
+ {
+ debug("tunning failed, seek auto failed");
+ ret =-1;
+ }
+ #if 0
+ for(i=0;i<50; i++)
+ {
+ if( (ret = seek(&(Si4709_dev.settings.seek_preset[i]),1)) == 0 )
+ {
+ get_cur_chan_freq(&(Si4709_dev.rssi_freq[i].frequency), Si4709_dev.registers[READCHAN]);
+ Si4709_dev_cur_RSSI_get(&(Si4709_dev.rssi_freq[i].rsssi_val));
+ rssi_seek ++;
+ }
+
+ else
+ {
+ debug("seek failed");
+
+ }
+ }
+ #endif
+
+
+
+ /***new method ****/
+ for(i=1;i<30; i++)
+ {
+ if( (ret = seek(&(Si4709_dev.settings.seek_preset[i]),1)) == 0 )
+ {
+ get_cur_chan_freq(&(Si4709_dev.rssi_freq[i].frequency), Si4709_dev.registers[READCHAN]);
+ Si4709_dev_cur_RSSI_get(&(Si4709_dev.rssi_freq[i].rsssi_val));
+ }
+
+ else
+ {
+ debug("seek failed");
+
+ }
+ }
+ /***Sort the array of structures on the basis of RSSI value****/
+ for(i=0;i<29;i++)
+ {
+
+ for(j=i+1;j<30;j++)
+ {
+
+ if( Si4709_dev.rssi_freq[j].rsssi_val>Si4709_dev.rssi_freq[i].rsssi_val)
+ {
+ temp=Si4709_dev.rssi_freq[i];
+ Si4709_dev.rssi_freq[i]=Si4709_dev.rssi_freq[j];
+ Si4709_dev.rssi_freq[j]=temp;
+ }
+
+ }
+
+ }
+
+ /***Store the frequency in Array*****/
+ for(i=0;i<19;i++)
+ {
+ Si4709_dev.settings.seek_preset[i]=Si4709_dev.rssi_freq[i].frequency;
+ }
+
+
+
+ }
+ memcpy(seek_preset_user, Si4709_dev.settings.seek_preset , sizeof(int)*NUM_SEEK_PRESETS);
+ kfree(rssi_seek);
+ return ret;
+}
+#endif
+
+
+
+int Si4709_dev_RSSI_seek_th_set(u8 seek_th)
+{
+ int ret = 0;
+ u16 sysconfig2 = 0;
+
+ debug("Si4709_dev_RSSI_seek_th_set called");
+
+ mutex_lock(&(Si4709_dev.lock));
+ sysconfig2 = Si4709_dev.registers[SYSCONFIG2];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_RSSI_seek_th_set called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ SYSCONFIG2_BITSET_SEEKTH(&Si4709_dev.registers[SYSCONFIG2], seek_th);
+ Si4709_dev.settings.curr_rssi_th=seek_th;
+ if( (ret = i2c_write( SYSCONFIG2 )) < 0 )
+ {
+ debug("Si4709_dev_RSSI_seek_th_set i2c_write 1 failed");
+ Si4709_dev.registers[SYSCONFIG2] = sysconfig2;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_seek_SNR_th_set(u8 seek_SNR)
+{
+ int ret = 0;
+ u16 sysconfig3 = 0;
+
+ debug("Si4709_dev_seek_SNR_th_set called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ sysconfig3 = Si4709_dev.registers[SYSCONFIG3];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_seek_SNR_th_set called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ SYSCONFIG3_BITSET_SKSNR(&Si4709_dev.registers[SYSCONFIG3], seek_SNR);
+ SYSCONFIG3_BITSET_RESERVED(&Si4709_dev.registers[SYSCONFIG3]);
+ Si4709_dev.settings.curr_snr=seek_SNR;
+
+ if( (ret = i2c_write( SYSCONFIG3 )) < 0 )
+ {
+ debug("Si4709_dev_seek_SNR_th_set i2c_write 1 failed");
+ Si4709_dev.registers[SYSCONFIG3] = sysconfig3;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_seek_FM_ID_th_set(u8 seek_FM_ID_th)
+{
+ int ret = 0;
+ u16 sysconfig3 = 0;
+
+ debug("Si4709_dev_seek_FM_ID_th_set called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ sysconfig3 = Si4709_dev.registers[SYSCONFIG3];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_seek_SNR_th_set called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ SYSCONFIG3_BITSET_SKCNT(&Si4709_dev.registers[SYSCONFIG3], seek_FM_ID_th);
+ SYSCONFIG3_BITSET_RESERVED(&Si4709_dev.registers[SYSCONFIG3]);
+
+ if( (ret = i2c_write( SYSCONFIG3 )) < 0 )
+ {
+ debug("Si4709_dev_seek_FM_ID_th_set i2c_write 1 failed");
+ sysconfig3 = Si4709_dev.registers[SYSCONFIG3];
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_cur_RSSI_get(rssi_snr_t *cur_RSSI)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_cur_RSSI_get called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_cur_RSSI_get called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ if( (ret = i2c_read(STATUSRSSI)) < 0 )
+ {
+ debug("Si4709_dev_cur_RSSI_get i2c_read 1 failed");
+ }
+ else
+ {
+
+ cur_RSSI->curr_rssi= STATUSRSSI_RSSI_SIGNAL_STRENGTH(Si4709_dev.registers[STATUSRSSI]);
+ cur_RSSI->curr_rssi_th=Si4709_dev.settings.curr_rssi_th;
+ cur_RSSI->curr_snr=Si4709_dev.settings.curr_snr;
+ }
+ }
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+/*VNVS:START 13-OCT'09---- Functions which reads device-id,chip-id,power configuration, system configuration2 registers */
+int Si4709_dev_device_id(device_id *dev_id)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_device_id called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_device_id called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ if( (ret = i2c_read(DEVICE_ID)) < 0 )
+ {
+ debug("Si4709_dev_device_id i2c_read failed");
+ }
+ else
+ {
+
+ dev_id->part_number= DEVICE_ID_PART_NUMBER(Si4709_dev.registers[DEVICE_ID]);
+ dev_id->manufact_number = DEVICE_ID_MANUFACT_NUMBER(Si4709_dev.registers[DEVICE_ID]);
+
+ }
+ }
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_chip_id(chip_id *chp_id)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_chip_id called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_chip_id called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ if( (ret = i2c_read(CHIP_ID)) < 0 )
+ {
+ debug("Si4709_dev_chip_id i2c_read failed");
+ }
+ else
+ {
+
+ chp_id->chip_version= CHIP_ID_CHIP_VERSION(Si4709_dev.registers[CHIP_ID]);
+ chp_id->device = CHIP_ID_DEVICE(Si4709_dev.registers[CHIP_ID]);
+ chp_id->firmware_version = CHIP_ID_FIRMWARE_VERSION(Si4709_dev.registers[CHIP_ID]);
+ }
+ }
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_sys_config2(sys_config2 *sys_conf2)
+{
+ int ret = 0;
+
+ debug("Si4709_sys_config2 called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_sys_config2 called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ if((ret = i2c_read(SYSCONFIG2)) < 0)
+ {
+ debug("Si4709_sys_config2 i2c_read failed");
+ }
+ else
+ {
+ sys_conf2->rssi_th =SYS_CONFIG2_RSSI_TH(Si4709_dev.registers[SYSCONFIG2]);
+ sys_conf2->fm_band = SYS_CONFIG2_FM_BAND(Si4709_dev.registers[SYSCONFIG2]);
+ sys_conf2->fm_chan_spac = SYS_CONFIG2_FM_CHAN_SPAC(Si4709_dev.registers[SYSCONFIG2]);
+ sys_conf2->fm_vol = SYS_CONFIG2_FM_VOL(Si4709_dev.registers[SYSCONFIG2]);
+ }
+ }
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_sys_config3(sys_config3 *sys_conf3)
+{
+ int ret = 0;
+
+ debug("Si4709_sys_config3 called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_sys_config3 called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ if((ret = i2c_read(SYSCONFIG3)) < 0)
+ {
+ debug("Si4709_sys_config3 i2c_read failed");
+ }
+ else
+ {
+ sys_conf3->smmute = (Si4709_dev.registers[SYSCONFIG3] & 0xC000) >> 14;
+ sys_conf3->smutea = (Si4709_dev.registers[SYSCONFIG3] & 0x3000) >> 12;
+ sys_conf3->volext = (Si4709_dev.registers[SYSCONFIG3] & 0x0100) >> 8;
+ sys_conf3->sksnr = (Si4709_dev.registers[SYSCONFIG3] & 0x00F0) >> 4;
+ sys_conf3->skcnt = (Si4709_dev.registers[SYSCONFIG3] & 0x000F);
+ }
+ }
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_status_rssi(status_rssi *status)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_status_rssi called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_status_rssi called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ if((ret = i2c_read(STATUSRSSI)) < 0)
+ {
+ debug("Si4709_sys_config3 i2c_read failed");
+ }
+ else
+ {
+ status->rdsr = (Si4709_dev.registers[STATUSRSSI] & 0x8000) >> 15;
+ status->stc = (Si4709_dev.registers[STATUSRSSI] & 0x4000) >> 14;
+ status->sfbl = (Si4709_dev.registers[STATUSRSSI] & 0x2000) >> 13;
+ status->afcrl = (Si4709_dev.registers[STATUSRSSI] & 0x1000) >> 12;
+ status->rdss = (Si4709_dev.registers[STATUSRSSI] & 0x0800) >> 11;
+ status->blera = (Si4709_dev.registers[STATUSRSSI] & 0x0600) >> 9;
+ status->st = (Si4709_dev.registers[STATUSRSSI] & 0x0100) >> 8;
+ status->rssi = (Si4709_dev.registers[STATUSRSSI] & 0x00FF);
+ }
+ }
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_sys_config2_set(sys_config2 *sys_conf2)
+{
+ int ret = 0;
+ u16 register_bak = 0;
+
+ debug("Si4709_dev_sys_config2_set called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ register_bak = Si4709_dev.registers[SYSCONFIG2];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_sys_config2_set called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ printk(KERN_ERR "Si4709_dev_sys_config2_set() : Register Value = [0x%X], rssi-th = [%X]\n", Si4709_dev.registers[SYSCONFIG2], sys_conf2->rssi_th);
+ Si4709_dev.registers[SYSCONFIG2] = (Si4709_dev.registers[SYSCONFIG2] & 0x00FF) | ((sys_conf2->rssi_th) << 8);
+ Si4709_dev.registers[SYSCONFIG2] = (Si4709_dev.registers[SYSCONFIG2] & 0xFF3F) | ((sys_conf2->fm_band) << 6);
+ Si4709_dev.registers[SYSCONFIG2] = (Si4709_dev.registers[SYSCONFIG2] & 0xFFCF) | ((sys_conf2->fm_chan_spac) << 4);
+ Si4709_dev.registers[SYSCONFIG2] = (Si4709_dev.registers[SYSCONFIG2] & 0xFFF0) | (sys_conf2->fm_vol);
+ printk(KERN_ERR "Si4709_dev_sys_config2_set() : After Register Value = [0x%X]\n", Si4709_dev.registers[SYSCONFIG2]);
+
+ if( (ret = i2c_write( SYSCONFIG2 )) < 0 )
+ {
+ debug("Si4709_dev_sys_config2_set i2c_write 1 failed");
+ Si4709_dev.registers[SYSCONFIG2] = register_bak;
+ }
+ else
+ printk(KERN_ERR "Si4709_dev_sys_config2_set() : Write Sucess!!");
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_sys_config3_set(sys_config3 *sys_conf3)
+{
+ int ret = 0;
+ u16 register_bak = 0;
+
+ debug("Si4709_dev_sys_config3_set called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ register_bak = Si4709_dev.registers[SYSCONFIG3];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_sys_config3_set called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ printk(KERN_ERR "Si4709_dev_sys_config3_set() : Register Value = [0x%X], sksnrth = [%X]\n", Si4709_dev.registers[SYSCONFIG3], sys_conf3->sksnr);
+ Si4709_dev.registers[SYSCONFIG3] = (Si4709_dev.registers[SYSCONFIG3] & 0x3FFF) | ((sys_conf3->smmute) << 14);
+ Si4709_dev.registers[SYSCONFIG3] = (Si4709_dev.registers[SYSCONFIG3] & 0xCFFF) | ((sys_conf3->smutea) << 12);
+ Si4709_dev.registers[SYSCONFIG3] = (Si4709_dev.registers[SYSCONFIG3] & 0xFEFF) | ((sys_conf3->volext) << 8);
+ Si4709_dev.registers[SYSCONFIG3] = (Si4709_dev.registers[SYSCONFIG3] & 0xFF0F) | ((sys_conf3->sksnr) << 4);
+ Si4709_dev.registers[SYSCONFIG3] = (Si4709_dev.registers[SYSCONFIG3] & 0xFFF0) | (sys_conf3->skcnt);
+ printk(KERN_ERR "Si4709_dev_sys_config3_set() : After Register Value = [0x%X]\n", Si4709_dev.registers[SYSCONFIG3]);
+
+ if((ret = i2c_write( SYSCONFIG3)) < 0)
+ {
+ debug("Si4709_dev_sys_config3_set i2c_write 1 failed");
+ Si4709_dev.registers[SYSCONFIG3] = register_bak;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_power_config(power_config *pow_conf)
+{
+ int ret =0;
+
+ debug("Si4709_dev_power_config called");
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_power_config called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ if( (ret = i2c_read(POWERCFG)) < 0 )
+ {
+ debug("Si4709_dev_power_config i2c_read failed");
+ }
+ else
+ {
+
+ pow_conf->dsmute =POWER_CONFIG_SOFTMUTE_STATUS(Si4709_dev.registers[POWERCFG]);
+ pow_conf->dmute =POWER_CONFIG_MUTE_STATUS(Si4709_dev.registers[POWERCFG]);
+ pow_conf->mono =POWER_CONFIG_MONO_STATUS(Si4709_dev.registers[POWERCFG]);
+ pow_conf->rds_mode =POWER_CONFIG_RDS_MODE_STATUS(Si4709_dev.registers[POWERCFG]);
+ pow_conf->sk_mode =POWER_CONFIG_SKMODE_STATUS(Si4709_dev.registers[POWERCFG]);
+ pow_conf->seek_up =POWER_CONFIG_SEEKUP_STATUS(Si4709_dev.registers[POWERCFG]);
+ pow_conf->seek =POWER_CONFIG_SEEK_STATUS(Si4709_dev.registers[POWERCFG]);
+ pow_conf->power_disable =POWER_CONFIG_DISABLE_STATUS(Si4709_dev.registers[POWERCFG]);
+ pow_conf->power_enable =POWER_CONFIG_ENABLE_STATUS(Si4709_dev.registers[POWERCFG]);
+ }
+ }
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+/*VNVS:END*/
+
+/*VNVS:START 18-NOV'09*/
+/*Reading AFCRL Bit*/
+int Si4709_dev_AFCRL_get(u8 *afc)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_AFCRL_get called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_AFCRL_get called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ if( (ret = i2c_read(STATUSRSSI)) < 0 )
+ {
+ debug("Si4709_dev_AFCRL_get i2c_read failed");
+ }
+ *afc = STATUSRSSI_AFC_RAIL_STATUS(Si4709_dev.registers[STATUSRSSI]);
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+/*Setting DE-emphasis time constant 50us(Europe,Japan,Australia) or 75us(USA)*/
+int Si4709_dev_DE_set(u8 de_tc)
+{
+ u16 sysconfig1 = 0;
+ int ret = 0;
+
+ debug("Si4709_dev_DE_set called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ sysconfig1 = Si4709_dev.registers[SYSCONFIG1];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_DE_set called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ switch(de_tc)
+ {
+ case DE_TIME_CONSTANT_50:
+ SYSCONFIG1_BITSET_DE_50(&Si4709_dev.registers[SYSCONFIG1]);
+ SYSCONFIG1_BITSET_RESERVED( &Si4709_dev.registers[SYSCONFIG1] );
+ break;
+ case DE_TIME_CONSTANT_75:
+ SYSCONFIG1_BITSET_DE_75(&Si4709_dev.registers[SYSCONFIG1]);
+ SYSCONFIG1_BITSET_RESERVED( &Si4709_dev.registers[SYSCONFIG1] );
+ break;
+ default:
+ ret = -1;
+ }
+
+ if(0==ret)
+ if( (ret = i2c_write(SYSCONFIG1)) < 0 )
+ {
+ debug("Si4709_dev_DE_set i2c_write failed");
+ Si4709_dev.registers[SYSCONFIG1] = sysconfig1;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+/*Resetting the RDS Data Buffer*/
+int Si4709_dev_reset_rds_data()
+{
+ int ret = 0;
+
+ debug_rds("Si4709_dev_reset_rds_data called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_reset_rds_data called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ RDS_Buffer_Index_write = 0;
+ RDS_Buffer_Index_read = 0;
+ RDS_Data_Lost = 0;
+ RDS_Data_Available = 0;
+ memset(RDS_Block_Data_buffer,0,RDS_BUFFER_LENGTH*8);
+ memset(RDS_Block_Error_buffer,0,RDS_BUFFER_LENGTH*4);
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+/*VNVS:END*/
+int Si4709_dev_VOLEXT_ENB(void)
+{
+ int ret = 0;
+ u16 sysconfig3 = 0;
+
+ debug("Si4709_dev_VOLEXT_ENB called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ sysconfig3 = Si4709_dev.registers[SYSCONFIG3];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_VOLEXT_ENB called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ SYSCONFIG3_BITSET_VOLEXT_ENB(&Si4709_dev.registers[SYSCONFIG3]);
+ SYSCONFIG3_BITSET_RESERVED(&Si4709_dev.registers[SYSCONFIG3]);
+
+ if( (ret = i2c_write( SYSCONFIG3 )) < 0 )
+ {
+ debug("Si4709_dev_VOLEXT_ENB i2c_write failed");
+ Si4709_dev.registers[SYSCONFIG3] = sysconfig3;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_VOLEXT_DISB(void)
+{
+ int ret = 0;
+ u16 sysconfig3 = 0;
+
+ debug("Si4709_dev_VOLEXT_DISB called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ sysconfig3 = Si4709_dev.registers[SYSCONFIG3];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_VOLEXT_DISB called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ SYSCONFIG3_BITSET_VOLEXT_DISB(&Si4709_dev.registers[SYSCONFIG3]);
+ SYSCONFIG3_BITSET_RESERVED(&Si4709_dev.registers[SYSCONFIG3]);
+
+ if( (ret = i2c_write( SYSCONFIG3 )) < 0 )
+ {
+ debug("Si4709_dev_VOLEXT_DISB i2c_write failed");
+ Si4709_dev.registers[SYSCONFIG3] = sysconfig3;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_volume_set(u8 volume)
+{
+ int ret = 0;
+ u16 sysconfig2 = 0;
+
+ debug("Si4709_dev_volume_set called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ sysconfig2 = Si4709_dev.registers[SYSCONFIG2];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_volume_set called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ SYSCONFIG2_BITSET_VOLUME(&Si4709_dev.registers[SYSCONFIG2], volume);
+
+ if( (ret = i2c_write( SYSCONFIG2 )) < 0 )
+ {
+ debug("Si4709_dev_volume_set i2c_write failed");
+ Si4709_dev.registers[SYSCONFIG2] = sysconfig2;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_volume_get(u8 *volume)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_volume_get called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_volume_get called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ *volume = SYSCONFIG2_GET_VOLUME(Si4709_dev.registers[SYSCONFIG2]);
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+/*
+ VNVS:START 19-AUG'10---- Adding DSMUTE ON/OFF feature.The Soft Mute feature is available to attenuate the audio
+ outputs and minimize audible noise in very weak signal conditions.
+ */
+int Si4709_dev_DSMUTE_ON(void)
+{
+ int ret = 0;
+ u16 powercfg = 0;
+
+ debug("Si4709_dev_DSMUTE_ON called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ powercfg = Si4709_dev.registers[POWERCFG];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_DSMUTE_ON called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ POWERCFG_BITSET_DSMUTE_LOW(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_RESERVED(&Si4709_dev.registers[POWERCFG]);
+
+ if( (ret = i2c_write( POWERCFG )) < 0 )
+ {
+ error("Si4709_dev_DSMUTE_ON i2c_write failed");
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_DSMUTE_OFF(void)
+{
+ int ret = 0;
+ u16 powercfg = 0;
+
+ debug("Si4709_dev_DSMUTE_OFF called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ powercfg = Si4709_dev.registers[POWERCFG];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_DSMUTE_OFF called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ POWERCFG_BITSET_DSMUTE_HIGH(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_RESERVED(&Si4709_dev.registers[POWERCFG]);
+
+ if( (ret = i2c_write( POWERCFG )) < 0 )
+ {
+ error("Si4709_dev_DSMUTE_OFF i2c_write failed");
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+/*VNVS:END*/
+
+int Si4709_dev_MUTE_ON(void)
+{
+ int ret = 0;
+ u16 powercfg = 0;
+
+ debug("Si4709_dev_MUTE_ON called");
+
+ mutex_lock(&(Si4709_dev.lock));
+ powercfg = Si4709_dev.registers[POWERCFG];
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_MUTE_ON called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ POWERCFG_BITSET_DMUTE_LOW(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_RESERVED(&Si4709_dev.registers[POWERCFG]);
+
+ if( (ret = i2c_write( POWERCFG )) < 0 )
+ {
+ debug("Si4709_dev_MUTE_ON i2c_write failed");
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_MUTE_OFF(void)
+{
+ int ret = 0;
+ u16 powercfg = 0;
+
+ debug("Si4709_dev_MUTE_OFF called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ powercfg = Si4709_dev.registers[POWERCFG];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_MUTE_OFF called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ POWERCFG_BITSET_DMUTE_HIGH(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_RESERVED(&Si4709_dev.registers[POWERCFG]);
+
+ if( (ret = i2c_write( POWERCFG )) < 0 )
+ {
+ debug("Si4709_dev_MUTE_OFF i2c_write failed");
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_MONO_SET(void)
+{
+ int ret = 0;
+ u16 powercfg = 0;
+
+ debug("Si4709_dev_MONO_SET called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ powercfg = Si4709_dev.registers[POWERCFG];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_MONO_SET called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ POWERCFG_BITSET_MONO_HIGH(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_RESERVED(&Si4709_dev.registers[POWERCFG]);
+
+ if( (ret = i2c_write( POWERCFG )) < 0 )
+ {
+ debug("Si4709_dev_MONO_SET i2c_write failed");
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_STEREO_SET(void)
+{
+ int ret = 0;
+ u16 powercfg = 0;
+
+ debug("Si4709_dev_STEREO_SET called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ powercfg = Si4709_dev.registers[POWERCFG];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_STEREO_SET called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ POWERCFG_BITSET_MONO_LOW(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_RESERVED(&Si4709_dev.registers[POWERCFG]);
+
+ if( (ret = i2c_write( POWERCFG )) < 0 )
+ {
+ debug("Si4709_dev_STEREO_SET i2c_write failed");
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_RDS_ENABLE(void)
+{
+ u16 sysconfig1 = 0;
+ int ret = 0;
+
+ debug("Si4709_dev_RDS_ENABLE called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ sysconfig1 = Si4709_dev.registers[SYSCONFIG1];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_RDS_ENABLE called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ SYSCONFIG1_BITSET_RDS_HIGH(&Si4709_dev.registers[SYSCONFIG1]);
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+ SYSCONFIG1_BITSET_RDSIEN_HIGH(&Si4709_dev.registers[SYSCONFIG1]);
+#endif
+ SYSCONFIG1_BITSET_RESERVED( &Si4709_dev.registers[SYSCONFIG1] );
+ if( (ret = i2c_write(SYSCONFIG1)) < 0 )
+ {
+ debug("Si4709_dev_RDS_ENABLE i2c_write failed");
+ Si4709_dev.registers[SYSCONFIG1] = sysconfig1;
+ }
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+ else
+ Si4709_RDS_flag = RDS_WAITING;
+#endif
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+
+
+int Si4709_dev_RDS_DISABLE(void)
+{
+ u16 sysconfig1 = 0;
+ int ret = 0;
+
+ debug("Si4709_dev_RDS_DISABLE called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ sysconfig1 = Si4709_dev.registers[SYSCONFIG1];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_RDS_DISABLE called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ SYSCONFIG1_BITSET_RDS_LOW(&Si4709_dev.registers[SYSCONFIG1]);
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+ SYSCONFIG1_BITSET_RDSIEN_LOW(&Si4709_dev.registers[SYSCONFIG1]);
+#endif
+ SYSCONFIG1_BITSET_RESERVED( &Si4709_dev.registers[SYSCONFIG1] );
+ if( (ret = i2c_write(SYSCONFIG1)) < 0 )
+ {
+ debug("Si4709_dev_RDS_DISABLE i2c_write failed");
+ Si4709_dev.registers[SYSCONFIG1] = sysconfig1;
+ }
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+ else
+ Si4709_RDS_flag = NO_WAIT;
+#endif
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+
+int Si4709_dev_rstate_get(dev_state_t *dev_state)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_rstate_get called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_rstate_get called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ dev_state->power_state = Si4709_dev.state.power_state;
+ dev_state->seek_state = Si4709_dev.state.seek_state;
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+
+/*VNVS:START 7-JUNE'10 Function call for work-queue "Si4709_wq"*/
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+void Si4709_work_func(struct work_struct *work)
+{
+ int i,ret = 0;
+#ifdef RDS_TESTING
+ u8 group_type;
+#endif
+ debug_rds("%s",__func__);
+// mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ error("Si4709_dev_RDS_data_get called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+
+ if(RDS_Data_Lost > 1)
+ debug_rds("No_of_RDS_groups_Lost till now : %d",RDS_Data_Lost);
+
+
+ /*RDSR bit and RDS Block data, so reading the RDS registers*/
+ if((ret = i2c_read(RDSD)) < 0)
+ error("Si4709_work_func i2c_read failed");
+ else
+ {
+ /*Checking whether RDS Ready bit is set or not, if not set return immediately*/
+ if(!(STATUSRSSI_RDS_READY_STATUS(Si4709_dev.registers[STATUSRSSI])))
+ {
+ error("RDS Ready Bit Not set");
+ return;
+ }
+
+ debug_rds("RDS Ready bit is set");
+
+ debug_rds("No_of_RDS_groups_Available : %d",RDS_Data_Available);
+
+ RDS_Data_Available = 0;
+
+ debug_rds("RDS_Buffer_Index_write = %d",RDS_Buffer_Index_write);
+
+ /*Writing into the Circular Buffer*/
+
+ /*Writing into RDS_Block_Data_buffer*/
+ i = 0;
+ RDS_Block_Data_buffer[i++ + 4*RDS_Buffer_Index_write] = Si4709_dev.registers[RDSA];
+ RDS_Block_Data_buffer[i++ + 4*RDS_Buffer_Index_write] = Si4709_dev.registers[RDSB];
+ RDS_Block_Data_buffer[i++ + 4*RDS_Buffer_Index_write] = Si4709_dev.registers[RDSC];
+ RDS_Block_Data_buffer[i++ + 4*RDS_Buffer_Index_write] = Si4709_dev.registers[RDSD];
+
+ /*Writing into RDS_Block_Error_buffer*/
+ i = 0;
+ RDS_Block_Error_buffer[i++ + 4*RDS_Buffer_Index_write] = STATUSRSSI_RDS_BLOCK_A_ERRORS(Si4709_dev.registers[STATUSRSSI]);
+ RDS_Block_Error_buffer[i++ + 4*RDS_Buffer_Index_write] = READCHAN_BLOCK_B_ERRORS(Si4709_dev.registers[READCHAN]);
+ RDS_Block_Error_buffer[i++ + 4*RDS_Buffer_Index_write] = READCHAN_BLOCK_C_ERRORS(Si4709_dev.registers[READCHAN]);
+ RDS_Block_Error_buffer[i++ + 4*RDS_Buffer_Index_write] = READCHAN_BLOCK_D_ERRORS(Si4709_dev.registers[READCHAN]);
+
+#ifdef RDS_TESTING
+ if(RDS_Block_Error_buffer[0 + 4*RDS_Buffer_Index_write] < 3)
+ {
+ debug_rds("PI Code is %d",RDS_Block_Data_buffer[0 + 4*RDS_Buffer_Index_write]);
+ }
+ if(RDS_Block_Error_buffer[1 + 4*RDS_Buffer_Index_write] < 2)
+ {
+ group_type = RDS_Block_Data_buffer[1 + 4*RDS_Buffer_Index_write] >> 11;
+
+ if (group_type & 0x01)
+ {
+ debug_rds("PI Code is %d",RDS_Block_Data_buffer[2 + 4*RDS_Buffer_Index_write]);
+ }
+ if(group_type == GROUP_TYPE_2A || group_type == GROUP_TYPE_2B )
+ {
+ if(RDS_Block_Error_buffer[2 + 4*RDS_Buffer_Index_write] < 3)
+ {
+ debug_rds("Update RT with RDSC");
+ }
+ else
+ {
+ debug_rds("RDS_Block_Error_buffer of Block C is greater than 3");
+ }
+ }
+ }
+#endif
+ RDS_Buffer_Index_write++;
+
+ if(RDS_Buffer_Index_write >= RDS_BUFFER_LENGTH)
+ RDS_Buffer_Index_write = 0;
+
+ debug_rds("RDS_Buffer_Index_write = %d",RDS_Buffer_Index_write);
+ }
+ }
+
+// mutex_unlock(&(Si4709_dev.lock));
+}
+#endif
+/*VNVS:END*/
+
+int Si4709_dev_RDS_data_get(radio_data_t *data)
+{
+ int i,ret = 0;
+ u16 sysconfig1 = 0;
+
+ debug_rds("Si4709_dev_RDS_data_get called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ sysconfig1 = Si4709_dev.registers[SYSCONFIG1];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ error("Si4709_dev_RDS_data_get called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+
+ debug_rds("RDS_Buffer_Index_read = %d",RDS_Buffer_Index_read);
+
+ /*If No New RDS Data is available return error*/
+ if(RDS_Buffer_Index_read == RDS_Buffer_Index_write)
+ {
+ debug_rds("No_New_RDS_Data_is_available");
+ if((ret = i2c_read(READCHAN)) < 0)
+ error("Si4709_dev_RDS_data_get i2c_read 1 failed");
+ else
+ {
+ get_cur_chan_freq(&(data->curr_channel), Si4709_dev.registers[READCHAN]);
+ data->curr_rssi = STATUSRSSI_RSSI_SIGNAL_STRENGTH(Si4709_dev.registers[STATUSRSSI]);
+ debug_rds("curr_channel: %u, curr_rssi:%u",data->curr_channel,(u32)data->curr_rssi);
+ }
+ ret = -1;
+ }
+ else
+ {
+ if((ret = i2c_read(READCHAN)) < 0)
+ error("Si4709_dev_RDS_data_get i2c_read 2 failed");
+ else
+ {
+ get_cur_chan_freq(&(data->curr_channel), Si4709_dev.registers[READCHAN]);
+ data->curr_rssi = STATUSRSSI_RSSI_SIGNAL_STRENGTH(Si4709_dev.registers[STATUSRSSI]);
+ debug_rds("curr_channel: %u, curr_rssi:%u",data->curr_channel,(u32)data->curr_rssi);
+
+ /*Reading from RDS_Block_Data_buffer*/
+ i = 0;
+ data->rdsa = RDS_Block_Data_buffer[i++ + 4*RDS_Buffer_Index_read];
+ data->rdsb = RDS_Block_Data_buffer[i++ + 4*RDS_Buffer_Index_read];
+ data->rdsc = RDS_Block_Data_buffer[i++ + 4*RDS_Buffer_Index_read];
+ data->rdsd = RDS_Block_Data_buffer[i++ + 4*RDS_Buffer_Index_read];
+
+ /*Reading from RDS_Block_Error_buffer*/
+ i = 0;
+ data->blera = RDS_Block_Error_buffer[i++ + 4*RDS_Buffer_Index_read];
+ data->blerb = RDS_Block_Error_buffer[i++ + 4*RDS_Buffer_Index_read];
+ data->blerc = RDS_Block_Error_buffer[i++ + 4*RDS_Buffer_Index_read];
+ data->blerd = RDS_Block_Error_buffer[i++ + 4*RDS_Buffer_Index_read];
+
+ /*Flushing the read data*/
+ memset(&RDS_Block_Data_buffer[0+4*RDS_Buffer_Index_read],0,8);
+ memset(&RDS_Block_Error_buffer[0+4*RDS_Buffer_Index_read],0,4);
+
+ RDS_Buffer_Index_read++;
+
+ if(RDS_Buffer_Index_read >= RDS_BUFFER_LENGTH)
+ RDS_Buffer_Index_read = 0;
+ }
+ }
+
+ debug_rds("RDS_Buffer_Index_read = %d",RDS_Buffer_Index_read);
+
+#else
+ SYSCONFIG1_BITSET_RDSIEN_HIGH(&Si4709_dev.registers[SYSCONFIG1]);
+
+ if((ret = i2c_write(SYSCONFIG1)) < 0)
+ {
+ debug("Si4709_dev_RDS_data_get i2c_write 1 failed");
+ Si4709_dev.registers[SYSCONFIG1] = sysconfig1;
+ }
+ else
+ {
+ if( (ret=i2c_read(SYSCONFIG1)) < 0)
+ debug("Si4709_dev_RDS_data_get i2c_read 1 failed");
+
+ debug("sysconfig1: 0x%x",Si4709_dev.registers[SYSCONFIG1] );
+ sysconfig1 = Si4709_dev.registers[SYSCONFIG1];
+
+ Si4709_dev_wait_flag = RDS_WAITING;
+
+ wait_RDS();
+
+ if((ret=i2c_read(STATUSRSSI)) < 0)
+ debug("Si4709_dev_RDS_data_get i2c_read 2 failed");
+
+ debug("statusrssi: 0x%x",Si4709_dev.registers[STATUSRSSI] );
+ SYSCONFIG1_BITSET_RDSIEN_LOW(&Si4709_dev.registers[SYSCONFIG1]);
+
+ if ((ret = i2c_write(SYSCONFIG1)) < 0)
+ {
+ debug("Si4709_dev_RDS_data_get i2c_write 2 failed");
+ Si4709_dev.registers[SYSCONFIG1] = sysconfig1;
+ }
+ else if(Si4709_dev_wait_flag == WAIT_OVER)
+ {
+ Si4709_dev_wait_flag = NO_WAIT;
+
+ if((ret = i2c_read(RDSD)) < 0)
+ debug("Si4709_dev_RDS_data_get i2c_read 3 failed");
+ else
+ {
+ data->rdsa = Si4709_dev.registers[RDSA];
+ data->rdsb = Si4709_dev.registers[RDSB];
+ data->rdsc = Si4709_dev.registers[RDSC];
+ data->rdsd = Si4709_dev.registers[RDSD];
+
+ get_cur_chan_freq(&(data->curr_channel), Si4709_dev.registers[READCHAN]);
+ debug("curr_channel: %u",data->curr_channel);
+ data->curr_rssi = STATUSRSSI_RSSI_SIGNAL_STRENGTH(Si4709_dev.registers[STATUSRSSI]);
+ debug("curr_rssi:%u",(u32)data->curr_rssi);
+ data->blera = STATUSRSSI_RDS_BLOCK_A_ERRORS(Si4709_dev.registers[STATUSRSSI]);
+ data->blerb = READCHAN_BLOCK_B_ERRORS(Si4709_dev.registers[READCHAN]);
+ data->blerc = READCHAN_BLOCK_C_ERRORS(Si4709_dev.registers[READCHAN]);
+ data->blerd = READCHAN_BLOCK_D_ERRORS(Si4709_dev.registers[READCHAN]);
+ }
+ }
+ else
+ {
+ debug("Si4709_dev_RDS_data_get failure no interrupt or timeout");
+ Si4709_dev_wait_flag = NO_WAIT;
+ ret = -1;
+ }
+ }
+#endif
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_RDS_timeout_set(u32 time_out)
+{
+ int ret = 0;
+ u32 jiffy_count = 0;
+
+ debug("Si4709_dev_RDS_timeout_set called");
+ /****convert time_out(in milliseconds) into jiffies*****/
+
+ jiffy_count = msecs_to_jiffies(time_out);
+
+ debug("jiffy_count%d",jiffy_count);
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_RDS_timeout_set called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ Si4709_dev.settings.timeout_RDS = jiffy_count;
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+
+/**************************************************************/
+static int powerup(void)
+{
+ int ret=0;
+ u16 powercfg = Si4709_dev.registers[POWERCFG];
+ int reg;
+ /****Resetting the device****/
+
+ gpio_set_value(FM_RESET, GPIO_LEVEL_LOW);
+ gpio_set_value(FM_RESET, GPIO_LEVEL_HIGH);
+
+#if 0
+ /*Add the i2c driver*/
+ if ( (ret = Si4709_i2c_drv_init() < 0) )
+ {
+ debug("Si4709_i2c_drv_init failed");
+ }
+#endif
+ /*Resetting the Si4709_dev.registers[] array*/
+ for(reg=0;reg < NUM_OF_REGISTERS;reg++)
+ Si4709_dev.registers[reg] = 0;
+
+ debug("Resetting the Si4709_dev.registers[] array");
+
+ POWERCFG_BITSET_DMUTE_HIGH( &Si4709_dev.registers[POWERCFG] );
+ POWERCFG_BITSET_ENABLE_HIGH( &Si4709_dev.registers[POWERCFG] );
+ POWERCFG_BITSET_DISABLE_LOW( &Si4709_dev.registers[POWERCFG] );
+ POWERCFG_BITSET_RESERVED( &Si4709_dev.registers[POWERCFG] );
+
+ if( (ret = i2c_write(POWERCFG)) < 0 )
+ {
+ debug("powerup->i2c_write 1 failed");
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ }
+ else
+ {
+ /*Si4709/09 datasheet: Table 7*/
+ mdelay(110);
+ Si4709_dev.state.power_state = RADIO_ON;
+ }
+
+ return ret;
+}
+
+static int powerdown(void)
+{
+ int ret = 0;
+ u16 test1 = Si4709_dev.registers[TEST1],
+ sysconfig1 = Si4709_dev.registers[SYSCONFIG1],
+ powercfg = Si4709_dev.registers[POWERCFG];
+
+ if(!(RADIO_POWERDOWN==Si4709_dev.state.power_state))
+ {
+ //TEST1_BITSET_AHIZEN_HIGH( &Si4709_dev.registers[TEST1] );
+ //TEST1_BITSET_RESERVED( &Si4709_dev.registers[TEST1] );
+
+ SYSCONFIG1_BITSET_GPIO_LOW(&Si4709_dev.registers[SYSCONFIG1]);
+ SYSCONFIG1_BITSET_RESERVED( &Si4709_dev.registers[SYSCONFIG1] );
+ /*VNVS: 13-OCT'09---- During Powerdown of the device RDS should be disabled
+ according to the Si4708/09 datasheet*/
+ SYSCONFIG1_BITSET_RDS_LOW(&Si4709_dev.registers[SYSCONFIG1]);
+
+ POWERCFG_BITSET_DMUTE_LOW( &Si4709_dev.registers[POWERCFG] );
+ POWERCFG_BITSET_ENABLE_HIGH( &Si4709_dev.registers[POWERCFG] );
+ POWERCFG_BITSET_DISABLE_HIGH( &Si4709_dev.registers[POWERCFG] );
+ POWERCFG_BITSET_RESERVED( &Si4709_dev.registers[POWERCFG] );
+
+ /*this will write all the above registers*/
+ if( (ret = i2c_write( TEST1 )) < 0 )
+ {
+ debug("powerdown->i2c_write failed");
+ Si4709_dev.registers[SYSCONFIG1] = sysconfig1;
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ Si4709_dev.registers[TEST1] = test1;
+ }
+ else
+ {
+ Si4709_dev.state.power_state = RADIO_POWERDOWN;
+ }
+
+ /****Resetting the device****/
+ gpio_set_value(FM_RESET, GPIO_LEVEL_LOW);
+ gpio_set_value(FM_RESET, GPIO_LEVEL_HIGH);
+ gpio_set_value(FM_RESET, GPIO_LEVEL_LOW);
+ }
+ else
+ debug("Device already Powered-OFF");
+
+ return ret;
+}
+
+static int seek(u32 *frequency, int up)
+{
+ int ret = 0;
+ u16 powercfg = Si4709_dev.registers[POWERCFG];
+ u16 channel = 0;
+ int valid_station_found = 0;
+
+ if( up )
+ {
+ POWERCFG_BITSET_SEEKUP_HIGH(&Si4709_dev.registers[POWERCFG]);
+ }
+ else
+ {
+ POWERCFG_BITSET_SEEKUP_LOW(&Si4709_dev.registers[POWERCFG]);
+ }
+
+ POWERCFG_BITSET_SKMODE_HIGH(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_SEEK_HIGH(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_RESERVED(&Si4709_dev.registers[POWERCFG]);
+
+ if( (ret = i2c_write(POWERCFG)) < 0 )
+ {
+ debug("seek i2c_write 1 failed");
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ }
+ else
+ {
+ Si4709_dev_wait_flag = SEEK_WAITING;
+
+ wait();
+
+ if ( Si4709_dev_wait_flag == SEEK_CANCEL )
+ {
+ powercfg = Si4709_dev.registers[POWERCFG];
+ POWERCFG_BITSET_SEEK_LOW(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_RESERVED(&Si4709_dev.registers[POWERCFG]);
+
+ if( (ret = i2c_write(POWERCFG)) < 0 )
+ {
+ debug("seek i2c_write 2 failed");
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ }
+
+ if( (ret = i2c_read( READCHAN )) < 0 )
+ {
+ debug("seek i2c_read 1 failed");
+ }
+ else
+ {
+ channel = READCHAN_GET_CHAN(Si4709_dev.registers[READCHAN]);
+ *frequency = channel_to_freq(channel);
+ }
+ *frequency = 0;
+ }
+
+ Si4709_dev_wait_flag = NO_WAIT;
+
+ if( (ret = i2c_read(STATUSRSSI)) < 0 )
+ {
+ debug("seek i2c_read 2 failed");
+ }
+ else
+ {
+ /*VNVS:START 13-OCT'09---- Checking the status of Seek/Tune Bit*/
+#ifdef TEST_FM
+ if(STATUSRSSI_SEEK_TUNE_STATUS(Si4709_dev.registers[STATUSRSSI]) == COMPLETE)
+ {
+ debug("Seek/Tune Status is set to 1 by device");
+ if(STATUSRSSI_SF_BL_STATUS(Si4709_dev.registers[STATUSRSSI]) == SEEK_SUCCESSFUL)
+ {
+ debug("Seek Fail/Band Limit Status is set to 0 by device ---SeekUp Operation Completed");
+ valid_station_found = 1;
+ }
+ else
+ debug("Seek Fail/Band Limit Status is set to 1 by device ---SeekUp Operation Not Completed");
+ }
+ else
+ debug("Seek/Tune Status is set to 0 by device ---SeekUp Operation Not Completed");
+
+#endif
+ /*VNVS:END*/
+
+ powercfg = Si4709_dev.registers[POWERCFG];
+
+ POWERCFG_BITSET_SEEK_LOW(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_RESERVED(&Si4709_dev.registers[POWERCFG]);
+
+ if( (ret = i2c_write(POWERCFG)) < 0 )
+ {
+ debug("seek i2c_write 2 failed");
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ }
+ else
+ {
+ do
+ {
+ if( (ret = i2c_read(STATUSRSSI)) < 0 )
+ {
+ debug("seek i2c_read 3 failed");
+ break;
+ }
+ }while( STATUSRSSI_SEEK_TUNE_STATUS(Si4709_dev.registers[STATUSRSSI]) != CLEAR );
+
+ if( ret == 0 && valid_station_found == 1 )
+ {
+ if( (ret = i2c_read( READCHAN )) < 0 )
+ {
+ debug("seek i2c_read 4 failed");
+ }
+ else
+ {
+ channel = READCHAN_GET_CHAN(Si4709_dev.registers[READCHAN]);
+ *frequency = channel_to_freq(channel);
+ debug("Frequency after seek-up is %d \n",*frequency);
+ }
+ }
+ else
+ {
+ debug("Valid station not found \n");
+ *frequency = 0;
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int tune_freq(u32 frequency)
+{
+ int ret = 0;
+ u16 channel = Si4709_dev.registers[CHANNEL];
+#ifdef TEST_FM
+ u16 read_channel;
+#endif
+ debug("tune_freq called");
+
+ Si4709_dev.registers[CHANNEL] = freq_to_channel(frequency);
+#ifdef TEST_FM
+ read_channel = Si4709_dev.registers[CHANNEL];
+ debug(" Input read_channel =%x",read_channel);
+#endif
+ CHANNEL_BITSET_TUNE_HIGH(&Si4709_dev.registers[CHANNEL]);
+ CHANNEL_BITSET_RESERVED(&Si4709_dev.registers[CHANNEL]);
+
+ if( (ret = i2c_write(CHANNEL)) < 0 )
+ {
+ debug("tune_freq i2c_write 1 failed");
+ Si4709_dev.registers[CHANNEL] = channel;
+ }
+ else
+ {
+
+ Si4709_dev_wait_flag = TUNE_WAITING;
+ debug("Si4709_dev_wait_flag = TUNE_WAITING");
+#ifdef TEST_FM
+ if( (ret = i2c_read(READCHAN)) < 0 )
+ {
+ debug("tune_freq i2c_read 1 failed");
+ }
+ else
+ {
+ read_channel=READCHAN_GET_CHAN(Si4709_dev.registers[READCHAN]);
+ debug("curr_channel before tuning = %x",read_channel);
+ }
+#endif
+
+ wait();
+
+ Si4709_dev_wait_flag = NO_WAIT;
+
+ /*VNVS:START 13-OCT'09---- Checking the status of Seek/Tune Bit*/
+#ifdef TEST_FM
+ if( (ret = i2c_read(STATUSRSSI)) < 0 )
+ {
+ debug("tune_freq i2c_read 2 failed");
+
+ }
+ else if(STATUSRSSI_SEEK_TUNE_STATUS(Si4709_dev.registers[STATUSRSSI]) == COMPLETE)
+ debug("Seek/Tune Status is set to 1 by device ---Tuning Operation Completed");
+ else
+ debug("Seek/Tune Status is set to 0 by device ---Tuning Operation Not Completed");
+#endif
+ /*VNVS:END*/
+
+ channel = Si4709_dev.registers[CHANNEL];
+
+ CHANNEL_BITSET_TUNE_LOW(&Si4709_dev.registers[CHANNEL]);
+ CHANNEL_BITSET_RESERVED(&Si4709_dev.registers[CHANNEL]);
+
+ if( (ret = i2c_write(CHANNEL)) < 0 )
+ {
+ debug("tune_freq i2c_write 2 failed");
+ Si4709_dev.registers[CHANNEL] = channel;
+ }
+ else
+ {
+ do
+ {
+ if( (ret = i2c_read(STATUSRSSI)) < 0 )
+ {
+ debug("tune_freq i2c_read 3 failed");
+ break;
+ }
+ }while( STATUSRSSI_SEEK_TUNE_STATUS(Si4709_dev.registers[STATUSRSSI]) != CLEAR );
+
+ }
+
+ /*VNVS:START 13-OCT'09---- Reading the READCHAN register after tuning operation*/
+#ifdef TEST_FM
+ if( (ret = i2c_read(READCHAN)) < 0 )
+ {
+ debug("tune_freq i2c_read 2 failed");
+ }
+ else
+ {
+ read_channel=READCHAN_GET_CHAN(Si4709_dev.registers[READCHAN]);
+ debug("curr_channel after tuning= %x",read_channel);
+ }
+#endif
+ /*VNVS:END*/
+ }
+
+ return ret;
+}
+
+static void get_cur_chan_freq(u32 *frequency, u16 readchan)
+{
+
+ u16 channel = 0;
+ debug("get_cur_chan_freq called");
+
+ channel = READCHAN_GET_CHAN(readchan);
+ debug("read_channel=%x",channel);
+
+ *frequency = channel_to_freq(channel);
+
+ debug("frequency-> %u",*frequency);
+}
+
+static u16 freq_to_channel(u32 frequency)
+{
+ u16 channel;
+
+ if( frequency < Si4709_dev.settings.bottom_of_band )
+ {
+ frequency = Si4709_dev.settings.bottom_of_band;
+ }
+
+ channel = (frequency - Si4709_dev.settings.bottom_of_band)
+ / Si4709_dev.settings.channel_spacing;
+
+ return channel;
+}
+
+static u32 channel_to_freq(u16 channel)
+{
+ u32 frequency;
+
+ frequency = Si4709_dev.settings.bottom_of_band +
+ Si4709_dev.settings.channel_spacing * channel;
+
+ return frequency;
+}
+
+/*Only one thread will be able to call this, since this function call is
+ protected by a mutex, so no race conditions can arise*/
+static void wait(void)
+{
+ wait_event_interruptible(Si4709_waitq,
+ (Si4709_dev_wait_flag == WAIT_OVER) || (Si4709_dev_wait_flag == SEEK_CANCEL));
+}
+
+static void wait_RDS(void)
+{
+ wait_event_interruptible_timeout(Si4709_waitq,
+ (Si4709_dev_wait_flag == WAIT_OVER),Si4709_dev.settings.timeout_RDS);
+}
+
+/*i2c read function*/
+/*Si4709_dev.client should be set before calling this function.
+ If Si4709_dev.valid = eTRUE then Si4709_dev.client will b valid
+ This function should be called from the functions in this file. The
+ callers should check if Si4709_dev.valid = eTRUE before
+ calling this function. If it is eFALSE then this function should not
+ be called*/
+static int i2c_read( u8 reg )
+{
+ u8 idx, reading_reg = STATUSRSSI;
+ u8 data[NUM_OF_REGISTERS * 2], data_high, data_low;
+ int msglen = 0, ret = 0;
+
+ for(idx = 0; idx < NUM_OF_REGISTERS * 2; idx++)
+ {
+ data[idx] = 0x00;
+ }
+
+ msglen = reg - reading_reg + 1;
+
+ if(msglen > 0)
+ {
+ msglen = msglen * 2;
+ }
+ else
+ {
+ msglen = (msglen + NUM_OF_REGISTERS) * 2;
+ }
+
+ ret = i2c_master_recv((struct i2c_client*)(Si4709_dev.client), data, msglen);
+
+ if(ret == msglen)
+ {
+ idx = 0;
+ do
+ {
+ data_high = data[idx];
+ data_low = data[idx+1];
+
+ Si4709_dev.registers[reading_reg] = 0x0000;
+ Si4709_dev.registers[reading_reg] = (data_high << 8) + data_low;
+ reading_reg = (reading_reg + 1) & RDSD;
+ idx = idx + 2;
+ } while(reading_reg != ((reg +1) & RDSD));
+
+ ret = 0;
+ }
+ else
+ {
+ ret = -1;
+ }
+
+ return ret;
+}
+
+/*i2c write function*/
+/*Si4709_dev.client should be set before calling this function.
+ If Si4709_dev.valid = eTRUE then Si4709_dev.client will b valid
+ This function should be called from the functions in this file. The
+ callers should check if Si4709_dev.valid = eTRUE before
+ calling this function. If it is eFALSE then this function should not
+ be called*/
+static int i2c_write( u8 reg )
+{
+ u8 writing_reg = POWERCFG;
+ u8 data[NUM_OF_REGISTERS * 2];
+ int i, msglen = 0, ret = 0;
+
+ for(i = 0; i < NUM_OF_REGISTERS * 2; i++)
+ {
+ data[i] = 0x00;
+ }
+
+ do
+ {
+ data[msglen++] = (u8)(Si4709_dev.registers[writing_reg] >> 8);
+ data[msglen++] = (u8)(Si4709_dev.registers[writing_reg] & 0xFF);
+
+ writing_reg = (writing_reg +1) & RDSD;
+ } while(writing_reg != ((reg + 1) & RDSD));
+
+ ret = i2c_master_send((struct i2c_client*)(Si4709_dev.client), ( const char *)data, msglen);
+
+ if(ret == msglen)
+ {
+ ret = 0;
+ }
+ else
+ {
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static int insert_preset(u32 frequency,u8 rssi,u8 *seek_preset_rssi)
+{
+ u8 i;
+ u8 min_rssi = 0xff;
+ u8 min_rssi_preset=0;
+ int ret = 0;
+
+ /* first find the minimum rssi and its location
+ this will always stop at the first location with a zero rssi */
+
+ debug("si4709 autoseek : insert preset\n");
+
+ for (i=0; i<NUM_SEEK_PRESETS; i++)
+ {
+ if (seek_preset_rssi[i] < min_rssi)
+ {
+ min_rssi = seek_preset_rssi[i];
+ min_rssi_preset = i;
+ }
+ }
+
+ if (rssi < min_rssi)
+ ret = -1;
+
+ /***Delete the preset with the minimum rssi, and clear the last preset
+ since it would only be a copy of the second to last preset after
+ the deletion ***/
+ for (i=min_rssi_preset; i<NUM_SEEK_PRESETS-1; i++)
+ {
+ Si4709_dev.settings.seek_preset[i]= Si4709_dev.settings.seek_preset[i+1];
+ seek_preset_rssi[i] = seek_preset_rssi[i+1];
+ }
+
+ Si4709_dev.settings.seek_preset[i] = 0;
+ seek_preset_rssi[i] = 0;
+
+ /*** Fill the first preset with a zero for the frequency. This will
+ always overwrite the last preset once all presets have been filled. ***/
+ for (i=min_rssi_preset; i<NUM_SEEK_PRESETS; i++)
+ {
+ if(Si4709_dev.settings.seek_preset[i] == 0)
+ {
+ Si4709_dev.settings.seek_preset[i]= frequency;
+ seek_preset_rssi[i] = rssi;
+ break;
+ }
+ }
+ return ret;
+}
+
+
diff --git a/drivers/media/radio/si4709/radio-si4709_dev.h b/drivers/media/radio/si4709/radio-si4709_dev.h
new file mode 100644
index 0000000..bdcde4f
--- /dev/null
+++ b/drivers/media/radio/si4709/radio-si4709_dev.h
@@ -0,0 +1,181 @@
+#ifndef _Si4709_DEV_H
+#define _Si4709_DEV_H
+
+#include <linux/i2c.h>
+#include "radio-si4709_common.h"
+
+typedef struct
+{
+ int power_state;
+ int seek_state;
+}dev_state_t;
+
+typedef struct
+{
+ u8 curr_rssi;
+ u8 curr_rssi_th;
+ u8 curr_snr;
+}rssi_snr_t;
+
+typedef struct
+{
+ u8 part_number;
+ u16 manufact_number;
+} device_id;
+
+typedef struct
+{
+ u8 chip_version;
+ u8 device;
+ u8 firmware_version;
+}chip_id;
+
+typedef struct
+{
+ u16 rssi_th;
+ u8 fm_band;
+ u8 fm_chan_spac;
+ u8 fm_vol;
+} sys_config2;
+
+typedef struct
+{
+ u8 smmute;
+ u8 smutea;
+ u8 volext;
+ u8 sksnr;
+ u8 skcnt;
+} sys_config3;
+
+typedef struct
+{
+ u8 rdsr;
+ u8 stc;
+ u8 sfbl;
+ u8 afcrl;
+ u8 rdss;
+ u8 blera;
+ u8 st;
+ u16 rssi;
+} status_rssi;
+
+typedef struct
+{
+ u16 dsmute :1;
+ u16 dmute:1;
+ u16 mono:1;
+ u16 rds_mode:1;
+ u16 sk_mode:1;
+ u16 seek_up:1;
+ u16 seek:1;
+ u16 power_disable:1;
+ u16 power_enable:1;
+} power_config;
+
+typedef struct
+{
+ u16 rdsa;
+ u16 rdsb;
+ u16 rdsc;
+ u16 rdsd;
+ u8 curr_rssi;
+ u32 curr_channel;
+ u8 blera;
+ u8 blerb;
+ u8 blerc;
+ u8 blerd;
+}radio_data_t;
+
+#define NUM_SEEK_PRESETS 20
+
+#define WAIT_OVER 0
+#define SEEK_WAITING 1
+#define NO_WAIT 2
+#define TUNE_WAITING 4
+#define RDS_WAITING 5
+#define SEEK_CANCEL 6
+
+/*dev settings*/
+/*band*/
+#define BAND_87500_108000_kHz 1
+#define BAND_76000_108000_kHz 2
+#define BAND_76000_90000_kHz 3
+
+/*channel spacing*/
+#define CHAN_SPACING_200_kHz 20 /*US*/
+#define CHAN_SPACING_100_kHz 10 /*Europe,Japan*/
+#define CHAN_SPACING_50_kHz 5
+
+/*DE-emphasis Time Constant*/
+#define DE_TIME_CONSTANT_50 1 /*Europe,Japan,Australia*/
+#define DE_TIME_CONSTANT_75 0 /*US*/
+
+extern int Si4709_dev_wait_flag;
+
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+extern int Si4709_RDS_flag;
+extern int RDS_Data_Available;
+extern int RDS_Data_Lost;
+extern int RDS_Groups_Available_till_now;
+extern struct workqueue_struct *Si4709_wq;
+extern struct work_struct Si4709_work;
+#endif
+
+/*Function prototypes*/
+extern int Si4709_dev_init(struct i2c_client *);
+extern int Si4709_dev_exit(void);
+
+extern void Si4709_dev_mutex_init(void);
+
+extern int Si4709_dev_suspend(void);
+extern int Si4709_dev_resume(void);
+
+extern int Si4709_dev_powerup(void);
+extern int Si4709_dev_powerdown(void);
+
+extern int Si4709_dev_band_set(int);
+extern int Si4709_dev_ch_spacing_set(int);
+
+extern int Si4709_dev_chan_select(u32);
+extern int Si4709_dev_chan_get(u32*);
+
+extern int Si4709_dev_seek_up(u32*);
+extern int Si4709_dev_seek_down(u32*);
+extern int Si4709_dev_seek_auto(u32*);
+
+extern int Si4709_dev_RSSI_seek_th_set(u8);
+extern int Si4709_dev_seek_SNR_th_set(u8);
+extern int Si4709_dev_seek_FM_ID_th_set(u8);
+extern int Si4709_dev_cur_RSSI_get(rssi_snr_t*);
+extern int Si4709_dev_VOLEXT_ENB(void);
+extern int Si4709_dev_VOLEXT_DISB(void);
+extern int Si4709_dev_volume_set(u8);
+extern int Si4709_dev_volume_get(u8*);
+extern int Si4709_dev_DSMUTE_ON(void);
+extern int Si4709_dev_DSMUTE_OFF(void);
+extern int Si4709_dev_MUTE_ON(void);
+extern int Si4709_dev_MUTE_OFF(void);
+extern int Si4709_dev_MONO_SET(void);
+extern int Si4709_dev_STEREO_SET(void);
+extern int Si4709_dev_rstate_get(dev_state_t*);
+extern int Si4709_dev_RDS_data_get(radio_data_t*);
+extern int Si4709_dev_RDS_ENABLE(void);
+extern int Si4709_dev_RDS_DISABLE(void);
+extern int Si4709_dev_RDS_timeout_set(u32);
+extern int Si4709_dev_device_id(device_id *);
+extern int Si4709_dev_chip_id(chip_id *);
+extern int Si4709_dev_sys_config2(sys_config2 *);
+extern int Si4709_dev_sys_config3(sys_config3 *);
+extern int Si4709_dev_power_config(power_config *);
+extern int Si4709_dev_AFCRL_get(u8*);
+extern int Si4709_dev_DE_set(u8);
+extern int Si4709_dev_status_rssi(status_rssi *status);
+extern int Si4709_dev_sys_config2_set(sys_config2 *sys_conf2);
+extern int Si4709_dev_sys_config3_set(sys_config3 *sys_conf3);
+extern int Si4709_dev_reset_rds_data(void);
+
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+extern void Si4709_work_func(struct work_struct*);
+#endif
+#endif
+
diff --git a/drivers/media/radio/si4709/radio-si4709_i2c_drv.c b/drivers/media/radio/si4709/radio-si4709_i2c_drv.c
new file mode 100644
index 0000000..5885b04
--- /dev/null
+++ b/drivers/media/radio/si4709/radio-si4709_i2c_drv.c
@@ -0,0 +1,196 @@
+
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+
+#include "radio-si4709_dev.h"
+#include "radio-si4709_common.h"
+
+/*extern functions*/
+int Si4709_i2c_drv_init(void);
+void Si4709_i2c_drv_exit(void);
+
+/*static functions*/
+static int Si4709_probe (struct i2c_client *);
+static int Si4709_remove(struct i2c_client *);
+static int Si4709_suspend(struct i2c_client *, pm_message_t mesg);
+static int Si4709_resume(struct i2c_client *);
+
+static struct i2c_client *Si4709_i2c_client;
+
+
+struct si4709_data {
+ struct i2c_client *client;
+};
+
+/*I2C Setting*/
+#define SI4709_I2C_ADDRESS 0x20
+
+static unsigned short Si4709_normal_i2c[] = { I2C_CLIENT_END };
+
+static struct i2c_driver Si4709_i2c_driver;
+
+static const struct i2c_device_id si4709_id[] = {
+ {"Si4709", 0},
+ {}
+};
+
+static int Si4709_probe (struct i2c_client *client)
+{
+ int ret = 0;
+
+ debug("Si4709 i2c driver Si4709_probe called");
+
+ if( strcmp(client->name, "Si4709") != 0 )
+ {
+ ret = -1;
+ debug("Si4709_probe: device not supported");
+ }
+ else if( (ret = Si4709_dev_init(client)) < 0 )
+ {
+ debug("Si4709_dev_init failed");
+ }
+
+ return ret;
+}
+
+static int Si4709_remove(struct i2c_client *client)
+{
+ int ret = 0;
+
+ debug("Si4709 i2c driver Si4709_remove called");
+
+ if( strcmp(client->name, "Si4709") != 0 )
+ {
+ ret = -1;
+ debug("Si4709_remove: device not supported");
+ }
+ else if( (ret = Si4709_dev_exit()) < 0 )
+ {
+ debug("Si4709_dev_exit failed");
+ }
+
+ return ret;
+}
+
+static int __devinit si4709_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ int err = 0;
+ struct si4709_data *si4709_dev;
+
+ debug("----- %s %d\n", __func__, __LINE__);
+
+ si4709_dev = kzalloc(sizeof(struct si4709_data), GFP_KERNEL);
+
+ if(!si4709_dev)
+ {
+ err = -ENOMEM;
+ return err;
+ }
+
+ Si4709_i2c_client = client;
+ i2c_set_clientdata(client, si4709_dev);
+
+ if(Si4709_i2c_client == NULL)
+ {
+ error("Si4709 i2c_client is NULL");
+ return -ENODEV;
+ }
+
+ Si4709_probe(Si4709_i2c_client);
+
+ return 0;
+}
+
+static int __devexit si4709_i2c_remove(struct i2c_client *client)
+{
+ struct si4709_data *si4709_dev = i2c_get_clientdata(client);
+
+ printk("----- %s %d\n", __func__, __LINE__);
+
+ Si4709_remove(Si4709_i2c_client);
+ kfree(si4709_dev);
+ kfree(client);
+ si4709_dev = NULL;
+ Si4709_i2c_client = NULL;
+
+ return 0;
+}
+
+
+MODULE_DEVICE_TABLE(i2c, si4709_id);
+
+static struct i2c_driver Si4709_i2c_driver =
+{
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "Si4709",
+ },
+ .id_table = si4709_id,
+ .probe = si4709_i2c_probe,
+ .remove = __devexit_p(si4709_i2c_remove),
+ .suspend = Si4709_suspend,
+ .resume = Si4709_resume,
+ .address_list = Si4709_normal_i2c,
+};
+
+static int Si4709_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+ int ret = 0;
+
+ debug("Si4709 i2c driver Si4709_suspend called");
+
+ if( strcmp(client->name, "Si4709") != 0 )
+ {
+ ret = -1;
+ debug("Si4709_suspend: device not supported");
+ }
+ else if( (ret = Si4709_dev_suspend()) < 0 )
+ {
+ debug("Si4709_dev_disable failed");
+ }
+
+ return 0;
+}
+
+static int Si4709_resume(struct i2c_client *client)
+{
+ int ret = 0;
+
+// debug("Si4709 i2c driver Si4709_resume called");
+
+ if( strcmp(client->name, "Si4709") != 0 )
+ {
+ ret = -1;
+ debug("Si4709_resume: device not supported");
+ }
+ else if( (ret = Si4709_dev_resume()) < 0 )
+ {
+ debug("Si4709_dev_enable failed");
+ }
+
+ return 0;
+}
+
+int Si4709_i2c_drv_init(void)
+{
+ int ret = 0;
+
+ debug("Si4709 i2c driver Si4709_i2c_driver_init called");
+
+ if ( (ret = i2c_add_driver(&Si4709_i2c_driver) < 0) )
+ {
+ error("Si4709 i2c_add_driver failed");
+ }
+
+ return ret;
+}
+
+void Si4709_i2c_drv_exit(void)
+{
+ debug("Si4709 i2c driver Si4709_i2c_driver_exit called");
+
+ i2c_del_driver(&Si4709_i2c_driver);
+}
+
+
diff --git a/drivers/media/radio/si4709/radio-si4709_i2c_drv.h b/drivers/media/radio/si4709/radio-si4709_i2c_drv.h
new file mode 100644
index 0000000..fb705a3
--- /dev/null
+++ b/drivers/media/radio/si4709/radio-si4709_i2c_drv.h
@@ -0,0 +1,8 @@
+#ifndef _Si4709_I2C_DRV_H
+#define _Si4709_I2C_DRV_H
+
+extern int Si4709_i2c_drv_init(void);
+extern int Si4709_i2c_drv_exit(void);
+
+#endif
+
diff --git a/drivers/media/radio/si4709/radio-si4709_ioctl.h b/drivers/media/radio/si4709/radio-si4709_ioctl.h
new file mode 100644
index 0000000..5165a99
--- /dev/null
+++ b/drivers/media/radio/si4709/radio-si4709_ioctl.h
@@ -0,0 +1,104 @@
+#ifndef _Si4709_IOCTL_H
+#define _Si4709_IOCTL_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#include "radio-si4709_dev.h"
+
+/*****************IOCTLS******************/
+/*magic no*/
+#define Si4709_IOC_MAGIC 0xFA
+/*max seq no*/
+#define Si4709_IOC_NR_MAX 40
+
+/*commands*/
+
+#define Si4709_IOC_POWERUP _IO(Si4709_IOC_MAGIC, 0)
+
+#define Si4709_IOC_POWERDOWN _IO(Si4709_IOC_MAGIC, 1)
+
+#define Si4709_IOC_BAND_SET _IOW(Si4709_IOC_MAGIC, 2, int)
+
+#define Si4709_IOC_CHAN_SPACING_SET _IOW(Si4709_IOC_MAGIC, 3, int)
+
+#define Si4709_IOC_CHAN_SELECT _IOW(Si4709_IOC_MAGIC, 4, u32)
+
+#define Si4709_IOC_CHAN_GET _IOR(Si4709_IOC_MAGIC, 5, u32)
+
+#define Si4709_IOC_SEEK_UP _IOR(Si4709_IOC_MAGIC, 6, u32)
+
+#define Si4709_IOC_SEEK_DOWN _IOR(Si4709_IOC_MAGIC, 7, u32)
+
+/*VNVS:28OCT'09---- Si4709_IOC_SEEK_AUTO is disabled as of now*/
+//#define Si4709_IOC_SEEK_AUTO _IOR(Si4709_IOC_MAGIC, 8, u32)
+
+#define Si4709_IOC_RSSI_SEEK_TH_SET _IOW(Si4709_IOC_MAGIC, 9, u8)
+
+#define Si4709_IOC_SEEK_SNR_SET _IOW(Si4709_IOC_MAGIC, 10, u8)
+
+#define Si4709_IOC_SEEK_CNT_SET _IOW(Si4709_IOC_MAGIC, 11, u8)
+
+#define Si4709_IOC_CUR_RSSI_GET _IOR(Si4709_IOC_MAGIC, 12, rssi_snr_t)
+
+#define Si4709_IOC_VOLEXT_ENB _IO(Si4709_IOC_MAGIC, 13)
+
+#define Si4709_IOC_VOLEXT_DISB _IO(Si4709_IOC_MAGIC, 14)
+
+#define Si4709_IOC_VOLUME_SET _IOW(Si4709_IOC_MAGIC, 15, u8)
+
+#define Si4709_IOC_VOLUME_GET _IOR(Si4709_IOC_MAGIC, 16, u8)
+
+#define Si4709_IOC_MUTE_ON _IO(Si4709_IOC_MAGIC, 17)
+
+#define Si4709_IOC_MUTE_OFF _IO(Si4709_IOC_MAGIC, 18)
+
+#define Si4709_IOC_MONO_SET _IO(Si4709_IOC_MAGIC, 19)
+
+#define Si4709_IOC_STEREO_SET _IO(Si4709_IOC_MAGIC, 20)
+
+#define Si4709_IOC_RSTATE_GET _IOR(Si4709_IOC_MAGIC, 21, dev_state_t)
+
+#define Si4709_IOC_RDS_DATA_GET _IOR(Si4709_IOC_MAGIC, 22, radio_data_t)
+
+#define Si4709_IOC_RDS_ENABLE _IO(Si4709_IOC_MAGIC, 23)
+
+#define Si4709_IOC_RDS_DISABLE _IO(Si4709_IOC_MAGIC, 24)
+
+#define Si4709_IOC_RDS_TIMEOUT_SET _IOW(Si4709_IOC_MAGIC, 25, u32)
+
+#define Si4709_IOC_SEEK_CANCEL _IO(Si4709_IOC_MAGIC, 26)
+
+/*VNVS:START 13-OCT'09---- Added IOCTLs for reading the device-id,chip-id,power configuration, system configuration2 registers*/
+#define Si4709_IOC_DEVICE_ID_GET _IOR(Si4709_IOC_MAGIC, 27,device_id)
+
+#define Si4709_IOC_CHIP_ID_GET _IOR(Si4709_IOC_MAGIC, 28,chip_id)
+
+#define Si4709_IOC_SYS_CONFIG2_GET _IOR(Si4709_IOC_MAGIC,29,sys_config2)
+
+#define Si4709_IOC_POWER_CONFIG_GET _IOR(Si4709_IOC_MAGIC,30,power_config)
+
+#define Si4709_IOC_AFCRL_GET _IOR(Si4709_IOC_MAGIC,31,u8) /*For reading AFCRL bit, to check for a valid channel*/
+
+#define Si4709_IOC_DE_SET _IOW(Si4709_IOC_MAGIC,32,u8) /*Setting DE-emphasis Time Constant. For DE=0,TC=50us(Europe,Japan,Australia) and DE=1,TC=75us(USA)*/
+/*VNVS:END*/
+
+#define Si4709_IOC_SYS_CONFIG3_GET _IOR(Si4709_IOC_MAGIC, 33, sys_config3)
+
+#define Si4709_IOC_STATUS_RSSI_GET _IOR(Si4709_IOC_MAGIC, 34, status_rssi)
+
+#define Si4709_IOC_SYS_CONFIG2_SET _IOW(Si4709_IOC_MAGIC, 35, sys_config2)
+
+#define Si4709_IOC_SYS_CONFIG3_SET _IOW(Si4709_IOC_MAGIC, 36, sys_config3)
+
+#define Si4709_IOC_DSMUTE_ON _IO(Si4709_IOC_MAGIC, 37)
+
+#define Si4709_IOC_DSMUTE_OFF _IO(Si4709_IOC_MAGIC, 38)
+
+#define Si4709_IOC_RESET_RDS_DATA _IO(Si4709_IOC_MAGIC, 39)
+
+
+/*****************************************/
+
+#endif
+
diff --git a/drivers/media/radio/si4709/radio-si4709_main.c b/drivers/media/radio/si4709/radio-si4709_main.c
new file mode 100644
index 0000000..a202b50
--- /dev/null
+++ b/drivers/media/radio/si4709/radio-si4709_main.c
@@ -0,0 +1,799 @@
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/miscdevice.h>
+#include <linux/interrupt.h>
+#include <asm/uaccess.h>
+#include <linux/irq.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <linux/wait.h>
+#include <linux/stat.h>
+#include <linux/ioctl.h>
+
+#include <plat/gpio-cfg.h>
+#include <mach/gpio.h>
+#include <../../../arch/arm/mach-s5pv210/include/mach/gpio-aries.h>
+
+#include "radio-si4709_i2c_drv.h"
+#include "radio-si4709_dev.h"
+#include "radio-si4709_ioctl.h"
+#include "radio-si4709_common.h"
+
+/*******************************************************/
+
+/*Si4709 IRQ Number*/
+
+#define FM_IRQ_INT (IRQ_EINT_GROUP20_BASE+4) /* J2_4 */
+
+/*static functions*/
+
+/*file operatons*/
+static int Si4709_open (struct inode *, struct file *);
+static int Si4709_release (struct inode *, struct file *);
+static int Si4709_ioctl(struct file *, unsigned int, unsigned long);
+
+static DEFINE_MUTEX(Si4709_mutex);
+
+/*ISR*/
+static irqreturn_t Si4709_isr( int irq, void *unused );
+//static void __iomem *gpio_mask_mem;
+/**********************************************************/
+
+static struct file_operations Si4709_fops =
+{
+ .owner = THIS_MODULE,
+ .open = Si4709_open,
+ .unlocked_ioctl = Si4709_ioctl,
+ .release = Si4709_release,
+};
+
+static struct miscdevice Si4709_misc_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "radio0",
+ .fops = &Si4709_fops,
+};
+/*VNVS:START 13-OCT'09----dummy struct which is used as a cookie for FM Radio interrupt */
+typedef struct
+{
+ int i;
+ int j;
+} radio0;
+radio0 radio0_1;
+/*VNVS:END*/
+
+wait_queue_head_t Si4709_waitq;
+
+/***************************************************************/
+
+static int Si4709_open (struct inode *inode, struct file *filp)
+{
+ debug("Si4709_open called");
+
+ return nonseekable_open(inode, filp);
+}
+
+static int Si4709_release (struct inode *inode, struct file *filp)
+{
+ debug("Si4709_release called");
+
+ return 0;
+}
+
+static int Si4709_ioctl(struct file *filp, unsigned int ioctl_cmd, unsigned long arg)
+{
+ int ret = 0;
+ void __user *argp = (void __user *)arg;
+
+ mutex_lock(&Si4709_mutex);
+
+ if( _IOC_TYPE(ioctl_cmd) != Si4709_IOC_MAGIC )
+ {
+ debug("Inappropriate ioctl 1 0x%x",ioctl_cmd);
+ ret = -ENOTTY;
+ goto exit;
+ }
+
+ if( _IOC_NR(ioctl_cmd) > Si4709_IOC_NR_MAX )
+ {
+ debug("Inappropriate ioctl 2 0x%x",ioctl_cmd);
+ ret = -ENOTTY;
+ goto exit;
+ }
+
+ switch (ioctl_cmd)
+ {
+ case Si4709_IOC_POWERUP:
+ debug("Si4709_IOC_POWERUP called");
+
+ if( (ret = Si4709_dev_powerup()) < 0 )
+ debug("Si4709_IOC_POWERUP failed");
+ break;
+
+ case Si4709_IOC_POWERDOWN:
+ debug("Si4709_IOC_POWERDOWN called");
+
+ if( (ret = Si4709_dev_powerdown()) < 0 )
+ debug("Si4709_IOC_POWERDOWN failed");
+ break;
+
+ case Si4709_IOC_BAND_SET:
+ {
+ int band;
+ debug("Si4709_IOC_BAND_SET called");
+
+ if(copy_from_user((void*) &band, argp, sizeof(int)))
+ ret = -EFAULT;
+ else if( (ret = Si4709_dev_band_set(band)) < 0)
+ debug("Si4709_IOC_BAND_SET failed");
+
+ }
+ break;
+
+ case Si4709_IOC_CHAN_SPACING_SET:
+ {
+ int ch_spacing;
+ debug("Si4709_IOC_CHAN_SPACING_SET called");
+
+ if( copy_from_user((void*) &ch_spacing, argp, sizeof(int)) )
+ ret = -EFAULT;
+ else if ((ret = Si4709_dev_ch_spacing_set(ch_spacing)) < 0)
+ debug("Si4709_IOC_CHAN_SPACING_SET failed");
+
+ }
+ break;
+
+ case Si4709_IOC_CHAN_SELECT:
+ {
+ u32 frequency;
+ debug("Si4709_IOC_CHAN_SELECT called");
+
+ if( copy_from_user((void*) &frequency, argp, sizeof(u32)) )
+ ret = -EFAULT;
+ else if ( (ret = Si4709_dev_chan_select(frequency)) < 0 )
+ debug("Si4709_IOC_CHAN_SELECT failed");
+ }
+ break;
+
+ case Si4709_IOC_CHAN_GET:
+ {
+ u32 frequency;
+ debug("Si4709_IOC_CHAN_GET called");
+
+ if( (ret = Si4709_dev_chan_get(&frequency)) < 0)
+ debug("Si4709_IOC_CHAN_GET failed");
+ else if( copy_to_user(argp, (void*) &frequency, sizeof(u32)))
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si4709_IOC_SEEK_UP:
+ {
+ u32 frequency;
+ debug("Si4709_IOC_SEEK_UP called");
+
+ if( (ret = Si4709_dev_seek_up(&frequency)) < 0)
+ debug("Si4709_IOC_SEEK_UP failed");
+ else if( copy_to_user(argp, (void*) &frequency, sizeof(u32)) )
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si4709_IOC_SEEK_DOWN:
+ {
+ u32 frequency;
+ debug("Si4709_IOC_SEEK_DOWN called");
+
+ if( (ret = Si4709_dev_seek_down(&frequency)) < 0)
+ debug("Si4709_IOC_SEEK_DOWN failed");
+ else if( copy_to_user(argp, (void*) &frequency, sizeof(u32)) )
+ ret = -EFAULT;
+ }
+ break;
+
+#if 0
+ case Si4709_IOC_SEEK_AUTO:
+ {
+ u32 *seek_preset_user;
+ int i = 0;
+
+ debug("Si4709_IOC_SEEK_AUTO called");
+
+ if( (seek_preset_user = (u32 *)kzalloc(sizeof(u32) * NUM_SEEK_PRESETS,
+ GFP_KERNEL)) == NULL )
+ {
+ debug("Si4709_ioctl: no memory");
+ ret = -ENOMEM;
+ }
+ else
+ {
+ if((ret = Si4709_dev_seek_auto(seek_preset_user)) < 0)
+ {
+ debug("Si4709_IOC_SEEK_AUTO failed");
+ }
+
+ else if ( copy_to_user(argp, (u32*) seek_preset_user, sizeof(int) * NUM_SEEK_PRESETS) )
+ {
+ ret = -EFAULT;
+ }
+
+ kfree(seek_preset_user);
+ }
+ }
+ break;
+#endif
+
+ case Si4709_IOC_RSSI_SEEK_TH_SET:
+ {
+ u8 RSSI_seek_th;
+ debug("Si4709_IOC_RSSI_SEEK_TH_SET called");
+
+ if( copy_from_user((void*) &RSSI_seek_th, argp, sizeof(u8)) )
+ ret = -EFAULT;
+ else if ( (ret = Si4709_dev_RSSI_seek_th_set(RSSI_seek_th)) < 0 )
+ debug("Si4709_IOC_RSSI_SEEK_TH_SET failed");
+ }
+ break;
+
+ case Si4709_IOC_SEEK_SNR_SET:
+ {
+ u8 seek_SNR_th;
+ debug("Si4709_IOC_SEEK_SNR_SET called");
+
+ if( copy_from_user((void*) &seek_SNR_th, argp, sizeof(u8)) )
+ ret = -EFAULT;
+ else if( (ret = Si4709_dev_seek_SNR_th_set(seek_SNR_th)) < 0 )
+ debug("Si4709_IOC_SEEK_SNR_SET failed");
+ }
+ break;
+
+ case Si4709_IOC_SEEK_CNT_SET:
+ {
+ u8 seek_FM_ID_th;
+ debug("Si4709_IOC_SEEK_CNT_SET called");
+
+ if( copy_from_user((void*) &seek_FM_ID_th, argp, sizeof(u8)) )
+ ret = -EFAULT;
+ else if ( (ret = Si4709_dev_seek_FM_ID_th_set(seek_FM_ID_th)) < 0 )
+ debug("Si4709_IOC_SEEK_CNT_SET failed");
+ }
+ break;
+
+ case Si4709_IOC_CUR_RSSI_GET:
+ {
+ rssi_snr_t data;
+ debug("Si4709_IOC_CUR_RSSI_GET called");
+
+ if( (ret = Si4709_dev_cur_RSSI_get(&data)) < 0)
+ debug("Si4709_IOC_CUR_RSSI_GET failed");
+ else if( copy_to_user(argp, (void*) &data, sizeof(rssi_snr_t )) )
+ ret = -EFAULT;
+
+ debug("curr_rssi:%d\ncurr_rssi_th:%d\ncurr_snr:%d\n",data.curr_rssi,data.curr_rssi_th,data.curr_snr);
+ }
+ break;
+
+ case Si4709_IOC_VOLEXT_ENB:
+ debug("Si4709_IOC_VOLEXT_ENB called");
+
+ if( (ret = Si4709_dev_VOLEXT_ENB()) < 0 )
+ debug("Si4709_IOC_VOLEXT_ENB failed");
+ break;
+
+ case Si4709_IOC_VOLEXT_DISB:
+ debug("Si4709_IOC_VOLEXT_DISB called");
+
+ if( (ret = Si4709_dev_VOLEXT_DISB()) < 0 )
+ debug("Si4709_IOC_VOLEXT_DISB failed");
+ break;
+
+ case Si4709_IOC_VOLUME_SET:
+ {
+ u8 volume;
+ debug("Si4709_IOC_VOLUME_SET called");
+
+ if( copy_from_user((void*) &volume, argp, sizeof(u8)) )
+ ret = -EFAULT;
+ else if ( (ret = Si4709_dev_volume_set(volume)) < 0 )
+ debug("Si4709_IOC_VOLUME_SET failed");
+ }
+ break;
+
+ case Si4709_IOC_VOLUME_GET:
+ {
+ u8 volume;
+ debug("Si4709_IOC_VOLUME_GET called");
+
+ if( (ret = Si4709_dev_volume_get(&volume)) < 0)
+ debug("Si4709_IOC_VOLUME_GET failed");
+ else if( copy_to_user(argp, (void*) &volume, sizeof(u8)) )
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si4709_IOC_DSMUTE_ON:
+ debug("Si4709_IOC_DSMUTE_ON called");
+
+ if( (ret = Si4709_dev_DSMUTE_ON()) < 0 )
+ error("Si4709_IOC_DSMUTE_ON failed");
+ break;
+
+ case Si4709_IOC_DSMUTE_OFF:
+ debug("Si4709_IOC_DSMUTE_OFF called");
+
+ if( (ret = Si4709_dev_DSMUTE_OFF()) < 0 )
+ error("Si4709_IOC_DSMUTE_OFF failed");
+ break;
+
+ case Si4709_IOC_MUTE_ON:
+ debug("Si4709_IOC_MUTE_ON called");
+
+ if( (ret = Si4709_dev_MUTE_ON()) < 0 )
+ debug("Si4709_IOC_MUTE_ON failed");
+ break;
+
+ case Si4709_IOC_MUTE_OFF:
+ debug("Si4709_IOC_MUTE_OFF called");
+
+ if( (ret = Si4709_dev_MUTE_OFF()) < 0 )
+ debug("Si4709_IOC_MUTE_OFF failed");
+ break;
+
+ case Si4709_IOC_MONO_SET:
+ debug("Si4709_IOC_MONO_SET called");
+
+ if( (ret = Si4709_dev_MONO_SET()) < 0 )
+ debug("Si4709_IOC_MONO_SET failed");
+ break;
+
+ case Si4709_IOC_STEREO_SET:
+ debug("Si4709_IOC_STEREO_SET called");
+
+ if( (ret = Si4709_dev_STEREO_SET()) < 0 )
+ debug("Si4709_IOC_STEREO_SET failed");
+ break;
+
+ case Si4709_IOC_RSTATE_GET:
+ {
+ dev_state_t dev_state;
+
+ debug("Si4709_IOC_RSTATE_GET called");
+
+ if( (ret = Si4709_dev_rstate_get(&dev_state)) < 0)
+ debug("Si4709_IOC_RSTATE_GET failed");
+ else if( copy_to_user(argp, (void*) &dev_state, sizeof(dev_state_t)) )
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si4709_IOC_RDS_DATA_GET:
+ {
+ radio_data_t data;
+ debug("Si4709_IOC_RDS_DATA_GET called");
+
+ if( (ret = Si4709_dev_RDS_data_get(&data)) < 0)
+ debug("Si4709_IOC_RDS_DATA_GET failed");
+ else if( copy_to_user(argp, (void*) &data, sizeof(radio_data_t)) )
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si4709_IOC_RDS_ENABLE:
+ debug("Si4709_IOC_RDS_ENABLE called");
+
+ if( (ret = Si4709_dev_RDS_ENABLE()) < 0 )
+ debug("Si4709_IOC_RDS_ENABLE failed");
+ break;
+
+ case Si4709_IOC_RDS_DISABLE:
+ debug("Si4709_IOC_RDS_DISABLE called");
+
+ if( (ret = Si4709_dev_RDS_DISABLE()) < 0 )
+ debug("Si4709_IOC_RDS_DISABLE failed");
+ break;
+
+ case Si4709_IOC_RDS_TIMEOUT_SET:
+ {
+ u32 time_out;
+ debug("Si4709_IOC_RDS_TIMEOUT_SET called");
+
+ if( copy_from_user((void*) &time_out, argp, sizeof(u32)) )
+ ret = -EFAULT;
+ else if ( (ret = Si4709_dev_RDS_timeout_set(time_out)) < 0 )
+ debug("Si4709_IOC_RDS_TIMEOUT_SET failed");
+ }
+ break;
+
+ case Si4709_IOC_SEEK_CANCEL:
+ debug("Si4709_IOC_SEEK_CANCEL called");
+
+ if( Si4709_dev_wait_flag == SEEK_WAITING )
+ {
+ Si4709_dev_wait_flag = SEEK_CANCEL;
+ wake_up_interruptible(&Si4709_waitq);
+ }
+ break;
+
+ /*VNVS:START 13-OCT'09---- Switch Case statements for calling functions which reads device-id,
+ chip-id,power configuration, system configuration2 registers */
+ case Si4709_IOC_CHIP_ID_GET:
+ {
+ chip_id chp_id;
+ debug("Si4709_IOC_CHIP_ID called");
+
+ if( (ret = Si4709_dev_chip_id(&chp_id)) < 0)
+ debug("Si4709_IOC_CHIP_ID failed");
+ else if( copy_to_user(argp, (void*) &chp_id, sizeof(chip_id)) )
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si4709_IOC_DEVICE_ID_GET:
+ {
+ device_id dev_id;
+ debug("Si4709_IOC_DEVICE_ID called");
+
+ if( (ret = Si4709_dev_device_id(&dev_id)) < 0)
+ debug("Si4709_IOC_DEVICE_ID failed");
+ else if( copy_to_user(argp, (void*) &dev_id, sizeof(device_id)) )
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si4709_IOC_SYS_CONFIG2_GET:
+ {
+ sys_config2 sys_conf2;
+ debug("Si4709_IOC_SYS_CONFIG2 called");
+
+ if( (ret = Si4709_dev_sys_config2(&sys_conf2)) < 0)
+ debug("Si4709_IOC_SYS_CONFIG2 failed");
+ else if( copy_to_user(argp, (void*) &sys_conf2, sizeof(sys_config2)) )
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si4709_IOC_SYS_CONFIG3_GET:
+ {
+ sys_config3 sys_conf3;
+ debug("Si4709_IOC_SYS_CONFIG3 called");
+
+ if( (ret = Si4709_dev_sys_config3(&sys_conf3)) < 0)
+ debug("Si4709_IOC_SYS_CONFIG3 failed");
+ else if(copy_to_user(argp, (void*) &sys_conf3, sizeof(sys_config3)))
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si4709_IOC_POWER_CONFIG_GET:
+ {
+ power_config pow_conf;
+ debug("Si4709_IOC_POWER_CONFIG called");
+
+ if( (ret = Si4709_dev_power_config(&pow_conf)) < 0)
+ debug("Si4709_IOC_POWER_CONFIG failed");
+ else if( copy_to_user(argp, (void*) &pow_conf, sizeof(power_config)) )
+ ret = -EFAULT;
+ }
+ break;
+ /*VNVS:END*/
+ /*VNVS:START 18-NOV'09*/
+ /*Reading AFCRL Bit*/
+ case Si4709_IOC_AFCRL_GET:
+ {
+ u8 afc;
+ debug("Si4709_IOC_AFCRL_GET called");
+
+ if( (ret = Si4709_dev_AFCRL_get(&afc)) < 0)
+ debug("Si4709_IOC_AFCRL_GET failed");
+ else if( copy_to_user(argp, (void*) &afc, sizeof(u8)) )
+ ret = -EFAULT;
+ }
+ break;
+ /*Setting DE-emphasis Time Constant. For DE=0,TC=50us(Europe,Japan,Australia) and DE=1,TC=75us(USA)*/
+ case Si4709_IOC_DE_SET:
+ {
+ u8 de_tc;
+ debug("Si4709_IOC_DE_SET called");
+
+ if( copy_from_user((void*) &de_tc, argp, sizeof(u8)) )
+ ret = -EFAULT;
+ else if ( (ret = Si4709_dev_DE_set(de_tc)) < 0 )
+ debug("Si4709_IOC_DE_SET failed");
+ }
+ break;
+
+ case Si4709_IOC_STATUS_RSSI_GET:
+ {
+ status_rssi status;
+ debug("Si4709_IOC_STATUS_RSSI_GET called");
+
+ if( (ret = Si4709_dev_status_rssi(&status)) < 0)
+ debug("Si4709_IOC_STATUS_RSSI_GET failed");
+ else if(copy_to_user(argp, (void*) &status, sizeof(status_rssi)))
+ ret = -EFAULT;
+ }
+ break;
+
+
+ case Si4709_IOC_SYS_CONFIG2_SET:
+ {
+ sys_config2 sys_conf2;
+ unsigned long n;
+ debug("Si4709_IOC_SYS_CONFIG2_SET called");
+
+ n = copy_from_user((void*) &sys_conf2, argp, sizeof(sys_config2));
+
+ if(n)
+ {
+ debug("Si4709_IOC_SYS_CONFIG2_SET() : copy_from_user() has error!!Failed to read [%d] byes!", n);
+ ret = -EFAULT;
+ }
+ else if ( (ret = Si4709_dev_sys_config2_set(&sys_conf2)) < 0 )
+ debug("Si4709_IOC_SYS_CONFIG2_SET failed");
+ }
+ break;
+
+ case Si4709_IOC_SYS_CONFIG3_SET:
+ {
+ sys_config3 sys_conf3;
+ unsigned long n;
+
+ debug("Si4709_IOC_SYS_CONFIG3_SET called");
+
+ n = copy_from_user((void*) &sys_conf3, argp, sizeof(sys_config3));
+
+ if(n < 0)
+ {
+ debug("Si4709_IOC_SYS_CONFIG3_SET() : copy_from_user() has error!!Failed to read [%d] byes!", n);
+ ret = -EFAULT;
+ }else if ( (ret = Si4709_dev_sys_config3_set(&sys_conf3)) < 0 )
+ debug("Si4709_IOC_SYS_CONFIG3_SET failed");
+ }
+ break;
+ /*Resetting the RDS Data Buffer*/
+ case Si4709_IOC_RESET_RDS_DATA:
+ {
+ debug("Si4709_IOC_RESET_RDS_DATA called");
+
+ if( (ret = Si4709_dev_reset_rds_data()) < 0)
+ error("Si4709_IOC_RESET_RDS_DATA failed");
+ }
+ break;
+
+ /*VNVS:END*/
+ default:
+ debug(" ioctl default");
+ ret = -ENOTTY;
+ break;
+ }
+
+exit:
+ mutex_unlock(&Si4709_mutex);
+ return ret;
+}
+
+static irqreturn_t Si4709_isr( int irq, void *unused )
+{
+ debug("Si4709_isr: FM device called IRQ: %d",irq);
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+ if( (Si4709_dev_wait_flag == SEEK_WAITING) || (Si4709_dev_wait_flag == TUNE_WAITING))
+ {
+ debug("Si4709_isr: FM Seek/Tune Interrupt called IRQ %d",irq);
+ Si4709_dev_wait_flag = WAIT_OVER;
+ wake_up_interruptible(&Si4709_waitq);
+ }
+ else if(Si4709_RDS_flag == RDS_WAITING) //RDS Interrupt
+ {
+ debug_rds("Si4709_isr: FM RDS Interrupt called IRQ %d",irq);
+ RDS_Data_Available++;
+ RDS_Groups_Available_till_now++;
+
+ debug_rds("RDS_Groups_Available_till_now b/w Power ON/OFF : %d",RDS_Groups_Available_till_now);
+
+ if (RDS_Data_Available > 1)
+ RDS_Data_Lost++;
+
+ if(!work_pending(&Si4709_work))
+ queue_work(Si4709_wq,&Si4709_work);
+ }
+#else
+ if( (Si4709_dev_wait_flag == SEEK_WAITING) || (Si4709_dev_wait_flag == TUNE_WAITING) ||(Si4709_dev_wait_flag == RDS_WAITING))
+ {
+ Si4709_dev_wait_flag = WAIT_OVER;
+ wake_up_interruptible(&Si4709_waitq);
+ }
+#endif
+ return IRQ_HANDLED;
+}
+
+#if 0
+int Si4709_dev_abort_seek(void)
+{
+ int ret = 0;
+
+ if( Si4709_dev_wait_flag = SEEK_WAITING )
+ {
+ wake_up_interruptible(&Si4709_waitq);
+ }
+ return ret;
+}
+#endif
+
+
+/************************************************************/
+
+
+void debug_ioctls(void)
+{
+
+ debug("------------------------------------------------");
+
+ debug("Si4709_IOC_POWERUP 0x%x",Si4709_IOC_POWERUP );
+
+ debug("Si4709_IOC_POWERDOWN 0x%x",Si4709_IOC_POWERDOWN );
+
+ debug("Si4709_IOC_BAND_SET 0x%x",Si4709_IOC_BAND_SET );
+
+ debug("Si4709_IOC_CHAN_SPACING_SET 0x%x",Si4709_IOC_CHAN_SPACING_SET );
+
+ debug("Si4709_IOC_CHAN_SELECT 0x%x",Si4709_IOC_CHAN_SELECT );
+
+ debug("Si4709_IOC_CHAN_GET 0x%x",Si4709_IOC_CHAN_GET );
+
+ debug("Si4709_IOC_SEEK_UP 0x%x",Si4709_IOC_SEEK_UP );
+
+ debug("Si4709_IOC_SEEK_DOWN 0x%x",Si4709_IOC_SEEK_DOWN );
+
+ /*VNVS:28OCT'09---- Si4709_IOC_SEEK_AUTO is disabled as of now*/
+ // debug("Si4709_IOC_SEEK_AUTO 0x%x",Si4709_IOC_SEEK_AUTO );
+
+ debug("Si4709_IOC_RSSI_SEEK_TH_SET 0x%x",Si4709_IOC_RSSI_SEEK_TH_SET );
+
+ debug("Si4709_IOC_SEEK_SNR_SET 0x%x",Si4709_IOC_SEEK_SNR_SET );
+
+ debug("Si4709_IOC_SEEK_CNT_SET 0x%x",Si4709_IOC_SEEK_CNT_SET );
+
+ debug("Si4709_IOC_CUR_RSSI_GET 0x%x",Si4709_IOC_CUR_RSSI_GET );
+
+ debug("Si4709_IOC_VOLEXT_ENB 0x%x",Si4709_IOC_VOLEXT_ENB );
+
+ debug("Si4709_IOC_VOLEXT_DISB 0x%x",Si4709_IOC_VOLEXT_DISB );
+
+ debug("Si4709_IOC_VOLUME_SET 0x%x",Si4709_IOC_VOLUME_SET );
+
+ debug("Si4709_IOC_VOLUME_GET 0x%x",Si4709_IOC_VOLUME_GET );
+
+ debug("Si4709_IOC_MUTE_ON 0x%x",Si4709_IOC_MUTE_ON );
+
+ debug("Si4709_IOC_MUTE_OFF 0x%x",Si4709_IOC_MUTE_OFF );
+
+ debug("Si4709_IOC_MONO_SET 0x%x",Si4709_IOC_MONO_SET );
+
+ debug("Si4709_IOC_STEREO_SET 0x%x",Si4709_IOC_STEREO_SET );
+
+ debug("Si4709_IOC_RSTATE_GET 0x%x",Si4709_IOC_RSTATE_GET );
+
+ debug("Si4709_IOC_RDS_DATA_GET 0x%x",Si4709_IOC_RDS_DATA_GET );
+
+ debug("Si4709_IOC_RDS_ENABLE 0x%x",Si4709_IOC_RDS_ENABLE);
+
+ debug("Si4709_IOC_RDS_DISABLE 0x%x",Si4709_IOC_RDS_DISABLE);
+
+ debug("Si4709_IOC_RDS_TIMEOUT_SET 0x%x",Si4709_IOC_RDS_TIMEOUT_SET);
+
+ debug("Si4709_IOC_DEVICE_ID_GET 0x%x",Si4709_IOC_DEVICE_ID_GET);
+
+ debug("Si4709_IOC_CHIP_ID_GET 0x%x",Si4709_IOC_CHIP_ID_GET);
+
+ debug("Si4709_IOC_SYS_CONFIG2_GET 0x%x",Si4709_IOC_SYS_CONFIG2_GET);
+
+ debug("Si4709_IOC_POWER_CONFIG_GET 0x%x",Si4709_IOC_POWER_CONFIG_GET);
+
+ debug("Si4709_IOC_AFCRL_GET 0x%x",Si4709_IOC_AFCRL_GET);
+
+ debug("Si4709_IOC_DE_SET 0x%x",Si4709_IOC_DE_SET);
+
+ debug("Si4709_IOC_DSMUTE_ON 0x%x",Si4709_IOC_DSMUTE_ON);
+
+ debug("Si4709_IOC_DSMUTE_OFF 0x%x",Si4709_IOC_DSMUTE_OFF);
+
+ debug("Si4709_IOC_RESET_RDS_DATA 0x%x",Si4709_IOC_RESET_RDS_DATA);
+
+ debug("------------------------------------------------");
+
+}
+
+
+
+
+ int __init Si4709_driver_init(void)
+{
+ int ret = 0;
+
+
+ debug("Si4709_driver_init called");
+
+ /*Initialize the Si4709 dev mutex*/
+ Si4709_dev_mutex_init();
+
+
+ /*misc device registration*/
+ if( (ret = misc_register(&Si4709_misc_device)) < 0 )
+ {
+ error("Si4709_driver_init misc_register failed");
+ return ret;
+ }
+
+ s3c_gpio_cfgpin(GPIO_FM_INT, S3C_GPIO_SFN(0xF));
+ s3c_gpio_setpull(GPIO_FM_INT, S3C_GPIO_PULL_NONE);
+
+ irq_set_irq_type(FM_IRQ_INT, IRQ_TYPE_EDGE_FALLING);
+
+ /*KGVS: Configuring the GPIO_FM_INT in mach-jupiter.c*/
+ if( (ret = request_irq(FM_IRQ_INT, Si4709_isr, IRQF_DISABLED , "Si4709", NULL )) )
+ {
+ error("Si4709_driver_init request_irq failed %d", GPIO_FM_INT);
+ goto MISC_DREG;
+ }
+ else
+ debug("Si4709_driver_init request_irq success %d", GPIO_FM_INT);
+
+ if (gpio_is_valid(FM_RESET)) {
+ if (gpio_request(FM_RESET, "GPJ2"))
+ printk(KERN_ERR "Failed to request FM_RESET!\n");
+ gpio_direction_output(FM_RESET, GPIO_LEVEL_LOW);
+ }
+
+ /*VNVS: 13-OCT'09---- Initially Pulling the interrupt pin HIGH as the FM Radio device gives 5ms low pulse*/
+ s3c_gpio_setpull(GPIO_FM_INT, S3C_GPIO_PULL_UP);
+
+ /****Resetting the device****/
+ gpio_set_value(FM_RESET, GPIO_LEVEL_LOW);
+ gpio_set_value(FM_RESET, GPIO_LEVEL_HIGH);
+ /*VNVS: 13-OCT'09---- Freeing the FM_RESET pin*/
+ gpio_free(FM_RESET);
+
+ /*Add the i2c driver*/
+ if ( (ret = Si4709_i2c_drv_init() < 0) )
+ {
+ goto MISC_IRQ_DREG;
+ }
+
+ init_waitqueue_head(&Si4709_waitq);
+
+ debug("Si4709_driver_init successful");
+
+ return ret;
+
+MISC_IRQ_DREG:
+ free_irq(FM_IRQ_INT, NULL);
+MISC_DREG:
+ misc_deregister(&Si4709_misc_device);
+
+ return ret;
+}
+
+
+void __exit Si4709_driver_exit(void)
+{
+ debug("Si4709_driver_exit called");
+
+ /*Delete the i2c driver*/
+ Si4709_i2c_drv_exit();
+ free_irq(FM_IRQ_INT, NULL);
+
+ /*misc device deregistration*/
+ misc_deregister(&Si4709_misc_device);
+}
+
+module_init(Si4709_driver_init);
+module_exit(Si4709_driver_exit);
+MODULE_AUTHOR("Varun Mahajan <m.varun@samsung.com>");
+MODULE_DESCRIPTION("Si4709 FM tuner driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/media/radio/si4709/radio-si4709_main.h b/drivers/media/radio/si4709/radio-si4709_main.h
new file mode 100644
index 0000000..adf98e1
--- /dev/null
+++ b/drivers/media/radio/si4709/radio-si4709_main.h
@@ -0,0 +1,9 @@
+#ifndef _Si4709_MAIN_H
+#define _Si4709_MAIN_H
+
+#include <linux/wait.h>
+
+extern wait_queue_head_t Si4709_waitq;
+
+#endif
+
diff --git a/drivers/media/radio/si4709/radio-si4709_regs.h b/drivers/media/radio/si4709/radio-si4709_regs.h
new file mode 100644
index 0000000..599d009
--- /dev/null
+++ b/drivers/media/radio/si4709/radio-si4709_regs.h
@@ -0,0 +1,859 @@
+#ifndef _Si4709_REGS_H
+#define _Si4709_REGS_H
+
+#define NUM_OF_REGISTERS 0x10
+
+/*Si4709 registers*/
+#define DEVICE_ID 0x00
+#define CHIP_ID 0x01
+#define POWERCFG 0x02
+#define CHANNEL 0x03
+#define SYSCONFIG1 0x04
+#define SYSCONFIG2 0x05
+#define SYSCONFIG3 0x06
+#define TEST1 0x07
+#define TEST2 0x08
+#define BOOTCONFIG 0x09
+#define STATUSRSSI 0x0A
+#define READCHAN 0x0B
+#define RDSA 0x0C
+#define RDSB 0x0D
+#define RDSC 0x0E
+#define RDSD 0x0F
+
+/***********POWERCFG************/
+#define POWERCFG_DSMUTE 0x8000
+#define POWERCFG_DMUTE 0x4000
+#define POWERCFG_MONO 0x2000
+#define POWERCFG_RDSM 0x0800
+#define POWERCFG_SKMODE 0x0400
+#define POWERCFG_SEEKUP 0x0200
+#define POWERCFG_SEEK 0x0100
+#define POWERCFG_DISABLE 0x0040
+#define POWERCFG_ENABLE 0x0001
+/************************************/
+
+/***********CHANNEL************/
+#define CHANNEL_TUNE 0x8000
+/************************************/
+
+/***********SYSCONFIG1************/
+#define SYSCONFIG1_RDSIEN 0x8000
+#define SYSCONFIG1_STCIEN 0x4000
+#define SYSCONFIG1_RDS 0x1000
+#define SYSCONFIG1_DE 0x0800
+#define SYSCONFIG1_AGCD 0x0400
+#define SYSCONFIG1_BLNDADJ1 0x0080
+#define SYSCONFIG1_BLNDADJ0 0x0040
+#define SYSCONFIG1_GPO1 0x0008
+#define SYSCONFIG1_GPO0 0x0004
+/************************************/
+
+/***********SYSCONFIG2************/
+#define SYSCONFIG2_BAND1 0x0080
+#define SYSCONFIG2_BAND0 0x0040
+#define SYSCONFIG2_SPACE1 0x0020
+#define SYSCONFIG2_SPACE0 0x0010
+#define SYSCONFIG2_VOLUME3 0x0008
+#define SYSCONFIG2_VOLUME2 0x0004
+#define SYSCONFIG2_VOLUME1 0x0002
+#define SYSCONFIG2_VOLUME0 0x0001
+/************************************/
+
+/***********SYSCONFIG3************/
+#define SYSCONFIG3_SMUTER1 0x8000
+#define SYSCONFIG3_SMUTER0 0x4000
+#define SYSCONFIG3_SMUTEA1 0x2000
+#define SYSCONFIG3_SMUTEA0 0x1000
+#define SYSCONFIG3_VOLEXT 0x0100
+#define SYSCONFIG3_SKSNR3 0x0080
+#define SYSCONFIG3_SKSNR2 0x0040
+#define SYSCONFIG3_SKSNR1 0x0020
+#define SYSCONFIG3_SKSNR0 0x0010
+#define SYSCONFIG3_SKCNT3 0x0008
+#define SYSCONFIG3_SKCNT2 0x0004
+#define SYSCONFIG3_SKCNT1 0x0002
+#define SYSCONFIG3_SKCNT0 0x0001
+/************************************/
+
+/***********TEST1************/
+#define TEST1_AHIZEN 0x4000
+/************************************/
+
+/***********STATUSRSSI************/
+#define STATUSRSSI_RDSR 0x8000
+#define STATUSRSSI_STC 0x4000
+#define STATUSRSSI_SF_BL 0x2000
+#define STATUSRSSI_AFCRL 0x1000
+#define STATUSRSSI_RDSS 0x0800
+#define STATUSRSSI_BLERA1 0x0400
+#define STATUSRSSI_BLERA0 0x0200
+#define STATUSRSSI_ST 0x0100
+/************************************/
+
+/***********READCHAN************/
+#define READCHAN_BLERB1 0x8000
+#define READCHAN_BLERB0 0x4000
+#define READCHAN_BLERC1 0x2000
+#define READCHAN_BLERC0 0x1000
+#define READCHAN_BLERD1 0x0800
+#define READCHAN_BLERD0 0x0400
+
+#define READCHAN_CHAN_MASK 0x03FF
+/************************************/
+
+/*************************************************************/
+static inline void switch_on_bits(u16 *data, u16 bits_on)
+{
+ *data |= bits_on;
+}
+
+static inline void switch_off_bits(u16 *data, u16 bits_off)
+{
+ u16 aux = 0xFFFF;
+ aux ^= bits_off;
+ *data &= aux;
+}
+
+#define BIT_ON 1
+#define BIT_OFF 0
+
+static inline int check_bit(u16 data, u16 bit)
+{
+ return (data&bit) ? BIT_ON : BIT_OFF;
+}
+/**************************************************************/
+
+
+/********************************************************************/
+static inline void POWERCFG_BITSET_ENABLE_HIGH(u16 *data)
+{
+ switch_on_bits(data, (POWERCFG_ENABLE));
+}
+
+static inline void POWERCFG_BITSET_DISABLE_HIGH(u16 *data)
+{
+ switch_on_bits(data, (POWERCFG_DISABLE));
+}
+
+static inline void POWERCFG_BITSET_DISABLE_LOW(u16 *data)
+{
+ switch_off_bits(data, (POWERCFG_DISABLE));
+}
+
+static inline void POWERCFG_BITSET_DMUTE_HIGH(u16 *data)
+{
+ switch_on_bits(data, (POWERCFG_DMUTE));
+}
+
+static inline void POWERCFG_BITSET_DMUTE_LOW(u16 *data)
+{
+ switch_off_bits(data, (POWERCFG_DMUTE));
+}
+
+static inline void POWERCFG_BITSET_DSMUTE_HIGH(u16 *data)
+{
+ switch_on_bits(data, (POWERCFG_DSMUTE));
+}
+
+static inline void POWERCFG_BITSET_DSMUTE_LOW(u16 *data)
+{
+ switch_off_bits(data, (POWERCFG_DSMUTE));
+}
+
+static inline void POWERCFG_BITSET_MONO_HIGH(u16 *data)
+{
+ switch_on_bits(data, (POWERCFG_MONO));
+}
+
+static inline void POWERCFG_BITSET_MONO_LOW(u16 *data)
+{
+ switch_off_bits(data, (POWERCFG_MONO));
+}
+
+static inline void POWERCFG_BITSET_RDSM_HIGH(u16 *data)
+{
+ switch_on_bits(data, (POWERCFG_RDSM));
+}
+
+static inline void POWERCFG_BITSET_RDSM_LOW(u16 *data)
+{
+ switch_off_bits(data, (POWERCFG_RDSM));
+}
+
+static inline void POWERCFG_BITSET_SKMODE_HIGH(u16 *data)
+{
+ switch_on_bits(data, (POWERCFG_SKMODE));
+}
+
+static inline void POWERCFG_BITSET_SKMODE_LOW(u16 *data)
+{
+ switch_off_bits(data, (POWERCFG_SKMODE));
+}
+
+static inline void POWERCFG_BITSET_SEEKUP_HIGH(u16 *data)
+{
+ switch_on_bits(data, (POWERCFG_SEEKUP));
+}
+
+static inline void POWERCFG_BITSET_SEEKUP_LOW(u16 *data)
+{
+ switch_off_bits(data, (POWERCFG_SEEKUP));
+}
+
+static inline void POWERCFG_BITSET_SEEK_HIGH(u16 *data)
+{
+ switch_on_bits(data, (POWERCFG_SEEK));
+}
+
+static inline void POWERCFG_BITSET_SEEK_LOW(u16 *data)
+{
+ switch_off_bits(data, (POWERCFG_SEEK));
+}
+
+static inline void POWERCFG_BITSET_RESERVED(u16 *data)
+{
+ *data &= 0xEF41;
+}
+
+/********************************************************************/
+
+static inline void CHANNEL_BITSET_TUNE_HIGH(u16 *data)
+{
+ switch_on_bits(data, (CHANNEL_TUNE));
+}
+
+static inline void CHANNEL_BITSET_TUNE_LOW(u16 *data)
+{
+ switch_off_bits(data, (CHANNEL_TUNE));
+}
+
+static inline void CHANNEL_BITSET_RESERVED(u16 *data)
+{
+ *data &= 0x83FF;
+}
+
+/********************************************************************/
+
+static inline void SYSCONFIG1_BITSET_RDSIEN_HIGH(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_RDSIEN));
+}
+
+static inline void SYSCONFIG1_BITSET_RDSIEN_LOW(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG1_RDSIEN));
+}
+
+static inline void SYSCONFIG1_BITSET_STCIEN_HIGH(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_STCIEN));
+}
+
+static inline void SYSCONFIG1_BITSET_STCIEN_LOW(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG1_STCIEN));
+}
+
+static inline void SYSCONFIG1_BITSET_RDS_HIGH(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_RDS));
+}
+
+static inline void SYSCONFIG1_BITSET_RDS_LOW(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG1_RDS));
+}
+
+static inline void SYSCONFIG1_BITSET_DE_50(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_DE));
+}
+
+static inline void SYSCONFIG1_BITSET_DE_75(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG1_DE));
+}
+
+static inline void SYSCONFIG1_BITSET_AGCD_HIGH(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_AGCD));
+}
+
+static inline void SYSCONFIG1_BITSET_AGCD_LOW(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG1_AGCD));
+}
+
+static inline void SYSCONFIG1_BITSET_RSSI_DEF_31_49(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG1_BLNDADJ1|SYSCONFIG1_BLNDADJ0));
+}
+
+static inline void SYSCONFIG1_BITSET_RSSI_37_55(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_BLNDADJ0));
+ switch_off_bits(data, (SYSCONFIG1_BLNDADJ1));
+}
+
+static inline void SYSCONFIG1_BITSET_RSSI_19_37(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_BLNDADJ1));
+ switch_off_bits(data, (SYSCONFIG1_BLNDADJ0));
+}
+
+static inline void SYSCONFIG1_BITSET_RSSI_25_43(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_BLNDADJ1|SYSCONFIG1_BLNDADJ0));
+}
+
+static inline void SYSCONFIG1_BITSET_GPIO_HIGH_IMP(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG1_GPO1|SYSCONFIG1_GPO0));
+}
+
+static inline void SYSCONFIG1_BITSET_GPIO_STC_RDS_INT(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_GPO0));
+ switch_off_bits(data, (SYSCONFIG1_GPO1));
+}
+
+static inline void SYSCONFIG1_BITSET_GPIO_LOW(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_GPO1));
+ switch_off_bits(data, (SYSCONFIG1_GPO0));
+}
+
+static inline void SYSCONFIG1_BITSET_GPIO_HIGH(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_GPO1|SYSCONFIG1_GPO0));
+}
+
+static inline void SYSCONFIG1_BITSET_RESERVED(u16 *data)
+{
+ *data &= 0xDCCC;
+ *data |= 0x22;
+}
+
+/********************************************************************/
+
+/*US/EUROPE (Default)*/
+static inline void SYSCONFIG2_BITSET_BAND_87p5_108_MHz(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG2_BAND1|SYSCONFIG2_BAND0));
+}
+
+/*Japan wide band*/
+static inline void SYSCONFIG2_BITSET_BAND_76_108_MHz(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG2_BAND0));
+ switch_off_bits(data, (SYSCONFIG2_BAND1));
+}
+
+/*Japan*/
+static inline void SYSCONFIG2_BITSET_BAND_76_90_MHz(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG2_BAND1));
+ switch_off_bits(data, (SYSCONFIG2_BAND0));
+}
+
+/*US, Australia (Default)*/
+static inline void SYSCONFIG2_BITSET_SPACE_200_KHz(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG2_SPACE1|SYSCONFIG2_SPACE0));
+}
+
+/*Europe, Japan*/
+static inline void SYSCONFIG2_BITSET_SPACE_100_KHz(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG2_SPACE0));
+ switch_off_bits(data, (SYSCONFIG2_SPACE1));
+}
+
+static inline void SYSCONFIG2_BITSET_SPACE_50_KHz(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG2_SPACE1));
+ switch_off_bits(data, (SYSCONFIG2_SPACE0));
+}
+
+static inline void SYSCONFIG2_BITSET_VOLUME(u16 *data, u8 volume)
+{
+ *data &= 0xFFF0;
+ *data |= (volume & 0x0F);
+}
+
+static inline void SYSCONFIG2_BITSET_SEEKTH(u16 *data, u8 seek_th)
+{
+ *data &= 0x00FF;
+ *data |= ((seek_th << 8) & 0xFF00);
+}
+
+static inline u8 SYSCONFIG2_GET_VOLUME(u16 data)
+{
+ return ( (u8) (data & 0x000F) );
+}
+
+/********************************************************************/
+
+static inline void SYSCONFIG3_BITSET_SMUTER_FASTEST(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG3_SMUTER1|SYSCONFIG3_SMUTER0));
+}
+
+static inline void SYSCONFIG3_BITSET_SMUTER_FAST(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG3_SMUTER1));
+ switch_on_bits(data, (SYSCONFIG3_SMUTER0));
+}
+
+static inline void SYSCONFIG3_BITSET_SMUTER_SLOW(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG3_SMUTER0));
+ switch_on_bits(data, (SYSCONFIG3_SMUTER1));
+}
+
+static inline void SYSCONFIG3_BITSET_SMUTER_SLOWEST(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG3_SMUTER1|SYSCONFIG3_SMUTER0));
+}
+
+static inline void SYSCONFIG3_BITSET_SMUTEA_16_dB(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG3_SMUTEA1|SYSCONFIG3_SMUTEA0));
+}
+
+static inline void SYSCONFIG3_BITSET_SMUTEA_14dB(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG3_SMUTEA1));
+ switch_on_bits(data, (SYSCONFIG3_SMUTEA0));
+}
+
+static inline void SYSCONFIG3_BITSET_SMUTEA_12dB(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG3_SMUTEA0));
+ switch_on_bits(data, (SYSCONFIG3_SMUTEA1));
+}
+
+static inline void SYSCONFIG3_BITSET_SMUTEA_10dB(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG3_SMUTEA1|SYSCONFIG3_SMUTEA0));
+}
+
+static inline void SYSCONFIG3_BITSET_VOLEXT_DISB(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG3_VOLEXT));
+}
+
+static inline void SYSCONFIG3_BITSET_VOLEXT_ENB(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG3_VOLEXT));
+}
+
+static inline void SYSCONFIG3_BITSET_SKSNR(u16 *data, u8 seeksnr)
+{
+ *data &= 0xFF0F;
+ *data |= ((seeksnr<<4) & 0xF0);
+}
+
+static inline void SYSCONFIG3_BITSET_SKCNT(u16 *data, u8 seekcnt)
+{
+ *data &= 0xFFF0;
+ *data |= ((seekcnt) & 0x0F);
+}
+
+static inline void SYSCONFIG3_BITSET_RESERVED(u16 *data)
+{
+ *data &= 0xF1FF;
+}
+
+/********************************************************************/
+
+static inline void TEST1_BITSET_AHIZEN_HIGH(u16 *data)
+{
+ switch_on_bits(data, (TEST1_AHIZEN));
+}
+
+static inline void TEST1_BITSET_AHIZEN_LOW(u16 *data)
+{
+ switch_off_bits(data, (TEST1_AHIZEN));
+}
+
+static inline void TEST1_BITSET_RESERVED(u16 *data)
+{
+ *data &= 0x7FFF;
+}
+
+/********************************************************************/
+
+#define NEW_RDS_GROUP_READY 1
+#define NO_RDS_GROUP_READY 0
+
+#define COMPLETE 1
+#define CLEAR 0
+
+#define SEEK_SUCCESSFUL 1
+#define SEEK_FAILURE_BAND_LMT_RCHD 0
+
+#define AFC_RAILED 1
+#define AFC_NOT_RAILED 0
+
+#define RDS_DECODER_SYNCHRONIZED 1
+#define RDS_DECODER_NOT_SYNCHRONIZED 0
+
+#define STEREO 1
+#define MONO 0
+
+#define ERRORS_0 0
+#define ERRORS_1_2 1
+#define ERRORS_3_5 2
+#define ERRORS_NO_CORREC_POSSIBLE_6_p 3
+
+static inline int STATUSRSSI_RDS_READY_STATUS(u16 data)
+{
+ if( check_bit(data, STATUSRSSI_RDSR) == BIT_ON )
+ {
+ return NEW_RDS_GROUP_READY;
+ }
+ else
+ {
+ return NO_RDS_GROUP_READY;
+ }
+}
+
+static inline int STATUSRSSI_SEEK_TUNE_STATUS(u16 data)
+{
+ if( check_bit(data, STATUSRSSI_STC) == BIT_ON )
+ {
+ return COMPLETE;
+ }
+ else
+ {
+ return CLEAR;
+ }
+}
+
+static inline int STATUSRSSI_SF_BL_STATUS(u16 data)
+{
+ if( check_bit(data, STATUSRSSI_SF_BL) == BIT_ON )
+ {
+ return SEEK_FAILURE_BAND_LMT_RCHD;
+ }
+ else
+ {
+ return SEEK_SUCCESSFUL;
+ }
+}
+
+static inline int STATUSRSSI_AFC_RAIL_STATUS(u16 data)
+{
+ if( check_bit(data, STATUSRSSI_AFCRL) == BIT_ON )
+ {
+ return AFC_RAILED;
+ }
+ else
+ {
+ return AFC_NOT_RAILED;
+ }
+}
+
+static inline int STATUSRSSI_RDS_SYNC_STATUS(u16 data)
+{
+ if( check_bit(data, STATUSRSSI_RDSS) == BIT_ON )
+ {
+ return RDS_DECODER_SYNCHRONIZED;
+ }
+ else
+ {
+ return RDS_DECODER_NOT_SYNCHRONIZED;
+ }
+}
+
+static inline int STATUSRSSI_RDS_BLOCK_A_ERRORS(u16 data)
+{
+ int ret = 0;
+ int bits_status = 0;
+
+ ret = check_bit(data,STATUSRSSI_BLERA1);
+
+ if( ret == BIT_ON )
+ bits_status = 0x02;
+ else
+ bits_status = 0x00;
+
+ ret = check_bit(data,STATUSRSSI_BLERA0);
+
+ if( ret == BIT_ON )
+ bits_status |= 0x01;
+
+ return bits_status;
+}
+
+static inline int STATUSRSSI_STEREO_STATUS(u16 data)
+{
+ if( check_bit(data, STATUSRSSI_RDSS) == BIT_ON )
+ {
+ return STEREO;
+ }
+ else
+ {
+ return MONO;
+ }
+}
+
+static inline u8 STATUSRSSI_RSSI_SIGNAL_STRENGTH(u16 data)
+{
+ return ((u8) (0x00FF & data));
+}
+
+static inline u8 DEVICE_ID_PART_NUMBER(u16 data) //vnv.srikanth
+{
+ data = data>>12;
+ return((u8)(0x000F & data));
+}
+
+static inline u16 DEVICE_ID_MANUFACT_NUMBER(u16 data) //vnv.srikanth
+{
+ return((u16)(0x0FFF & data));
+}
+
+static inline u8 CHIP_ID_CHIP_VERSION(u16 data) //vnv.srikanth
+{
+ data = data>>10;
+ return((u8)(0x003F & data));
+}
+
+static inline u8 CHIP_ID_DEVICE(u16 data) //vnv.srikanth
+{
+ data = data>>6;
+ return((u8)(0x000F & data));
+}
+
+static inline u8 CHIP_ID_FIRMWARE_VERSION(u16 data) //vnv.srikanth
+{
+ return((u8)(0x003F & data));
+}
+
+static inline u8 SYS_CONFIG2_RSSI_TH(u16 data) //vnv.srikanth
+{
+ data=data>>8;
+ return((u8)(0x00FF&data));
+}
+
+static inline u8 SYS_CONFIG2_FM_BAND(u16 data) //vnv.srikanth
+{
+ data=data>>6;
+ return((u8)(0x0003&data));
+}
+
+static inline u8 SYS_CONFIG2_FM_CHAN_SPAC(u16 data) //vnv.srikanth
+{
+ data=data>>4;
+ return((u8)(0x0003&data));
+}
+
+static inline u8 SYS_CONFIG2_FM_VOL(u16 data) //vnv.srikanth
+{
+ return((u8)(0x000F&data));
+}
+
+//POWER_CONFIG_STATUS
+ //vnv.srikanth-start
+#define SOFTMUTE_ENABLE 0
+#define SOFTMUTE_DISABLE 1
+
+#define MUTE_ENABLE 0
+#define MUTE_DISABLE 1
+
+#define STEREO_SELECT 0
+#define MONO_SELECT 1
+
+#define RDS_MODE_STANDARD 0
+#define RDS_MODE_VERBOSE 1
+
+#define SEEK_MODE_CONT_SEEK 0
+#define SEEK_MODE_STOP_SEEK 1
+
+#define SEEK_DOWN 0
+#define SEEK_UP 1
+
+#define SEEK_DISABLE 0
+#define SEEK_ABLE 1
+
+static inline int POWER_CONFIG_SOFTMUTE_STATUS(u16 data)
+{
+ if( check_bit(data, POWERCFG_DSMUTE) == BIT_ON )
+ {
+ return SOFTMUTE_DISABLE;
+ }
+ else
+ {
+ return SOFTMUTE_ENABLE;
+ }
+}
+
+static inline int POWER_CONFIG_MUTE_STATUS(u16 data)
+{
+ if( check_bit(data, POWERCFG_DMUTE) == BIT_ON )
+ {
+ return MUTE_DISABLE;
+ }
+ else
+ {
+ return MUTE_ENABLE;
+ }
+}
+
+static inline int POWER_CONFIG_MONO_STATUS(u16 data)
+{
+ if( check_bit(data, POWERCFG_MONO) == BIT_ON )
+ {
+ return MONO_SELECT;
+ }
+ else
+ {
+ return STEREO_SELECT;
+ }
+}
+
+static inline int POWER_CONFIG_RDS_MODE_STATUS(u16 data)
+{
+ if( check_bit(data, POWERCFG_RDSM ) == BIT_ON )
+ {
+ return RDS_MODE_VERBOSE;
+ }
+ else
+ {
+ return RDS_MODE_STANDARD;
+ }
+}
+
+static inline int POWER_CONFIG_SKMODE_STATUS(u16 data)
+{
+ if( check_bit(data, POWERCFG_SKMODE ) == BIT_ON )
+ {
+ return SEEK_MODE_STOP_SEEK;
+ }
+ else
+ {
+ return SEEK_MODE_CONT_SEEK;
+ }
+}
+
+static inline int POWER_CONFIG_SEEKUP_STATUS(u16 data)
+{
+ if( check_bit(data, POWERCFG_SEEKUP ) == BIT_ON )
+ {
+ return SEEK_UP;
+ }
+ else
+ {
+ return SEEK_DOWN;
+ }
+}
+
+static inline int POWER_CONFIG_SEEK_STATUS(u16 data)
+{
+ if( check_bit(data, POWERCFG_SEEK ) == BIT_ON )
+ {
+ return SEEK_ABLE;
+ }
+ else
+ {
+ return SEEK_DISABLE;
+ }
+}
+
+static inline int POWER_CONFIG_DISABLE_STATUS(u16 data)
+{
+ if( check_bit(data, POWERCFG_DISABLE ) == BIT_ON )
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static inline int POWER_CONFIG_ENABLE_STATUS(u16 data)
+{
+ if( check_bit(data, POWERCFG_ENABLE ) == BIT_ON )
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+} //vnv.srikanth-end
+/********************************************************************/
+
+static inline int READCHAN_BLOCK_B_ERRORS(u16 data)
+{
+ int ret = 0;
+ int bits_status = 0;
+
+ ret = check_bit(data,READCHAN_BLERB1);
+
+ if( ret == BIT_ON )
+ bits_status = 0x02;
+ else
+ bits_status = 0x00;
+
+ ret = check_bit(data,READCHAN_BLERB0);
+
+ if( ret == BIT_ON )
+ bits_status |= 0x01;
+
+ return bits_status;
+}
+
+static inline int READCHAN_BLOCK_C_ERRORS(u16 data)
+{
+ int ret = 0;
+ int bits_status = 0;
+
+ ret = check_bit(data,READCHAN_BLERC1);
+
+ if( ret == BIT_ON )
+ bits_status = 0x02;
+ else
+ bits_status = 0x00;
+
+ ret = check_bit(data,READCHAN_BLERC0);
+
+ if( ret == BIT_ON )
+ bits_status |= 0x01;
+
+ return bits_status;
+}
+
+static inline int READCHAN_BLOCK_D_ERRORS(u16 data)
+{
+ int ret = 0;
+ int bits_status = 0;
+
+ ret = check_bit(data,READCHAN_BLERD1);
+
+ if( ret == BIT_ON )
+ bits_status = 0x02;
+ else
+ bits_status = 0x00;
+
+ ret = check_bit(data,READCHAN_BLERD0);
+
+ if( ret == BIT_ON )
+ bits_status |= 0x01;
+
+ return bits_status;
+}
+
+static inline u16 READCHAN_GET_CHAN(u16 data)
+{
+ return ( data & READCHAN_CHAN_MASK );
+}
+
+/********************************************************************/
+
+#endif
+