diff options
author | codeworkx <daniel.hillenbrand@codeworkx.de> | 2012-06-02 13:09:29 +0200 |
---|---|---|
committer | codeworkx <daniel.hillenbrand@codeworkx.de> | 2012-06-02 13:09:29 +0200 |
commit | c6da2cfeb05178a11c6d062a06f8078150ee492f (patch) | |
tree | f3b4021d252c52d6463a9b3c1bb7245e399b009c /drivers/samsung/fm_si4709/Si4705_main.c | |
parent | c6d7c4dbff353eac7919342ae6b3299a378160a6 (diff) | |
download | kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.zip kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.tar.gz kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.tar.bz2 |
samsung update 1
Diffstat (limited to 'drivers/samsung/fm_si4709/Si4705_main.c')
-rw-r--r-- | drivers/samsung/fm_si4709/Si4705_main.c | 864 |
1 files changed, 864 insertions, 0 deletions
diff --git a/drivers/samsung/fm_si4709/Si4705_main.c b/drivers/samsung/fm_si4709/Si4705_main.c new file mode 100644 index 0000000..aaccd5f --- /dev/null +++ b/drivers/samsung/fm_si4709/Si4705_main.c @@ -0,0 +1,864 @@ +#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 "Si4709_i2c_drv.h" +#include "Si4709_dev.h" +#include "Si4709_ioctl.h" +#include "Si4709_common.h" + +/*******************************************************/ + +/*static functions*/ + +/*file operatons*/ +static int Si4709_open(struct inode *, struct file *); +static int Si4709_release(struct inode *, struct file *); +static long Si4709_ioctl(struct file *, unsigned int, unsigned long); + +/*ISR*/ +static irqreturn_t Si4709_isr(int irq, void *unused); +/* static void __iomem *gpio_mask_mem; */ +/**********************************************************/ + +static const struct file_operations Si4709_fops = { + .owner = THIS_MODULE, + .open = Si4709_open, + .unlocked_ioctl = Si4709_ioctl, + .release = Si4709_release, +}; + +static struct miscdevice Si4709_misc_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = "fmradio", + .fops = &Si4709_fops, +}; + +/*VNVS:START 13-OCT'09---- +dummy struct which is used as a cookie for FM Radio interrupt */ +struct fm_radio { + int i; + int j; +}; + +struct fm_radio fm_radio_1; +/*VNVS:END*/ + +wait_queue_head_t Si4709_waitq; + +unsigned int Si4709_int; +unsigned int Si4709_irq; + +/***************************************************************/ + +static int Si4709_open(struct inode *inode, struct file *filp) +{ + debug("Si4709_open called\n"); + + return nonseekable_open(inode, filp); +} + +static int Si4709_release(struct inode *inode, struct file *filp) +{ + debug("Si4709_release called\n\n"); + + return 0; +} + +static long Si4709_ioctl(struct file *filp, unsigned int ioctl_cmd, + unsigned long arg) +{ + long ret = 0; + void __user *argp = (void __user *)arg; + + debug("Si4709 ioctl 0x%x", ioctl_cmd); + + if (_IOC_TYPE(ioctl_cmd) != Si4709_IOC_MAGIC) { + debug("Inappropriate ioctl 1 0x%x", ioctl_cmd); + return -ENOTTY; + } + + if (_IOC_NR(ioctl_cmd) > Si4709_IOC_NR_MAX) { + debug("Inappropriate ioctl 2 0x%x", ioctl_cmd); + return -ENOTTY; + } + + + switch (ioctl_cmd) { + case Si4709_IOC_POWERUP: + debug("Si4709_IOC_POWERUP called\n\n"); + + ret = (long)Si4709_dev_powerup(); + if (ret < 0) + debug("Si4709_IOC_POWERUP failed\n"); + break; + + case Si4709_IOC_POWERDOWN: + debug("Si4709_IOC_POWERDOWN called\n"); + + ret = (long)Si4709_dev_powerdown(); + if (ret < 0) + debug("Si4709_IOC_POWERDOWN failed\n"); + break; + + case Si4709_IOC_BAND_SET: + { + int band; + debug("Si4709_IOC_BAND_SET called\n\n"); + + if (copy_from_user((void *)&band, argp, sizeof(int))) + ret = -EFAULT; + else { + ret = (long)Si4709_dev_band_set(band); + if (ret < 0) + debug("Si4709_IOC_BAND_SET failed\n"); + } + } + break; + + case Si4709_IOC_CHAN_SPACING_SET: + { + int ch_spacing; + debug("Si4709_IOC_CHAN_SPACING_SET called\n"); + + if (copy_from_user + ((void *)&ch_spacing, argp, sizeof(int))) + ret = -EFAULT; + else { + ret = (long)Si4709_dev_ch_spacing_set(ch_spacing); + if (ret < 0) + debug("Si4709_IOC_CHAN_SPACING_SET " + "failed\n"); + } + } + break; + + case Si4709_IOC_CHAN_SELECT: + { + u32 frequency; + debug("Si4709_IOC_CHAN_SELECT called\n"); + + if (copy_from_user + ((void *)&frequency, argp, sizeof(u32))) + ret = -EFAULT; + else { + ret = (long)Si4709_dev_chan_select(frequency); + if (ret < 0) + debug("Si4709_IOC_CHAN_SELECT " + "failed\n"); + } + } + break; + + case Si4709_IOC_CHAN_GET: + { + u32 frequency = 0; + debug("Si4709_IOC_CHAN_GET called\n"); + + ret = (long)Si4709_dev_chan_get(&frequency); + if (ret < 0) + debug("Si4709_IOC_CHAN_GET failed\n"); + else if (copy_to_user + (argp, (void *)&frequency, sizeof(u32))) + ret = -EFAULT; + } + 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; + debug("Si4709_IOC_SEEK_UP called\n"); + + ret = (long)Si4709_dev_seek_up(&frequency); + if (ret < 0) + debug("Si4709_IOC_SEEK_UP failed\n"); + else if (copy_to_user + (argp, (void *)&frequency, sizeof(u32))) + ret = -EFAULT; + } + break; + + case Si4709_IOC_SEEK_DOWN: + { + u32 frequency = 0; + debug("Si4709_IOC_SEEK_DOWN called\n"); + + ret = (long)Si4709_dev_seek_down(&frequency); + if (ret < 0) + debug("Si4709_IOC_SEEK_DOWN failed\n"); + else if (copy_to_user + (argp, (void *)&frequency, sizeof(u32))) + ret = -EFAULT; + } + break; + + case Si4709_IOC_RSSI_SEEK_TH_SET: + { + u8 RSSI_seek_th; + debug("Si4709_IOC_RSSI_SEEK_TH_SET called\n"); + + if (copy_from_user + ((void *)&RSSI_seek_th, argp, sizeof(u8))) + ret = -EFAULT; + else { + ret = (long)Si4709_dev_RSSI_seek_th_set(RSSI_seek_th); + if (ret < 0) + debug("Si4709_IOC_RSSI_SEEK_TH_SET " + "failed\n"); + } + } + break; + + case Si4709_IOC_SEEK_SNR_SET: + { + u8 seek_SNR_th; + debug("Si4709_IOC_SEEK_SNR_SET called\n"); + + if (copy_from_user + ((void *)&seek_SNR_th, argp, sizeof(u8))) + ret = -EFAULT; + else { + ret = (long)Si4709_dev_seek_SNR_th_set(seek_SNR_th); + if (ret < 0) + debug("Si4709_IOC_SEEK_SNR_SET " + "failed\n"); + } + } + break; + + case Si4709_IOC_SEEK_CNT_SET: + { + u8 seek_FM_ID_th; + debug("Si4709_IOC_SEEK_CNT_SET called\n"); + + if (copy_from_user + ((void *)&seek_FM_ID_th, argp, sizeof(u8))) + ret = -EFAULT; + else { + ret = + (long)Si4709_dev_seek_FM_ID_th_set(seek_FM_ID_th); + if (ret < 0) + debug("Si4709_IOC_SEEK_CNT_SET " + "failed\n"); + } + } + break; + + case Si4709_IOC_CUR_RSSI_GET: + { + struct rssi_snr_t data; + debug("Si4709_IOC_CUR_RSSI_GET called\n"); + + ret = (long)Si4709_dev_cur_RSSI_get(&data); + if (ret < 0) + debug("Si4709_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 Si4709_IOC_VOLEXT_ENB: + debug("Si4709_IOC_VOLEXT_ENB called\n"); + + ret = (long)Si4709_dev_VOLEXT_ENB(); + if (ret < 0) + debug("Si4709_IOC_VOLEXT_ENB failed\n"); + break; + + case Si4709_IOC_VOLEXT_DISB: + debug("Si4709_IOC_VOLEXT_DISB called\n"); + + ret = (long)Si4709_dev_VOLEXT_DISB(); + if (ret < 0) + debug("Si4709_IOC_VOLEXT_DISB failed\n"); + break; + + case Si4709_IOC_VOLUME_SET: + { + u8 volume; + if (copy_from_user((void *)&volume, argp, sizeof(u8))) + ret = -EFAULT; + else { + debug("Si4709_IOC_VOLUME_SET called " + "vol %d\n", volume); + ret = (long)Si4709_dev_volume_set(volume); + if (ret < 0) + debug("Si4709_IOC_VOLUME_SET failed\n"); + } + } + break; + + case Si4709_IOC_VOLUME_GET: + { + u8 volume; + 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 + (argp, (void *)&volume, sizeof(u8))) + ret = -EFAULT; + } + break; + + case Si4709_IOC_DSMUTE_ON: + debug("Si4709_IOC_DSMUTE_ON called\n\n"); + + ret = (long)Si4709_dev_DSMUTE_ON(); + if (ret < 0) + error("Si4709_IOC_DSMUTE_ON failed\n"); + break; + + case Si4709_IOC_DSMUTE_OFF: + debug("Si4709_IOC_DSMUTE_OFF called\n\n"); + + ret = (long)Si4709_dev_DSMUTE_OFF(); + if (ret < 0) + error("Si4709_IOC_DSMUTE_OFF failed\n"); + break; + + case Si4709_IOC_MUTE_ON: + debug("Si4709_IOC_MUTE_ON called\n"); + + ret = (long)Si4709_dev_MUTE_ON(); + if (ret < 0) + debug("Si4709_IOC_MUTE_ON failed\n"); + break; + + case Si4709_IOC_MUTE_OFF: + debug("Si4709_IOC_MUTE_OFF called\n"); + + ret = (long)Si4709_dev_MUTE_OFF(); + if (ret < 0) + debug("Si4709_IOC_MUTE_OFF failed\n"); + break; + + case Si4709_IOC_MONO_SET: + debug("Si4709_IOC_MONO_SET called\n"); + + ret = (long)Si4709_dev_MONO_SET(); + if (ret < 0) + debug("Si4709_IOC_MONO_SET failed\n"); + break; + + case Si4709_IOC_STEREO_SET: + debug("Si4709_IOC_STEREO_SET called\n"); + + ret = (long)Si4709_dev_STEREO_SET(); + if (ret < 0) + debug("Si4709_IOC_STEREO_SET failed\n"); + break; + + case Si4709_IOC_RSTATE_GET: + { + struct dev_state_t dev_state; + + debug("Si4709_IOC_RSTATE_GET called\n"); + + ret = (long)Si4709_dev_rstate_get(&dev_state); + if (ret < 0) + debug("Si4709_IOC_RSTATE_GET failed\n"); + else if (copy_to_user(argp, (void *)&dev_state, + sizeof(dev_state))) + ret = -EFAULT; + } + break; + + case Si4709_IOC_RDS_DATA_GET: + { + struct radio_data_t data; + debug("Si4709_IOC_RDS_DATA_GET called\n"); + + ret = (long)Si4709_dev_RDS_data_get(&data); + if (ret < 0) + debug(" Si4709_IOC_RDS_DATA_GET failed\n"); + else if (copy_to_user(argp, (void *)&data, + sizeof(data))) + ret = -EFAULT; + } + break; + + case Si4709_IOC_RDS_ENABLE: + debug("Si4709_IOC_RDS_ENABLE called\n"); + + ret = (long)Si4709_dev_RDS_ENABLE(); + if (ret < 0) + debug("Si4709_IOC_RDS_ENABLE failed\n"); + break; + + case Si4709_IOC_RDS_DISABLE: + debug("Si4709_IOC_RDS_DISABLE called\n"); + + ret = (long)Si4709_dev_RDS_DISABLE(); + if (ret < 0) + debug("Si4709_IOC_RDS_DISABLE failed\n"); + break; + + case Si4709_IOC_RDS_TIMEOUT_SET: + { + u32 time_out; + debug("Si4709_IOC_RDS_TIMEOUT_SET called\n"); + + if (copy_from_user + ((void *)&time_out, argp, sizeof(u32))) + ret = -EFAULT; + else { + ret = (long)Si4709_dev_RDS_timeout_set(time_out); + if (ret < 0) + debug("Si4709_IOC_RDS_TIMEOUT_SET " + "failed\n"); + } + } + break; + + case Si4709_IOC_SEEK_CANCEL: + debug("Si4709_IOC_SEEK_CANCEL called\n"); + + if (Si4709_dev_wait_flag == SEEK_WAITING) { + Si4709_dev_wait_flag = SEEK_CANCEL; + wake_up_interruptible(&Si4709_waitq); + } + break; + +/*VNVS:START 13-OCT'09---- +Switch Case statements for calling functions which reads device-id, +chip-id,power configuration, system configuration2 registers */ + case Si4709_IOC_CHIP_ID_GET: + { + struct chip_id chp_id; + debug("Si4709_IOC_CHIP_ID called\n"); + + ret = (long)Si4709_dev_chip_id(&chp_id); + if (ret < 0) + debug("Si4709_IOC_CHIP_ID failed\n"); + else if (copy_to_user(argp, (void *)&chp_id, + sizeof(chp_id))) + ret = -EFAULT; + } + break; + + case Si4709_IOC_DEVICE_ID_GET: + { + struct device_id dev_id; + debug("Si4709_IOC_DEVICE_ID called\n"); + + ret = (long)Si4709_dev_device_id(&dev_id); + if (ret < 0) + debug("Si4709_IOC_DEVICE_ID failed\n"); + else if (copy_to_user(argp, (void *)&dev_id, + sizeof(dev_id))) + ret = -EFAULT; + } + break; + + case Si4709_IOC_SYS_CONFIG2_GET: + { + struct sys_config2 sys_conf2; + debug("Si4709_IOC_SYS_CONFIG2 called\n"); + + ret = (long)Si4709_dev_sys_config2(&sys_conf2); + if (ret < 0) + debug("Si4709_IOC_SYS_CONFIG2 failed\n"); + else if (copy_to_user(argp, (void *)&sys_conf2, + sizeof(sys_conf2))) + ret = -EFAULT; + } + break; + + case Si4709_IOC_SYS_CONFIG3_GET: + { + struct sys_config3 sys_conf3; + debug("Si4709_IOC_SYS_CONFIG3 called\n"); + + ret = (long)Si4709_dev_sys_config3(&sys_conf3); + if (ret < 0) + debug("Si4709_IOC_SYS_CONFIG3 failed\n"); + else if (copy_to_user(argp, (void *)&sys_conf3, + sizeof(sys_conf3))) + ret = -EFAULT; + } + break; + + case Si4709_IOC_POWER_CONFIG_GET: + { + struct power_config pow_conf; + debug("Si4709_IOC_POWER_CONFIG called\n"); + + ret = (long)Si4709_dev_power_config(&pow_conf); + if (ret < 0) + debug("Si4709_IOC_POWER_CONFIG failed\n"); + else if (copy_to_user(argp, (void *)&pow_conf, + sizeof(pow_conf))) + ret = -EFAULT; + } + break; +/*VNVS:END*/ + +/*VNVS:START 18-NOV'09*/ + /*Reading AFCRL Bit */ + case Si4709_IOC_AFCRL_GET: + { + u8 afc; + debug("Si4709_IOC_AFCRL_GET called\n"); + + ret = (long)Si4709_dev_AFCRL_get(&afc); + if (ret < 0) + debug("Si4709_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 Si4709_IOC_DE_SET: + { + u8 de_tc; + debug("Si4709_IOC_DE_SET called\n"); + + if (copy_from_user((void *)&de_tc, argp, sizeof(u8))) + ret = -EFAULT; + else { + ret = (long)Si4709_dev_DE_set(de_tc); + if (ret < 0) + debug("Si4709_IOC_DE_SET failed\n"); + } + } + break; + + case Si4709_IOC_STATUS_RSSI_GET: + { + struct status_rssi status; + debug("Si4709_IOC_STATUS_RSSI_GET called\n"); + + ret = (long)Si4709_dev_status_rssi(&status); + if (ret < 0) + debug("Si4709_IOC_STATUS_RSSI_GET failed\n"); + else if (copy_to_user(argp, (void *)&status, + sizeof(status))) + ret = -EFAULT; + } + break; + + case Si4709_IOC_SYS_CONFIG2_SET: + { + struct sys_config2 sys_conf2; + unsigned long n; + debug("Si4709_IOC_SYS_CONFIG2_SET called\n"); + + n = copy_from_user((void *)&sys_conf2, argp, + sizeof(sys_conf2)); + if (n) { + debug("Si4709_IOC_SYS_CONFIG2_SET() : " + "copy_from_user() has error!! " + "Failed to read [%lu] byes!", n); + ret = -EFAULT; + } else { + ret = (long)Si4709_dev_sys_config2_set(&sys_conf2); + if (ret < 0) + debug("Si4709_IOC_SYS_CONFIG2_SET" + "failed\n"); + } + } + break; + + case Si4709_IOC_SYS_CONFIG3_SET: + { + struct sys_config3 sys_conf3; + unsigned long n; + + debug("Si4709_IOC_SYS_CONFIG3_SET called\n"); + + n = copy_from_user((void *)&sys_conf3, argp, + sizeof(sys_conf3)); + if (n) { + debug("Si4709_IOC_SYS_CONFIG3_SET() : " + "copy_from_user() has error!! " + "Failed to read [%lu] byes!", n); + ret = -EFAULT; + } else { + ret = (long)Si4709_dev_sys_config3_set(&sys_conf3); + if (ret < 0) + debug("Si4709_IOC_SYS_CONFIG3_SET " + "failed\n"); + } + } + break; + + /*Resetting the RDS Data Buffer */ + case Si4709_IOC_RESET_RDS_DATA: + { + debug("Si4709_IOC_RESET_RDS_DATA called\n"); + + ret = (long)Si4709_dev_reset_rds_data(); + if (ret < 0) + error("Si4709_IOC_RESET_RDS_DATA failed\n"); + } + break; +/*VNVS:END*/ + default: + debug(" ioctl default\n"); + ret = -ENOTTY; + break; + } + + return ret; +} + +static irqreturn_t Si4709_isr(int irq, void *unused) +{ + debug("Si4709_isr: FM device called IRQ: %d\n", irq); +#ifdef RDS_INTERRUPT_ON_ALWAYS + if ((Si4709_dev_wait_flag == SEEK_WAITING) || + (Si4709_dev_wait_flag == TUNE_WAITING)) { + debug("Si4709_isr: FM Seek/Tune Interrupt " + "called IRQ %d\n", irq); + Si4709_dev_wait_flag = WAIT_OVER; + wake_up_interruptible(&Si4709_waitq); + } else if (Si4709_RDS_flag == RDS_WAITING) { /* RDS Interrupt */ + debug_rds("Si4709_isr: FM RDS Interrupt " + "called IRQ %d", irq); + + debug_rds("RDS_Groups_Available_till_now b/w " + "Power ON/OFF : %d", + RDS_Groups_Available_till_now); + + if (!work_pending(&Si4709_work)) + queue_work(Si4709_wq, &Si4709_work); + } +#else + if ((Si4709_dev_wait_flag == SEEK_WAITING) || + (Si4709_dev_wait_flag == TUNE_WAITING) || + (Si4709_dev_wait_flag == RDS_WAITING)) { + Si4709_dev_wait_flag = WAIT_OVER; + wake_up_interruptible(&Si4709_waitq); + } +#endif + return IRQ_HANDLED; +} + +/************************************************************/ + +void debug_ioctls(void) +{ + debug("------------------------------------------------\n"); + + debug("Si4709_IOC_POWERUP 0x%x", Si4709_IOC_POWERUP); + + debug("Si4709_IOC_POWERDOWN 0x%x", Si4709_IOC_POWERDOWN); + + debug("Si4709_IOC_BAND_SET 0x%x", Si4709_IOC_BAND_SET); + + debug("Si4709_IOC_CHAN_SPACING_SET 0x%x", Si4709_IOC_CHAN_SPACING_SET); + + debug("Si4709_IOC_CHAN_SELECT 0x%x", Si4709_IOC_CHAN_SELECT); + + debug("Si4709_IOC_CHAN_GET 0x%x", Si4709_IOC_CHAN_GET); + + debug("Si4709_IOC_SEEK_UP 0x%x", Si4709_IOC_SEEK_UP); + + debug("Si4709_IOC_SEEK_DOWN 0x%x", Si4709_IOC_SEEK_DOWN); + + /*VNVS:28OCT'09---- Si4709_IOC_SEEK_AUTO is disabled as of now */ + /* debug("Si4709_IOC_SEEK_AUTO 0x%x", Si4709_IOC_SEEK_AUTO); */ + + debug("Si4709_IOC_RSSI_SEEK_TH_SET 0x%x", Si4709_IOC_RSSI_SEEK_TH_SET); + + debug("Si4709_IOC_SEEK_SNR_SET 0x%x", Si4709_IOC_SEEK_SNR_SET); + + debug("Si4709_IOC_SEEK_CNT_SET 0x%x", Si4709_IOC_SEEK_CNT_SET); + + debug("Si4709_IOC_CUR_RSSI_GET 0x%x", Si4709_IOC_CUR_RSSI_GET); + + debug("Si4709_IOC_VOLEXT_ENB 0x%x", Si4709_IOC_VOLEXT_ENB); + + debug("Si4709_IOC_VOLEXT_DISB 0x%x", Si4709_IOC_VOLEXT_DISB); + + debug("Si4709_IOC_VOLUME_SET 0x%x", Si4709_IOC_VOLUME_SET); + + debug("Si4709_IOC_VOLUME_GET 0x%x", Si4709_IOC_VOLUME_GET); + + debug("Si4709_IOC_MUTE_ON 0x%x", Si4709_IOC_MUTE_ON); + + debug("Si4709_IOC_MUTE_OFF 0x%x", Si4709_IOC_MUTE_OFF); + + debug("Si4709_IOC_MONO_SET 0x%x", Si4709_IOC_MONO_SET); + + debug("Si4709_IOC_STEREO_SET 0x%x", Si4709_IOC_STEREO_SET); + + debug("Si4709_IOC_RSTATE_GET 0x%x", Si4709_IOC_RSTATE_GET); + + debug("Si4709_IOC_RDS_DATA_GET 0x%x", Si4709_IOC_RDS_DATA_GET); + + debug("Si4709_IOC_RDS_ENABLE 0x%x", Si4709_IOC_RDS_ENABLE); + + debug("Si4709_IOC_RDS_DISABLE 0x%x", Si4709_IOC_RDS_DISABLE); + + debug("Si4709_IOC_RDS_TIMEOUT_SET 0x%x", Si4709_IOC_RDS_TIMEOUT_SET); + + debug("Si4709_IOC_DEVICE_ID_GET 0x%x", Si4709_IOC_DEVICE_ID_GET); + + debug("Si4709_IOC_CHIP_ID_GET 0x%x", Si4709_IOC_CHIP_ID_GET); + + debug("Si4709_IOC_SYS_CONFIG2_GET 0x%x", Si4709_IOC_SYS_CONFIG2_GET); + + debug("Si4709_IOC_POWER_CONFIG_GET 0x%x", Si4709_IOC_POWER_CONFIG_GET); + + debug("Si4709_IOC_AFCRL_GET 0x%x", Si4709_IOC_AFCRL_GET); + + debug("Si4709_IOC_DE_SET 0x%x", Si4709_IOC_DE_SET); + + debug("Si4709_IOC_DSMUTE_ON 0x%x", Si4709_IOC_DSMUTE_ON); + + debug("Si4709_IOC_DSMUTE_OFF 0x%x", Si4709_IOC_DSMUTE_OFF); + + debug("Si4709_IOC_RESET_RDS_DATA 0x%x", Si4709_IOC_RESET_RDS_DATA); + + debug("------------------------------------------------\n"); +} + +int __init Si4709_driver_init(void) +{ + int ret = 0; + + debug("Si4709_driver_init called\n"); + + /*Initialize the Si4709 dev mutex */ + Si4709_dev_mutex_init(); + + /*misc device registration */ + ret = misc_register(&Si4709_misc_device); + if (ret < 0) { + error("Si4709_driver_init misc_register failed\n"); + return ret; + } + +#if defined(CONFIG_MACH_M0) + if (system_rev >= 15) + Si4709_int = GPIO_FM_INT_REV15; + else +#endif + Si4709_int = GPIO_FM_INT; + + Si4709_irq = gpio_to_irq(Si4709_int); + + irq_set_irq_type(Si4709_irq, IRQ_TYPE_EDGE_FALLING); + /*KGVS: Configuring the GPIO_FM_INT in mach-jupiter.c */ + ret = request_irq(Si4709_irq, Si4709_isr, + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "Si4709", NULL); + if (ret) { + error("Si4709_driver_init request_irq " + "failed %d", Si4709_int); + goto MISC_DREG; + } else + debug("Si4709_driver_init request_irq " + "success %d", Si4709_int); + + if (gpio_is_valid(GPIO_FM_RST)) { + if (gpio_request(GPIO_FM_RST, "GPC1")) + debug(KERN_ERR "Failed to request " + "FM_RESET!\n\n"); + 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")) + debug(KERN_ERR "Failed to request " + "FM_MIC_SW!\n\n"); + gpio_direction_output(GPIO_FM_RST, GPIO_LEVEL_LOW); + } +#endif + + /*VNVS: 13-OCT'09---- + Initially Pulling the interrupt pin HIGH + 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); + 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); + 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); + + /*Add the i2c driver */ + ret = Si4709_i2c_drv_init(); + if (ret < 0) + goto MISC_IRQ_DREG; + + init_waitqueue_head(&Si4709_waitq); + + debug("Si4709_driver_init successful\n"); + + return ret; + +MISC_IRQ_DREG: + free_irq(Si4709_irq, NULL); +MISC_DREG: + misc_deregister(&Si4709_misc_device); + + return ret; +} + +void __exit Si4709_driver_exit(void) +{ + debug("Si4709_driver_exit called\n"); + +#if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_M0_CTC) + gpio_free(GPIO_FM_MIC_SW); +#endif + + /*Delete the i2c driver */ + Si4709_i2c_drv_exit(); + free_irq(Si4709_irq, NULL); + + /*misc device deregistration */ + misc_deregister(&Si4709_misc_device); +} + +module_init(Si4709_driver_init); +module_exit(Si4709_driver_exit); +MODULE_AUTHOR("Varun Mahajan <m.varun@samsung.com>"); +MODULE_DESCRIPTION("Si4709 FM tuner driver"); +MODULE_LICENSE("GPL"); |