aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/samsung/fm_si47xx/Si47xx_i2c_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/samsung/fm_si47xx/Si47xx_i2c_drv.c')
-rw-r--r--drivers/samsung/fm_si47xx/Si47xx_i2c_drv.c768
1 files changed, 768 insertions, 0 deletions
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");
+