#include <linux/mfd/core.h>
#include <linux/mfd/rk610_core.h>
#include <linux/clk.h>
-#include <mach/iomux.h>
+#include <linux/gpio.h>
#include <linux/err.h>
#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
#if defined(CONFIG_DEBUG_FS)
#include <linux/fs.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
-
#endif
-
+#define GPIO_HIGH 1
+#define GPIO_LOW 0
/*
* Debug
static struct i2c_client *rk610_control_client = NULL;
+int i2c_master_reg8_send(const struct i2c_client *client, const char reg, const char *buf, int count, int scl_rate)
+{
+ struct i2c_adapter *adap=client->adapter;
+ struct i2c_msg msg;
+ int ret;
+ char *tx_buf = (char *)kmalloc(count + 1, GFP_KERNEL);
+ if(!tx_buf)
+ return -ENOMEM;
+ tx_buf[0] = reg;
+ memcpy(tx_buf+1, buf, count);
+
+ msg.addr = client->addr;
+ msg.flags = client->flags;
+ msg.len = count + 1;
+ msg.buf = (char *)tx_buf;
+ msg.scl_rate = scl_rate;
+// msg.udelay = client->udelay;
+
+ ret = i2c_transfer(adap, &msg, 1);
+ kfree(tx_buf);
+ return (ret == 1) ? count : ret;
+
+}
+
+int i2c_master_reg8_recv(const struct i2c_client *client, const char reg, char *buf, int count, int scl_rate)
+{
+ struct i2c_adapter *adap=client->adapter;
+ struct i2c_msg msgs[2];
+ int ret;
+ char reg_buf = reg;
+
+ msgs[0].addr = client->addr;
+ msgs[0].flags = client->flags;
+ msgs[0].len = 1;
+ msgs[0].buf = ®_buf;
+ msgs[0].scl_rate = scl_rate;
+// msgs[0].udelay = client->udelay;
+
+ msgs[1].addr = client->addr;
+ msgs[1].flags = client->flags | I2C_M_RD;
+ msgs[1].len = count;
+ msgs[1].buf = (char *)buf;
+ msgs[1].scl_rate = scl_rate;
+// msgs[1].udelay = client->udelay;
+
+ ret = i2c_transfer(adap, msgs, 2);
+
+ return (ret == 2)? count : ret;
+}
+
static struct mfd_cell rk610_devs[] = {
{
const struct i2c_device_id *id)
{
int ret;
- struct clk *iis_clk;
struct rk610_core_info *core_info = NULL;
- struct rk610_ctl_platform_data *pdata = client->dev.platform_data;
+ struct device_node *rk610_np;
+
DBG("[%s] start\n", __FUNCTION__);
core_info = kmalloc(sizeof(struct rk610_core_info), GFP_KERNEL);
if(!core_info)
return -ENOMEM;
}
memset(core_info, 0, sizeof(struct rk610_core_info));
- core_info->pdata = pdata;
- #if defined(CONFIG_SND_RK29_SOC_I2S_8CH)
- iis_clk = clk_get_sys("rk29_i2s.0", "i2s");
- #elif defined(CONFIG_SND_RK29_SOC_I2S_2CH)
- iis_clk = clk_get_sys("rk29_i2s.1", "i2s");
- #else
- iis_clk = clk_get_sys("rk29_i2s.2", "i2s");
- #endif
- if (IS_ERR(iis_clk)) {
- printk("failed to get i2s clk\n");
- ret = PTR_ERR(iis_clk);
- }else{
- DBG("got i2s clk ok!\n");
- clk_enable(iis_clk);
- clk_set_rate(iis_clk, 11289600);
- #if defined(CONFIG_ARCH_RK29)
- rk29_mux_api_set(GPIO2D0_I2S0CLK_MIIRXCLKIN_NAME, GPIO2H_I2S0_CLK);
- #elif defined(CONFIG_ARCH_RK3066B)||defined(CONFIG_ARCH_RK3188)
- iomux_set(I2S0_MCLK);
- #elif defined(CONFIG_ARCH_RK30)
- rk30_mux_api_set(GPIO0B0_I2S8CHCLK_NAME, GPIO0B_I2S_8CH_CLK);
- #endif
- clk_put(iis_clk);
- }
rk610_control_client = client;
- if(core_info->pdata->rk610_power_on_init)
- core_info->pdata->rk610_power_on_init();
+
core_info->client = client;
core_info->dev = &client->dev;
i2c_set_clientdata(client,core_info);
+
+ rk610_np = core_info->dev->of_node;
+ core_info->reset_gpio = of_get_named_gpio(rk610_np,"rk610-reset-io", 0);
+ if (!gpio_is_valid(core_info->reset_gpio)){
+ printk("invalid core_info->reset_gpio: %d\n",core_info->reset_gpio);
+ return -1;
+ }
+ ret = gpio_request(core_info->reset_gpio, "rk610-reset-io");
+ if( ret != 0){
+ printk("gpio_request core_info->reset_gpio invalid: %d\n",core_info->reset_gpio);
+ return ret;
+ }
+ gpio_direction_output(core_info->reset_gpio, GPIO_HIGH);
+ msleep(100);
+ gpio_direction_output(core_info->reset_gpio, GPIO_LOW);
+ msleep(100);
+ gpio_set_value(core_info->reset_gpio, GPIO_HIGH);
+
+ core_info->i2s_clk= clk_get(&client->dev, "i2s_clk");
+ if (IS_ERR(core_info->i2s_clk)) {
+ dev_err(&client->dev, "Can't retrieve i2s clock\n");
+ ret = PTR_ERR(core_info->i2s_clk);
+ return ret;
+ }
+ clk_set_rate(core_info->i2s_clk, 11289600);
+ clk_prepare_enable(core_info->i2s_clk);
+
ret = mfd_add_devices(&client->dev, -1,
rk610_devs, ARRAY_SIZE(rk610_devs),
- NULL,0);
+ NULL,0,NULL);
#if defined(CONFIG_DEBUG_FS)
core_info->debugfs_dir = debugfs_create_dir("rk610", NULL);
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>
-#include <mach/gpio.h>
-#include <mach/iomux.h>
#include <linux/workqueue.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
#include "rk610_codec.h"
-#include <mach/board.h>
#define RK610_PROC
-#ifdef RK610_PROC
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/vmalloc.h>
-#endif
+
#define HP_OUT 0
#define HP_IN 1
struct delayed_work rk610_delayed_work;
unsigned int spk_ctrl_io;
+ /*
+ Some amplifiers enable a longer time.
+ config after pa_enable_io delay pa_enable_time(ms)
+ default = 0,preferably not more than 1000ms
+ so value range is 0 - 1000.
+ */
unsigned int pa_enable_time;
bool hdmi_ndet;
+ int boot_depop;//if found boot pop,set boot_depop 1 test
#if RESUME_PROBLEM
int rk610_workstatus;
#endif
- struct rk610_codec_platform_data *pdata;
int call_enable;
int headset_status;
};
struct i2c_msg xfer[1];
u8 reg = r;
int ret;
- struct i2c_client *client = codec->control_data;
+ struct i2c_client *i2c = to_i2c_client(codec->dev);
/* Read register */
- xfer[0].addr = (client->addr& 0x60)|(reg);
+ xfer[0].addr = (i2c->addr& 0x60)|(reg);
xfer[0].flags = I2C_M_RD;
xfer[0].len = 1;
xfer[0].buf = ®
xfer[0].scl_rate = 100000;
- ret = i2c_transfer(client->adapter, xfer, 1);
+ ret = i2c_transfer(i2c->adapter, xfer, 1);
if (ret != 1) {
- dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
+ dev_err(&i2c->dev, "i2c_transfer() returned %d\n", ret);
return 0;
}
static int rk610_codec_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
+
struct rk610_codec_priv *rk610_codec = snd_soc_codec_get_drvdata(rk610_codec_codec);
u8 data[2];
- struct i2c_client *i2c;
+ struct i2c_client *i2c = to_i2c_client(codec->dev);
#ifdef CONFIG_MODEM_SOUND
if(rk610_codec->call_enable)
return 0;
#endif
+ if(value == rk610_codec_read_reg_cache(codec,reg))
+ return 0;
DBG("Enter::%s, %d, reg=0x%02X, value=0x%02X\n",__FUNCTION__,__LINE__, reg, value);
data[0] = value & 0x00ff;
- rk610_codec_write_reg_cache (codec, reg, value);
- i2c = (struct i2c_client *)codec->control_data;
+
i2c->addr = (i2c->addr & 0x60)|reg;
- if (codec->hw_write(codec->control_data, data, 1) == 1){
+ if (codec->hw_write(i2c, data, 1) == 1){
// DBG("================%s %d Run OK================\n",__FUNCTION__,__LINE__);
+ rk610_codec_write_reg_cache (codec, reg, value);
return 0;
}else{
DBG("================%s %d Run EIO================\n",__FUNCTION__,__LINE__);
unsigned int value)
{
u8 data[2];
- struct i2c_client *i2c;
+ struct i2c_client *i2c = to_i2c_client(codec->dev);
DBG("Enter::%s, %d, reg=0x%02X, value=0x%02X\n",__FUNCTION__,__LINE__, reg, value);
data[0] = value & 0x00ff;
rk610_codec_write_reg_cache (codec, reg, value);
i2c = (struct i2c_client *)codec->control_data;
i2c->addr = (i2c->addr & 0x60)|reg;
- if (codec->hw_write(codec->control_data, data, 1) == 1)
+ if (codec->hw_write(i2c, data, 1) == 1)
return 0;
else
return -EIO;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec;
struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec);
- unsigned int dai_fmt = snd_soc_pcm_runtime->card->dai_link[0].dai_fmt
+ unsigned int dai_fmt = rtd->card->dai_link[0].dai_fmt;
u16 iface = rk610_codec_read_reg_cache(codec, ACCELCODEC_R09) & 0x1f3;
u16 srate = rk610_codec_read_reg_cache(codec, ACCELCODEC_R00) & 0x180;
{
struct snd_soc_codec *codec = dai->codec;
struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec);
- DBG("Enter::%s----%d--mute=%d\n",__FUNCTION__,__LINE__,mute);
+ printk("Enter::%s----%d--mute=%d\n",__FUNCTION__,__LINE__,mute);
if (mute)
{
#endif
// schedule_delayed_work(&rk610_codec->rk610_delayed_work, 0);
// rk610_codec_reg_read();
- if(rk610_codec->hdmi_ndet)
+ if(rk610_codec->hdmi_ndet){
if(rk610_codec->pa_enable_time == 0 )
spk_ctrl_fun(GPIO_HIGH);
else if(rk610_codec->pa_enable_time > 0 && rk610_codec->pa_enable_time < 300){
}
else if(rk610_codec->pa_enable_time >=300 && rk610_codec->pa_enable_time < 1000)
msleep(rk610_codec->pa_enable_time);
+ }
}
return 0;
{
struct snd_soc_codec *codec = rk610_codec_codec;
struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec);
- struct rk610_codec_platform_data *pdata= rk610_codec->pdata;
+
DBG("--------%s----------\n",__FUNCTION__);
- if(!pdata->boot_depop){
+ if(!rk610_codec->boot_depop){
#if OUT_CAPLESS
rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE);
#else
{
struct snd_soc_codec *codec = rk610_codec_codec;
struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec);
- struct rk610_codec_platform_data *pdata= rk610_codec->pdata;
+
unsigned int digital_gain;
unsigned int mic_vol = Volume_Input;
rk610_codec_write(codec,ACCELCODEC_R1D, 0x30);
rk610_codec_write(codec,ACCELCODEC_R0B, ASC_DEC_ENABLE|ASC_INT_ENABLE);
gR0BReg = ASC_DEC_ENABLE|ASC_INT_ENABLE; //ASC_DEC_DISABLE|ASC_INT_ENABLE;
- if(pdata->boot_depop){
+ if(rk610_codec->boot_depop){
#if OUT_CAPLESS
rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE);
#else
}
}
-#ifdef RK610_PROC
-static int RK610_PROC_init(void);
-#endif
-
static int rk610_codec_probe(struct snd_soc_codec *codec)
{
struct rk610_codec_priv *rk610_codec = snd_soc_codec_get_drvdata(codec);
int ret;
-#ifdef RK610_PROC
- RK610_PROC_init();
-#endif
rk610_codec_codec = codec;
DBG("[%s] start\n", __FUNCTION__);
ret = snd_soc_codec_set_cache_io(codec, 8, 16, rk610_codec->control_type);
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
+
//For RK610, i2c write&read method is special, do not use system default method.
codec->write = rk610_codec_write;
codec->read = rk610_codec_read;
}
INIT_DELAYED_WORK(&rk610_codec->rk610_delayed_work, rk610_delayedwork_fun);
-
+
if(rk610_codec->spk_ctrl_io)
{
ret = gpio_request(rk610_codec->spk_ctrl_io, "rk610 spk_ctrl");
gpio_direction_output(rk610_codec->spk_ctrl_io, GPIO_LOW);
gpio_set_value(rk610_codec->spk_ctrl_io, GPIO_LOW);
}
-
+
rk610_codec->hdmi_ndet = true;
rk610_codec->call_enable = 0;
rk610_codec->headset_status = HP_OUT;
const struct i2c_device_id *id)
{
struct rk610_codec_priv *rk610_codec;
- struct rk610_codec_platform_data *pdata = i2c->dev.platform_data;
+ struct device_node *rk610_np = i2c->dev.of_node;
int ret;
+ int val = 0;
DBG("%s start\n", __FUNCTION__);
rk610_codec = kzalloc(sizeof(struct rk610_codec_priv), GFP_KERNEL);
if (rk610_codec == NULL)
return -ENOMEM;
-//qjb 2013-01-14
- rk610_codec->pdata = pdata;
- rk610_codec->spk_ctrl_io = pdata->spk_ctl_io;
-//qjb 2013-06-27
- rk610_codec->pa_enable_time = pdata->pa_enable_time;
+
+ if(!of_property_read_u32(rk610_np, "boot_depop", &val))
+ rk610_codec->boot_depop = val;
+ if(!of_property_read_u32(rk610_np, "pa_enable_time", &val))
+ rk610_codec->pa_enable_time = val;
if(rk610_codec->pa_enable_time > 1000)
rk610_codec->pa_enable_time = 1000;
- if(pdata->io_init){
- ret = pdata->io_init();
- if (ret < 0) {
- dev_err(&i2c->dev, "Failed to register codec pdata io_init error: %d\n", ret);
- kfree(rk610_codec);
- return ret;
- }
+
+ rk610_codec->spk_ctrl_io = of_get_named_gpio(rk610_np,"spk_ctl_io", 0);
+ if (!gpio_is_valid(rk610_codec->spk_ctrl_io)){
+ printk("invalid core_info->reset_gpio: %d\n",rk610_codec->spk_ctrl_io);
+ return -1;
}
-
+
i2c_set_clientdata(i2c, rk610_codec);
rk610_codec->control_type = SND_SOC_I2C;
}
static const struct i2c_device_id rk610_codec_i2c_id[] = {
- { "rk610_i2c_codec", 0 },
+ { "rk610_codec", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rk610_codec_i2c_id);
/* corgi i2c codec control layer */
static struct i2c_driver rk610_codec_i2c_driver = {
.driver = {
- .name = "RK610_CODEC",
+ .name = "rk610_codec",
.owner = THIS_MODULE,
},
.probe = rk610_codec_i2c_probe,
//=====================================================================
//Proc
#ifdef RK610_PROC
-static ssize_t RK610_PROC_write(struct file *file, const char __user *buffer,
- unsigned long len, void *data)
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/vmalloc.h>
+static ssize_t rk610_reg_write(struct file *file,
+ const char __user *buffer, size_t len, loff_t *ppos)
{
char *cookie_pot;
char *p;
return len;
}
-
-static int RK610_PROC_init(void)
+static int proc_reg_show(struct seq_file *s, void *v)
{
- struct proc_dir_entry *RK610_PROC_entry;
- RK610_PROC_entry = create_proc_entry("driver/rk610_ts", 0777, NULL);
- if(RK610_PROC_entry != NULL)
- {
- RK610_PROC_entry->write_proc = RK610_PROC_write;
- return -1;
- }
- else
- {
- printk("create proc error !\n");
- }
+
return 0;
}
+static int proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, proc_reg_show, NULL);
+}
+static const struct file_operations proc_i2s_fops = {
+ .open = proc_open,
+ .read = seq_read,
+ .write = rk610_reg_write,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+static int __init rk610_proc_init(void)
+{
+ proc_create("driver/rk610_ts", 0, NULL, &proc_i2s_fops);
+ return 0;
+}
+late_initcall(rk610_proc_init);
#endif