aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/samsung
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/samsung')
-rw-r--r--drivers/samsung/Kconfig9
-rw-r--r--drivers/samsung/Makefile4
-rw-r--r--drivers/samsung/fm_si4709/Si4705_dev.c2064
-rw-r--r--drivers/samsung/fm_si4709/Si4705_main.c24
-rw-r--r--drivers/samsung/fm_si4709/Si4709_dev.c35
-rw-r--r--drivers/samsung/fm_si4709/Si4709_dev.h3
-rw-r--r--drivers/samsung/fm_si4709/Si4709_main.c14
-rw-r--r--drivers/samsung/fm_si47xx/Makefile7
-rw-r--r--drivers/samsung/fm_si47xx/Si47xx_dev.c1791
-rw-r--r--drivers/samsung/fm_si47xx/Si47xx_dev.h246
-rw-r--r--drivers/samsung/fm_si47xx/Si47xx_i2c_drv.c768
-rw-r--r--drivers/samsung/fm_si47xx/Si47xx_ioctl.h129
-rw-r--r--drivers/samsung/fm_si47xx/commanddefs.h199
-rw-r--r--drivers/samsung/fm_si47xx/propertydefs.h585
14 files changed, 3790 insertions, 2088 deletions
diff --git a/drivers/samsung/Kconfig b/drivers/samsung/Kconfig
index ab0026b..2d70864 100644
--- a/drivers/samsung/Kconfig
+++ b/drivers/samsung/Kconfig
@@ -1,17 +1,8 @@
#
#
#
-
-menuconfig SAMSUNG_MODULES
- tristate "Samsung Kernel Modules"
- default n
- help
- Say Y to enable Samsung kernel modules. j4fs and param
- modules are included.
-
menuconfig FM_RADIO
tristate "FM Radio Driver"
- depends on SAMSUNG_MODULES
default n
help
Say Y to enable FM Radio Driver
diff --git a/drivers/samsung/Makefile b/drivers/samsung/Makefile
index 811c209..68916b7 100644
--- a/drivers/samsung/Makefile
+++ b/drivers/samsung/Makefile
@@ -3,5 +3,5 @@
#
# Object files in subdirectories
-
-obj-$(CONFIG_FM_RADIO) += fm_si4709/
+obj-$(CONFIG_FM_SI4705) += fm_si47xx/
+obj-$(CONFIG_FM_SI4709) += fm_si4709/
diff --git a/drivers/samsung/fm_si4709/Si4705_dev.c b/drivers/samsung/fm_si4709/Si4705_dev.c
deleted file mode 100644
index 0898882..0000000
--- a/drivers/samsung/fm_si4709/Si4705_dev.c
+++ /dev/null
@@ -1,2064 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-#include <linux/time.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-
-#include <mach/gpio.h>
-#include <plat/gpio-cfg.h>
-
-#include "Si4709_regs.h"
-#include "Si4709_main.h"
-#include "Si4709_dev.h"
-#include "Si4709_common.h"
-
-#if 1 /* To do */
-#include "commanddefs.h"
-#include "propertydefs.h"
-#endif
-
-
-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 10
-#define TUNE_SNR_THRESHOLD 4
-#define TUNE_CNT_THRESHOLD 0x00
-
-#define _ENABLE_RDS_
-
-#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
-
-u8 cmd[8];
-u8 rsp[13];
-u8 RsqInts;
-u8 Status;
-u8 SMUTE;
-u8 AFCRL;
-u8 Valid;
-u8 Pilot;
-u8 Blend;
-u16 Freq;
-u8 RSSI;
-u8 ASNR;
-u8 FreqOff;
-u8 STC;
-u8 BLTF;
-u16 AntCap;
-u8 RdsInts;
-u8 RdsSync;
-u8 GrpLost;
-u8 RdsFifoUsed;
-u16 BlockA;
-u16 BlockB;
-u16 BlockC;
-u16 BlockD;
-u8 BleA;
-u8 BleB;
-u8 BleC;
-u8 BleD;
-
-
-
-/*static functions*/
-/**********************************************/
-static void wait(void);
-
-#ifndef RDS_INTERRUPT_ON_ALWAYS
-static void wait_RDS(void);
-#endif
-
-static int powerup(void);
-static int powerdown(void);
-
-static int seek(u32 *, int, int);
-static int tune_freq(u32);
-static u16 freq_to_channel(u32);
-static void fmTuneStatus(u8 cancel, u8 intack);
-static void fmRsqStatus(u8 intack);
-static void si47xx_set_property(u16 propNumber, u16 propValue);
-static int si47xx_command(u8 cmd_size, u8 *cmd, u8 reply_size, u8 *reply);
-static void fmRdsStatus(u8 intack, u8 mtfifo);
-static void fmTuneFreq(u16 frequency);
-static void fmSeekStart(u8 seekUp, u8 wrap);
-static u8 si47xx_readStatus(void);
-static void si47xx_waitForCTS(void);
-static u8 getIntStatus(void);
-static int i2c_write(u8 number_bytes, u8 *data_out);
-static int i2c_read(u8 number_bytes, u8 *data_in);
-/**********************************************/
-
-/*Si4709 device structure*/
-static struct 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
-
-unsigned int Si4709_dev_int;
-unsigned int Si4709_dev_irq;
-
-#if defined(CONFIG_MACH_M0)
-unsigned int Si4709_dev_sw;
-#endif
-
-#if defined(CONFIG_MACH_M0_CTC)
-static const u16 rx_vol[] = {
-0x0, 0x15, 0x18, 0x1B, 0x1E, 0x21, 0x24, 0x27,
-0x2A, 0x2D, 0x30, 0x33, 0x36, 0x39, 0x3C, 0x3F};
-#else
-static const u16 rx_vol[] = {
-0x0, 0x13, 0x16, 0x19, 0x1C, 0x1F, 0x22, 0x25,
-0x28, 0x2B, 0x2E, 0x31, 0x34, 0x37, 0x3A, 0x3D};
-#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;
-
-#if defined(CONFIG_MACH_M0)
- if (system_rev >= 15)
- Si4709_dev_int = GPIO_FM_INT_REV15;
- else
-#endif
- Si4709_dev_int = GPIO_FM_INT;
-
- Si4709_dev_irq = gpio_to_irq(Si4709_dev_int);
-
-#if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_M0_CTC)
- Si4709_dev_sw = GPIO_FM_MIC_SW;
-#endif
-
- disable_irq(Si4709_dev_irq);
-
- Si4709_dev.state.power_state = RADIO_POWERDOWN;
- Si4709_dev.state.seek_state = RADIO_SEEK_OFF;
- 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 */
- /* 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);
-
- kfree(RDS_Block_Error_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");
-
- if (!(RADIO_ON == Si4709_dev.state.power_state)) {
- ret = powerup();
- if (ret < 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 */
-#ifdef _ENABLE_RDS_
- si47xx_set_property(FM_RDS_CONFIG, 1);
- si47xx_set_property(GPO_IEN, GPO_IEN_STCIEN_MASK |
- GPO_IEN_STCREP_MASK);
- si47xx_set_property(GPO_IEN, GPO_IEN_STCIEN_MASK |
- GPO_IEN_RDSIEN_MASK | GPO_IEN_STCREP_MASK);
- si47xx_set_property(FM_RDS_INTERRUPT_SOURCE,
- FM_RDS_INTERRUPT_SOURCE_RECV_MASK);
- si47xx_set_property(FM_RDS_CONFIG,
- FM_RDS_CONFIG_RDSEN_MASK |
- (3 << FM_RDS_CONFIG_BLETHA_SHFT) |
- (3 << FM_RDS_CONFIG_BLETHB_SHFT) |
- (3 << FM_RDS_CONFIG_BLETHC_SHFT) |
- (3 << FM_RDS_CONFIG_BLETHD_SHFT));
-#endif
-/*VNVS:18-NOV'09 : Setting DE-Time Constant as 50us(Europe,Japan,Australia)*/
- si47xx_set_property(FM_DEEMPHASIS, FM_DEEMPH_50US);
- /* SYSCONFIG2_BITSET_SEEKTH( */
- /* &Si4709_dev.registers[SYSCONFIG2],2); */
-/*VNVS:18-NOV'09 : modified for detecting more stations of good quality*/
- si47xx_set_property(FM_SEEK_TUNE_RSSI_THRESHOLD,
- TUNE_RSSI_THRESHOLD);
- si47xx_set_property(FM_SEEK_BAND_BOTTOM, 8750);
- si47xx_set_property(FM_SEEK_BAND_TOP, 10800);
- Si4709_dev.settings.band = BAND_87500_108000_kHz;
- Si4709_dev.settings.bottom_of_band = FREQ_87500_kHz;
- si47xx_set_property(FM_SEEK_FREQ_SPACING,
- CHAN_SPACING_100_kHz);
- Si4709_dev.settings.channel_spacing =
- CHAN_SPACING_100_kHz;
-
- /* SYSCONFIG3_BITSET_SKSNR( */
- /* &Si4709_dev.registers[SYSCONFIG3],3); */
-/*VNVS:18-NOV'09 : modified for detecting more stations of good quality*/
- si47xx_set_property(FM_SEEK_TUNE_SNR_THRESHOLD,
- TUNE_SNR_THRESHOLD);
- 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;
- Si4709_dev_STEREO_SET();
-
-/*this will write all the above registers */
- if (ret < 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");
- enable_irq(Si4709_dev_irq);
- si47xx_set_property(0xff00, 0);
-
- 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));
-
- disable_irq(Si4709_dev_irq);
-
- if (Si4709_dev.valid == eFALSE) {
- debug("Si4709_dev_powerdown called when DS is invalid");
- ret = -1;
- } else {
- ret = powerdown();
- if (ret < 0)
- debug("powerdown failed");
- }
- mutex_unlock(&(Si4709_dev.lock));
-
- return ret;
-}
-
-int Si4709_dev_suspend(void)
-{
- int ret = 0;
-
- debug("Si4709_dev_suspend called");
-
-#ifndef _ENABLE_RDS_
- disable_irq(Si4709_dev_irq);
-#endif
-
- 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;
- }
- 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");
-
-#ifndef _ENABLE_RDS_
- enable_irq(Si4709_dev_irq);
-#endif
-
- 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;
- }
-
- mutex_unlock(&(Si4709_dev.lock));
- debug("Si4709_dev_disable call over");
-
- return ret;
-}
-
-int Si4709_dev_band_set(int band)
-{
- int ret = 0;
- u16 prev_band = 0;
- u32 prev_bottom_of_band = 0;
-
- debug("Si4709_dev_band_set called");
-
- 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:
- si47xx_set_property(FM_SEEK_BAND_BOTTOM, 8750);
- si47xx_set_property(FM_SEEK_BAND_TOP, 10800);
- Si4709_dev.settings.band = BAND_87500_108000_kHz;
- Si4709_dev.settings.bottom_of_band = FREQ_87500_kHz;
- break;
- case BAND_76000_108000_kHz:
- si47xx_set_property(FM_SEEK_BAND_BOTTOM, 7600);
- si47xx_set_property(FM_SEEK_BAND_TOP, 10800);
- Si4709_dev.settings.band = BAND_76000_108000_kHz;
- Si4709_dev.settings.bottom_of_band = FREQ_76000_kHz;
- break;
- case BAND_76000_90000_kHz:
- si47xx_set_property(FM_SEEK_BAND_BOTTOM, 7600);
- si47xx_set_property(FM_SEEK_BAND_TOP, 9000);
- Si4709_dev.settings.band = BAND_76000_90000_kHz;
- Si4709_dev.settings.bottom_of_band = FREQ_76000_kHz;
- break;
- default:
- ret = -1;
- }
- }
-
- return ret;
-}
-
-int Si4709_dev_ch_spacing_set(int ch_spacing)
-{
- int ret = 0;
- u16 prev_ch_spacing = 0;
-
- debug("Si4709_dev_ch_spacing_set called");
-
- mutex_lock(&(Si4709_dev.lock));
- 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:
- si47xx_set_property(FM_SEEK_FREQ_SPACING, 20);
- Si4709_dev.settings.channel_spacing =
- CHAN_SPACING_200_kHz;
- break;
-
- case CHAN_SPACING_100_kHz:
- si47xx_set_property(FM_SEEK_FREQ_SPACING, 10);
- Si4709_dev.settings.channel_spacing =
- CHAN_SPACING_100_kHz;
- break;
-
- case CHAN_SPACING_50_kHz:
- si47xx_set_property(FM_SEEK_FREQ_SPACING, 5);
- Si4709_dev.settings.channel_spacing =
- CHAN_SPACING_50_kHz;
- break;
-
- default:
- ret = -1;
- }
-
- if (ret == 0) {
- if (ret < 0) {
- debug("Si4709_dev_ch_spacing_set "
- "i2c_write 1 failed");
- Si4709_dev.settings.channel_spacing =
- prev_ch_spacing;
- }
- }
- }
-
- mutex_unlock(&(Si4709_dev.lock));
-
- return ret;
-}
-
-int Si4709_dev_chan_select(u32 frequency)
-{
- int ret = 0;
-
- debug("Si4709_dev_chan_select called");
-
- 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;
- }
- 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 < 0)
- debug("Si4709_dev_chan_get i2c_read failed");
- else {
- fmTuneStatus(0, 0);
- *frequency = Freq;
- }
- }
- mutex_unlock(&(Si4709_dev.lock));
- return ret;
-}
-
-int Si4709_dev_seek_full(u32 *frequency)
-{
- int ret = 0;
-
- debug("Si4709_dev_seek_full called\n");
- mutex_lock(&(Si4709_dev.lock));
-
- if (Si4709_dev.valid == eFALSE) {
- debug("Si4709_dev_seek_full called when DS is invalid");
- ret = -1;
- } else {
- Si4709_dev.state.seek_state = RADIO_SEEK_ON;
- ret = seek(frequency, 1, 0);
- Si4709_dev.state.seek_state = RADIO_SEEK_OFF;
- }
-
- mutex_unlock(&(Si4709_dev.lock));
-
- return ret;
-}
-
-int Si4709_dev_seek_up(u32 *frequency)
-{
- int ret = 0;
-
- debug("Si4709_dev_seek_up called\n");
- 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, 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\n");
-
- 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, 1);
-
- Si4709_dev.state.seek_state = RADIO_SEEK_OFF;
- }
-
- mutex_unlock(&(Si4709_dev.lock));
-
- return ret;
-}
-
-int Si4709_dev_RSSI_seek_th_set(u8 seek_th)
-{
- int ret = 0;
-
- debug("Si4709_dev_RSSI_seek_th_set called");
-
- mutex_lock(&(Si4709_dev.lock));
-
- if (Si4709_dev.valid == eFALSE) {
- debug("Si4709_dev_RSSI_seek_th_set called "
- "when DS is invalid");
- ret = -1;
- } else {
- si47xx_set_property(FM_SEEK_TUNE_RSSI_THRESHOLD, seek_th);
- Si4709_dev.settings.curr_rssi_th = seek_th;
- if (ret < 0)
- debug("Si4709_dev_RSSI_seek_th_set i2c_write 1 failed");
- }
- mutex_unlock(&(Si4709_dev.lock));
-
- return ret;
-}
-
-int Si4709_dev_seek_SNR_th_set(u8 seek_SNR)
-{
- int ret = 0;
-
- debug("Si4709_dev_seek_SNR_th_set called");
-
- mutex_lock(&(Si4709_dev.lock));
-
- if (Si4709_dev.valid == eFALSE) {
- debug("Si4709_dev_seek_SNR_th_set called "
- "when DS is invalid");
- ret = -1;
- } else {
- si47xx_set_property(FM_SEEK_TUNE_SNR_THRESHOLD, seek_SNR);
- Si4709_dev.settings.curr_snr = seek_SNR;
-
- if (ret < 0)
- debug("Si4709_dev_seek_SNR_th_set i2c_write 1 failed");
- }
- mutex_unlock(&(Si4709_dev.lock));
-
- return ret;
-}
-
-int Si4709_dev_seek_FM_ID_th_set(u8 seek_FM_ID_th)
-{
- int ret = 0;
-
- debug("Si4709_dev_seek_FM_ID_th_set called");
-
- return ret;
-}
-
-int Si4709_dev_cur_RSSI_get(struct 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 {
- fmRsqStatus(0);
- if (ret < 0) {
- debug("Si4709_dev_cur_RSSI_get i2c_read 1 failed");
- } else {
- cur_RSSI->curr_rssi = RSSI;
- 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(struct device_id *dev_id)
-{
- int ret = 0;
-
- debug("Si4709_dev_device_id called");
-#if 0 /*To Do*/
- mutex_lock(&(Si4709_dev.lock));
-
- if (Si4709_dev.valid == eFALSE) {
- debug("Si4709_dev_device_id called when DS is invalid");
- ret = -1;
- } else {
- ret = i2c_read(DEVICE_ID);
- if (ret < 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));
-#endif
- return ret;
-}
-
-int Si4709_dev_chip_id(struct chip_id *chp_id)
-{
- int ret = 0;
-
- debug("Si4709_dev_chip_id called");
-#if 0 /*To Do*/
- mutex_lock(&(Si4709_dev.lock));
-
- if (Si4709_dev.valid == eFALSE) {
- debug("Si4709_dev_chip_id called when DS is invalid");
- ret = -1;
- } else {
- ret = i2c_read(CHIP_ID);
- if (ret < 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));
-#endif
- return ret;
-}
-
-int Si4709_dev_sys_config2(struct sys_config2 *sys_conf2)
-{
- int ret = 0;
-
- debug("Si4709_sys_config2 called\n");
-
- mutex_lock(&(Si4709_dev.lock));
-
- if (Si4709_dev.valid == eFALSE) {
- debug("Si4709_sys_config2 called when DS is invalid");
- ret = -1;
- } else {
- if (ret < 0) {
- debug("Si4709_sys_config2 i2c_read failed");
- } else {
- sys_conf2->rssi_th = Si4709_dev.settings.curr_rssi_th;
- sys_conf2->fm_band = Si4709_dev.settings.band;
- sys_conf2->fm_chan_spac =
- Si4709_dev.settings.channel_spacing;
- sys_conf2->fm_vol = 0;
- }
- }
-
- mutex_unlock(&(Si4709_dev.lock));
-
- return ret;
-}
-
-int Si4709_dev_sys_config3(struct sys_config3 *sys_conf3)
-{
- int ret = 0;
-
- debug("Si4709_sys_config3 called\n");
- mutex_lock(&(Si4709_dev.lock));
-
- if (Si4709_dev.valid == eFALSE) {
- debug("Si4709_sys_config3 called when DS is invalid");
- mutex_unlock(&(Si4709_dev.lock));
- return -1;
- }
- if (ret < 0) {
- debug("Si4709_sys_config3 i2c_read failed");
- } else {
- sys_conf3->smmute = 0;
- sys_conf3->smutea = 0;
- sys_conf3->volext = 0;
- sys_conf3->sksnr = Si4709_dev.settings.curr_snr;
- sys_conf3->skcnt = 0;
- }
- mutex_unlock(&(Si4709_dev.lock));
-
- return ret;
-}
-
-int Si4709_dev_status_rssi(struct 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");
- mutex_unlock(&(Si4709_dev.lock));
- return -1;
- }
- fmRsqStatus(0);
- if (ret < 0) {
- debug("Si4709_sys_config3 i2c_read failed");
- } else {
- debug("Si4709_dev_status_rssi %d\n", RSSI);
- status->rssi = RSSI;
- }
-
- mutex_unlock(&(Si4709_dev.lock));
-
- return ret;
-}
-
-int Si4709_dev_sys_config2_set(struct 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 {
- si47xx_set_property(FM_SEEK_TUNE_RSSI_THRESHOLD,
- sys_conf2->rssi_th);
- Si4709_dev_band_set(sys_conf2->fm_band);
- si47xx_set_property(FM_SEEK_FREQ_SPACING,
- sys_conf2->fm_chan_spac);
- Si4709_dev.settings.curr_rssi_th = sys_conf2->rssi_th;
- Si4709_dev.settings.band = sys_conf2->fm_band;
- Si4709_dev.settings.channel_spacing = sys_conf2->fm_chan_spac;
-
- if (ret < 0) {
- debug("Si4709_dev_sys_config2_set i2c_write 1 failed");
- } else
- debug(KERN_ERR "Si4709_dev_sys_config2_set() "
- ": Write Sucess!!");
- }
-
- mutex_unlock(&(Si4709_dev.lock));
-
- return ret;
-}
-
-int Si4709_dev_sys_config3_set(struct sys_config3 *sys_conf3)
-{
- int ret = 0;
- u16 register_bak = 0;
-
- debug("Si4709_dev_sys_config3_set called");
-
- mutex_lock(&(Si4709_dev.lock));
-
- if (Si4709_dev.valid == eFALSE) {
- debug("Si4709_dev_sys_config3_set called "
- "when DS is invalid");
- ret = -1;
- } else {
- si47xx_set_property(FM_SEEK_TUNE_SNR_THRESHOLD,
- sys_conf3->sksnr);
- Si4709_dev.settings.curr_snr = sys_conf3->sksnr;
- if (ret < 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(struct power_config *pow_conf)
-{
- int ret = 0;
-
- debug("Si4709_dev_power_config called");
-
- 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 {
- fmRsqStatus(0);
- if (ret < 0)
- debug("Si4709_dev_AFCRL_get i2c_read failed");
- *afc = AFCRL;
- }
-
- 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:
- si47xx_set_property(FM_DEEMPHASIS, FM_DEEMPH_50US);
- break;
-
- case DE_TIME_CONSTANT_75:
- si47xx_set_property(FM_DEEMPHASIS, FM_DEEMPH_75US);
- break;
-
- default:
- ret = -1;
- }
-
- if (0 == ret) {
- if (ret < 0)
- debug("Si4709_dev_DE_set i2c_write failed");
- }
- }
-
- 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;
-
- debug("Si4709_dev_VOLEXT_ENB called");
-
- return ret;
-}
-
-int Si4709_dev_VOLEXT_DISB(void)
-{
- int ret = 0;
-
- debug("Si4709_dev_VOLEXT_DISB called");
-
- 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));
-
- if (Si4709_dev.valid == eFALSE) {
- debug("Si4709_dev_volume_set called when DS is invalid");
- ret = -1;
- } else {
- si47xx_set_property(RX_VOLUME, rx_vol[volume] & RX_VOLUME_MASK);
-
- if (ret < 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");
-#if 0 /*To Do*/
- 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));
-#endif
- 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 {
- si47xx_set_property(FM_SOFT_MUTE_RATE, 64);
- si47xx_set_property(FM_SOFT_MUTE_MAX_ATTENUATION, 0);
- si47xx_set_property(FM_SOFT_MUTE_SNR_THRESHOLD, 4);
- if (ret < 0)
- error("Si4709_dev_DSMUTE_ON i2c_write failed");
- }
-
- 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 {
- si47xx_set_property(FM_SOFT_MUTE_RATE, 64);
- si47xx_set_property(FM_SOFT_MUTE_MAX_ATTENUATION, 16);
- si47xx_set_property(FM_SOFT_MUTE_SNR_THRESHOLD, 4);
- if (ret < 0)
- error("Si4709_dev_DSMUTE_OFF i2c_write failed");
- }
-
- 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 {
- si47xx_set_property(RX_HARD_MUTE,
- RX_HARD_MUTE_RMUTE_MASK |
- RX_HARD_MUTE_LMUTE_MASK);
- if (ret < 0)
- debug("Si4709_dev_MUTE_ON i2c_write failed");
- }
-
- 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 {
- si47xx_set_property(RX_HARD_MUTE, 0);
- if (ret < 0)
- debug("Si4709_dev_MUTE_OFF i2c_write failed");
- }
-
- 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 {
- si47xx_set_property(FM_BLEND_MONO_THRESHOLD, 127);
- si47xx_set_property(FM_BLEND_STEREO_THRESHOLD, 127);
- if (ret < 0)
- debug("Si4709_dev_MONO_SET i2c_write failed");
- }
-
- 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 {
- si47xx_set_property(FM_BLEND_MONO_THRESHOLD, 30);
- si47xx_set_property(FM_BLEND_STEREO_THRESHOLD, 49);
- if (ret < 0)
- debug("Si4709_dev_STEREO_SET i2c_write failed");
- }
-
- mutex_unlock(&(Si4709_dev.lock));
-
- return ret;
-}
-
-int Si4709_dev_RDS_ENABLE(void)
-{
- int ret = 0;
-
- debug("Si4709_dev_RDS_ENABLE called");
-
- mutex_lock(&(Si4709_dev.lock));
- if (Si4709_dev.valid == eFALSE) {
- debug("Si4709_dev_RDS_ENABLE called when DS is invalid");
- ret = -1;
- } else {
-#ifdef RDS_INTERRUPT_ON_ALWAYS
- si47xx_set_property(GPO_IEN, GPO_IEN_STCIEN_MASK |
- GPO_IEN_STCREP_MASK | GPO_IEN_RDSIEN_MASK |
- GPO_IEN_RDSREP_MASK);
-#endif
- si47xx_set_property(FM_RDS_INTERRUPT_SOURCE,
- FM_RDS_INTERRUPT_SOURCE_RECV_MASK);
- si47xx_set_property(FM_RDS_CONFIG, FM_RDS_CONFIG_RDSEN_MASK |
- (3 << FM_RDS_CONFIG_BLETHA_SHFT) |
- (3 << FM_RDS_CONFIG_BLETHB_SHFT) |
- (3 << FM_RDS_CONFIG_BLETHC_SHFT) |
- (3 << FM_RDS_CONFIG_BLETHD_SHFT));
- if (ret < 0)
- debug("Si4709_dev_RDS_ENABLE i2c_write failed");
-#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)
-{
- int ret = 0;
-
- debug("Si4709_dev_RDS_DISABLE called");
-
- mutex_lock(&(Si4709_dev.lock));
- if (Si4709_dev.valid == eFALSE) {
- debug("Si4709_dev_RDS_DISABLE called when DS is invalid");
- ret = -1;
- } else {
- si47xx_set_property(FM_RDS_CONFIG, 0);
-
- if (ret < 0)
- debug("Si4709_dev_RDS_DISABLE i2c_write failed");
-#ifdef RDS_INTERRUPT_ON_ALWAYS
- else
- Si4709_RDS_flag = NO_WAIT;
-#endif
- }
-
- mutex_unlock(&(Si4709_dev.lock));
-
- return ret;
-}
-
-int Si4709_dev_rstate_get(struct 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 = 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");
- return;
- }
-
- if (RDS_Data_Lost > 1)
- debug_rds("No_of_RDS_groups_Lost till now : %d",
- RDS_Data_Lost);
- fmRdsStatus(1, 0);
- /* RDSR bit and RDS Block data, so reading the RDS registers */
- do {
- /* Writing into RDS_Block_Data_buffer */
- i = 0;
- RDS_Block_Data_buffer[i++ + 4 * RDS_Buffer_Index_write] =
- BlockA;
- RDS_Block_Data_buffer[i++ + 4 * RDS_Buffer_Index_write] =
- BlockB;
- RDS_Block_Data_buffer[i++ + 4 * RDS_Buffer_Index_write] =
- BlockC;
- RDS_Block_Data_buffer[i++ + 4 * RDS_Buffer_Index_write] =
- BlockD;
-
- /*Writing into RDS_Block_Error_buffer */
- i = 0;
-
- RDS_Block_Error_buffer[i++ + 4 * RDS_Buffer_Index_write] =
- BleA;
- RDS_Block_Error_buffer[i++ + 4 * RDS_Buffer_Index_write] =
- BleB;
- RDS_Block_Error_buffer[i++ + 4 * RDS_Buffer_Index_write] =
- BleC;
- RDS_Block_Error_buffer[i++ + 4 * RDS_Buffer_Index_write] =
- BleD;
- fmRdsStatus(1, 0);
- } while (RdsFifoUsed != 0);
-
-#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(struct radio_data_t *data)
-{
- int i, ret = 0;
-
- debug_rds("Si4709_dev_RDS_data_get called");
-
- mutex_lock(&(Si4709_dev.lock));
-
- if (Si4709_dev.valid == eFALSE) {
- error("Si4709_dev_RDS_data_get called when DS is invalid");
- mutex_unlock(&(Si4709_dev.lock));
- return -1;
- }
-#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 < 0)
- error("Si4709_dev_RDS_data_get i2c_read 1 failed");
- else {
- fmTuneStatus(0, 0);
- data->curr_channel = Freq;
- data->curr_rssi = RSSI;
- debug_rds("curr_channel: %u, curr_rssi:%u",
- data->curr_channel,
- (u32) data->curr_rssi);
- }
- mutex_unlock(&(Si4709_dev.lock));
- return -1;
- }
- if (ret < 0)
- error("Si4709_dev_RDS_data_get i2c_read 2 failed");
- else {
- fmTuneStatus(0, 0);
- data->curr_channel = Freq;
- data->curr_rssi = RSSI;
- 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
-#if 0 /*To Do*/
- SYSCONFIG1_BITSET_RDSIEN_HIGH(&Si4709_dev.registers[SYSCONFIG1]);
-
- ret = i2c_write(SYSCONFIG1);
- if (ret < 0) {
- debug("Si4709_dev_RDS_data_get i2c_write 1 failed");
- Si4709_dev.registers[SYSCONFIG1] = sysconfig1;
- } else {
- ret = i2c_read(SYSCONFIG1);
- if (ret < 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();
-
- ret = i2c_read(STATUSRSSI);
- if (ret < 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]);
-
- ret = i2c_write(SYSCONFIG1);
- if (ret < 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;
-
- ret = i2c_read(RDSD);
- if (ret < 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;
- mutex_unlock(&(Si4709_dev.lock));
- return -1;
- }
- }
-#endif
-#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];
-
-#if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_M0_CTC)
- gpio_set_value(Si4709_dev_sw, GPIO_LEVEL_HIGH);
-#endif
-
- gpio_set_value(GPIO_FM_RST, GPIO_LEVEL_LOW);
- usleep_range(5, 10);
- s3c_gpio_cfgpin(Si4709_dev_int, S3C_GPIO_OUTPUT);
- s3c_gpio_setpull(Si4709_dev_int, S3C_GPIO_PULL_DOWN);
- gpio_set_value(Si4709_dev_int, GPIO_LEVEL_LOW);
- usleep_range(10, 15);
- gpio_set_value(GPIO_FM_RST, GPIO_LEVEL_HIGH);
- usleep_range(5, 10);
- s3c_gpio_cfgpin(Si4709_dev_int, S3C_GPIO_SFN(0xF));
- s3c_gpio_setpull(Si4709_dev_int, S3C_GPIO_PULL_UP);
- usleep_range(10, 15);
-
- cmd[0] = POWER_UP;
- cmd[1] = POWER_UP_IN_GPO2OEN;
- cmd[1] |= POWER_UP_IN_FUNC_FMRX;
- cmd[2] = POWER_UP_IN_OPMODE_RX_ANALOG;
- ret = si47xx_command(3, cmd, 8, rsp);
-
- if (ret < 0) {
- debug("powerup->i2c_write 1 failed");
- Si4709_dev.registers[POWERCFG] = powercfg;
- } else {
- /* Si4709/09 datasheet: Table 7 */
- msleep(110);
- Si4709_dev.state.power_state = RADIO_ON;
- }
- return ret;
-}
-
-static int powerdown(void)
-{
- int ret = 0;
-
- if (!(RADIO_POWERDOWN == Si4709_dev.state.power_state)) {
- cmd[0] = POWER_DOWN;
- ret = si47xx_command(1, cmd, 1, rsp);
- msleep(110);
-
- if (ret < 0)
- debug("powerdown->i2c_write failed");
- else
- Si4709_dev.state.power_state = RADIO_POWERDOWN;
-
- gpio_set_value(GPIO_FM_RST, GPIO_LEVEL_LOW);
- } else
- debug("Device already Powered-OFF\n");
-
-#if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_M0_CTC)
- gpio_set_value(Si4709_dev_sw, GPIO_LEVEL_LOW);
-#endif
-
- return ret;
-}
-
-static int seek(u32 *frequency, int up, int mode)
-{
- int ret = 0;
- u8 get_int;
-
- if (ret < 0) {
- debug("seek i2c_write 1 failed");
- } else {
- Si4709_dev_wait_flag = SEEK_WAITING;
- fmSeekStart(up, mode); /* mode 0 is full scan */
- wait();
- do {
- get_int = getIntStatus();
- } while (!(get_int & STCINT));
-
- if (Si4709_dev_wait_flag == SEEK_CANCEL) {
- fmTuneStatus(1, 0);
- if (ret < 0) {
- debug("seek i2c_write 2 failed");
- }
- if (ret < 0)
- debug("seek i2c_read 1 failed");
- else
- *frequency = Freq;
-
- *frequency = 0;
- }
-
- Si4709_dev_wait_flag = NO_WAIT;
-
- fmTuneStatus(0, 1);
- if (BLTF != 1)
- *frequency = Freq;
-
- else {
- if (Valid)
- *frequency = Freq;
- else
- *frequency = 0;
- }
- }
- return ret;
-}
-
-static int tune_freq(u32 frequency)
-{
- int ret = 0;
-
- u16 channel = Si4709_dev.registers[CHANNEL];
- mutex_lock(&(Si4709_dev.lock));
-
- channel = freq_to_channel(frequency);
- if (ret < 0) {
- debug("tune_freq i2c_write 1 failed");
- Si4709_dev.registers[CHANNEL] = channel;
- } else {
- Si4709_dev_wait_flag = TUNE_WAITING;
- fmTuneFreq(frequency);
- wait();
- Si4709_dev_wait_flag = NO_WAIT;
- debug("Si4709_dev_wait_flag = TUNE_WAITING\n");
-
- if (!(getIntStatus() & STCINT)) {
- printk(KERN_INFO "%s tune is failed!\n", __func__);
- fmTuneStatus(1, 1);
- mutex_unlock(&(Si4709_dev.lock));
- return -1;
- }
-
- fmTuneStatus(0, 1);
-
- debug("Si4709 tune_freq fmTuneStatus %x\n", rsp[0]);
-
- }
- mutex_unlock(&(Si4709_dev.lock));
-
- return ret;
-}
-
-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;
-}
-
-/* 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));
-}
-
-#ifndef RDS_INTERRUPT_ON_ALWAYS
-static void wait_RDS(void)
-{
- wait_event_interruptible_timeout(Si4709_waitq,
- (Si4709_dev_wait_flag == WAIT_OVER),
- Si4709_dev.settings.timeout_RDS);
-}
-#endif
-
-/*-----------------------------------------------------------------------------
- Helper function that sends the GET_INT_STATUS command to the part
-
- Returns:
- The status byte from the part.
------------------------------------------------------------------------------*/
-u8 getIntStatus(void)
-{
- cmd[0] = GET_INT_STATUS;
- si47xx_command(1, cmd, 1, rsp);
-
- debug("Si4709 getIntStatus return %x\n", rsp[0]);
- return rsp[0];
-}
-
-/*-----------------------------------------------------------------------------
- Helper function that sends the FM_TUNE_FREQ command to the part
-
- Inputs:
- frequency in 10kHz steps
------------------------------------------------------------------------------*/
-static void fmTuneFreq(u16 frequency)
-{
- cmd[0] = FM_TUNE_FREQ;
- cmd[1] = 0;
- cmd[2] = (u8)(frequency >> 8);
- cmd[3] = (u8)(frequency & 0x00FF);
- cmd[4] = (u8)0;
- si47xx_command(5, cmd, 1, rsp);
-}
-
-/*-----------------------------------------------------------------------------
- Helper function that sends the FM_TUNE_STATUS command to the part
-
- Inputs:
- cancel: If non-zero the current seek will be cancelled.
- intack: If non-zero the interrupt for STCINT will be cleared.
-
-Outputs: These are global variables and are set by this method
-STC: The seek/tune is complete
-BLTF: The seek reached the band limit or original start frequency
-AFCRL: The AFC is railed if this is non-zero
-Valid: The station is valid if this is non-zero
-Freq: The current frequency
-RSSI: The RSSI level read at tune.
-ASNR: The audio SNR level read at tune.
-AntCap: The current level of the tuning capacitor.
------------------------------------------------------------------------------*/
-
-static void fmTuneStatus(u8 cancel, u8 intack)
-{
- cmd[0] = FM_TUNE_STATUS;
- cmd[1] = 0;
- if (cancel)
- cmd[1] |= FM_TUNE_STATUS_IN_CANCEL;
- if (intack)
- cmd[1] |= FM_TUNE_STATUS_IN_INTACK;
-
- si47xx_command(2, cmd, 8, rsp);
-
- STC = !!(rsp[0] & STCINT);
- BLTF = !!(rsp[1] & FM_TUNE_STATUS_OUT_BTLF);
- AFCRL = !!(rsp[1] & FM_TUNE_STATUS_OUT_AFCRL);
- Valid = !!(rsp[1] & FM_TUNE_STATUS_OUT_VALID);
- Freq = ((u16)rsp[2] << 8) | (u16)rsp[3];
- RSSI = rsp[4];
- ASNR = rsp[5];
- AntCap = rsp[7];
-}
-
-/*-----------------------------------------------------------------------------
- Helper function that sends the FM_RDS_STATUS command to the part
-
- Inputs:
- intack: If non-zero the interrupt for STCINT will be cleared.
- mtfifo: If non-zero the fifo will be cleared.
-
-Outputs:
-Status: Contains bits about the status returned from the part.
-RdsInts: Contains bits about the interrupts that have fired
-related to RDS.
-RdsSync: If non-zero the RDS is currently synced.
-GrpLost: If non-zero some RDS groups were lost.
-RdsFifoUsed: The amount of groups currently remaining
-in the RDS fifo.
-BlockA: Block A group data from the oldest FIFO entry.
-BlockB: Block B group data from the oldest FIFO entry.
-BlockC: Block C group data from the oldest FIFO entry.
-BlockD: Block D group data from the oldest FIFO entry.
-BleA: Block A corrected error information.
-BleB: Block B corrected error information.
-BleC: Block C corrected error information.
-BleD: Block D corrected error information.
------------------------------------------------------------------------------*/
-void fmRdsStatus(u8 intack, u8 mtfifo)
-{
- cmd[0] = FM_RDS_STATUS;
- cmd[1] = 0;
- if (intack)
- cmd[1] |= FM_RDS_STATUS_IN_INTACK;
- if (mtfifo)
- cmd[1] |= FM_RDS_STATUS_IN_MTFIFO;
-
- si47xx_command(2, cmd, 13, rsp);
-
- Status = rsp[0];
- RdsInts = rsp[1];
- RdsSync = !!(rsp[2] & FM_RDS_STATUS_OUT_SYNC);
- GrpLost = !!(rsp[2] & FM_RDS_STATUS_OUT_GRPLOST);
- RdsFifoUsed = rsp[3];
- BlockA = ((u16)rsp[4] << 8) | (u16)rsp[5];
- BlockB = ((u16)rsp[6] << 8) | (u16)rsp[7];
- BlockC = ((u16)rsp[8] << 8) | (u16)rsp[9];
- BlockD = ((u16)rsp[10] << 8) | (u16)rsp[11];
- BleA = (rsp[12] & FM_RDS_STATUS_OUT_BLEA) >>
- FM_RDS_STATUS_OUT_BLEA_SHFT;
- BleB = (rsp[12] & FM_RDS_STATUS_OUT_BLEB) >>
- FM_RDS_STATUS_OUT_BLEB_SHFT;
- BleC = (rsp[12] & FM_RDS_STATUS_OUT_BLEC) >>
- FM_RDS_STATUS_OUT_BLEC_SHFT;
- BleD = (rsp[12] & FM_RDS_STATUS_OUT_BLED) >>
- FM_RDS_STATUS_OUT_BLED_SHFT;
-}
-
-
-/*-----------------------------------------------------------------------------
- Helper function that sends the FM_RSQ_STATUS command to the part
-
- Inputs:
- intack: If non-zero the interrupt for STCINT will be cleared.
-
-Outputs:
-Status: Contains bits about the status returned from the part.
-RsqInts: Contains bits about the interrupts that have fired related to RSQ.
-SMUTE: The soft mute function is currently enabled
-AFCRL: The AFC is railed if this is non-zero
-Valid: The station is valid if this is non-zero
-Pilot: A pilot tone is currently present
-Blend: Percentage of blend for stereo. (100 = full stereo)
-RSSI: The RSSI level read at tune.
-ASNR: The audio SNR level read at tune.
-FreqOff: The frequency offset in kHz of the current station from the tuned
-frequency.
------------------------------------------------------------------------------*/
-static void fmRsqStatus(u8 intack)
-{
- cmd[0] = FM_RSQ_STATUS;
- cmd[1] = 0;
- if (intack)
- cmd[1] |= FM_RSQ_STATUS_IN_INTACK;
-
- si47xx_command(2, cmd, 8, rsp);
-
- Status = rsp[0];
- RsqInts = rsp[1];
- SMUTE = !!(rsp[2] & FM_RSQ_STATUS_OUT_SMUTE);
- AFCRL = !!(rsp[2] & FM_RSQ_STATUS_OUT_AFCRL);
- Valid = !!(rsp[2] & FM_RSQ_STATUS_OUT_VALID);
- Pilot = !!(rsp[3] & FM_RSQ_STATUS_OUT_PILOT);
- Blend = rsp[3] & FM_RSQ_STATUS_OUT_STBLEND;
- RSSI = rsp[4];
- ASNR = rsp[5];
- FreqOff = rsp[7];
-}
-
-
-/*-----------------------------------------------------------------------------
- Helper function that sends the FM_SEEK_START command to the part
-
-Inputs:
-seekUp: If non-zero seek will increment otherwise decrement
-wrap: If non-zero seek will wrap around band limits when hitting the end
-of the band limit.
------------------------------------------------------------------------------*/
-static void fmSeekStart(u8 seekUp, u8 wrap)
-{
- cmd[0] = FM_SEEK_START;
- cmd[1] = 0;
- if (seekUp)
- cmd[1] |= FM_SEEK_START_IN_SEEKUP;
- if (wrap)
- cmd[1] |= FM_SEEK_START_IN_WRAP;
-
- si47xx_command(2, cmd, 1, rsp);
-}
-
-
-/*-----------------------------------------------------------------------------
- Set the passed property number to the passed value.
-
- Inputs:
- propNumber: The number identifying the property to set
- propValue: The value of the property.
------------------------------------------------------------------------------*/
-void si47xx_set_property(u16 propNumber, u16 propValue)
-{
- cmd[0] = SET_PROPERTY;
- cmd[1] = 0;
- cmd[2] = (u8)(propNumber >> 8);
- cmd[3] = (u8)(propNumber & 0x00FF);
- cmd[4] = (u8)(propValue >> 8);
- cmd[5] = (u8)(propValue & 0x00FF);
-
- si47xx_command(6, cmd, 0, NULL);
-}
-
-/*-----------------------------------------------------------------------------
- This command returns the status
------------------------------------------------------------------------------*/
-u8 si47xx_readStatus(void)
-{
- u8 status;
- i2c_read(1, &status);
-
- return status;
-}
-
-
-/*-----------------------------------------------------------------------------
- Command that will wait for CTS before returning
------------------------------------------------------------------------------*/
-void si47xx_waitForCTS(void)
-{
- u16 i = 1000;
- u8 rStatus = 0;
-
- do {
- rStatus = si47xx_readStatus();
- usleep_range(5, 10);
- } while (--i && !(rStatus & CTS));
-}
-
-/*-----------------------------------------------------------------------------
- Sends a command to the part and returns the reply bytes
------------------------------------------------------------------------------*/
-int si47xx_command(u8 cmd_size, u8 *cmd, u8 reply_size, u8 *reply)
-{
- int ret = 0;
- ret = i2c_write(cmd_size, cmd);
- si47xx_waitForCTS();
-
- if (reply_size)
- i2c_read(reply_size, reply);
-
- if (ret < 0)
- printk(KERN_INFO "%s i2c_write failed %d\n", __func__, ret);
-
- return ret;
-}
-
-static int i2c_write(u8 number_bytes, u8 *data_out)
-{
- int ret = 0;
-
- ret = i2c_master_send((struct i2c_client *)(Si4709_dev.client),
- (const char *)data_out, number_bytes);
- if (ret == number_bytes)
- ret = 0;
- else
- ret = -1;
-
- return ret;
-}
-
-static int i2c_read(u8 number_bytes, u8 *data_in)
-{
- int ret = 0;
-
- ret = i2c_master_recv((struct i2c_client *)(Si4709_dev.client), data_in,
- number_bytes);
- if (ret < 0)
- printk(KERN_INFO "%s i2c_read failed %d\n", __func__, ret);
-
- return ret;
-}
diff --git a/drivers/samsung/fm_si4709/Si4705_main.c b/drivers/samsung/fm_si4709/Si4705_main.c
index aaccd5f..0695e17 100644
--- a/drivers/samsung/fm_si4709/Si4705_main.c
+++ b/drivers/samsung/fm_si4709/Si4705_main.c
@@ -329,6 +329,7 @@ static long Si4709_ioctl(struct file *filp, unsigned int ioctl_cmd,
debug("Si4709_IOC_VOLUME_GET called\n");
ret = (long)Si4709_dev_volume_get(&volume);
+
if (ret < 0)
debug("Si4709_IOC_VOLUME_GET failed\n");
else if (copy_to_user
@@ -757,9 +758,14 @@ void debug_ioctls(void)
int __init Si4709_driver_init(void)
{
int ret = 0;
+ unsigned int gpio_fm_rst = GPIO_FM_RST;
debug("Si4709_driver_init called\n");
+#if defined(CONFIG_MACH_T0)
+ if (system_rev >= 3)
+ gpio_fm_rst = GPIO_FM_RST_REV03;
+#endif
/*Initialize the Si4709 dev mutex */
Si4709_dev_mutex_init();
@@ -791,19 +797,19 @@ int __init Si4709_driver_init(void)
debug("Si4709_driver_init request_irq "
"success %d", Si4709_int);
- if (gpio_is_valid(GPIO_FM_RST)) {
- if (gpio_request(GPIO_FM_RST, "GPC1"))
+ if (gpio_is_valid(gpio_fm_rst)) {
+ if (gpio_request(gpio_fm_rst, "FM_RST"))
debug(KERN_ERR "Failed to request "
"FM_RESET!\n\n");
- gpio_direction_output(GPIO_FM_RST, GPIO_LEVEL_LOW);
+ gpio_direction_output(gpio_fm_rst, GPIO_LEVEL_LOW);
}
#if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_M0_CTC)
if (gpio_is_valid(GPIO_FM_MIC_SW)) {
- if (gpio_request(GPIO_FM_MIC_SW, "GPL0"))
+ if (gpio_request(GPIO_FM_MIC_SW, "FM_MIC_SW"))
debug(KERN_ERR "Failed to request "
"FM_MIC_SW!\n\n");
- gpio_direction_output(GPIO_FM_RST, GPIO_LEVEL_LOW);
+ gpio_direction_output(GPIO_FM_MIC_SW, GPIO_LEVEL_LOW);
}
#endif
@@ -812,15 +818,15 @@ int __init Si4709_driver_init(void)
as the FM Radio device gives 5ms low pulse*/
s3c_gpio_setpull(Si4709_int, S3C_GPIO_PULL_UP);
/****Resetting the device****/
- gpio_set_value(GPIO_FM_RST, GPIO_LEVEL_LOW);
+ gpio_set_value(gpio_fm_rst, GPIO_LEVEL_LOW);
s3c_gpio_cfgpin(Si4709_int, S3C_GPIO_OUTPUT);
s3c_gpio_setpull(Si4709_int, S3C_GPIO_PULL_DOWN);
- gpio_set_value(GPIO_FM_RST, GPIO_LEVEL_HIGH);
+ gpio_set_value(gpio_fm_rst, GPIO_LEVEL_HIGH);
usleep_range(10, 15);
s3c_gpio_cfgpin(Si4709_int, S3C_GPIO_SFN(0xF));
s3c_gpio_setpull(Si4709_int, S3C_GPIO_PULL_UP);
- gpio_free(FM_RESET);
+ gpio_free(gpio_fm_rst);
/*Add the i2c driver */
ret = Si4709_i2c_drv_init();
@@ -838,6 +844,8 @@ MISC_IRQ_DREG:
MISC_DREG:
misc_deregister(&Si4709_misc_device);
+ Si4709_dev_mutex_destroy();
+
return ret;
}
diff --git a/drivers/samsung/fm_si4709/Si4709_dev.c b/drivers/samsung/fm_si4709/Si4709_dev.c
index 32ef932..6b483e1 100644
--- a/drivers/samsung/fm_si4709/Si4709_dev.c
+++ b/drivers/samsung/fm_si4709/Si4709_dev.c
@@ -71,7 +71,7 @@ static void wait_RDS(void);
static int powerup(void);
static int powerdown(void);
-static int seek(u32 *, int);
+static int seek(u32 *, int, int);
static int tune_freq(u32);
static void get_cur_chan_freq(u32 *, u16);
@@ -602,6 +602,24 @@ int Si4709_dev_chan_get(u32 *frequency)
return ret;
}
+int Si4709_dev_seek_full(u32 *frequency)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_seek_full called\n");
+
+ if (Si4709_dev.valid == eFALSE) {
+ error("Si4709_dev_seek_full called when DS is invalid");
+ ret = -1;
+ } else {
+ Si4709_dev.state.seek_state = RADIO_SEEK_ON;
+ ret = seek(frequency, 1, 1);
+ Si4709_dev.state.seek_state = RADIO_SEEK_OFF;
+ }
+
+ return ret;
+}
+
int Si4709_dev_seek_up(u32 *frequency)
{
int ret = 0;
@@ -616,7 +634,7 @@ int Si4709_dev_seek_up(u32 *frequency)
} else {
Si4709_dev.state.seek_state = RADIO_SEEK_ON;
- ret = seek(frequency, 1);
+ ret = seek(frequency, 1, 0);
Si4709_dev.state.seek_state = RADIO_SEEK_OFF;
}
@@ -640,7 +658,7 @@ int Si4709_dev_seek_down(u32 *frequency)
} else {
Si4709_dev.state.seek_state = RADIO_SEEK_ON;
- ret = seek(frequency, 0);
+ ret = seek(frequency, 0, 0);
Si4709_dev.state.seek_state = RADIO_SEEK_OFF;
}
@@ -2102,7 +2120,7 @@ static int powerdown(void)
return ret;
}
-static int seek(u32 *frequency, int up)
+static int seek(u32 *frequency, int up, int mode)
{
int ret = 0;
u16 powercfg = Si4709_dev.registers[POWERCFG];
@@ -2114,7 +2132,14 @@ static int seek(u32 *frequency, int up)
else
POWERCFG_BITSET_SEEKUP_LOW(&Si4709_dev.registers[POWERCFG]);
- POWERCFG_BITSET_SKMODE_HIGH(&Si4709_dev.registers[POWERCFG]);
+ /* add mode that configure skmode high(1) is stop freq if it reach end,
+ * low is wrap freq and this value is default value
+ */
+ if (mode)
+ POWERCFG_BITSET_SKMODE_HIGH(&Si4709_dev.registers[POWERCFG]);
+ else
+ POWERCFG_BITSET_SKMODE_LOW(&Si4709_dev.registers[POWERCFG]);
+
POWERCFG_BITSET_SEEK_HIGH(&Si4709_dev.registers[POWERCFG]);
POWERCFG_BITSET_RESERVED(&Si4709_dev.registers[POWERCFG]);
diff --git a/drivers/samsung/fm_si4709/Si4709_dev.h b/drivers/samsung/fm_si4709/Si4709_dev.h
index 8b8371f..7a0ba73 100644
--- a/drivers/samsung/fm_si4709/Si4709_dev.h
+++ b/drivers/samsung/fm_si4709/Si4709_dev.h
@@ -147,6 +147,8 @@ struct Si4709_device_t {
/*will be true is the client ans state fields are correct */
unsigned short valid_client_state;
+
+ u8 vol_idx;
};
extern int Si4709_dev_wait_flag;
@@ -174,6 +176,7 @@ extern int Si4709_dev_init(struct i2c_client *);
extern int Si4709_dev_exit(void);
extern void Si4709_dev_mutex_init(void);
+extern void Si4709_dev_mutex_destroy(void);
extern int Si4709_dev_suspend(void);
extern int Si4709_dev_resume(void);
diff --git a/drivers/samsung/fm_si4709/Si4709_main.c b/drivers/samsung/fm_si4709/Si4709_main.c
index 5531c12..c0fcbfc 100644
--- a/drivers/samsung/fm_si4709/Si4709_main.c
+++ b/drivers/samsung/fm_si4709/Si4709_main.c
@@ -182,6 +182,20 @@ static long Si4709_ioctl(struct file *filp, unsigned int ioctl_cmd,
}
break;
+ case Si4709_IOC_SEEK_FULL:
+ {
+ u32 frequency = 0;
+ debug("Si4709_IOC_SEEK_FULL called\n");
+
+ ret = (long)Si4709_dev_seek_full(&frequency);
+ if (ret < 0)
+ debug("Si4709_IOC_SEEK_FULL failed\n");
+ else if (copy_to_user
+ (argp, (void *)&frequency, sizeof(u32)))
+ ret = -EFAULT;
+ }
+ break;
+
case Si4709_IOC_SEEK_UP:
{
u32 frequency = 0;
diff --git a/drivers/samsung/fm_si47xx/Makefile b/drivers/samsung/fm_si47xx/Makefile
new file mode 100644
index 0000000..33a4e59
--- /dev/null
+++ b/drivers/samsung/fm_si47xx/Makefile
@@ -0,0 +1,7 @@
+ifeq ($(CONFIG_FM_SI4705),y)
+obj-$(CONFIG_FM_SI4705) += si47xx-drv.o
+si47xx-drv-y := Si47xx_i2c_drv.o Si47xx_dev.o
+else
+obj-$(CONFIG_FM_SI4705) += Si4709_driver.o
+Si4709_driver-y := Si47xx_i2c_drv.o Si47xx_dev.o
+endif \ No newline at end of file
diff --git a/drivers/samsung/fm_si47xx/Si47xx_dev.c b/drivers/samsung/fm_si47xx/Si47xx_dev.c
new file mode 100644
index 0000000..bf64915
--- /dev/null
+++ b/drivers/samsung/fm_si47xx/Si47xx_dev.c
@@ -0,0 +1,1791 @@
+/* drivers/samsung/fm_si47xx/Si47xx_dev.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+
+#include <mach/gpio.h>
+#include <plat/gpio-cfg.h>
+
+#include "Si47xx_dev.h"
+#include <linux/i2c/si47xx_common.h>
+
+#include "commanddefs.h"
+#include "propertydefs.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 TUNE_RSSI_THRESHOLD 10
+#define TUNE_SNR_THRESHOLD 4
+#define TUNE_CNT_THRESHOLD 0x00
+
+#define _ENABLE_RDS_
+
+#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 Si47xx_RDS_flag;
+int RDS_Data_Available;
+int RDS_Data_Lost;
+int RDS_Groups_Available_till_now;
+struct workqueue_struct *Si47xx_wq;
+struct work_struct Si47xx_work;
+#endif
+
+/*Si47xx device structure*/
+static struct Si47xx_device_t *Si47xx_dev;
+static struct si47xx_platform_data *pSi47xxdata;
+
+static int si47xx_irq;
+wait_queue_head_t Si47xx_waitq;
+
+/*Wait flag*/
+/*WAITING or WAIT_OVER or NO_WAIT*/
+int Si47xx_dev_wait_flag = NO_WAIT;
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+int Si47xx_RDS_flag = NO_WAIT;
+#endif
+
+static irqreturn_t Si47xx_isr(int irq, void *unused)
+{
+ debug("Si47xx_isr: FM device called IRQ: %d\n", irq);
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+ if ((Si47xx_dev_wait_flag == SEEK_WAITING) ||
+ (Si47xx_dev_wait_flag == TUNE_WAITING)) {
+ debug("Si47xx_isr: FM Seek/Tune Interrupt "
+ "called IRQ %d\n", irq);
+ Si47xx_dev_wait_flag = WAIT_OVER;
+ wake_up_interruptible(&Si47xx_waitq);
+ } else if (Si47xx_RDS_flag == RDS_WAITING) { /* RDS Interrupt */
+ debug_rds("Si47xx_isr: FM RDS Interrupt "
+ "called IRQ %d", irq);
+
+ debug_rds("RDS_Groups_Available_till_now b/w "
+ "Power ON/OFF : %d",
+ RDS_Groups_Available_till_now);
+
+ if (!work_pending(&Si47xx_work))
+ queue_work(Si47xx_wq, &Si47xx_work);
+ }
+#else
+ if ((Si47xx_dev_wait_flag == SEEK_WAITING) ||
+ (Si47xx_dev_wait_flag == TUNE_WAITING) ||
+ (Si47xx_dev_wait_flag == RDS_WAITING)) {
+ Si47xx_dev_wait_flag = WAIT_OVER;
+ wake_up_interruptible(&Si47xx_waitq);
+ }
+#endif
+ return IRQ_HANDLED;
+}
+
+
+/*-----------------------------------------------------------------------------
+ This command returns the status
+-----------------------------------------------------------------------------*/
+static u8 si47xx_readStatus(void)
+{
+ u8 status;
+ int ret = 0;
+ ret = i2c_master_recv((struct i2c_client *)(Si47xx_dev->client),
+ &status, 1);
+
+ if (ret < 0) {
+ dev_err(Si47xx_dev->dev, "%s si47xx_readStatus failed %d\n",
+ __func__, ret);
+
+ return ret;
+ }
+
+ return status;
+}
+
+
+/*-----------------------------------------------------------------------------
+ Command that will wait for CTS before returning
+-----------------------------------------------------------------------------*/
+static void si47xx_waitForCTS(void)
+{
+ u16 i = 1000;
+ u8 rStatus = 0;
+
+ do {
+ rStatus = si47xx_readStatus();
+ usleep_range(5, 10);
+ } while (--i && !(rStatus & CTS));
+}
+
+/*-----------------------------------------------------------------------------
+ Sends a command to the part and returns the reply bytes
+-----------------------------------------------------------------------------*/
+static int si47xx_command(u8 cmd_size, u8 *cmd, u8 reply_size, u8 *reply)
+{
+ int ret = 0;
+ ret = i2c_master_send((struct i2c_client *)(Si47xx_dev->client),
+ cmd, cmd_size);
+ if (ret < 0) {
+ dev_err(Si47xx_dev->dev, "%s si47xx_command failed %d\n",
+ __func__, ret);
+
+ return ret;
+ }
+ si47xx_waitForCTS();
+
+ if (reply_size) {
+ ret = i2c_master_recv((struct i2c_client *)(Si47xx_dev->client),
+ reply, reply_size);
+
+ if (ret < 0)
+ dev_err(Si47xx_dev->dev,
+ "%s si47xx_command failed %d\n", __func__, ret);
+
+ return ret;
+ }
+
+ return ret;
+}
+
+/*-----------------------------------------------------------------------------
+ Set the passed property number to the passed value.
+
+ Inputs:
+ propNumber: The number identifying the property to set
+ propValue: The value of the property.
+-----------------------------------------------------------------------------*/
+static void si47xx_set_property(u16 propNumber, u16 propValue)
+{
+ u8 cmd[8];
+ int ret = 0;
+
+ cmd[0] = SET_PROPERTY;
+ cmd[1] = 0;
+ cmd[2] = (u8)(propNumber >> 8);
+ cmd[3] = (u8)(propNumber & 0x00FF);
+ cmd[4] = (u8)(propValue >> 8);
+ cmd[5] = (u8)(propValue & 0x00FF);
+
+ ret = si47xx_command(6, cmd, 0, NULL);
+
+ if (ret < 0)
+ dev_err(Si47xx_dev->dev,
+ "%s si47xx_set_property failed %d\n", __func__, ret);
+}
+
+static int powerup(void)
+{
+ int ret = 0;
+ u8 cmd[8];
+ u8 rsp[13];
+
+ pSi47xxdata->power(1);
+
+ cmd[0] = POWER_UP;
+ cmd[1] = POWER_UP_IN_GPO2OEN | POWER_UP_IN_FUNC_FMRX;
+ cmd[2] = POWER_UP_IN_OPMODE_RX_ANALOG;
+ ret = si47xx_command(3, cmd, 8, rsp);
+
+ if (ret < 0) {
+ dev_err(Si47xx_dev->dev, "%s failed %d\n", __func__, ret);
+ } else {
+ /* Si4709/09 datasheet: Table 7 */
+ msleep(110);
+ Si47xx_dev->state.power_state = RADIO_ON;
+ }
+ return ret;
+}
+
+static int powerdown(void)
+{
+ int ret = 0;
+ u8 cmd[8];
+ u8 rsp[13];
+
+ if (!(RADIO_POWERDOWN == Si47xx_dev->state.power_state)) {
+ cmd[0] = POWER_DOWN;
+ ret = si47xx_command(1, cmd, 1, rsp);
+
+ if (ret < 0)
+ dev_err(Si47xx_dev->dev, "%s failed %d\n",
+ __func__, ret);
+ else
+ Si47xx_dev->state.power_state = RADIO_POWERDOWN;
+
+ msleep(110);
+ pSi47xxdata->power(0);
+ } else
+ debug("Device already Powered-OFF\n");
+
+ return ret;
+}
+
+/*-----------------------------------------------------------------------------
+ Helper function that sends the GET_INT_STATUS command to the part
+
+ Returns:
+ The status byte from the part.
+-----------------------------------------------------------------------------*/
+static s8 getIntStatus(void)
+{
+ u8 cmd[8];
+ u8 rsp[13];
+ int ret = 0;
+ cmd[0] = GET_INT_STATUS;
+ ret = si47xx_command(1, cmd, 1, rsp);
+
+ if (ret < 0) {
+ dev_err(Si47xx_dev->dev, "%s getIntStatus failed %d\n",
+ __func__, ret);
+ return ret;
+ }
+ return rsp[0];
+}
+
+/*-----------------------------------------------------------------------------
+ Helper function that sends the FM_SEEK_START command to the part
+
+Inputs:
+seekUp: If non-zero seek will increment otherwise decrement
+wrap: If non-zero seek will wrap around band limits when hitting the end
+of the band limit.
+-----------------------------------------------------------------------------*/
+static int fmSeekStart(u8 seekUp, u8 wrap)
+{
+ u8 cmd[8];
+ u8 rsp[13];
+ int ret;
+
+ cmd[0] = FM_SEEK_START;
+ cmd[1] = 0;
+ if (seekUp)
+ cmd[1] |= FM_SEEK_START_IN_SEEKUP;
+ if (wrap)
+ cmd[1] |= FM_SEEK_START_IN_WRAP;
+
+ ret = si47xx_command(2, cmd, 1, rsp);
+ return ret;
+
+}
+
+static u16 freq_to_channel(u32 frequency)
+{
+ u16 channel;
+
+ if (frequency < Si47xx_dev->settings.bottom_of_band)
+ frequency = Si47xx_dev->settings.bottom_of_band;
+
+ channel = (frequency - Si47xx_dev->settings.bottom_of_band)
+ / Si47xx_dev->settings.channel_spacing;
+
+ return channel;
+}
+
+/* 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(Si47xx_waitq,
+ (Si47xx_dev_wait_flag == WAIT_OVER) ||
+ (Si47xx_dev_wait_flag == SEEK_CANCEL));
+}
+
+#ifndef RDS_INTERRUPT_ON_ALWAYS
+static void wait_RDS(void)
+{
+ wait_event_interruptible_timeout(Si47xx_waitq,
+ (Si47xx_dev_wait_flag == WAIT_OVER),
+ Si47xx_dev->settings.timeout_RDS);
+}
+#endif
+
+/*-----------------------------------------------------------------------------
+ Helper function that sends the FM_TUNE_FREQ command to the part
+
+ Inputs:
+ frequency in 10kHz steps
+-----------------------------------------------------------------------------*/
+static int fmTuneFreq(u16 frequency)
+{
+ u8 cmd[8];
+ u8 rsp[13];
+ int ret;
+
+ cmd[0] = FM_TUNE_FREQ;
+ cmd[1] = 0;
+ cmd[2] = (u8)(frequency >> 8);
+ cmd[3] = (u8)(frequency & 0x00FF);
+ cmd[4] = (u8)0;
+ ret = si47xx_command(5, cmd, 1, rsp);
+
+ return ret;
+}
+
+/*-----------------------------------------------------------------------------
+ Helper function that sends the FM_TUNE_STATUS command to the part
+
+ Inputs:
+ cancel: If non-zero the current seek will be cancelled.
+ intack: If non-zero the interrupt for STCINT will be cleared.
+
+Outputs: These are global variables and are set by this method
+STC: The seek/tune is complete
+BLTF: The seek reached the band limit or original start frequency
+AFCRL: The AFC is railed if this is non-zero
+Valid: The station is valid if this is non-zero
+Freq: The current frequency
+RSSI: The RSSI level read at tune.
+ASNR: The audio SNR level read at tune.
+AntCap: The current level of the tuning capacitor.
+-----------------------------------------------------------------------------*/
+
+static int fmTuneStatus(u8 cancel, u8 intack, struct tune_data_t *tune_data)
+{
+ u8 cmd[8];
+ u8 rsp[13];
+ int ret;
+
+ cmd[0] = FM_TUNE_STATUS;
+ cmd[1] = 0;
+ if (cancel)
+ cmd[1] |= FM_TUNE_STATUS_IN_CANCEL;
+ if (intack)
+ cmd[1] |= FM_TUNE_STATUS_IN_INTACK;
+
+ ret = si47xx_command(2, cmd, 8, rsp);
+
+ tune_data->stc = !!(rsp[0] & STCINT);
+ tune_data->bltf = !!(rsp[1] & FM_TUNE_STATUS_OUT_BTLF);
+ tune_data->afcrl = !!(rsp[1] & FM_TUNE_STATUS_OUT_AFCRL);
+ tune_data->valid = !!(rsp[1] & FM_TUNE_STATUS_OUT_VALID);
+ tune_data->freq = ((u16)rsp[2] << 8) | (u16)rsp[3];
+ tune_data->rssi = rsp[4];
+ tune_data->asnr = rsp[5];
+ tune_data->antcap = rsp[7];
+
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ Helper function that sends the FM_RSQ_STATUS command to the part
+
+ Inputs:
+ intack: If non-zero the interrupt for STCINT will be cleared.
+
+ Outputs:
+ Si47xx_status.Status: Contains bits about the status returned from the part.
+ Si47xx_status.RsqInts: Contains bits about the interrupts
+ that have fired related to RSQ.
+ SMUTE: The soft mute function is currently enabled
+ AFCRL: The AFC is railed if this is non-zero
+ Valid: The station is valid if this is non-zero
+ Pilot: A pilot tone is currently present
+ Blend: Percentage of blend for stereo. (100 = full stereo)
+ RSSI: The RSSI level read at tune.
+ ASNR: The audio SNR level read at tune.
+ FreqOff: The frequency offset in kHz of the current station
+ from the tuned frequency.
+-----------------------------------------------------------------------------*/
+static void fmRsqStatus(u8 intack, struct rsq_data_t *rsq_data)
+{
+ u8 cmd[8];
+ u8 rsp[13];
+
+ cmd[0] = FM_RSQ_STATUS;
+ cmd[1] = 0;
+
+ if (intack)
+ cmd[1] |= FM_RSQ_STATUS_IN_INTACK;
+
+ si47xx_command(2, cmd, 8, rsp);
+
+ rsq_data->rsqints = rsp[1];
+ rsq_data->smute = !!(rsp[2] & FM_RSQ_STATUS_OUT_SMUTE);
+ rsq_data->afcrl = !!(rsp[2] & FM_RSQ_STATUS_OUT_AFCRL);
+ rsq_data->valid = !!(rsp[2] & FM_RSQ_STATUS_OUT_VALID);
+ rsq_data->pilot = !!(rsp[3] & FM_RSQ_STATUS_OUT_PILOT);
+ rsq_data->blend = rsp[3] & FM_RSQ_STATUS_OUT_STBLEND;
+ rsq_data->rssi = rsp[4];
+ rsq_data->snr = rsp[5];
+ rsq_data->freqoff = rsp[7];
+}
+
+/*-----------------------------------------------------------------------------
+ Helper function that sends the FM_RDS_STATUS command to the part
+
+ Inputs:
+ intack: If non-zero the interrupt for STCINT will be cleared.
+ mtfifo: If non-zero the fifo will be cleared.
+
+Outputs:
+Status: Contains bits about the status returned from the part.
+RdsInts: Contains bits about the interrupts that have fired
+related to RDS.
+RdsSync: If non-zero the RDS is currently synced.
+GrpLost: If non-zero some RDS groups were lost.
+RdsFifoUsed: The amount of groups currently remaining
+in the RDS fifo.
+BlockA: Block A group data from the oldest FIFO entry.
+BlockB: Block B group data from the oldest FIFO entry.
+BlockC: Block C group data from the oldest FIFO entry.
+BlockD: Block D group data from the oldest FIFO entry.
+BleA: Block A corrected error information.
+BleB: Block B corrected error information.
+BleC: Block C corrected error information.
+BleD: Block D corrected error information.
+-----------------------------------------------------------------------------*/
+static void fmRdsStatus(u8 intack, u8 mtfifo, struct radio_data_t *rds_data,
+ u8 *RdsFifoUsed)
+{
+ u8 cmd[8];
+ u8 rsp[13];
+ int ret = 0;
+
+ cmd[0] = FM_RDS_STATUS;
+ cmd[1] = 0;
+ if (intack)
+ cmd[1] |= FM_RDS_STATUS_IN_INTACK;
+ if (mtfifo)
+ cmd[1] |= FM_RDS_STATUS_IN_MTFIFO;
+
+ ret = si47xx_command(2, cmd, 13, rsp);
+ if (ret < 0) {
+ dev_err(Si47xx_dev->dev, "%s fmRdsStatusfailed %d\n",
+ __func__, ret);
+ return;
+ }
+
+ *RdsFifoUsed = rsp[3];
+ rds_data->rdsa = ((u16)rsp[4] << 8) | (u16)rsp[5];
+ rds_data->rdsb = ((u16)rsp[6] << 8) | (u16)rsp[7];
+ rds_data->rdsc = ((u16)rsp[8] << 8) | (u16)rsp[9];
+ rds_data->rdsd = ((u16)rsp[10] << 8) | (u16)rsp[11];
+ rds_data->blera = (rsp[12] & FM_RDS_STATUS_OUT_BLEA) >>
+ FM_RDS_STATUS_OUT_BLEA_SHFT;
+ rds_data->blerb = (rsp[12] & FM_RDS_STATUS_OUT_BLEB) >>
+ FM_RDS_STATUS_OUT_BLEB_SHFT;
+ rds_data->blerc = (rsp[12] & FM_RDS_STATUS_OUT_BLEC) >>
+ FM_RDS_STATUS_OUT_BLEC_SHFT;
+ rds_data->blerd = (rsp[12] & FM_RDS_STATUS_OUT_BLED) >>
+ FM_RDS_STATUS_OUT_BLED_SHFT;
+}
+
+static int seek(u32 *frequency, int up, int mode)
+{
+ int ret = 0;
+ struct tune_data_t tune_data;
+
+ Si47xx_dev_wait_flag = SEEK_WAITING;
+ ret = fmSeekStart(up, mode); /* mode 0 is full scan */
+ wait();
+
+ if (Si47xx_dev_wait_flag == SEEK_CANCEL) {
+ ret = fmTuneStatus(1, 1, &tune_data);
+
+ *frequency = 0;
+
+ Si47xx_dev_wait_flag = NO_WAIT;
+
+ return ret;
+ }
+
+ Si47xx_dev_wait_flag = NO_WAIT;
+
+ if (!(getIntStatus() & STCINT)) {
+ dev_err(Si47xx_dev->dev, "%s seek is failed!\n", __func__);
+ fmTuneStatus(1, 1, &tune_data);
+ return -1;
+ }
+
+ ret = fmTuneStatus(0, 1, &tune_data);
+ if (tune_data.bltf != 1)
+ *frequency = tune_data.freq;
+
+ else {
+ if (tune_data.valid)
+ *frequency = tune_data.freq;
+ else
+ *frequency = 0;
+ }
+ return ret;
+}
+
+static int tune_freq(u32 frequency)
+{
+ int ret = 0;
+
+ u16 channel = 0;
+ struct tune_data_t tune_data;
+ mutex_lock(&(Si47xx_dev->lock));
+
+ channel = freq_to_channel(frequency);
+
+ Si47xx_dev_wait_flag = TUNE_WAITING;
+ ret = fmTuneFreq(frequency);
+ wait();
+ Si47xx_dev_wait_flag = NO_WAIT;
+ debug("Si47xx_dev_wait_flag = TUNE_WAITING\n");
+
+ if (!(getIntStatus() & STCINT)) {
+ dev_err(Si47xx_dev->dev, "%s tune is failed!\n", __func__);
+ fmTuneStatus(1, 1, &tune_data);
+ mutex_unlock(&(Si47xx_dev->lock));
+ return -1;
+ }
+
+ ret = fmTuneStatus(0, 1, &tune_data);
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+
+int Si47xx_dev_init(struct Si47xx_device_t *si47xx_dev)
+{
+ int ret = 0;
+ Si47xx_dev = si47xx_dev;
+ Si47xx_dev->client = si47xx_dev->client;
+ pSi47xxdata = si47xx_dev->pdata;
+ si47xx_irq = Si47xx_dev->client->irq;
+
+ debug("Si47xx_dev_init called");
+
+ mutex_lock(&Si47xx_dev->lock);
+
+ Si47xx_dev->state.power_state = RADIO_POWERDOWN;
+ Si47xx_dev->state.seek_state = RADIO_SEEK_OFF;
+ Si47xx_dev->valid_client_state = eTRUE;
+ Si47xx_dev->valid = eFALSE;
+
+#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) {
+ dev_err(Si47xx_dev->dev, "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) {
+ dev_err(Si47xx_dev->dev, "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 */
+ Si47xx_wq = create_singlethread_workqueue("Si47xx_wq");
+ if (!Si47xx_wq) {
+ dev_err(Si47xx_dev->dev, "Not sufficient memory for Si47xx_wq, work-queue");
+ ret = -ENOMEM;
+ kfree(RDS_Block_Error_buffer);
+ kfree(RDS_Block_Data_buffer);
+ goto EXIT;
+ }
+
+ /*Initialising work_queue */
+ INIT_WORK(&Si47xx_work, Si47xx_work_func);
+
+ RDS_Data_Available = 0;
+ RDS_Data_Lost = 0;
+ RDS_Groups_Available_till_now = 0;
+EXIT:
+#endif
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ debug("Si47xx_dev_init call over");
+
+ return ret;
+}
+
+int Si47xx_dev_exit(void)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_exit called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+ if (Si47xx_wq)
+ destroy_workqueue(Si47xx_wq);
+
+ kfree(RDS_Block_Error_buffer);
+ kfree(RDS_Block_Data_buffer);
+#endif
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ debug("Si47xx_dev_exit call over");
+
+ return ret;
+}
+
+int Si47xx_dev_powerup(void)
+{
+ int ret = 0;
+ u32 value = 100;
+
+ debug("Si47xx_dev_powerup called");
+
+ if (!(RADIO_ON == Si47xx_dev->state.power_state)) {
+ ret = powerup();
+ if (ret < 0) {
+ dev_err(Si47xx_dev->dev, "%s failed %d\n",
+ __func__, ret);
+ } else if (Si47xx_dev->valid_client_state == eFALSE) {
+ dev_err(Si47xx_dev->dev, "Si47xx_dev_powerup called "
+ "when DS(state, client) is invalid");
+ ret = -1;
+ } else {
+/* initial settings */
+#ifdef _ENABLE_RDS_
+ si47xx_set_property(FM_RDS_CONFIG, 1);
+ si47xx_set_property(GPO_IEN, GPO_IEN_STCIEN_MASK |
+ GPO_IEN_STCREP_MASK);
+ si47xx_set_property(GPO_IEN, GPO_IEN_STCIEN_MASK |
+ GPO_IEN_RDSIEN_MASK | GPO_IEN_STCREP_MASK);
+ si47xx_set_property(FM_RDS_INTERRUPT_SOURCE,
+ FM_RDS_INTERRUPT_SOURCE_RECV_MASK);
+ si47xx_set_property(FM_RDS_CONFIG,
+ FM_RDS_CONFIG_RDSEN_MASK |
+ (3 << FM_RDS_CONFIG_BLETHA_SHFT) |
+ (3 << FM_RDS_CONFIG_BLETHB_SHFT) |
+ (3 << FM_RDS_CONFIG_BLETHC_SHFT) |
+ (3 << FM_RDS_CONFIG_BLETHD_SHFT));
+#endif
+/*VNVS:18-NOV'09 : Setting DE-Time Constant as 50us(Europe,Japan,Australia)*/
+ si47xx_set_property(FM_DEEMPHASIS, FM_DEEMPH_50US);
+ /* SYSCONFIG2_BITSET_SEEKTH( */
+ /* &Si47xx_dev->registers[SYSCONFIG2],2); */
+/*VNVS:18-NOV'09 : modified for detecting more stations of good quality*/
+ si47xx_set_property(FM_SEEK_TUNE_RSSI_THRESHOLD,
+ TUNE_RSSI_THRESHOLD);
+ si47xx_set_property(FM_SEEK_BAND_BOTTOM, 8750);
+ si47xx_set_property(FM_SEEK_BAND_TOP, 10800);
+ Si47xx_dev->settings.band = BAND_87500_108000_kHz;
+ Si47xx_dev->settings.bottom_of_band = FREQ_87500_kHz;
+ si47xx_set_property(FM_SEEK_FREQ_SPACING,
+ CHAN_SPACING_100_kHz);
+ Si47xx_dev->settings.channel_spacing =
+ CHAN_SPACING_100_kHz;
+
+ /* SYSCONFIG3_BITSET_SKSNR( */
+ /* &Si47xx_dev->registers[SYSCONFIG3],3); */
+/*VNVS:18-NOV'09 : modified for detecting more stations of good quality*/
+ si47xx_set_property(FM_SEEK_TUNE_SNR_THRESHOLD,
+ TUNE_SNR_THRESHOLD);
+ Si47xx_dev->settings.timeout_RDS =
+ msecs_to_jiffies(value);
+ Si47xx_dev->settings.curr_snr = TUNE_SNR_THRESHOLD;
+ Si47xx_dev->settings.curr_rssi_th = TUNE_RSSI_THRESHOLD;
+ Si47xx_dev->valid = eTRUE;
+
+ Si47xx_dev_STEREO_SET();
+#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");
+
+ ret = request_irq(si47xx_irq, Si47xx_isr,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "Si47xx", NULL);
+ si47xx_set_property(0xff00, 0);
+
+ /* tune initial frequency to remove tunestatus func err
+ * sometimes occur tunestatus func err when execute tunestatus function
+ * before to complete tune_freq.
+ * so run tune_freq just after to complete booting sequence*/
+ ret = tune_freq(Si47xx_dev->settings.bottom_of_band);
+
+ return ret;
+}
+
+int Si47xx_dev_powerdown(void)
+{
+ int ret = 0;
+
+ msleep(500); /* For avoiding turned off pop noise */
+ debug("Si47xx_dev_powerdown called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ free_irq(si47xx_irq, NULL);
+
+ if (Si47xx_dev->valid == eFALSE) {
+ dev_err(Si47xx_dev->dev, "Si47xx_dev_powerdown called when DS is invalid");
+ ret = -1;
+ } else {
+ ret = powerdown();
+ if (ret < 0)
+ dev_err(Si47xx_dev->dev, "%s failed %d\n",
+ __func__, ret);
+ }
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+int Si47xx_dev_suspend(void)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_suspend called");
+
+#ifndef _ENABLE_RDS_
+ disable_irq(si47xx_irq);
+#endif
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid_client_state == eFALSE) {
+ dev_err(Si47xx_dev->dev, "Si47xx_dev_suspend called "
+ "when DS(state, client) is invalid");
+ ret = -1;
+ }
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ debug("Si47xx_dev_enable call over");
+
+ return ret;
+}
+
+int Si47xx_dev_resume(void)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_resume called");
+
+#ifndef _ENABLE_RDS_
+ enable_irq(si47xx_irq);
+#endif
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid_client_state == eFALSE) {
+ dev_err(Si47xx_dev->dev, "Si47xx_dev_resume called "
+ "when DS(state, client) is invalid");
+ ret = -1;
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+ debug("Si47xx_dev_disable call over");
+
+ return ret;
+}
+
+int Si47xx_dev_band_set(int band)
+{
+ int ret = 0;
+ u16 prev_band = 0;
+ u32 prev_bottom_of_band = 0;
+
+ debug("Si47xx_dev_band_set called");
+
+ prev_band = Si47xx_dev->settings.band;
+ prev_bottom_of_band = Si47xx_dev->settings.bottom_of_band;
+ if (Si47xx_dev->valid == eFALSE) {
+ dev_err(Si47xx_dev->dev, "Si47xx_dev_band_set called when DS is invalid");
+ ret = -1;
+ } else {
+ switch (band) {
+ case BAND_87500_108000_kHz:
+ si47xx_set_property(FM_SEEK_BAND_BOTTOM, 8750);
+ si47xx_set_property(FM_SEEK_BAND_TOP, 10800);
+ Si47xx_dev->settings.band = BAND_87500_108000_kHz;
+ Si47xx_dev->settings.bottom_of_band = FREQ_87500_kHz;
+ break;
+ case BAND_76000_108000_kHz:
+ si47xx_set_property(FM_SEEK_BAND_BOTTOM, 7600);
+ si47xx_set_property(FM_SEEK_BAND_TOP, 10800);
+ Si47xx_dev->settings.band = BAND_76000_108000_kHz;
+ Si47xx_dev->settings.bottom_of_band = FREQ_76000_kHz;
+ break;
+ case BAND_76000_90000_kHz:
+ si47xx_set_property(FM_SEEK_BAND_BOTTOM, 7600);
+ si47xx_set_property(FM_SEEK_BAND_TOP, 9000);
+ Si47xx_dev->settings.band = BAND_76000_90000_kHz;
+ Si47xx_dev->settings.bottom_of_band = FREQ_76000_kHz;
+ break;
+ default:
+ ret = -1;
+ }
+ }
+
+ return ret;
+}
+
+int Si47xx_dev_ch_spacing_set(int ch_spacing)
+{
+ int ret = 0;
+ u16 prev_ch_spacing = 0;
+
+ debug("Si47xx_dev_ch_spacing_set called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+ prev_ch_spacing = Si47xx_dev->settings.channel_spacing;
+ if (Si47xx_dev->valid == eFALSE) {
+ dev_err(Si47xx_dev->dev, "Si47xx_dev_ch_spacing_set called "
+ "when DS is invalid");
+ ret = -1;
+ } else {
+ switch (ch_spacing) {
+ case CHAN_SPACING_200_kHz:
+ si47xx_set_property(FM_SEEK_FREQ_SPACING, 20);
+ Si47xx_dev->settings.channel_spacing =
+ CHAN_SPACING_200_kHz;
+ break;
+
+ case CHAN_SPACING_100_kHz:
+ si47xx_set_property(FM_SEEK_FREQ_SPACING, 10);
+ Si47xx_dev->settings.channel_spacing =
+ CHAN_SPACING_100_kHz;
+ break;
+
+ case CHAN_SPACING_50_kHz:
+ si47xx_set_property(FM_SEEK_FREQ_SPACING, 5);
+ Si47xx_dev->settings.channel_spacing =
+ CHAN_SPACING_50_kHz;
+ break;
+
+ default:
+ ret = -1;
+ }
+
+ if (ret == 0) {
+ if (ret < 0) {
+ dev_err(Si47xx_dev->dev, "Si47xx_dev_ch_spacing_set "
+ "i2c_write 1 failed");
+ Si47xx_dev->settings.channel_spacing =
+ prev_ch_spacing;
+ }
+ }
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+int Si47xx_dev_chan_select(u32 frequency)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_chan_select called");
+
+ if (Si47xx_dev->valid == eFALSE) {
+ debug("Si47xx_dev_chan_select called when DS is invalid");
+ ret = -1;
+ } else {
+ Si47xx_dev->state.seek_state = RADIO_SEEK_ON;
+
+ ret = tune_freq(frequency);
+ debug("Si47xx_dev_chan_select called1");
+ Si47xx_dev->state.seek_state = RADIO_SEEK_OFF;
+ }
+ return ret;
+}
+
+int Si47xx_dev_chan_get(u32 *frequency)
+{
+ int ret = 0;
+ struct tune_data_t tune_data;
+
+ debug("Si47xx_dev_chan_get called\n");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ dev_err(Si47xx_dev->dev, "Si47xx_dev_chan_get called when DS is invalid");
+ ret = -1;
+ } else {
+ if (ret < 0)
+ debug("Si47xx_dev_chan_get i2c_read failed");
+ else {
+ ret = fmTuneStatus(0, 1, &tune_data);
+ *frequency = tune_data.freq;
+ }
+ }
+ mutex_unlock(&(Si47xx_dev->lock));
+ return ret;
+}
+
+int Si47xx_dev_seek_full(u32 *frequency)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_seek_full called\n");
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ dev_err(Si47xx_dev->dev, "Si47xx_dev_seek_full called when DS is invalid");
+ ret = -1;
+ } else {
+ Si47xx_dev->state.seek_state = RADIO_SEEK_ON;
+ ret = seek(frequency, 1, 0);
+ Si47xx_dev->state.seek_state = RADIO_SEEK_OFF;
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+int Si47xx_dev_seek_up(u32 *frequency)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_seek_up called\n");
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ dev_err(Si47xx_dev->dev, "Si47xx_dev_seek_up called when DS is invalid");
+ ret = -1;
+ } else {
+ Si47xx_dev->state.seek_state = RADIO_SEEK_ON;
+ ret = seek(frequency, 1, 1);
+ Si47xx_dev->state.seek_state = RADIO_SEEK_OFF;
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+int Si47xx_dev_seek_down(u32 *frequency)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_seek_down called\n");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ debug("Si47xx_dev_seek_down called when DS is invalid");
+ ret = -1;
+ } else {
+ Si47xx_dev->state.seek_state = RADIO_SEEK_ON;
+
+ ret = seek(frequency, 0, 1);
+
+ Si47xx_dev->state.seek_state = RADIO_SEEK_OFF;
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+int Si47xx_dev_RSSI_seek_th_set(u8 seek_th)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_RSSI_seek_th_set called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ debug("Si47xx_dev_RSSI_seek_th_set called "
+ "when DS is invalid");
+ ret = -1;
+ } else {
+ si47xx_set_property(FM_SEEK_TUNE_RSSI_THRESHOLD, seek_th);
+ Si47xx_dev->settings.curr_rssi_th = seek_th;
+ if (ret < 0)
+ debug("Si47xx_dev_RSSI_seek_th_set i2c_write 1 failed");
+ }
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+int Si47xx_dev_seek_SNR_th_set(u8 seek_SNR)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_seek_SNR_th_set called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ dev_err(Si47xx_dev->dev, "Si47xx_dev_seek_SNR_th_set called "
+ "when DS is invalid");
+ ret = -1;
+ } else {
+ si47xx_set_property(FM_SEEK_TUNE_SNR_THRESHOLD, seek_SNR);
+ Si47xx_dev->settings.curr_snr = seek_SNR;
+
+ if (ret < 0)
+ debug("Si47xx_dev_seek_SNR_th_set i2c_write 1 failed");
+ }
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+/*ToDo Don't use anymore*/
+int Si47xx_dev_seek_FM_ID_th_set(u8 seek_FM_ID_th)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_seek_FM_ID_th_set called");
+
+ return ret;
+}
+
+int Si47xx_dev_cur_RSSI_get(struct rssi_snr_t *cur_RSSI)
+{
+ int ret = 0;
+
+ struct rsq_data_t rsq_data;
+ debug("Si47xx_dev_cur_RSSI_get called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ dev_err(Si47xx_dev->dev, "Si47xx_dev_cur_RSSI_get called when DS is invalid");
+ ret = -1;
+ } else {
+ fmRsqStatus(0, &rsq_data);
+ cur_RSSI->curr_rssi = rsq_data.rssi;
+ cur_RSSI->curr_rssi_th =
+ Si47xx_dev->settings.curr_rssi_th;
+ cur_RSSI->curr_snr = rsq_data.snr;
+
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+/*ToDo Don't use anymore*/
+int Si47xx_dev_device_id(struct device_id *dev_id)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_device_id called");
+
+ return ret;
+}
+
+/*ToDo Don't use anymore*/
+int Si47xx_dev_chip_id(struct chip_id *chp_id)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_chip_id called");
+
+ return ret;
+}
+
+int Si47xx_dev_sys_config2(struct sys_config2 *sys_conf2)
+{
+ int ret = 0;
+
+ debug("Si4709_sys_config2 called\n");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ dev_err(Si47xx_dev->dev, "Si4709_sys_config2 called when DS is invalid");
+ ret = -1;
+ } else {
+ sys_conf2->rssi_th = Si47xx_dev->settings.curr_rssi_th;
+ sys_conf2->fm_band = Si47xx_dev->settings.band;
+ sys_conf2->fm_chan_spac =
+ Si47xx_dev->settings.channel_spacing;
+ sys_conf2->fm_vol = 0;
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+int Si47xx_dev_sys_config3(struct sys_config3 *sys_conf3)
+{
+ int ret = 0;
+
+ debug("Si4709_sys_config3 called\n");
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ dev_err(Si47xx_dev->dev, "Si4709_sys_config3 called when DS is invalid");
+ ret = -1;
+ } else {
+ sys_conf3->smmute = 0;
+ sys_conf3->smutea = 0;
+ sys_conf3->volext = 0;
+ sys_conf3->sksnr = Si47xx_dev->settings.curr_snr;
+ sys_conf3->skcnt = 0;
+ }
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+int Si47xx_dev_status_rssi(struct status_rssi *status)
+{
+ int ret = 0;
+ struct rsq_data_t rsq_data;
+
+ debug("Si47xx_dev_status_rssi called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ debug("Si47xx_dev_status_rssi called when DS is invalid");
+ mutex_unlock(&(Si47xx_dev->lock));
+ return -1;
+ }
+ fmRsqStatus(0, &rsq_data);
+
+ pr_debug("%s: Si47xx_dev_status_rssi %d\n",
+ __func__, rsq_data.rssi);
+
+ Si47xx_dev->settings.curr_rssi = rsq_data.rssi;
+ status->rssi = rsq_data.rssi;
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+int Si47xx_dev_sys_config2_set(struct sys_config2 *sys_conf2)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_sys_config2_set called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ dev_err(Si47xx_dev->dev, "Si47xx_dev_sys_config2_set called when DS is invalid");
+ ret = -1;
+ } else {
+ si47xx_set_property(FM_SEEK_TUNE_RSSI_THRESHOLD,
+ sys_conf2->rssi_th);
+ Si47xx_dev_band_set(sys_conf2->fm_band);
+ si47xx_set_property(FM_SEEK_FREQ_SPACING,
+ sys_conf2->fm_chan_spac);
+ Si47xx_dev->settings.curr_rssi_th = sys_conf2->rssi_th;
+ Si47xx_dev->settings.band = sys_conf2->fm_band;
+ Si47xx_dev->settings.channel_spacing = sys_conf2->fm_chan_spac;
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+int Si47xx_dev_sys_config3_set(struct sys_config3 *sys_conf3)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_sys_config3_set called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ dev_err(Si47xx_dev->dev, "Si47xx_dev_sys_config3_set called "
+ "when DS is invalid");
+ ret = -1;
+ } else {
+ si47xx_set_property(FM_SEEK_TUNE_SNR_THRESHOLD,
+ sys_conf3->sksnr);
+ Si47xx_dev->settings.curr_snr = sys_conf3->sksnr;
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+/* VNVS:END */
+
+/* VNVS:START 18-NOV'09 */
+/* Reading AFCRL Bit */
+int Si47xx_dev_AFCRL_get(u8 *afc)
+{
+ int ret = 0;
+ struct rsq_data_t rsq_data;
+
+ debug("Si47xx_dev_AFCRL_get called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ dev_err(Si47xx_dev->dev, "Si47xx_dev_AFCRL_get called when DS is invalid");
+ ret = -1;
+ } else {
+ fmRsqStatus(0, &rsq_data);
+ *afc = rsq_data.afcrl;
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+/* Setting DE
+ emphasis time constant 50us(Europe,Japan,Australia) or 75us(USA)
+ */
+int Si47xx_dev_DE_set(u8 de_tc)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_DE_set called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ dev_err(Si47xx_dev->dev, "Si47xx_dev_DE_set called when DS is invalid");
+ ret = -1;
+ } else {
+ switch (de_tc) {
+ case DE_TIME_CONSTANT_50:
+ si47xx_set_property(FM_DEEMPHASIS, FM_DEEMPH_50US);
+ break;
+
+ case DE_TIME_CONSTANT_75:
+ si47xx_set_property(FM_DEEMPHASIS, FM_DEEMPH_75US);
+ break;
+
+ default:
+ ret = -1;
+ }
+
+ if (0 == ret) {
+ if (ret < 0)
+ dev_err(Si47xx_dev->dev, "%s failed %d\n",
+ __func__, ret);
+ }
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+/*Resetting the RDS Data Buffer*/
+int Si47xx_dev_reset_rds_data()
+{
+ int ret = 0;
+
+ debug_rds("Si47xx_dev_reset_rds_data called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ dev_err(Si47xx_dev->dev, "Si47xx_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(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+int Si47xx_dev_volume_set(u8 volume)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_volume_set called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ dev_err(Si47xx_dev->dev, "Si47xx_dev_volume_set called when DS is invalid");
+ ret = -1;
+ } else {
+ si47xx_set_property(RX_VOLUME, pSi47xxdata->rx_vol[volume] &
+ RX_VOLUME_MASK);
+ Si47xx_dev->vol_idx = volume;
+
+ if (ret < 0)
+ dev_err(Si47xx_dev->dev, "%s failed %d\n",
+ __func__, ret);
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+int Si47xx_dev_volume_get(u8 *volume)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_volume_get called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ debug("Si4709_dev_volume_get called when DS is invalid");
+ ret = -1;
+ } else
+ *volume = Si47xx_dev->vol_idx;
+
+ mutex_unlock(&(Si47xx_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 Si47xx_dev_DSMUTE_ON(void)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_DSMUTE_ON called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ debug("Si47xx_dev_DSMUTE_ON called when DS is invalid");
+ ret = -1;
+ } else {
+ si47xx_set_property(FM_SOFT_MUTE_RATE, 64);
+ si47xx_set_property(FM_SOFT_MUTE_MAX_ATTENUATION, 0);
+ si47xx_set_property(FM_SOFT_MUTE_SNR_THRESHOLD, 4);
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+int Si47xx_dev_DSMUTE_OFF(void)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_DSMUTE_OFF called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ debug("Si47xx_dev_DSMUTE_OFF called when DS is invalid");
+ ret = -1;
+ } else {
+ si47xx_set_property(FM_SOFT_MUTE_RATE, 64);
+ si47xx_set_property(FM_SOFT_MUTE_MAX_ATTENUATION, 16);
+ si47xx_set_property(FM_SOFT_MUTE_SNR_THRESHOLD, 4);
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+/*VNVS:END*/
+
+int Si47xx_dev_MUTE_ON(void)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_MUTE_ON called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ debug("Si47xx_dev_MUTE_ON called when DS is invalid");
+ ret = -1;
+ } else {
+ si47xx_set_property(RX_HARD_MUTE,
+ RX_HARD_MUTE_RMUTE_MASK |
+ RX_HARD_MUTE_LMUTE_MASK);
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+int Si47xx_dev_MUTE_OFF(void)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_MUTE_OFF called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ debug("Si47xx_dev_MUTE_OFF called when DS is invalid");
+ ret = -1;
+ } else {
+ si47xx_set_property(RX_HARD_MUTE, 0);
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+int Si47xx_dev_MONO_SET(void)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_MONO_SET called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ debug("Si47xx_dev_MONO_SET called when DS is invalid");
+ ret = -1;
+ } else {
+ si47xx_set_property(FM_BLEND_MONO_THRESHOLD, 127);
+ si47xx_set_property(FM_BLEND_STEREO_THRESHOLD, 127);
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+int Si47xx_dev_STEREO_SET(void)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_STEREO_SET called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ debug("Si47xx_dev_STEREO_SET called when DS is invalid");
+ ret = -1;
+ } else {
+ si47xx_set_property(FM_BLEND_MONO_THRESHOLD, 30);
+ si47xx_set_property(FM_BLEND_STEREO_THRESHOLD, 49);
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+int Si47xx_dev_RDS_ENABLE(void)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_RDS_ENABLE called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+ if (Si47xx_dev->valid == eFALSE) {
+ debug("Si47xx_dev_RDS_ENABLE called when DS is invalid");
+ ret = -1;
+ } else {
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+ si47xx_set_property(GPO_IEN, GPO_IEN_STCIEN_MASK |
+ GPO_IEN_STCREP_MASK | GPO_IEN_RDSIEN_MASK |
+ GPO_IEN_RDSREP_MASK);
+#endif
+ si47xx_set_property(FM_RDS_INTERRUPT_SOURCE,
+ FM_RDS_INTERRUPT_SOURCE_RECV_MASK);
+ si47xx_set_property(FM_RDS_CONFIG, FM_RDS_CONFIG_RDSEN_MASK |
+ (3 << FM_RDS_CONFIG_BLETHA_SHFT) |
+ (3 << FM_RDS_CONFIG_BLETHB_SHFT) |
+ (3 << FM_RDS_CONFIG_BLETHC_SHFT) |
+ (3 << FM_RDS_CONFIG_BLETHD_SHFT));
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+ Si47xx_RDS_flag = RDS_WAITING;
+#endif
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+int Si47xx_dev_RDS_DISABLE(void)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_RDS_DISABLE called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+ if (Si47xx_dev->valid == eFALSE) {
+ debug("Si47xx_dev_RDS_DISABLE called when DS is invalid");
+ ret = -1;
+ } else {
+ si47xx_set_property(FM_RDS_CONFIG, 0);
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+ Si47xx_RDS_flag = NO_WAIT;
+#endif
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+int Si47xx_dev_rstate_get(struct dev_state_t *dev_state)
+{
+ int ret = 0;
+
+ debug("Si47xx_dev_rstate_get called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ debug("Si47xx_dev_rstate_get called when DS is invalid");
+ ret = -1;
+ } else {
+ dev_state->power_state = Si47xx_dev->state.power_state;
+ dev_state->seek_state = Si47xx_dev->state.seek_state;
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+/* VNVS:START 7-JUNE'10 Function call for work-queue "Si47xx_wq" */
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+void Si47xx_work_func(struct work_struct *work)
+{
+ struct radio_data_t rds_data;
+ int i = 0;
+ u8 RdsFifoUsed;
+#ifdef RDS_TESTING
+ u8 group_type;
+#endif
+ debug_rds("%s", __func__);
+mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ dev_err(Si47xx_dev->dev, "Si47xx_dev_RDS_data_get called when DS is invalid");
+ return;
+ }
+
+ if (RDS_Data_Lost > 1)
+ debug_rds("No_of_RDS_groups_Lost till now : %d",
+ RDS_Data_Lost);
+ fmRdsStatus(1, 0, &rds_data, &RdsFifoUsed);
+ /* RDSR bit and RDS Block data, so reading the RDS registers */
+ do {
+ /* Writing into RDS_Block_Data_buffer */
+ i = 0;
+ RDS_Block_Data_buffer[i++ + 4 * RDS_Buffer_Index_write] =
+ rds_data.rdsa;
+ RDS_Block_Data_buffer[i++ + 4 * RDS_Buffer_Index_write] =
+ rds_data.rdsb;
+ RDS_Block_Data_buffer[i++ + 4 * RDS_Buffer_Index_write] =
+ rds_data.rdsc;
+ RDS_Block_Data_buffer[i++ + 4 * RDS_Buffer_Index_write] =
+ rds_data.rdsd;
+
+ /*Writing into RDS_Block_Error_buffer */
+ i = 0;
+
+ RDS_Block_Error_buffer[i++ + 4 * RDS_Buffer_Index_write] =
+ rds_data.blera;
+ RDS_Block_Error_buffer[i++ + 4 * RDS_Buffer_Index_write] =
+ rds_data.blerb;
+ RDS_Block_Error_buffer[i++ + 4 * RDS_Buffer_Index_write] =
+ rds_data.blerc;
+ RDS_Block_Error_buffer[i++ + 4 * RDS_Buffer_Index_write] =
+ rds_data.blerd;
+ fmRdsStatus(1, 0, &rds_data, &RdsFifoUsed);
+ } while (RdsFifoUsed != 0);
+
+#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(&(Si47xx_dev->lock));
+}
+#endif
+/*VNVS:END*/
+
+int Si47xx_dev_RDS_data_get(struct radio_data_t *data)
+{
+ int i, ret = 0;
+ struct tune_data_t tune_data;
+ struct rsq_data_t rsq_data;
+
+ debug_rds("Si47xx_dev_RDS_data_get called");
+
+ mutex_lock(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ dev_err(Si47xx_dev->dev, "Si47xx_dev_RDS_data_get called when DS is invalid");
+ mutex_unlock(&(Si47xx_dev->lock));
+ return -1;
+ }
+#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");
+ ret = fmTuneStatus(0, 1, &tune_data);
+ data->curr_channel = tune_data.freq;
+ fmRsqStatus(0, &rsq_data);
+ data->curr_rssi = rsq_data.rssi;
+ debug_rds("curr_channel: %u, curr_rssi:%u",
+ data->curr_channel,
+ (u32) data->curr_rssi);
+ mutex_unlock(&(Si47xx_dev->lock));
+ return -1;
+ }
+
+ ret = fmTuneStatus(0, 1, &tune_data);
+ data->curr_channel = tune_data.freq;
+ fmRsqStatus(0, &rsq_data);
+ data->curr_rssi = rsq_data.rssi;
+ 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);
+#endif
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
+
+int Si47xx_dev_RDS_timeout_set(u32 time_out)
+{
+ int ret = 0;
+ u32 jiffy_count = 0;
+
+ debug("Si47xx_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(&(Si47xx_dev->lock));
+
+ if (Si47xx_dev->valid == eFALSE) {
+ debug("Si47xx_dev_RDS_timeout_set called when DS is invalid");
+ ret = -1;
+ } else {
+ Si47xx_dev->settings.timeout_RDS = jiffy_count;
+ }
+
+ mutex_unlock(&(Si47xx_dev->lock));
+
+ return ret;
+}
diff --git a/drivers/samsung/fm_si47xx/Si47xx_dev.h b/drivers/samsung/fm_si47xx/Si47xx_dev.h
new file mode 100644
index 0000000..5d32304
--- /dev/null
+++ b/drivers/samsung/fm_si47xx/Si47xx_dev.h
@@ -0,0 +1,246 @@
+/*
+ * Si47xx_dev.h -- Si47xx FM Radio driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _Si47xx_dev_H
+#define _Si47xx_dev_H
+
+#include <linux/i2c.h>
+
+#include <linux/i2c/si47xx_common.h>
+
+#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*/
+struct dev_state_t {
+ int power_state;
+ int seek_state;
+};
+
+struct rssi_snr_t {
+ u8 curr_rssi;
+ u8 curr_rssi_th;
+ u8 curr_snr;
+};
+
+struct device_id {
+ u8 part_number;
+ u16 manufact_number;
+};
+
+struct chip_id {
+ u8 chip_version;
+ u8 device;
+ u8 firmware_version;
+};
+
+struct sys_config2 {
+ u16 rssi_th;
+ u8 fm_band;
+ u8 fm_chan_spac;
+ u8 fm_vol;
+};
+
+struct sys_config3 {
+ u8 smmute;
+ u8 smutea;
+ u8 volext;
+ u8 sksnr;
+ u8 skcnt;
+};
+
+struct status_rssi {
+ u8 rdsr;
+ u8 stc;
+ u8 sfbl;
+ u8 afcrl;
+ u8 rdss;
+ u8 blera;
+ u8 st;
+ u16 rssi;
+};
+
+struct radio_data_t {
+ u16 rdsa;
+ u16 rdsb;
+ u16 rdsc;
+ u16 rdsd;
+ u8 curr_rssi;
+ u32 curr_channel;
+ u8 blera;
+ u8 blerb;
+ u8 blerc;
+ u8 blerd;
+};
+
+struct channel_into_t {
+ u32 frequency;
+ u8 rsssi_val;
+};
+
+struct tune_data_t {
+ u8 stc;
+ u8 bltf;
+ u8 afcrl;
+ u8 valid;
+ u16 freq;
+ u8 rssi;
+ u8 asnr;
+ u16 antcap;
+};
+
+struct rsq_data_t {
+ u8 rsqints;
+ u8 smute;
+ u8 afcrl;
+ u8 valid;
+ u8 pilot;
+ u8 blend;
+ u8 rssi;
+ u8 snr;
+ u8 mult;
+ u8 freqoff;
+};
+
+struct dev_settings_t {
+ 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;
+ u8 curr_rssi;
+};
+
+struct Si47xx_device_t {
+ /*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 si47xx_platform_data *pdata;
+ struct i2c_client *client;
+ struct device *dev;
+ struct dev_state_t state;
+ struct dev_settings_t settings;
+ struct channel_into_t rssi_freq[50];
+
+ /* 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;
+ u8 vol_idx;
+};
+
+extern int Si47xx_dev_wait_flag;
+extern wait_queue_head_t Si4709_waitq;
+
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+extern int Si47xx_RDS_flag;
+extern int RDS_Data_Available;
+extern int RDS_Data_Lost;
+extern int RDS_Groups_Available_till_now;
+extern struct workqueue_struct *Si47xx_wq;
+extern struct work_struct Si47xx_work;
+#endif
+
+/* Function prototypes */
+
+/*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
+*/
+/**********************************************/
+
+extern int Si47xx_dev_init(struct Si47xx_device_t *);
+extern int Si47xx_dev_exit(void);
+
+extern int Si47xx_dev_suspend(void);
+extern int Si47xx_dev_resume(void);
+
+extern int Si47xx_dev_powerup(void);
+extern int Si47xx_dev_powerdown(void);
+
+extern int Si47xx_dev_band_set(int);
+extern int Si47xx_dev_ch_spacing_set(int);
+
+extern int Si47xx_dev_chan_select(u32);
+extern int Si47xx_dev_chan_get(u32 *);
+
+extern int Si47xx_dev_seek_full(u32 *);
+extern int Si47xx_dev_seek_up(u32 *);
+extern int Si47xx_dev_seek_down(u32 *);
+extern int Si47xx_dev_seek_auto(u32 *);
+
+extern int Si47xx_dev_RSSI_seek_th_set(u8);
+extern int Si47xx_dev_seek_SNR_th_set(u8);
+extern int Si47xx_dev_seek_FM_ID_th_set(u8);
+extern int Si47xx_dev_cur_RSSI_get(struct rssi_snr_t *);
+extern int Si47xx_dev_volume_set(u8);
+extern int Si47xx_dev_volume_get(u8 *);
+extern int Si47xx_dev_DSMUTE_ON(void);
+extern int Si47xx_dev_DSMUTE_OFF(void);
+extern int Si47xx_dev_MUTE_ON(void);
+extern int Si47xx_dev_MUTE_OFF(void);
+extern int Si47xx_dev_MONO_SET(void);
+extern int Si47xx_dev_STEREO_SET(void);
+extern int Si47xx_dev_rstate_get(struct dev_state_t *);
+extern int Si47xx_dev_RDS_data_get(struct radio_data_t *);
+extern int Si47xx_dev_RDS_ENABLE(void);
+extern int Si47xx_dev_RDS_DISABLE(void);
+extern int Si47xx_dev_RDS_timeout_set(u32);
+extern int Si47xx_dev_device_id(struct device_id *);
+extern int Si47xx_dev_chip_id(struct chip_id *);
+extern int Si47xx_dev_sys_config2(struct sys_config2 *);
+extern int Si47xx_dev_sys_config3(struct sys_config3 *);
+extern int Si47xx_dev_AFCRL_get(u8 *);
+extern int Si47xx_dev_DE_set(u8);
+extern int Si47xx_dev_status_rssi(struct status_rssi *status);
+extern int Si47xx_dev_sys_config2_set(struct sys_config2 *sys_conf2);
+extern int Si47xx_dev_sys_config3_set(struct sys_config3 *sys_conf3);
+extern int Si47xx_dev_reset_rds_data(void);
+
+/***********************************************/
+
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+extern void Si47xx_work_func(struct work_struct *);
+#endif
+#endif
+
+
diff --git a/drivers/samsung/fm_si47xx/Si47xx_i2c_drv.c b/drivers/samsung/fm_si47xx/Si47xx_i2c_drv.c
new file mode 100644
index 0000000..fa030bf
--- /dev/null
+++ b/drivers/samsung/fm_si47xx/Si47xx_i2c_drv.c
@@ -0,0 +1,768 @@
+/* drivers/samsung/fm_si47xx/Si47xx_i2c_drv.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#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 <linux/uaccess.h>
+#include <linux/irq.h>
+#include <asm/irq.h>
+#include <linux/io.h>
+#include <linux/wait.h>
+#include <linux/stat.h>
+#include <linux/ioctl.h>
+#include <linux/delay.h>
+
+#include <plat/gpio-cfg.h>
+#include <mach/gpio.h>
+
+#include "Si47xx_dev.h"
+#include "Si47xx_ioctl.h"
+#include <linux/i2c/si47xx_common.h>
+
+
+/*******************************************************/
+
+/*static functions*/
+
+/*file operatons*/
+static int Si47xx_open(struct inode *, struct file *);
+static int Si47xx_release(struct inode *, struct file *);
+static long Si47xx_ioctl(struct file *, unsigned int, unsigned long);
+static int Si47xx_suspend(struct i2c_client *, pm_message_t mesg);
+static int Si47xx_resume(struct i2c_client *);
+
+/*I2C Setting*/
+
+static struct i2c_driver Si47xx_i2c_driver;
+static const struct i2c_device_id Si47xx_id[] = {
+ {"Si47xx", 0},
+ {}
+};
+
+/* static void __iomem *gpio_mask_mem; */
+/**********************************************************/
+
+static const struct file_operations Si47xx_fops = {
+ .owner = THIS_MODULE,
+ .open = Si47xx_open,
+ .unlocked_ioctl = Si47xx_ioctl,
+ .release = Si47xx_release,
+};
+
+static struct miscdevice Si47xx_misc_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "fmradio",
+ .fops = &Si47xx_fops,
+};
+
+/***************************************************************/
+
+static int Si47xx_open(struct inode *inode, struct file *filp)
+{
+ debug("Si47xx_open called\n");
+
+ return nonseekable_open(inode, filp);
+}
+
+static int Si47xx_release(struct inode *inode, struct file *filp)
+{
+ debug("Si47xx_release called\n\n");
+
+ return 0;
+}
+
+static long Si47xx_ioctl(struct file *filp, unsigned int ioctl_cmd,
+ unsigned long arg)
+{
+ long ret = 0;
+ void __user *argp = (void __user *)arg;
+
+ debug("Si47xx ioctl 0x%x", ioctl_cmd);
+
+ if (_IOC_TYPE(ioctl_cmd) != Si47xx_IOC_MAGIC) {
+ debug("Inappropriate ioctl 1 0x%x", ioctl_cmd);
+ return -ENOTTY;
+ }
+
+ if (_IOC_NR(ioctl_cmd) > Si47xx_IOC_NR_MAX) {
+ debug("Inappropriate ioctl 2 0x%x", ioctl_cmd);
+ return -ENOTTY;
+ }
+
+ switch (ioctl_cmd) {
+ case Si47xx_IOC_POWERUP:
+ debug("Si47xx_IOC_POWERUP called\n\n");
+
+ ret = (long)Si47xx_dev_powerup();
+ if (ret < 0)
+ debug("Si47xx_IOC_POWERUP failed\n");
+ break;
+
+ case Si47xx_IOC_POWERDOWN:
+ debug("Si47xx_IOC_POWERDOWN called\n");
+
+ ret = (long)Si47xx_dev_powerdown();
+ if (ret < 0)
+ debug("Si47xx_IOC_POWERDOWN failed\n");
+ break;
+
+ case Si47xx_IOC_BAND_SET:
+ {
+ int band;
+ debug("Si47xx_IOC_BAND_SET called\n\n");
+
+ if (copy_from_user((void *)&band, argp, sizeof(int)))
+ ret = -EFAULT;
+ else {
+ ret = (long)Si47xx_dev_band_set(band);
+ if (ret < 0)
+ debug("Si47xx_IOC_BAND_SET failed\n");
+ }
+ }
+ break;
+
+ case Si47xx_IOC_CHAN_SPACING_SET:
+ {
+ int ch_spacing;
+ debug("Si47xx_IOC_CHAN_SPACING_SET called\n");
+
+ if (copy_from_user
+ ((void *)&ch_spacing, argp, sizeof(int)))
+ ret = -EFAULT;
+ else {
+ ret = (long)Si47xx_dev_ch_spacing_set(ch_spacing);
+ if (ret < 0)
+ debug("Si47xx_IOC_CHAN_SPACING_SET "
+ "failed\n");
+ }
+ }
+ break;
+
+ case Si47xx_IOC_CHAN_SELECT:
+ {
+ u32 frequency;
+ debug("Si47xx_IOC_CHAN_SELECT called\n");
+
+ if (copy_from_user
+ ((void *)&frequency, argp, sizeof(u32)))
+ ret = -EFAULT;
+ else {
+ ret = (long)Si47xx_dev_chan_select(frequency);
+ if (ret < 0)
+ debug("Si47xx_IOC_CHAN_SELECT "
+ "failed\n");
+ }
+ }
+ break;
+
+ case Si47xx_IOC_CHAN_GET:
+ {
+ u32 frequency = 0;
+ debug("Si47xx_IOC_CHAN_GET called\n");
+
+ ret = (long)Si47xx_dev_chan_get(&frequency);
+ if (ret < 0)
+ debug("Si47xx_IOC_CHAN_GET failed\n");
+ else if (copy_to_user
+ (argp, (void *)&frequency, sizeof(u32)))
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si47xx_IOC_SEEK_FULL:
+ {
+ u32 frequency = 0;
+ debug("Si47xx_IOC_SEEK_FULL called\n");
+
+ ret = (long)Si47xx_dev_seek_full(&frequency);
+ if (ret < 0)
+ debug("Si47xx_IOC_SEEK_FULL failed\n");
+ else if (copy_to_user
+ (argp, (void *)&frequency, sizeof(u32)))
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si47xx_IOC_SEEK_UP:
+ {
+ u32 frequency = 0;
+ debug("Si47xx_IOC_SEEK_UP called\n");
+
+ ret = (long)Si47xx_dev_seek_up(&frequency);
+ if (ret < 0)
+ debug("Si47xx_IOC_SEEK_UP failed\n");
+ else if (copy_to_user
+ (argp, (void *)&frequency, sizeof(u32)))
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si47xx_IOC_SEEK_DOWN:
+ {
+ u32 frequency = 0;
+ debug("Si47xx_IOC_SEEK_DOWN called\n");
+
+ ret = (long)Si47xx_dev_seek_down(&frequency);
+ if (ret < 0)
+ debug("Si47xx_IOC_SEEK_DOWN failed\n");
+ else if (copy_to_user
+ (argp, (void *)&frequency, sizeof(u32)))
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si47xx_IOC_RSSI_SEEK_TH_SET:
+ {
+ u8 RSSI_seek_th;
+ debug("Si47xx_IOC_RSSI_SEEK_TH_SET called\n");
+
+ if (copy_from_user
+ ((void *)&RSSI_seek_th, argp, sizeof(u8)))
+ ret = -EFAULT;
+ else {
+ ret = (long)Si47xx_dev_RSSI_seek_th_set(RSSI_seek_th);
+ if (ret < 0)
+ debug("Si47xx_IOC_RSSI_SEEK_TH_SET "
+ "failed\n");
+ }
+ }
+ break;
+
+ case Si47xx_IOC_SEEK_SNR_SET:
+ {
+ u8 seek_SNR_th;
+ debug("Si47xx_IOC_SEEK_SNR_SET called\n");
+
+ if (copy_from_user
+ ((void *)&seek_SNR_th, argp, sizeof(u8)))
+ ret = -EFAULT;
+ else {
+ ret = (long)Si47xx_dev_seek_SNR_th_set(seek_SNR_th);
+ if (ret < 0)
+ debug("Si47xx_IOC_SEEK_SNR_SET "
+ "failed\n");
+ }
+ }
+ break;
+
+ case Si47xx_IOC_SEEK_CNT_SET:
+ {
+ u8 seek_FM_ID_th;
+ debug("Si47xx_IOC_SEEK_CNT_SET called\n");
+
+ if (copy_from_user
+ ((void *)&seek_FM_ID_th, argp, sizeof(u8)))
+ ret = -EFAULT;
+ else {
+ ret =
+ (long)Si47xx_dev_seek_FM_ID_th_set(seek_FM_ID_th);
+ if (ret < 0)
+ debug("Si47xx_IOC_SEEK_CNT_SET "
+ "failed\n");
+ }
+ }
+ break;
+
+ case Si47xx_IOC_CUR_RSSI_GET:
+ {
+ struct rssi_snr_t data;
+ debug("Si47xx_IOC_CUR_RSSI_GET called\n");
+
+ ret = (long)Si47xx_dev_cur_RSSI_get(&data);
+ if (ret < 0)
+ debug("Si47xx_IOC_CUR_RSSI_GET failed\n");
+ else if (copy_to_user(argp, (void *)&data,
+ sizeof(data)))
+ 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 Si47xx_IOC_VOLUME_SET:
+ {
+ u8 volume;
+ if (copy_from_user((void *)&volume, argp, sizeof(u8)))
+ ret = -EFAULT;
+ else {
+ debug("Si47xx_IOC_VOLUME_SET called "
+ "vol %d\n", volume);
+ ret = (long)Si47xx_dev_volume_set(volume);
+ if (ret < 0)
+ debug("Si47xx_IOC_VOLUME_SET failed\n");
+ }
+ }
+ break;
+
+ case Si47xx_IOC_VOLUME_GET:
+ {
+ u8 volume;
+ debug("Si47xx_IOC_VOLUME_GET called\n");
+
+ ret = (long)Si47xx_dev_volume_get(&volume);
+
+ if (ret < 0)
+ debug("Si47xx_IOC_VOLUME_GET failed\n");
+ else if (copy_to_user
+ (argp, (void *)&volume, sizeof(u8)))
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si47xx_IOC_DSMUTE_ON:
+ debug("Si47xx_IOC_DSMUTE_ON called\n\n");
+
+ ret = (long)Si47xx_dev_DSMUTE_ON();
+ if (ret < 0)
+ error("Si47xx_IOC_DSMUTE_ON failed\n");
+ break;
+
+ case Si47xx_IOC_DSMUTE_OFF:
+ debug("Si47xx_IOC_DSMUTE_OFF called\n\n");
+
+ ret = (long)Si47xx_dev_DSMUTE_OFF();
+ if (ret < 0)
+ error("Si47xx_IOC_DSMUTE_OFF failed\n");
+ break;
+
+ case Si47xx_IOC_MUTE_ON:
+ debug("Si47xx_IOC_MUTE_ON called\n");
+
+ ret = (long)Si47xx_dev_MUTE_ON();
+ if (ret < 0)
+ debug("Si47xx_IOC_MUTE_ON failed\n");
+ break;
+
+ case Si47xx_IOC_MUTE_OFF:
+ debug("Si47xx_IOC_MUTE_OFF called\n");
+
+ ret = (long)Si47xx_dev_MUTE_OFF();
+ if (ret < 0)
+ debug("Si47xx_IOC_MUTE_OFF failed\n");
+ break;
+
+ case Si47xx_IOC_MONO_SET:
+ debug("Si47xx_IOC_MONO_SET called\n");
+
+ ret = (long)Si47xx_dev_MONO_SET();
+ if (ret < 0)
+ debug("Si47xx_IOC_MONO_SET failed\n");
+ break;
+
+ case Si47xx_IOC_STEREO_SET:
+ debug("Si47xx_IOC_STEREO_SET called\n");
+
+ ret = (long)Si47xx_dev_STEREO_SET();
+ if (ret < 0)
+ debug("Si47xx_IOC_STEREO_SET failed\n");
+ break;
+
+ case Si47xx_IOC_RSTATE_GET:
+ {
+ struct dev_state_t dev_state;
+
+ debug("Si47xx_IOC_RSTATE_GET called\n");
+
+ ret = (long)Si47xx_dev_rstate_get(&dev_state);
+ if (ret < 0)
+ debug("Si47xx_IOC_RSTATE_GET failed\n");
+ else if (copy_to_user(argp, (void *)&dev_state,
+ sizeof(dev_state)))
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si47xx_IOC_RDS_DATA_GET:
+ {
+ struct radio_data_t data;
+ debug("Si47xx_IOC_RDS_DATA_GET called\n");
+
+ ret = (long)Si47xx_dev_RDS_data_get(&data);
+ if (ret < 0)
+ debug(" Si47xx_IOC_RDS_DATA_GET failed\n");
+ else if (copy_to_user(argp, (void *)&data,
+ sizeof(data)))
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si47xx_IOC_RDS_ENABLE:
+ debug("Si47xx_IOC_RDS_ENABLE called\n");
+
+ ret = (long)Si47xx_dev_RDS_ENABLE();
+ if (ret < 0)
+ debug("Si47xx_IOC_RDS_ENABLE failed\n");
+ break;
+
+ case Si47xx_IOC_RDS_DISABLE:
+ debug("Si47xx_IOC_RDS_DISABLE called\n");
+
+ ret = (long)Si47xx_dev_RDS_DISABLE();
+ if (ret < 0)
+ debug("Si47xx_IOC_RDS_DISABLE failed\n");
+ break;
+
+ case Si47xx_IOC_RDS_TIMEOUT_SET:
+ {
+ u32 time_out;
+ debug("Si47xx_IOC_RDS_TIMEOUT_SET called\n");
+
+ if (copy_from_user
+ ((void *)&time_out, argp, sizeof(u32)))
+ ret = -EFAULT;
+ else {
+ ret = (long)Si47xx_dev_RDS_timeout_set(time_out);
+ if (ret < 0)
+ debug("Si47xx_IOC_RDS_TIMEOUT_SET "
+ "failed\n");
+ }
+ }
+ break;
+
+ case Si47xx_IOC_SEEK_CANCEL:
+ debug("Si47xx_IOC_SEEK_CANCEL called\n");
+
+ if (Si47xx_dev_wait_flag == SEEK_WAITING) {
+ Si47xx_dev_wait_flag = SEEK_CANCEL;
+ wake_up_interruptible(&Si47xx_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 Si47xx_IOC_CHIP_ID_GET:
+ {
+ struct chip_id chp_id;
+ debug("Si47xx_IOC_CHIP_ID called\n");
+
+ ret = (long)Si47xx_dev_chip_id(&chp_id);
+ if (ret < 0)
+ debug("Si47xx_IOC_CHIP_ID failed\n");
+ else if (copy_to_user(argp, (void *)&chp_id,
+ sizeof(chp_id)))
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si47xx_IOC_DEVICE_ID_GET:
+ {
+ struct device_id dev_id;
+ debug("Si47xx_IOC_DEVICE_ID called\n");
+
+ ret = (long)Si47xx_dev_device_id(&dev_id);
+ if (ret < 0)
+ debug("Si47xx_IOC_DEVICE_ID failed\n");
+ else if (copy_to_user(argp, (void *)&dev_id,
+ sizeof(dev_id)))
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si47xx_IOC_SYS_CONFIG2_GET:
+ {
+ struct sys_config2 sys_conf2;
+ debug("Si47xx_IOC_SYS_CONFIG2 called\n");
+
+ ret = (long)Si47xx_dev_sys_config2(&sys_conf2);
+ if (ret < 0)
+ debug("Si47xx_IOC_SYS_CONFIG2 failed\n");
+ else if (copy_to_user(argp, (void *)&sys_conf2,
+ sizeof(sys_conf2)))
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si47xx_IOC_SYS_CONFIG3_GET:
+ {
+ struct sys_config3 sys_conf3;
+ debug("Si47xx_IOC_SYS_CONFIG3 called\n");
+
+ ret = (long)Si47xx_dev_sys_config3(&sys_conf3);
+ if (ret < 0)
+ debug("Si47xx_IOC_SYS_CONFIG3 failed\n");
+ else if (copy_to_user(argp, (void *)&sys_conf3,
+ sizeof(sys_conf3)))
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si47xx_IOC_POWER_CONFIG_GET:
+ {
+ debug("Si47xx_IOC_POWER_CONFIG called\n");
+ ret = -EFAULT;
+ }
+ break;
+/*VNVS:END*/
+
+/*VNVS:START 18-NOV'09*/
+ /*Reading AFCRL Bit */
+ case Si47xx_IOC_AFCRL_GET:
+ {
+ u8 afc;
+ debug("Si47xx_IOC_AFCRL_GET called\n");
+
+ ret = (long)Si47xx_dev_AFCRL_get(&afc);
+ if (ret < 0)
+ debug("Si47xx_IOC_AFCRL_GET failed\n");
+ 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 Si47xx_IOC_DE_SET:
+ {
+ u8 de_tc;
+ debug("Si47xx_IOC_DE_SET called\n");
+
+ if (copy_from_user((void *)&de_tc, argp, sizeof(u8)))
+ ret = -EFAULT;
+ else {
+ ret = (long)Si47xx_dev_DE_set(de_tc);
+ if (ret < 0)
+ debug("Si47xx_IOC_DE_SET failed\n");
+ }
+ }
+ break;
+
+ case Si47xx_IOC_STATUS_RSSI_GET:
+ {
+ struct status_rssi status;
+ debug("Si47xx_IOC_STATUS_RSSI_GET called\n");
+
+ ret = (long)Si47xx_dev_status_rssi(&status);
+ if (ret < 0)
+ debug("Si47xx_IOC_STATUS_RSSI_GET failed\n");
+ else if (copy_to_user(argp, (void *)&status,
+ sizeof(status)))
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si47xx_IOC_SYS_CONFIG2_SET:
+ {
+ struct sys_config2 sys_conf2;
+ unsigned long n;
+ debug("Si47xx_IOC_SYS_CONFIG2_SET called\n");
+
+ n = copy_from_user((void *)&sys_conf2, argp,
+ sizeof(sys_conf2));
+ if (n) {
+ debug("Si47xx_IOC_SYS_CONFIG2_SET() : "
+ "copy_from_user() has error!! "
+ "Failed to read [%lu] byes!", n);
+ ret = -EFAULT;
+ } else {
+ ret = (long)Si47xx_dev_sys_config2_set(&sys_conf2);
+ if (ret < 0)
+ debug("Si47xx_IOC_SYS_CONFIG2_SET"
+ "failed\n");
+ }
+ }
+ break;
+
+ case Si47xx_IOC_SYS_CONFIG3_SET:
+ {
+ struct sys_config3 sys_conf3;
+ unsigned long n;
+
+ debug("Si47xx_IOC_SYS_CONFIG3_SET called\n");
+
+ n = copy_from_user((void *)&sys_conf3, argp,
+ sizeof(sys_conf3));
+ if (n) {
+ debug("Si47xx_IOC_SYS_CONFIG3_SET() : "
+ "copy_from_user() has error!! "
+ "Failed to read [%lu] byes!", n);
+ ret = -EFAULT;
+ } else {
+ ret = (long)Si47xx_dev_sys_config3_set(&sys_conf3);
+ if (ret < 0)
+ debug("Si47xx_IOC_SYS_CONFIG3_SET "
+ "failed\n");
+ }
+ }
+ break;
+
+ /*Resetting the RDS Data Buffer */
+ case Si47xx_IOC_RESET_RDS_DATA:
+ {
+ debug("Si47xx_IOC_RESET_RDS_DATA called\n");
+
+ ret = (long)Si47xx_dev_reset_rds_data();
+ if (ret < 0)
+ error("Si47xx_IOC_RESET_RDS_DATA failed\n");
+ }
+ break;
+/*VNVS:END*/
+ default:
+ debug(" ioctl default\n");
+ ret = -ENOTTY;
+ break;
+ }
+
+ return ret;
+}
+
+static int __devinit Si47xx_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct Si47xx_device_t *Si47xx_dev;
+ struct si47xx_platform_data *pdata;
+ int err, ret = 0;
+
+ debug("----- %s %d\n", __func__, __LINE__);
+
+ Si47xx_dev = kzalloc(sizeof(struct Si47xx_device_t), GFP_KERNEL);
+
+ if (!Si47xx_dev) {
+ err = -ENOMEM;
+ return err;
+ }
+
+ Si47xx_dev->client = client;
+ i2c_set_clientdata(client, Si47xx_dev);
+
+ Si47xx_dev->dev = &client->dev;
+ dev_set_drvdata(Si47xx_dev->dev, Si47xx_dev);
+
+ Si47xx_dev->pdata = client->dev.platform_data;
+ pdata = Si47xx_dev->pdata;
+
+ mutex_init(&Si47xx_dev->lock);
+
+ ret = Si47xx_dev_init(Si47xx_dev);
+ if (ret < 0)
+ error("Si47xx_dev_init failed");
+
+ return ret;
+
+MISC_IRQ_DREG:
+ free_irq(client->irq, NULL);
+ mutex_destroy(&Si47xx_dev->lock);
+ kfree(Si47xx_dev);
+ return ret;
+
+}
+
+static int __devexit Si47xx_i2c_remove(struct i2c_client *client)
+{
+ struct Si47xx_device_t *Si47xx_dev = i2c_get_clientdata(client);
+ int ret = 0;
+
+ free_irq(client->irq, NULL);
+ i2c_set_clientdata(client, NULL);
+ ret = Si47xx_dev_exit();
+ mutex_destroy(&Si47xx_dev->lock);
+ kfree(Si47xx_dev);
+ return ret;
+}
+
+static struct i2c_driver Si47xx_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "Si47xx",
+ },
+ .id_table = Si47xx_id,
+ .probe = Si47xx_i2c_probe,
+ .remove = __devexit_p(Si47xx_i2c_remove),
+ .suspend = Si47xx_suspend,
+ .resume = Si47xx_resume,
+};
+
+static int Si47xx_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+ int ret = 0;
+
+ debug("Si47xx i2c driver Si47xx_suspend called");
+
+ if (strcmp(client->name, "Si47xx") != 0) {
+ ret = -1;
+ error("Si47xx_suspend: device not supported");
+ } else {
+ ret = Si47xx_dev_suspend();
+ if (ret < 0)
+ error("Si47xx_dev_disable failed");
+ }
+
+ return 0;
+}
+
+static int Si47xx_resume(struct i2c_client *client)
+{
+ int ret = 0;
+
+ if (strcmp(client->name, "Si47xx") != 0) {
+ ret = -1;
+ error("Si47xx_resume: device not supported");
+ } else {
+ ret = Si47xx_dev_resume();
+ if (ret < 0)
+ error("Si47xx_dev_enable failed");
+ }
+
+ return 0;
+}
+
+static __init int Si47xx_i2c_drv_init(void)
+{
+ int ret = 0;
+
+ debug("Si47xx i2c driver Si47xx_i2c_driver_init called");
+
+ /*misc device registration */
+ ret = misc_register(&Si47xx_misc_device);
+ if (ret < 0) {
+ error("Si47xx_driver_init misc_register failed\n");
+ goto MISC_DREG;
+ }
+
+ ret = i2c_add_driver(&Si47xx_i2c_driver);
+ if (ret < 0) {
+ error("Si47xx i2c_add_driver failed");
+ return ret;
+ }
+
+ init_waitqueue_head(&Si47xx_waitq);
+ debug("Si47xx_driver_init successful\n");
+
+ return ret;
+MISC_DREG:
+ misc_deregister(&Si47xx_misc_device);
+ return ret;
+
+
+}
+
+void __exit Si47xx_i2c_drv_exit(void)
+{
+ debug("Si47xx i2c driver Si47xx_i2c_driver_exit called");
+
+ i2c_del_driver(&Si47xx_i2c_driver);
+ /*misc device deregistration */
+ misc_deregister(&Si47xx_misc_device);
+}
+
+module_init(Si47xx_i2c_drv_init);
+module_exit(Si47xx_i2c_drv_exit);
+MODULE_AUTHOR("ashton seo <ashton.seo@samsung.com>");
+MODULE_DESCRIPTION("Si47xx FM tuner driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/samsung/fm_si47xx/Si47xx_ioctl.h b/drivers/samsung/fm_si47xx/Si47xx_ioctl.h
new file mode 100644
index 0000000..08f8238
--- /dev/null
+++ b/drivers/samsung/fm_si47xx/Si47xx_ioctl.h
@@ -0,0 +1,129 @@
+/*
+ * Si47xx_ioctl.h -- Si47xx FM Radio driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _Si47xx_IOCTL_H
+#define _Si47xx_IOCTL_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#include "Si47xx_dev.h"
+
+/*****************IOCTLS******************/
+/*magic no*/
+#define Si47xx_IOC_MAGIC 0xFA
+/*max seq no*/
+#define Si47xx_IOC_NR_MAX 40
+
+/*commands*/
+
+#define Si47xx_IOC_POWERUP _IO(Si47xx_IOC_MAGIC, 0)
+
+#define Si47xx_IOC_POWERDOWN _IO(Si47xx_IOC_MAGIC, 1)
+
+#define Si47xx_IOC_BAND_SET _IOW(Si47xx_IOC_MAGIC, 2, int)
+
+#define Si47xx_IOC_CHAN_SPACING_SET _IOW(Si47xx_IOC_MAGIC, 3, int)
+
+#define Si47xx_IOC_CHAN_SELECT _IOW(Si47xx_IOC_MAGIC, 4, u32)
+
+#define Si47xx_IOC_CHAN_GET _IOR(Si47xx_IOC_MAGIC, 5, u32)
+
+#define Si47xx_IOC_SEEK_UP _IOR(Si47xx_IOC_MAGIC, 6, u32)
+
+#define Si47xx_IOC_SEEK_DOWN _IOR(Si47xx_IOC_MAGIC, 7, u32)
+
+/*VNVS:28OCT'09---- Si47xx_IOC_SEEK_AUTO is disabled as of now*/
+/* #define Si47xx_IOC_SEEK_AUTO _IOR(Si47xx_IOC_MAGIC, 8, u32) */
+
+#define Si47xx_IOC_RSSI_SEEK_TH_SET _IOW(Si47xx_IOC_MAGIC, 9, u8)
+
+#define Si47xx_IOC_SEEK_SNR_SET _IOW(Si47xx_IOC_MAGIC, 10, u8)
+
+#define Si47xx_IOC_SEEK_CNT_SET _IOW(Si47xx_IOC_MAGIC, 11, u8)
+
+#define Si47xx_IOC_CUR_RSSI_GET \
+_IOR(Si47xx_IOC_MAGIC, 12, struct rssi_snr_t)
+
+#define Si47xx_IOC_VOLEXT_ENB _IO(Si47xx_IOC_MAGIC, 13)
+
+#define Si47xx_IOC_VOLEXT_DISB _IO(Si47xx_IOC_MAGIC, 14)
+
+#define Si47xx_IOC_VOLUME_SET _IOW(Si47xx_IOC_MAGIC, 15, u8)
+
+#define Si47xx_IOC_VOLUME_GET _IOR(Si47xx_IOC_MAGIC, 16, u8)
+
+#define Si47xx_IOC_MUTE_ON _IO(Si47xx_IOC_MAGIC, 17)
+
+#define Si47xx_IOC_MUTE_OFF _IO(Si47xx_IOC_MAGIC, 18)
+
+#define Si47xx_IOC_MONO_SET _IO(Si47xx_IOC_MAGIC, 19)
+
+#define Si47xx_IOC_STEREO_SET _IO(Si47xx_IOC_MAGIC, 20)
+
+#define Si47xx_IOC_RSTATE_GET \
+_IOR(Si47xx_IOC_MAGIC, 21, struct dev_state_t)
+
+#define Si47xx_IOC_RDS_DATA_GET \
+_IOR(Si47xx_IOC_MAGIC, 22, struct radio_data_t)
+
+#define Si47xx_IOC_RDS_ENABLE _IO(Si47xx_IOC_MAGIC, 23)
+
+#define Si47xx_IOC_RDS_DISABLE _IO(Si47xx_IOC_MAGIC, 24)
+
+#define Si47xx_IOC_RDS_TIMEOUT_SET _IOW(Si47xx_IOC_MAGIC, 25, u32)
+
+#define Si47xx_IOC_SEEK_CANCEL _IO(Si47xx_IOC_MAGIC, 26)
+
+/*VNVS:START 13-OCT'09 :
+ Added IOCTLs for reading the device-id,chip-id,power configuration,
+ system configuration2 registers*/
+#define Si47xx_IOC_DEVICE_ID_GET \
+_IOR(Si47xx_IOC_MAGIC, 27, struct device_id)
+
+#define Si47xx_IOC_CHIP_ID_GET \
+_IOR(Si47xx_IOC_MAGIC, 28, struct chip_id)
+
+#define Si47xx_IOC_SYS_CONFIG2_GET \
+_IOR(Si47xx_IOC_MAGIC, 29, struct sys_config2)
+
+#define Si47xx_IOC_POWER_CONFIG_GET \
+_IO(Si47xx_IOC_MAGIC, 30)
+
+/* For reading AFCRL bit, to check for a valid channel */
+#define Si47xx_IOC_AFCRL_GET _IOR(Si47xx_IOC_MAGIC, 31, u8)
+
+/* Setting DE-emphasis Time Constant.
+For DE=0,TC=50us(Europe,Japan,Australia) and DE=1,TC=75us(USA) */
+#define Si47xx_IOC_DE_SET _IOW(Si47xx_IOC_MAGIC, 32, u8)
+/*VNVS:END*/
+
+#define Si47xx_IOC_SYS_CONFIG3_GET \
+_IOR(Si47xx_IOC_MAGIC, 33, struct sys_config3)
+
+#define Si47xx_IOC_STATUS_RSSI_GET \
+_IOR(Si47xx_IOC_MAGIC, 34, struct status_rssi)
+
+#define Si47xx_IOC_SYS_CONFIG2_SET \
+_IOW(Si47xx_IOC_MAGIC, 35, struct sys_config2)
+
+#define Si47xx_IOC_SYS_CONFIG3_SET \
+_IOW(Si47xx_IOC_MAGIC, 36, struct sys_config3)
+
+#define Si47xx_IOC_DSMUTE_ON _IO(Si47xx_IOC_MAGIC, 37)
+
+#define Si47xx_IOC_DSMUTE_OFF _IO(Si47xx_IOC_MAGIC, 38)
+
+#define Si47xx_IOC_RESET_RDS_DATA _IO(Si47xx_IOC_MAGIC, 39)
+
+#define Si47xx_IOC_SEEK_FULL _IOR(Si47xx_IOC_MAGIC, 40, u32)
+
+
+/*****************************************/
+
+#endif
diff --git a/drivers/samsung/fm_si47xx/commanddefs.h b/drivers/samsung/fm_si47xx/commanddefs.h
new file mode 100644
index 0000000..55d5e16
--- /dev/null
+++ b/drivers/samsung/fm_si47xx/commanddefs.h
@@ -0,0 +1,199 @@
+/*
+ * commanddefs.h -- This file contains the command definitions for
+ * the Si47xx Parts.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _COMMAND_DEFS_H_
+#define _COMMAND_DEFS_H_
+
+/*==================================================================
+General Commands
+==================================================================*/
+
+/* STATUS bits - Used by all methods */
+#define STCINT 0x01
+#define ASQINT 0x02
+#define RDSINT 0x04
+#define RSQINT 0x08
+#define ERR 0x40
+#define CTS 0x80
+
+/* POWER_UP */
+#define POWER_UP 0x01
+#define POWER_UP_IN_FUNC_FMRX 0x00
+#define POWER_UP_IN_FUNC_AMRX 0x01
+#define POWER_UP_IN_FUNC_FMTX 0x02
+#define POWER_UP_IN_FUNC_WBRX 0x03
+#define POWER_UP_IN_FUNC_QUERY 0x0F
+#define POWER_UP_IN_PATCH 0x20
+#define POWER_UP_IN_GPO2OEN 0x40
+#define POWER_UP_IN_CTSIEN 0x80
+#define POWER_UP_IN_OPMODE_RX_ANALOG 0x05
+#define POWER_UP_IN_OPMODE_TX_ANALOG 0x50
+
+/* GET_REV */
+#define GET_REV 0x10
+
+/* POWER_DOWN */
+#define POWER_DOWN 0x11
+
+/* SET_PROPERTY */
+#define SET_PROPERTY 0x12
+
+/* GET_PROPERTY */
+#define GET_PROPERTY 0x13
+
+/* GET_INT_STATUS */
+#define GET_INT_STATUS 0x14
+
+/*==================================================================
+ FM Receive Commands
+==================================================================*/
+
+/* FM_TUNE_FREQ */
+#define FM_TUNE_FREQ 0x20
+
+/* FM_SEEK_START */
+#define FM_SEEK_START 0x21
+#define FM_SEEK_START_IN_WRAP 0x04
+#define FM_SEEK_START_IN_SEEKUP 0x08
+
+/* FM_TUNE_STATUS */
+#define FM_TUNE_STATUS 0x22
+#define FM_TUNE_STATUS_IN_INTACK 0x01
+#define FM_TUNE_STATUS_IN_CANCEL 0x02
+#define FM_TUNE_STATUS_OUT_VALID 0x01
+#define FM_TUNE_STATUS_OUT_AFCRL 0x02
+#define FM_TUNE_STATUS_OUT_BTLF 0x80
+
+/* FM_RSQ_STATUS */
+#define FM_RSQ_STATUS 0x23
+#define FM_RSQ_STATUS_IN_INTACK 0x01
+#define FM_RSQ_STATUS_OUT_RSSILINT 0x01
+#define FM_RSQ_STATUS_OUT_RSSIHINT 0x02
+#define FM_RSQ_STATUS_OUT_ASNRLINT 0x04
+#define FM_RSQ_STATUS_OUT_ASNRHINT 0x08
+#define FM_RSQ_STATUS_OUT_BLENDINT 0x80
+#define FM_RSQ_STATUS_OUT_VALID 0x01
+#define FM_RSQ_STATUS_OUT_AFCRL 0x02
+#define FM_RSQ_STATUS_OUT_SMUTE 0x08
+#define FM_RSQ_STATUS_OUT_PILOT 0x80
+#define FM_RSQ_STATUS_OUT_STBLEND 0x7F
+
+/* FM_RDS_STATUS */
+#define FM_RDS_STATUS 0x24
+#define FM_RDS_STATUS_IN_INTACK 0x01
+#define FM_RDS_STATUS_IN_MTFIFO 0x02
+#define FM_RDS_STATUS_OUT_RECV 0x01
+#define FM_RDS_STATUS_OUT_SYNCLOST 0x02
+#define FM_RDS_STATUS_OUT_SYNCFOUND 0x04
+#define FM_RDS_STATUS_OUT_SYNC 0x01
+#define FM_RDS_STATUS_OUT_GRPLOST 0x04
+#define FM_RDS_STATUS_OUT_BLED 0x03
+#define FM_RDS_STATUS_OUT_BLEC 0x0C
+#define FM_RDS_STATUS_OUT_BLEB 0x30
+#define FM_RDS_STATUS_OUT_BLEA 0xC0
+#define FM_RDS_STATUS_OUT_BLED_SHFT 0
+#define FM_RDS_STATUS_OUT_BLEC_SHFT 2
+#define FM_RDS_STATUS_OUT_BLEB_SHFT 4
+#define FM_RDS_STATUS_OUT_BLEA_SHFT 6
+
+/*==================================================================
+ AM Receive Commands
+==================================================================*/
+
+/* AM_TUNE_FREQ */
+#define AM_TUNE_FREQ 0x40
+
+/* AM_SEEK_START */
+#define AM_SEEK_START 0x41
+#define AM_SEEK_START_IN_WRAP 0x04
+#define AM_SEEK_START_IN_SEEKUP 0x08
+
+/* AM_TUNE_STATUS */
+#define AM_TUNE_STATUS 0x42
+#define AM_TUNE_STATUS_IN_INTACK 0x01
+#define AM_TUNE_STATUS_IN_CANCEL 0x02
+#define AM_TUNE_STATUS_OUT_VALID 0x01
+#define AM_TUNE_STATUS_OUT_AFCRL 0x02
+#define AM_TUNE_STATUS_OUT_BTLF 0x80
+
+/* AM_RSQ_STATUS */
+#define AM_RSQ_STATUS 0x23
+#define AM_RSQ_STATUS_IN_INTACK 0x01
+#define AM_RSQ_STATUS_OUT_RSSILINT 0x01
+#define AM_RSQ_STATUS_OUT_RSSIHINT 0x02
+#define AM_RSQ_STATUS_OUT_ASNRLINT 0x04
+#define AM_RSQ_STATUS_OUT_ASNRHINT 0x08
+#define AM_RSQ_STATUS_OUT_VALID 0x01
+#define AM_RSQ_STATUS_OUT_AFCRL 0x02
+#define AM_RSQ_STATUS_OUT_SMUTE 0x08
+
+/*==================================================================
+ FM Transmit Commands
+==================================================================*/
+
+/* TX_TUNE_FREQ */
+#define TX_TUNE_FREQ 0x30
+
+/* TX_TUNE_POWER */
+#define TX_TUNE_POWER 0x31
+
+/* TX_TUNE_MEASURE */
+#define TX_TUNE_MEASURE 0x32
+
+/* TX_TUNE_STATUS */
+#define TX_TUNE_STATUS 0x33
+#define TX_TUNE_STATUS_IN_INTACK 0x01
+
+/* TX_ASQ_STATUS */
+#define TX_ASQ_STATUS 0x34
+#define TX_ASQ_STATUS_IN_INTACK 0x01
+#define TX_ASQ_STATUS_OUT_IALL 0x01
+#define TX_ASQ_STATUS_OUT_IALH 0x02
+#define TX_ASQ_STATUS_OUT_OVERMOD 0x04
+
+/* TX_RDS_BUFF */
+#define TX_RDS_BUFF 0x35
+#define TX_RDS_BUFF_IN_INTACK 0x01
+#define TX_RDS_BUFF_IN_MTBUFF 0x02
+#define TX_RDS_BUFF_IN_LDBUFF 0x04
+#define TX_RDS_BUFF_IN_FIFO 0x80
+
+/* TX_RDS_PS */
+#define TX_RDS_PS 0x36
+
+/*==================================================================
+ WB Receive Commands
+==================================================================*/
+
+/* WB_TUNE_FREQ */
+#define WB_TUNE_FREQ 0x50
+
+/* WB_TUNE_STATUS */
+#define WB_TUNE_STATUS 0x52
+#define WB_TUNE_STATUS_IN_INTACK 0x01
+#define WB_TUNE_STATUS_OUT_VALID 0x01
+#define WB_TUNE_STATUS_OUT_AFCRL 0x02
+
+/* WB_RSQ_STATUS */
+#define WB_RSQ_STATUS 0x53
+#define WB_RSQ_STATUS_IN_INTACK 0x01
+#define WB_RSQ_STATUS_OUT_RSSILINT 0x01
+#define WB_RSQ_STATUS_OUT_RSSIHINT 0x02
+#define WB_RSQ_STATUS_OUT_ASNRLINT 0x04
+#define WB_RSQ_STATUS_OUT_ASNRHINT 0x08
+#define WB_RSQ_STATUS_OUT_VALID 0x01
+#define WB_RSQ_STATUS_OUT_AFCRL 0x02
+
+/* WB_ASQ_STATUS */
+#define WB_ASQ_STATUS 0x55
+#define WB_ASQ_STATUS_IN_INTACK 0x01
+#define WB_ASQ_STATUS_OUT_ALERTONINT 0x01
+#define WB_ASQ_STATUS_OUT_ALERTOFFINT 0x02
+#define WB_ASQ_STATUS_OUT_ALERT 0x01
+
+#endif
diff --git a/drivers/samsung/fm_si47xx/propertydefs.h b/drivers/samsung/fm_si47xx/propertydefs.h
new file mode 100644
index 0000000..e718b58
--- /dev/null
+++ b/drivers/samsung/fm_si47xx/propertydefs.h
@@ -0,0 +1,585 @@
+/*
+ * commanddefs.h -- This file contains the property definitions for
+ * the Si47xx Parts.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _PROPERTY_DEFS_H_
+#define _PROPERTY_DEFS_H_
+
+/*==================================================================
+ General Properties
+==================================================================*/
+
+/* GPO_IEN */
+#define GPO_IEN 0x0001
+#define GPO_IEN_STCIEN_MASK 0x0001
+#define GPO_IEN_ASQIEN_MASK 0x0002
+#define GPO_IEN_RDSIEN_MASK 0x0004
+#define GPO_IEN_RSQIEN_MASK 0x0008
+#define GPO_IEN_ERRIEN_MASK 0x0040
+#define GPO_IEN_CTSIEN_MASK 0x0080
+#define GPO_IEN_STCREP_MASK 0x0100
+#define GPO_IEN_ASQREP_MASK 0x0200
+#define GPO_IEN_RDSREP_MASK 0x0400
+#define GPO_IEN_RSQREP_MASK 0x0800
+#define GPO_IEN_STCIEN_SHFT 0
+#define GPO_IEN_ASQIEN_SHFT 1
+#define GPO_IEN_RDSIEN_SHFT 2
+#define GPO_IEN_RSQIEN_SHFT 3
+#define GPO_IEN_ERRIEN_SHFT 6
+#define GPO_IEN_CTSIEN_SHFT 7
+#define GPO_IEN_STCREP_SHFT 8
+#define GPO_IEN_ASQREP_SHFT 9
+#define GPO_IEN_RDSREP_SHFT 10
+#define GPO_IEN_RSQREP_SHFT 11
+
+/* DIGITAL_INPUT_FORMAT */
+#define DIGITAL_INPUT_FORMAT 0x0101
+#define DIGITAL_INPUT_FORMAT_ISIZE_MASK 0x0003
+#define DIGITAL_INPUT_FORMAT_IMONO_MASK 0x0004
+#define DIGITAL_INPUT_FORMAT_IMODE_MASK 0x0078
+#define DIGITAL_INPUT_FORMAT_IFALL_MASK 0x0080
+#define DIGITAL_INPUT_FORMAT_ISIZE_SHFT 0
+#define DIGITAL_INPUT_FORMAT_IMONO_SHFT 2
+#define DIGITAL_INPUT_FORMAT_IMODE_SHFT 3
+#define DIGITAL_INPUT_FORMAT_IFALL_SHFT 7
+
+/* DIGITAL_INPUT_SAMPLE_RATE */
+#define DIGITAL_INPUT_SAMPLE_RATE 0x0103
+
+/* DIGITAL_OUTPUT_FORMAT */
+#define DIGITAL_OUTPUT_FORMAT 0x0102
+#define DIGITAL_OUTPUT_FORMAT_OSIZE_MASK 0x0003
+#define DIGITAL_OUTPUT_FORMAT_OMONO_MASK 0x0004
+#define DIGITAL_OUTPUT_FORMAT_OMODE_MASK 0x0078
+#define DIGITAL_OUTPUT_FORMAT_OFALL_MASK 0x0080
+#define DIGITAL_OUTPUT_FORMAT_OSIZE_SHFT 0
+#define DIGITAL_OUTPUT_FORMAT_OMONO_SHFT 2
+#define DIGITAL_OUTPUT_FORMAT_OMODE_SHFT 3
+#define DIGITAL_OUTPUT_FORMAT_OFALL_SHFT 7
+
+/* DIGITAL_OUTPUT_SAMPLE_RATE */
+#define DIGITAL_OUTPUT_SAMPLE_RATE 0x0104
+
+/* REFCLK_FREQ */
+#define REFCLK_FREQ 0x0201
+
+/* REFCLK_PRESCALE */
+#define REFCLK_PRESCALE 0x0202
+#define REFCLK_PRESCALE_MASK 0x0FFF
+#define REFCLK_PRESCALE_SHFT 0
+
+/*==================================================================
+ FM Receive Properties
+==================================================================*/
+
+/* FM_DEEMPHASIS */
+#define FM_DEEMPHASIS 0x1100
+#define FM_DEEMPHASIS_MASK 0x0003
+#define FM_DEEMPHASIS_SHFT 0
+
+/* FM_BLEND_STEREO_THRESHOLD */
+#define FM_BLEND_STEREO_THRESHOLD 0x1105
+#define FM_BLEND_STEREO_THRESHOLD_MASK 0x007F
+#define FM_BLEND_STEREO_THRESHOLD_SHFT 0
+
+/* FM_BLEND_MONO_THRESHOLD */
+#define FM_BLEND_MONO_THRESHOLD 0x1106
+#define FM_BLEND_MONO_THRESHOLD_MASK 0x007F
+#define FM_BLEND_MONO_THRESHOLD_SHFT 0
+
+
+/* FM_MAX_TUNE_ERROR */
+#define FM_MAX_TUNE_ERROR 0x1108
+#define FM_MAX_TUNE_ERROR_MASK 0x007F
+#define FM_MAX_TUNE_ERROR_SHFT 0
+
+/* FM_RSQ_INT_SOURCE */
+#define FM_RSQ_INT_SOURCE 0x1200
+#define FM_RSQ_INT_SOURCE_RSSILIEN_MASK 0x0001
+#define FM_RSQ_INT_SOURCE_RSSIHIEN_MASK 0x0002
+#define FM_RSQ_INT_SOURCE_ASNRLIEN_MASK 0x0004
+#define FM_RSQ_INT_SOURCE_ASNRHIEN_MASK 0x0008
+#define FM_RSQ_INT_SOURCE_BLENDIEN_MASK 0x0080
+#define FM_RSQ_INT_SOURCE_RSSILIEN_SHFT 0
+#define FM_RSQ_INT_SOURCE_RSSIHIEN_SHFT 1
+#define FM_RSQ_INT_SOURCE_ASNRLIEN_SHFT 2
+#define FM_RSQ_INT_SOURCE_ASNRHIEN_SHFT 3
+#define FM_RSQ_INT_SOURCE_BLENDIEN_SHFT 7
+
+/* FM_RSQ_SNR_HI_THRESHOLD */
+#define FM_RSQ_SNR_HI_THRESHOLD 0x1201
+#define FM_RSQ_SNR_HI_THRESHOLD_MASK 0x007F
+#define FM_RSQ_SNR_HI_THRESHOLD_SHFT 0
+
+/* FM_RSQ_SNR_LO_THRESHOLD */
+#define FM_RSQ_SNR_LO_THRESHOLD 0x1202
+#define FM_RSQ_SNR_LO_THRESHOLD_MASK 0x007F
+#define FM_RSQ_SNR_LO_THRESHOLD_SHFT 0
+
+/* FM_RSQ_RSSI_HI_THRESHOLD */
+#define FM_RSQ_RSSI_HI_THRESHOLD 0x1203
+#define FM_RSQ_RSSI_HI_THRESHOLD_MASK 0x007F
+#define FM_RSQ_RSSI_HI_THRESHOLD_SHFT 0
+
+/* FM_RSQ_RSSI_LO_THRESHOLD */
+#define FM_RSQ_RSSI_LO_THRESHOLD 0x1204
+#define FM_RSQ_RSSI_LO_THRESHOLD_MASK 0x007F
+#define FM_RSQ_RSSI_LO_THRESHOLD_SHFT 0
+
+/* FM_RSQ_BLEND_THRESHOLD */
+#define FM_RSQ_BLEND_THRESHOLD 0x1207
+#define FM_RSQ_BLEND_THRESHOLD_BLEND_MASK 0x007F
+#define FM_RSQ_BLEND_THRESHOLD_PILOT_MASK 0x0080
+#define FM_RSQ_BLEND_THRESHOLD_BLEND_SHFT 0
+#define FM_RSQ_BLEND_THRESHOLD_PILOT_SHFT 7
+
+/* FM_SOFT_MUTE_RATE */
+#define FM_SOFT_MUTE_RATE 0x1300
+#define FM_SOFT_MUTE_RATE_MASK 0x00FF
+#define FM_SOFT_MUTE_RATE_SHFT 0
+
+/* FM_SOFT_MUTE_MAX_ATTENUATION */
+#define FM_SOFT_MUTE_MAX_ATTENUATION 0x1302
+#define FM_SOFT_MUTE_MAX_ATTENUATION_MASK 0x001F
+#define FM_SOFT_MUTE_MAX_ATTENUATION_SHFT 0
+
+/* FM_SOFT_MUTE_SNR_THRESHOLD */
+#define FM_SOFT_MUTE_SNR_THRESHOLD 0x1303
+#define FM_SOFT_MUTE_SNR_THRESHOLD_MASK 0x000F
+#define FM_SOFT_MUTE_SNR_THRESHOLD_SHFT 0
+
+/* FM_SEEK_BAND_BOTTOM */
+#define FM_SEEK_BAND_BOTTOM 0x1400
+
+/* FM_SEEK_BAND_TOP */
+#define FM_SEEK_BAND_TOP 0x1401
+
+/* FM_SEEK_FREQ_SPACING */
+#define FM_SEEK_FREQ_SPACING 0x1402
+#define FM_SEEK_FREQ_SPACING_MASK 0x001F
+#define FM_SEEK_FREQ_SPACING_SHFT 0
+
+/* FM_SEEK_TUNE_SNR_THRESHOLD */
+#define FM_SEEK_TUNE_SNR_THRESHOLD 0x1403
+#define FM_SEEK_TUNE_SNR_THRESHOLD_MASK 0x007F
+#define FM_SEEK_TUNE_SNR_THRESHOLD_SHFT 0
+
+/* FM_SEEK_TUNE_RSSI_THRESHOLD */
+#define FM_SEEK_TUNE_RSSI_THRESHOLD 0x1404
+#define FM_SEEK_TUNE_RSSI_THRESHOLD_MASK 0x007F
+#define FM_SEEK_TUNE_RSSI_THRESHOLD_SHFT 0
+
+/* FM_RDS_INTERRUPT_SOURCE */
+#define FM_RDS_INTERRUPT_SOURCE 0x1500
+#define FM_RDS_INTERRUPT_SOURCE_RECV_MASK 0x0001
+#define FM_RDS_INTERRUPT_SOURCE_SYNCLOST_MASK 0x0002
+#define FM_RDS_INTERRUPT_SOURCE_SYNCFOUND_MASK 0x0004
+#define FM_RDS_INTERRUPT_SOURCE_RECV_SHFT 0
+#define FM_RDS_INTERRUPT_SOURCE_SYNCLOST_SHFT 1
+#define FM_RDS_INTERRUPT_SOURCE_SYNCFOUND_SHFT 2
+
+/* FM_RDS_INTERRUPT_FIFO_COUNT */
+#define FM_RDS_INTERRUPT_FIFO_COUNT 0x1501
+#define FM_RDS_INTERRUPT_FIFO_COUNT_MASK 0x00FF
+#define FM_RDS_INTERRUPT_FIFO_COUNT_SHFT 0
+
+/* FM_RDS_CONFIG */
+#define FM_RDS_CONFIG 0x1502
+#define FM_RDS_CONFIG_RDSEN_MASK 0x0001
+#define FM_RDS_CONFIG_BLETHD_MASK 0x0300
+#define FM_RDS_CONFIG_BLETHC_MASK 0x0C00
+#define FM_RDS_CONFIG_BLETHB_MASK 0x3000
+#define FM_RDS_CONFIG_BLETHA_MASK 0xC000
+#define FM_RDS_CONFIG_RDSEN_SHFT 0
+#define FM_RDS_CONFIG_BLETHD_SHFT 8
+#define FM_RDS_CONFIG_BLETHC_SHFT 10
+#define FM_RDS_CONFIG_BLETHB_SHFT 12
+#define FM_RDS_CONFIG_BLETHA_SHFT 14
+
+/*==================================================================
+ FM Transmit Properties
+==================================================================*/
+
+/* TX_COMPONENT_ENABLE */
+#define TX_COMPONENT_ENABLE 0x2100
+#define TX_COMPONENT_ENABLE_PILOT_MASK 0x0001
+#define TX_COMPONENT_ENABLE_LMR_MASK 0x0002
+#define TX_COMPONENT_ENABLE_RDS_MASK 0x0004
+#define TX_COMPONENT_ENABLE_PILOT_SHFT 0
+#define TX_COMPONENT_ENABLE_LMR_SHFT 1
+#define TX_COMPONENT_ENABLE_RDS_SHFT 2
+
+/* TX_AUDIO_DEVIATION */
+#define TX_AUDIO_DEVIATION 0x2101
+
+/* TX_PILOT_DEVIATION */
+#define TX_PILOT_DEVIATION 0x2102
+
+/* TX_RDS_DEVIATION */
+#define TX_RDS_DEVIATION 0x2103
+
+/* TX_LINE_INPUT_LEVEL */
+#define TX_LINE_INPUT_LEVEL 0x2104
+#define TX_LINE_INPUT_LEVEL_LILEVEL_MASK 0x03FF
+#define TX_LINE_INPUT_LEVEL_LIATTEN_MASK 0x3000
+#define TX_LINE_INPUT_LEVEL_LILEVEL_SHFT 0
+#define TX_LINE_INPUT_LEVEL_LIATTEN_SHFT 12
+
+/* TX_LINE_INPUT_MUTE */
+#define TX_LINE_INPUT_MUTE 0x2105
+#define TX_LINE_INPUT_MUTE_RIMUTE_MASK 0x0001
+#define TX_LINE_INPUT_MUTE_LIMUTE_MASK 0x0002
+#define TX_LINE_INPUT_MUTE_RIMUTE_SHFT 0
+#define TX_LINE_INPUT_MUTE_LIMUTE_SHFT 1
+
+/* TX_PREEMPHASIS */
+#define TX_PREEMPHASIS 0x2106
+#define TX_PREMPHASIS_MASK 0x0003
+#define TX_PREMPHASIS_SHFT 0
+
+/* TX_PILOT_FREQUENCY */
+#define TX_PILOT_FREQUENCY 0x2107
+
+/* TX_ACOMP_ENABLE */
+#define TX_ACOMP_ENABLE 0x2200
+#define TX_ACOMP_ENABLE_ACEN_MASK 0x0001
+#define TX_ACOMP_ENABLE_LIMITEN_MASK 0x0002
+#define TX_ACOMP_ENABLE_ACEN_SHFT 0
+#define TX_ACOMP_ENABLE_LIMITEN_SHFT 1
+
+/* TX_ACOMP_THRESHOLD */
+#define TX_ACOMP_THRESHOLD 0x2201
+
+/* TX_ACOMP_ATTACK_TIME */
+#define TX_ACOMP_ATTACK_TIME 0x2202
+#define TX_ACOMP_ATTACK_TIME_MASK 0x000F
+#define TX_ACOMP_ATTACK_TIME_SHFT 0
+
+/* TX_ACOMP_RELEASE_TIME */
+#define TX_ACOMP_RELEASE_TIME 0x2203
+#define TX_ACOMP_RELEASE_TIME_MASK 0x0007
+#define TX_ACOMP_RELEASE_TIME_SHFT 0
+
+/* TX_ACOMP_GAIN */
+#define TX_ACOMP_GAIN 0x2204
+#define TX_ACOMP_GAIN_MASK 0x003F
+#define TX_ACOMP_GAIN_SHFT 0
+
+/* TX_LIMITER_RELEASE_TIME */
+#define TX_LIMITER_RELEASE_TIME 0x2205
+
+/* TX_ASQ_INT_SELECT */
+#define TX_ASQ_INT_SELECT 0x2300
+#define TX_ASQ_INT_SELECT_IALLIEN_MASK 0x0001
+#define TX_ASQ_INT_SELECT_IALHIEN_MASK 0x0002
+#define TX_ASQ_INT_SELECT_OVERMODIEN_MASK 0x0004
+#define TX_ASQ_INT_SELECT_IALLIEN_SHFT 0
+#define TX_ASQ_INT_SELECT_IALHIEN_SHFT 1
+#define TX_ASQ_INT_SELECT_OVERMODIEN_SHFT 2
+
+/* TX_ASQ_LEVEL_LOW */
+#define TX_ASQ_LEVEL_LOW 0x2301
+#define TX_ASQ_LEVEL_LOW_MASK 0x00FF
+#define TX_ASQ_LEVEL_LOW_SHFT 0
+
+/* TX_ASQ_DURATION_LOW */
+#define TX_ASQ_DURATION_LOW 0x2302
+
+/* TX_ASQ_LEVEL_HIGH */
+#define TX_ASQ_LEVEL_HIGH 0x2303
+#define TX_ASQ_LEVEL_HIGH_MASK 0x00FF
+#define TX_ASQ_LEVEL_HIGH_SHFT 0
+
+/* TX_ASQ_DURATION_LOW */
+#define TX_ASQ_DURATION_HIGH 0x2304
+
+/* TX_RDS_INT_SOURCE */
+#define TX_RDS_INT_SOURCE 0x2C00
+#define TX_RDS_INT_SOURCE_FIFOMT_MASK 0x0001
+#define TX_RDS_INT_SOURCE_CBUFWRAP_MASK 0x0002
+#define TX_RDS_INT_SOURCE_FIFOXMIT_MASK 0x0004
+#define TX_RDS_INT_SOURCE_CBUFXMIT_MASK 0x0008
+#define TX_RDS_INT_SOURCE_PSXMIT_MASK 0x0010
+#define TX_RDS_INT_SOURCE_FIFOMT_SHFT 0
+#define TX_RDS_INT_SOURCE_CBUFWRAP_SHFT 1
+#define TX_RDS_INT_SOURCE_FIFOXMIT_SHFT 2
+#define TX_RDS_INT_SOURCE_CBUFXMIT_SHFT 3
+#define TX_RDS_INT_SOURCE_PSXMIT_SHFT 4
+
+/* TX_RDS_PI */
+#define TX_RDS_PI 0x2C01
+
+/* TX_RDS_PS_MIX */
+#define TX_RDS_PS_MIX 0x2C02
+#define TX_RDS_PS_MIX_MASK 0x0007
+#define TX_RDS_PS_MIX_SHFT 0
+
+/* TX_RDS_PS_MISC */
+#define TX_RDS_PS_MISC 0x2C03
+#define TX_RDS_PS_MISC_RDSMS_MASK 0x0008
+#define TX_RDS_PS_MISC_RDSTA_MASK 0x0010
+#define TX_RDS_PS_MISC_RDSPTY_MASK 0x03E0
+#define TX_RDS_PS_MISC_RDSTP_MASK 0x0400
+#define TX_RDS_PS_MISC_FORCEB_MASK 0x0800
+#define TX_RDS_PS_MISC_RDSD0_MASK 0x1000
+#define TX_RDS_PS_MISC_RDSD1_MASK 0x2000
+#define TX_RDS_PS_MISC_RDSD2_MASK 0x4000
+#define TX_RDS_PS_MISC_RDSD3_MASK 0x8000
+#define TX_RDS_PS_MISC_RDSMS_SHFT 3
+#define TX_RDS_PS_MISC_RDSTA_SHFT 4
+#define TX_RDS_PS_MISC_RDSPTY_SHFT 5
+#define TX_RDS_PS_MISC_RDSTP_SHFT 10
+#define TX_RDS_PS_MISC_FORCEB_SHFT 11
+#define TX_RDS_PS_MISC_RDSD0_SHFT 12
+#define TX_RDS_PS_MISC_RDSD1_SHFT 13
+#define TX_RDS_PS_MISC_RDSD2_SHFT 14
+#define TX_RDS_PS_MISC_RDSD3_SHFT 15
+
+/* TX_RDS_PS_REPEAT_COUNT */
+#define TX_RDS_PS_REPEAT_COUNT 0x2C04
+#define TX_RDS_PS_REPEAT_COUNT_MASK 0x00FF
+#define TX_RDS_PS_REPEAT_COUNT_SHFT 0
+
+/* TX_RDS_PS_MESSAGE_COUNT */
+#define TX_RDS_PS_MESSAGE_COUNT 0x2C05
+#define TX_RDS_PS_MESSAGE_COUNT_MASK 0x000F
+#define TX_RDS_PS_MESSAGE_COUNT_SHFT 0
+
+/* TX_RDS_PS_AF */
+#define TX_RDS_PS_AF 0x2C06
+
+/* TX_RDS_FIFO_SIZE */
+#define TX_RDS_FIFO_SIZE 0x2C07
+#define TX_RDS_FIFO_SIZE_MASK 0x00FF
+#define TX_RDS_FIFO_SIZE_SHFT 0
+
+
+/*==================================================================
+ AM Receive Properties
+==================================================================*/
+
+/* AM_DEEMPHASIS */
+#define AM_DEEMPHASIS 0x3100
+#define AM_DEEMPHASIS_MASK 0x0001
+#define AM_DEEMPHASIS_SHFT 0
+
+/* AM_CHANNEL_FILTER */
+#define AM_CHANNEL_FILTER 0x3102
+#define AM_CHANNEL_FILTER_MASK 0x0007
+#define AM_CHANNEL_FILTER_SHFT 0
+
+/* AM_RSQ_INT_SOURCE */
+#define AM_RSQ_INT_SOURCE 0x3200
+#define AM_RSQ_INT_SOURCE_RSSILIEN_MASK 0x0001
+#define AM_RSQ_INT_SOURCE_RSSIHIEN_MASK 0x0002
+#define AM_RSQ_INT_SOURCE_ASNRLIEN_MASK 0x0004
+#define AM_RSQ_INT_SOURCE_ASNRHIEN_MASK 0x0008
+#define AM_RSQ_INT_SOURCE_RSSILIEN_SHFT 0
+#define AM_RSQ_INT_SOURCE_RSSIHIEN_SHFT 1
+#define AM_RSQ_INT_SOURCE_ASNRLIEN_SHFT 2
+#define AM_RSQ_INT_SOURCE_ASNRHIEN_SHFT 3
+
+/* AM_RSQ_SNR_HI_THRESHOLD */
+#define AM_RSQ_SNR_HI_THRESHOLD 0x3201
+#define AM_RSQ_SNR_HI_THRESHOLD_MASK 0x007F
+#define AM_RSQ_SNR_HI_THRESHOLD_SHFT 0
+
+/* AM_RSQ_SNR_LO_THRESHOLD */
+#define AM_RSQ_SNR_LO_THRESHOLD 0x3202
+#define AM_RSQ_SNR_LO_THRESHOLD_MASK 0x007F
+#define AM_RSQ_SNR_LO_THRESHOLD_SHFT 0
+
+/* AM_RSQ_RSSI_HI_THRESHOLD */
+#define AM_RSQ_RSSI_HI_THRESHOLD 0x3203
+#define AM_RSQ_RSSI_HI_THRESHOLD_MASK 0x007F
+#define AM_RSQ_RSSI_HI_THRESHOLD_SHFT 0
+
+/* AM_RSQ_RSSI_LO_THRESHOLD */
+#define AM_RSQ_RSSI_LO_THRESHOLD 0x3204
+#define AM_RSQ_RSSI_LO_THRESHOLD_MASK 0x007F
+#define AM_RSQ_RSSI_LO_THRESHOLD_SHFT 0
+
+/* AM_SOFT_MUTE_RATE */
+#define AM_SOFT_MUTE_RATE 0x3300
+
+/* AM_SOFT_MUTE_SLOPE */
+#define AM_SOFT_MUTE_SLOPE 0x3301
+#define AM_SOFT_MUTE_SLOPE_MASK 0x000F
+#define AM_SOFT_MUTE_SLOPE_SHFT 0
+
+/* AM_SOFT_MUTE_MAX_ATTENUATION */
+#define AM_SOFT_MUTE_MAX_ATTENUATION 0x3302
+#define AM_SOFT_MUTE_MAX_ATTENUATION_MASK 0x003F
+#define AM_SOFT_MUTE_MAX_ATTENUATION_SHFT 0
+
+/* AM_SOFT_MUTE_SNR_THRESHOLD */
+#define AM_SOFT_MUTE_SNR_THRESHOLD 0x3303
+#define AM_SOFT_MUTE_SNR_THRESHOLD_MASK 0x003F
+#define AM_SOFT_MUTE_SNR_THRESHOLD_SHFT 0
+
+/* AM_SEEK_BAND_BOTTOM */
+#define AM_SEEK_BAND_BOTTOM 0x3400
+
+/* AM_SEEK_BAND_TOP */
+#define AM_SEEK_BAND_TOP 0x3401
+
+/* AM_SEEK_FREQ_SPACING */
+#define AM_SEEK_FREQ_SPACING 0x3402
+#define AM_SEEK_FREQ_SPACING_MASK 0x000F
+#define AM_SEEK_FREQ_SPACING_SHFT 0
+
+/* AM_SEEK_TUNE_SNR_THRESHOLD */
+#define AM_SEEK_TUNE_SNR_THRESHOLD 0x3403
+#define AM_SEEK_TUNE_SNR_THRESHOLD_MASK 0x003F
+#define AM_SEEK_TUNE_SNR_THRESHOLD_SHFT 0
+
+/* AM_SEEK_TUNE_RSSI_THRESHOLD */
+#define AM_SEEK_TUNE_RSSI_THRESHOLD 0x3404
+#define AM_SEEK_TUNE_RSSI_THRESHOLD_MASK 0x003F
+#define AM_SEEK_TUNE_RSSI_THRESHOLD_SHFT 0
+
+/*==================================================================
+ General Receive Properties
+==================================================================*/
+
+/* RX_VOLUME */
+#define RX_VOLUME 0x4000
+#define RX_VOLUME_MASK 0x003F
+#define RX_VOLUME_SHFT 0
+
+/* RX_HARD_MUTE */
+#define RX_HARD_MUTE 0x4001
+#define RX_HARD_MUTE_RMUTE_MASK 0x0001
+#define RX_HARD_MUTE_LMUTE_MASK 0x0002
+#define RX_HARD_MUTE_RMUTE_SHFT 0
+#define RX_HARD_MUTE_LMUTE_SHFT 1
+
+/*==================================================================
+ Bit Definitions for Properties
+==================================================================*/
+
+/* DIGITAL_MODE - used for input or output */
+#define DIGITAL_MODE_I2S 0x0
+#define DIGITAL_MODE_LEFT 0x6
+#define DIGITAL_MODE_MSB1ST 0xC
+#define DIGITAL_MODE_MSB2ND 0x8
+
+/* DIGITAL_SIZE - used for input or output */
+#define DIGITAL_SIZE_16 0x0
+#define DIGITAL_SIZE_20 0x1
+#define DIGITAL_SIZE_24 0x2
+#define DIGITAL_SIZE_8 0x3
+
+/* FM_DEEMPH */
+#define FM_DEEMPH_75US 0x2
+#define FM_DEEMPH_50US 0x1
+
+/* FM_RDS_BLETH - used for all block error thresholds */
+#define FM_RDS_BLETH_NO_ERRORS 0x0
+#define FM_RDS_BLETH_1OR2_ERRORS 0x1
+#define FM_RDS_BLETH_3TO5_ERRORS 0x2
+#define FM_RDS_BLETH_UNCORRECTABLE 0x3
+
+/* TX_LINE_INPUT_LEVEL_LIATTEN */
+#define TX_LINE_INPUT_LEVEL_LIATTEN_396kOhm 0x0000
+#define TX_LINE_INPUT_LEVEL_LIATTEN_100kOhm 0x1000
+#define TX_LINE_INPUT_LEVEL_LIATTEN_74kOhm 0x2000
+#define TX_LINE_INPUT_LEVEL_LIATTEN_60kOhm 0x3000
+
+/* TX_DEEMPHASIS */
+#define TX_PREEMPHASIS_75US 0x0
+#define TX_PREEMPHASIS_50US 0x1
+#define TX_PREEMPHASIS_DISABLED 0x2
+
+/* TX_ACOMP_ATTACK_TIME */
+#define TX_ACOMP_ATTACK_TIME_0_5MS 0x0
+#define TX_ACOMP_ATTACK_TIME_1_0MS 0x1
+#define TX_ACOMP_ATTACK_TIME_1_5MS 0x2
+#define TX_ACOMP_ATTACK_TIME_2_0MS 0x3
+#define TX_ACOMP_ATTACK_TIME_2_5MS 0x4
+#define TX_ACOMP_ATTACK_TIME_3_0MS 0x5
+#define TX_ACOMP_ATTACK_TIME_3_5MS 0x6
+#define TX_ACOMP_ATTACK_TIME_4_0MS 0x7
+#define TX_ACOMP_ATTACK_TIME_4_5MS 0x8
+#define TX_ACOMP_ATTACK_TIME_5_0MS 0x9
+
+/* TX_ACOMP_RELEASE_TIME */
+#define TX_ACOMP_RELEASE_TIME_100MS 0x0
+#define TX_ACOMP_RELEASE_TIME_200MS 0x1
+#define TX_ACOMP_RELEASE_TIME_350MS 0x2
+#define TX_ACOMP_RELEASE_TIME_525MS 0x3
+#define TX_ACOMP_RELEASE_TIME_1000MS 0x4
+
+/* TX_RDS_PS_MIX */
+#define TX_RDS_PS_MIX_FIFO_EMPTY 0x0
+#define TX_RDS_PS_MIX_12_5_PCT 0x1
+#define TX_RDS_PS_MIX_25_PCT 0x2
+#define TX_RDS_PS_MIX_50_PCT 0x3
+#define TX_RDS_PS_MIX_75_PCT 0x4
+#define TX_RDS_PS_MIX_87_5_PCT 0x5
+#define TX_RDS_PS_MIX_100_PCT 0x6
+
+/* TX_RDS_PS_MISC_PTY */
+#define TX_RDS_PS_MISC_PTY_NONE 0
+#define TX_RDS_PS_MISC_PTY_NEWS 1
+#define TX_RDS_PS_MISC_PTY_INFO 2
+#define TX_RDS_PS_MISC_PTY_SPORTS 3
+#define TX_RDS_PS_MISC_PTY_TALK 4
+#define TX_RDS_PS_MISC_PTY_ROCK 5
+#define TX_RDS_PS_MISC_PTY_CLROCK 6
+#define TX_RDS_PS_MISC_PTY_ADHITS 7
+#define TX_RDS_PS_MISC_PTY_SOFTROCK 8
+#define TX_RDS_PS_MISC_PTY_TOP40 9
+#define TX_RDS_PS_MISC_PTY_COUNTRY 10
+#define TX_RDS_PS_MISC_PTY_OLDIES 11
+#define TX_RDS_PS_MISC_PTY_SOFT 12
+#define TX_RDS_PS_MISC_PTY_NOST 13
+#define TX_RDS_PS_MISC_PTY_JAZZ 14
+#define TX_RDS_PS_MISC_PTY_CLASS 15
+#define TX_RDS_PS_MISC_PTY_RHYBLUES 16
+#define TX_RDS_PS_MISC_PTY_SOFTRB 17
+#define TX_RDS_PS_MISC_PTY_FGNLANG 18
+#define TX_RDS_PS_MISC_PTY_RMUSIC 19
+#define TX_RDS_PS_MISC_PTY_RTALK 20
+#define TX_RDS_PS_MISC_PTY_PERS 21
+#define TX_RDS_PS_MISC_PTY_PUBLIC 22
+#define TX_RDS_PS_MISC_PTY_COLLEGE 23
+#define TX_RDS_PS_MISC_PTY_UN24 24
+#define TX_RDS_PS_MISC_PTY_UN25 25
+#define TX_RDS_PS_MISC_PTY_UN26 26
+#define TX_RDS_PS_MISC_PTY_UN27 27
+#define TX_RDS_PS_MISC_PTY_UN28 28
+#define TX_RDS_PS_MISC_PTY_WTHR 29
+#define TX_RDS_PS_MISC_PTY_EMERTEST 30
+#define TX_RDS_PS_MISC_PTY_ALERT 31
+
+/* AM_CHANNEL_FILTER_BW */
+#define AM_CHANNEL_FILTER_BW_6KHZ 0
+#define AM_CHANNEL_FILTER_BW_4KHZ 1
+#define AM_CHANNEL_FILTER_BW_3KHZ 2
+#define AM_CHANNEL_FILTER_BW_2KHZ 3
+
+
+/*==================================================================
+ WB Receive Properties
+==================================================================*/
+
+
+/* WB_MAX_TUNE_ERROR */
+#define WB_MAX_TUNE_ERROR 0x5108
+
+/* WB_VALID_SNR_THRESHOLD */
+#define WB_VALID_SNR_THRESHOLD 0x5403
+#define WB_VALID_SNR_THRESHOLD_MASK 0x007F
+#define WB_VALID_SNR_THRESHOLD_SHFT 0
+
+/* WB_VALID_RSSI_THRESHOLD */
+#define WB_VALID_RSSI_THRESHOLD 0x5404
+#define WB_VALID_RSSI_THRESHOLD_MASK 0x007F
+#define WB_VALID_RSSI_THRESHOLD_SHFT 0
+
+#endif