#include <linux/earlysuspend.h>
/* Debug */
-#if 0
+#if 1
#define DBG(x...) printk(x)
#else
#define DBG(x...) do { } while (0)
#define HEADSET 0
#define HOOK 1
+#define HEADSET_IN 1
+#define HEADSET_OUT 0
+#define HOOK_DOWN 0
+#define HOOK_UP 1
+#define enable 1
+#define disable 0
+
+extern int wm8994_set_status(void);
/* headset private data */
struct headset_priv {
struct input_dev *input_dev;
struct rk_headset_pdata *pdata;
unsigned int headset_status:1;
unsigned int hook_status:1;
-
- struct switch_dev sdev;
+ unsigned int isMic:1;
+ unsigned int isHook_irq:1;
int cur_headset_status;
- struct mutex mutex_lock[2];
unsigned int irq[2];
unsigned int irq_type[2];
- struct delayed_work h_delayed_work[2];
-
+ struct delayed_work h_delayed_work[2];
+ struct switch_dev sdev;
+ struct mutex mutex_lock[2];
+ struct timer_list headset_timer;
unsigned char *keycodes;
};
static struct headset_priv *headset_info;
static irqreturn_t headset_interrupt(int irq, void *dev_id)
{
// DBG("---headset_interrupt---\n");
- schedule_delayed_work(&headset_info->h_delayed_work[HEADSET], msecs_to_jiffies(20));
+ schedule_delayed_work(&headset_info->h_delayed_work[HEADSET], msecs_to_jiffies(50));
return IRQ_HANDLED;
}
static irqreturn_t Hook_interrupt(int irq, void *dev_id)
{
// DBG("---Hook_interrupt---\n");
+// disable_irq_nosync(headset_info->irq[HOOK]);
schedule_delayed_work(&headset_info->h_delayed_work[HOOK], msecs_to_jiffies(100));
return IRQ_HANDLED;
}
int i,level = 0;
struct rk_headset_pdata *pdata = headset_info->pdata;
static unsigned int old_status = 0;
-// DBG("---headsetobserve_work---\n");
+ DBG("---headsetobserve_work---\n");
mutex_lock(&headset_info->mutex_lock[HEADSET]);
for(i=0; i<3; i++)
if(level < 0)
{
printk("%s:get pin level err!\n",__FUNCTION__);
- return;
+ goto RE_ERROR;
}
old_status = headset_info->headset_status;
{
case HEADSET_IN_HIGH:
if(level > 0)
- headset_info->headset_status = 1;
+ headset_info->headset_status = HEADSET_IN;
else if(level == 0)
- headset_info->headset_status = 0;
+ headset_info->headset_status = HEADSET_OUT;
break;
case HEADSET_IN_LOW:
if(level == 0)
- headset_info->headset_status = 1;
+ headset_info->headset_status = HEADSET_IN;
else if(level > 0)
- headset_info->headset_status = 0;
+ headset_info->headset_status = HEADSET_OUT;
break;
default:
DBG("---- ERROR: on headset headset_in_type error -----\n");
}
if(old_status == headset_info->headset_status)
{
- printk("old_status == headset_info->headset_status\n");
- mutex_unlock(&headset_info->mutex_lock[HEADSET]);
- return;
+ DBG("old_status == headset_info->headset_status\n");
+ goto RE_ERROR;
}
switch(pdata->headset_in_type)
{
- case HEADSET_IN_HIGH:
- if(level > 0)
- {//in--High level
- DBG("--- HEADSET_IN_HIGH headset in HIGH---\n");
- enable_irq(headset_info->irq[HOOK]);
- headset_info->headset_status = 1;
- headset_info->cur_headset_status = BIT_HEADSET;
- headset_change_irqtype(HEADSET,IRQF_TRIGGER_FALLING);//
- }
- else if(level == 0)
- {//out--Low level
- DBG("---HEADSET_IN_HIGH headset out HIGH---\n");
+ case HEADSET_IN_HIGH:
+ if(level > 0)
+ {//in--High level
+ DBG("--- HEADSET_IN_HIGH headset in HIGH---\n");
+ // enable_irq(headset_info->irq[HOOK]);
+ headset_info->cur_headset_status = BIT_HEADSET;
+ headset_change_irqtype(HEADSET,IRQF_TRIGGER_FALLING);//
+ del_timer(&headset_info->headset_timer);//Æô¶¯¶¨Ê±Æ÷£¬µÈ´ýÇл»µ½¶ú»úͨ·
+ headset_info->headset_timer.expires = jiffies + 500;
+ add_timer(&headset_info->headset_timer);
+ }
+ else if(level == 0)
+ {//out--Low level
+ DBG("---HEADSET_IN_HIGH headset out HIGH---\n");
+ if(headset_info->isHook_irq == enable)
+ {
+ DBG("disable_irq\n");
+ headset_info->isHook_irq = disable;
disable_irq(headset_info->irq[HOOK]);
- headset_info->headset_status = 0;
- headset_info->cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC);
- headset_change_irqtype(HEADSET,IRQF_TRIGGER_RISING);//
- }
- break;
- case HEADSET_IN_LOW:
- if(level == 0)
- {//in--High level
- DBG("---HEADSET_IN_LOW headset in LOW ---\n");
- headset_info->headset_status = 1;
- headset_info->cur_headset_status = BIT_HEADSET;
- headset_change_irqtype(HEADSET,IRQF_TRIGGER_RISING);//
- enable_irq(headset_info->irq[HOOK]);
- }
- else if(level > 0)
- {//out--High level
- DBG("---HEADSET_IN_LOW headset out LOW ---\n");
- headset_info->headset_status = 0;
- headset_info->cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC);
- headset_change_irqtype(HEADSET,IRQF_TRIGGER_FALLING);//
- disable_irq(headset_info->irq[HOOK]);
- }
- break;
- default:
- DBG("---- ERROR: on headset headset_in_type error -----\n");
- break;
+ }
+ headset_info->cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC);
+ headset_change_irqtype(HEADSET,IRQF_TRIGGER_RISING);//
+ }
+ break;
+ case HEADSET_IN_LOW:
+ if(level == 0)
+ {//in--High level
+ DBG("---HEADSET_IN_LOW headset in LOW ---\n");
+ headset_info->cur_headset_status = BIT_HEADSET;
+ headset_change_irqtype(HEADSET,IRQF_TRIGGER_RISING);//
+ enable_irq(headset_info->irq[HOOK]);
+ }
+ else if(level > 0)
+ {//out--High level
+ DBG("---HEADSET_IN_LOW headset out LOW ---\n");
+ headset_info->cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC);
+ headset_change_irqtype(HEADSET,IRQF_TRIGGER_FALLING);//
+ disable_irq(headset_info->irq[HOOK]);
+ }
+ break;
+ default:
+ DBG("---- ERROR: on headset headset_in_type error -----\n");
+ break;
}
-
switch_set_state(&headset_info->sdev, headset_info->cur_headset_status);
- DBG("Headset_dev.cur_headset_status = %d\n",headset_info->cur_headset_status);
-
+ DBG("headset_info->cur_headset_status = %d\n",headset_info->cur_headset_status);
+RE_ERROR:
mutex_unlock(&headset_info->mutex_lock[HEADSET]);
}
int i,level = 0;
struct rk_headset_pdata *pdata = headset_info->pdata;
static unsigned int old_status = 0;
-
+
DBG("---Hook_work---\n");
mutex_lock(&headset_info->mutex_lock[HOOK]);
- if(headset_info->headset_status == 0)
+ if(headset_info->headset_status == HEADSET_OUT)
{
- printk("Headset is out\n");
- mutex_unlock(&headset_info->mutex_lock[HOOK]);
- return;
+ DBG("Headset is out\n");
+ goto RE_ERROR;
}
for(i=0; i<3; i++)
if(level < 0)
{
printk("%s:get pin level err!\n",__FUNCTION__);
- return;
+ goto RE_ERROR;
}
old_status = headset_info->hook_status;
if(level == 0)
- headset_info->hook_status = 1;
+ headset_info->hook_status = HOOK_UP;
else if(level > 0)
- headset_info->hook_status = 0;
+ headset_info->hook_status = HOOK_DOWN;
if(old_status == headset_info->hook_status)
{
- printk("old_status == headset_info->hook_status\n");
- mutex_unlock(&headset_info->mutex_lock[HOOK]);
- return;
+ DBG("old_status == headset_info->hook_status\n");
+ goto RE_ERROR;
}
if(level == 0)
{
DBG("---HOOK Down ---\n");
headset_change_irqtype(HOOK,IRQF_TRIGGER_RISING);//
- input_report_key(headset_info->input_dev,KEY_MEDIA,headset_info->hook_status);
- input_sync(headset_info->input_dev);
+ input_report_key(headset_info->input_dev,pdata->hook_key_code,headset_info->hook_status);
+ input_sync(headset_info->input_dev);
}
else if(level > 0)
{
DBG("---HOOK Up ---\n");
headset_change_irqtype(HOOK,IRQF_TRIGGER_FALLING);//
- input_report_key(headset_info->input_dev,KEY_MEDIA,headset_info->hook_status);
- input_sync(headset_info->input_dev);
+ input_report_key(headset_info->input_dev,pdata->hook_key_code,headset_info->hook_status);
+ input_sync(headset_info->input_dev);
}
-
+RE_ERROR:
mutex_unlock(&headset_info->mutex_lock[HOOK]);
}
+static void headset_timer_callback(unsigned long arg)
+{
+ struct headset_priv *headset = (struct headset_priv *)(arg);
+ struct rk_headset_pdata *pdata = headset->pdata;
+ int i,level = 0;
+
+ DBG("headset_timer_callback\n");
+
+ if(headset->headset_status == HEADSET_OUT)
+ {
+ DBG("Headset is out\n");
+ goto out;
+ }
+ if(wm8994_set_status() < 0)
+ {
+ DBG("wm8994 is not set on heatset channel\n");
+ headset_info->headset_timer.expires = jiffies + 500;
+ add_timer(&headset_info->headset_timer);
+ goto out;
+ }
+
+ for(i=0; i<3; i++)
+ {
+ level = gpio_get_value(pdata->Hook_gpio);
+ if(level < 0)
+ {
+ printk("%s:get pin level again,pin=%d,i=%d\n",__FUNCTION__,pdata->Hook_gpio,i);
+ msleep(1);
+ continue;
+ }
+ else
+ break;
+ }
+ if(level < 0)
+ {
+ printk("%s:get pin level err!\n",__FUNCTION__);
+ goto out;
+ }
+
+//ÑÓ³ÙÒ»¶Îʱ¼ä¶ú»ú»¹ÊÇ°´ÏµĻ°£¬ÄÇôӦ¸ÃÊÇÎÞ°´¼ü¶ú»ú
+ if(level == 0)
+ headset->isMic= 0;//No microphone
+ else if(level > 0)
+ {
+ headset->isMic = 1;//have mic
+ DBG("enable_irq\n");
+ enable_irq(headset_info->irq[HOOK]);
+ headset->isHook_irq = enable;
+ }
+ DBG("headset->isMic = %d\n",headset->isMic);
+out:
+ return;
+}
+
static ssize_t h2w_print_name(struct switch_dev *sdev, char *buf)
{
return sprintf(buf, "Headset\n");
}
headset->pdata = pdev->dev.platform_data;
pdata = headset->pdata;
- headset->headset_status = 0;
- headset->hook_status = 0;
+ headset->headset_status = HEADSET_OUT;
+ headset->hook_status = HOOK_UP;
+ headset->isHook_irq = disable;
headset->cur_headset_status = 0;
headset->sdev.name = "h2w";
headset->sdev.print_name = h2w_print_name;
INIT_DELAYED_WORK(&headset->h_delayed_work[HEADSET], headsetobserve_work);
INIT_DELAYED_WORK(&headset->h_delayed_work[HOOK], Hook_work);
+
+// init_timer(&headset->headset_timer);
+// headset->headset_timer.function = headset_timer_callback;
+// headset->headset_timer.data = (unsigned long)headset;
+// headset->headset_timer.expires = jiffies + 3000;
+ headset->isMic = 0;
+ setup_timer(&headset->headset_timer, headset_timer_callback, (unsigned long)headset);
+// headset->headset_timer.expires = jiffies + 1000;
+// add_timer(&headset->headset_timer);
//------------------------------------------------------------------
ret = gpio_request(pdata->Headset_gpio, NULL);
if (ret)
if (ret)
goto failed_free;
disable_irq(headset->irq[HOOK]);
-//------------------------------------------------------------------
-
+//------------------------------------------------------------------
// Create and register the input driver.
headset->input_dev = input_allocate_device();
if (!headset->input_dev) {
// set_bit(KEY_MEDIA, headset->input_dev->keybit);
// clear_bit(0, headset->input_dev->keybit);
- input_set_capability(headset->input_dev, EV_KEY, KEY_MEDIA);
+ input_set_capability(headset->input_dev, EV_KEY, pdata->hook_key_code);
// input_set_capability(headset->input_dev, EV_SW, SW_HEADPHONE_INSERT);
// input_set_capability(headset->input_dev, EV_KEY, KEY_END);
/* codec private data */
struct wm8994_priv {
struct mutex io_lock;
+ struct mutex route_lock;
unsigned int sysclk;
struct snd_soc_codec codec;
struct snd_kcontrol *kcontrol;//The current working path
return ret;
}
+int wm8994_set_status(void)
+{
+ struct wm8994_priv *wm8994 = wm8994_codec->private_data;
+ int ret = 1;
+ mutex_lock(&wm8994->route_lock);
+
+ switch(wm8994_current_mode)
+ {
+ case wm8994_AP_to_headset:
+ case wm8994_recorder_and_AP_to_headset:
+ case wm8994_handsetMIC_to_baseband_to_headset:
+ case wm8994_handsetMIC_to_baseband_to_headset_and_record:
+ ret = 1;
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+
+ mutex_unlock(&wm8994->route_lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm8994_set_status);
+
+
static int wm8994_read(unsigned short reg,unsigned short *value)
{
struct wm8994_priv *wm8994 = wm8994_codec->private_data;
msleep(WM8994_DELAY);
//clk
// wm8994_write(0x701, 0x0000);//MCLK2
- wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
- wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
- wm8994_write(0x210, 0x0083); // SR=48KHz
- wm8994_write(0x300, 0xC010); // i2s 16 bits
if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
{
wm8994_write(0x220, 0x0000);
wm8994_write(0x222, 0);
wm8994_write(0x223, 0x0400);
wm8994_write(0x220, 0x0004);
+ msleep(10);
wm8994_write(0x220, 0x0005);
- wm8994_write(0x200, 0x0011); // sysclk = MCLK1
+ msleep(5);
+ wm8994_write(0x200, 0x0010); // sysclk = MCLK1
}
+ wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+ wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+ wm8994_write(0x210, 0x0083); // SR=48KHz
+ wm8994_write(0x300, 0xC010); // i2s 16 bits
+ if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
+ wm8994_write(0x200, 0x0011); // sysclk = MCLK1
else
wm8994_write(0x200, 0x0001); // sysclk = MCLK1
// wm8994_write(0x200, 0x0009); // sysclk = MCLK2
wm8994_reset();
msleep(WM8994_DELAY);
- wm8994_write(0x01, 0x0023);
+ wm8994_write(0x01, 0x0003);
wm8994_write(0x200, 0x0000);
msleep(WM8994_DELAY);
//clk
- wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
- wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
- wm8994_write(0x210, 0x0083); // SR=48KHz
- wm8994_write(0x300, 0xC010); // i2s 16 bits
if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
{
wm8994_write(0x220, 0x0000);
wm8994_write(0x222, 0);
wm8994_write(0x223, 0x0400);
wm8994_write(0x220, 0x0004);
+ msleep(10);
wm8994_write(0x220, 0x0005);
- wm8994_write(0x200, 0x0011); // sysclk = MCLK1
+ msleep(5);
+ wm8994_write(0x200, 0x0010); // sysclk = MCLK1
}
+ wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+ wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+ wm8994_write(0x210, 0x0083); // SR=48KHz
+ wm8994_write(0x300, 0xC050); // i2s 16 bits
+ msleep(10);
+ if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
+ wm8994_write(0x200, 0x0011); // sysclk = MCLK1
else
- wm8994_write(0x200, 0x0001); // sysclk = MCLK1
+ wm8994_write(0x200, 0x0001); // sysclk = MCLK1
//recorder
wm8994_write(0x28, 0x0003); // IN1RP_TO_IN1R=1, IN1RN_TO_IN1R=1
wm8994_write(0x606, 0x0002); // ADC1L_TO_AIF1ADC1L=1
msleep(WM8994_DELAY);
//clk
// wm8994_write(0x701, 0x0000);//MCLK2
- wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
- wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
- wm8994_write(0x210, 0x0083); // SR=48KHz
- wm8994_write(0x300, 0xC010); // i2s 16 bits
-
if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
{
wm8994_write(0x220, 0x0000);
wm8994_write(0x222, 0);
wm8994_write(0x223, 0x0400);
wm8994_write(0x220, 0x0004);
+ msleep(10);
wm8994_write(0x220, 0x0005);
- wm8994_write(0x200, 0x0011); // sysclk = MCLK1
+ msleep(5);
+ wm8994_write(0x200, 0x0010); // sysclk = MCLK1
}
+ wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+ wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+ wm8994_write(0x210, 0x0083); // SR=48KHz
+ wm8994_write(0x300, 0xC010); // i2s 16 bits
+ if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
+ wm8994_write(0x200, 0x0011); // sysclk = MCLK1
else
wm8994_write(0x200, 0x0001); // sysclk = MCLK1
wm8994_write(0x200, 0x0000);
msleep(WM8994_DELAY);
//clk
- wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
- wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
- wm8994_write(0x210, 0x0083); // SR=48KHz
- wm8994_write(0x300, 0xC010); // i2s 16 bits
if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
{
wm8994_write(0x220, 0x0000);
wm8994_write(0x222, 0);
wm8994_write(0x223, 0x0400);
wm8994_write(0x220, 0x0004);
+ msleep(10);
wm8994_write(0x220, 0x0005);
- wm8994_write(0x200, 0x0011); // sysclk = MCLK1
+ msleep(5);
+ wm8994_write(0x200, 0x0010); // sysclk = MCLK1
}
+ wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+ wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+ wm8994_write(0x210, 0x0083); // SR=48KHz
+ wm8994_write(0x300, 0xC010); // i2s 16 bits
+ if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
+ wm8994_write(0x200, 0x0011); // sysclk = MCLK1
else
wm8994_write(0x200, 0x0001); // sysclk = MCLK1
//path
wm8994_write(0x200, 0x0000);
msleep(WM8994_DELAY);
//clk
- wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
- wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
- wm8994_write(0x210, 0x0083); // SR=48KHz
- wm8994_write(0x300, 0x4010); // i2s 16 bits
if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
{
wm8994_write(0x220, 0x0000);
wm8994_write(0x222, 0);
wm8994_write(0x223, 0x0400);
wm8994_write(0x220, 0x0004);
+ msleep(10);
wm8994_write(0x220, 0x0005);
- wm8994_write(0x200, 0x0011); // sysclk = MCLK1
+ msleep(5);
+ wm8994_write(0x200, 0x0010); // sysclk = MCLK1
}
+ wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+ wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+ wm8994_write(0x210, 0x0083); // SR=48KHz
+ wm8994_write(0x300, 0xC010); // i2s 16 bits
+ if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
+ wm8994_write(0x200, 0x0011); // sysclk = MCLK1
else
wm8994_write(0x200, 0x0001); // sysclk = MCLK1
//path
wm8994_write(0x200, 0x0000);
msleep(WM8994_DELAY);
//clk
- wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
- wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
- wm8994_write(0x210, 0x0083); // SR=48KHz
- wm8994_write(0x300, 0xC010); // i2s 16 bits
if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
{
wm8994_write(0x220, 0x0000);
wm8994_write(0x222, 0);
wm8994_write(0x223, 0x0400);
wm8994_write(0x220, 0x0004);
+ msleep(10);
wm8994_write(0x220, 0x0005);
- wm8994_write(0x200, 0x0011); // sysclk = MCLK1
+ msleep(5);
+ wm8994_write(0x200, 0x0010); // sysclk = MCLK1
}
+ wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+ wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+ wm8994_write(0x210, 0x0083); // SR=48KHz
+ wm8994_write(0x300, 0xC010); // i2s 16 bits
+ if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
+ wm8994_write(0x200, 0x0011); // sysclk = MCLK1
else
wm8994_write(0x200, 0x0001); // sysclk = MCLK1
//path
msleep(WM8994_DELAY);
//CLK
//AIF1CLK
- wm8994_write(0x208, 0x0008);
- wm8994_write(0x208, 0x000A);
- wm8994_write(0x210, 0x0083); // SMbus_16inx_16dat Write 0x34 * SR=48KHz
- wm8994_write(0x300, 0xC010); //DSP/PCM; 16bits; ADC L channel = R channel;MODE A
if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
{
wm8994_write(0x220, 0x0000);
wm8994_write(0x222, 0);
wm8994_write(0x223, 0x0400);
wm8994_write(0x220, 0x0004);
+ msleep(10);
wm8994_write(0x220, 0x0005);
- wm8994_write(0x200, 0x0011); // sysclk = MCLK1
+ msleep(5);
+ wm8994_write(0x200, 0x0010); // sysclk = MCLK1
}
+ wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+ wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+ wm8994_write(0x210, 0x0083); // SR=48KHz
+ wm8994_write(0x300, 0xC010); // i2s 16 bits
+ if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
+ wm8994_write(0x200, 0x0011); // sysclk = MCLK1
else
wm8994_write(0x200, 0x0001); // sysclk = MCLK1
//AIF2CLK use FLL2
wm8994_write(0x315, 0x0080);
wm8994_write(0x310, 0x0118); //DSP/PCM; 16bits; ADC L channel = R channel;MODE A
wm8994_write(0x204, 0x0019); // SMbus_16inx_16dat Write 0x34 * AIF2 Clocking (1)(204H): 0011 AIF2CLK_SRC=10, AIF2CLK_INV=0, AIF2CLK_DIV=0, AIF2CLK_ENA=1
-
/*
wm8994_write(0x310, 0x0118);
wm8994_write(0x204, 0x0001);
wm8994_write(0x208, 0x000F);
wm8994_write(0x211, 0x0009);
wm8994_write(0x312, 0x7000);
- wm8994_write(0x313, 0x00F0); */
-
+ wm8994_write(0x313, 0x00F0);
+*/
//GPIO
wm8994_write(0x702, 0x2100);
wm8994_write(0x703, 0x2100);
{
struct wm8994_priv *wm8994 = wm8994_codec->private_data;
char route = kcontrol->private_value & 0xff;
-
+ mutex_lock(&wm8994->route_lock);
wm8994->kcontrol = kcontrol;//save rount
- if(wm8994->First_Poweron == 1 &&
- route == SPEAKER_NORMAL)
+ if(wm8994->First_Poweron == 1 && route == SPEAKER_NORMAL )
{//First start & Poweron mast disable wm8994
PA_ctrl(GPIO_LOW);
wm8994_write(0,0);
- return 0;
+ msleep(50);
+ goto out;
}
//before set the route -- disable PA
switch(route)
break;
default:
printk("wm8994 error route!!!\n");
- return 0;
+ goto out;
}
//after set the route -- enable PA
switch(route)
case BLUETOOTH_SCO_NORMAL:
break;
default:
+ msleep(50);
PA_ctrl(GPIO_HIGH);
break;
}
-
+out:
+ mutex_unlock(&wm8994->route_lock);
return 0;
}
struct snd_soc_codec *codec = dai->codec;
struct wm8994_priv *wm8994 = codec->private_data;
- if(wm8994_current_mode > wm8994_handsetMIC_to_baseband_to_headset && wm8994_current_mode != null)
+ if(wm8994_current_mode >= wm8994_handsetMIC_to_baseband_to_headset && wm8994_current_mode != null)
return 0;
// DBG("%s::%d status = %d substream->stream '%s'\n",__FUNCTION__,__LINE__,
// cmd, substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "PLAYBACK":"CAPTURE");
!wm8994->capture_active )
{//suspend
DBG("It's going to power down wm8994\n");
+ cancel_delayed_work_sync(&wm8994->wm8994_delayed_work);
wm8994->work_type = SNDRV_PCM_TRIGGER_STOP;
- schedule_delayed_work(&wm8994->wm8994_delayed_work, msecs_to_jiffies(1000));
+ schedule_delayed_work(&wm8994->wm8994_delayed_work, msecs_to_jiffies(2000));
}
else if (wm8994->playback_active
|| wm8994->capture_active)
{//resume
- DBG("Power up wm8994\n");
+ DBG("Power up wm8994\n");
+ if(wm8994->work_type == SNDRV_PCM_TRIGGER_STOP)
+ cancel_delayed_work_sync(&wm8994->wm8994_delayed_work);
wm8994->work_type = SNDRV_PCM_TRIGGER_START;
schedule_delayed_work(&wm8994->wm8994_delayed_work, msecs_to_jiffies(0));
}
{
struct snd_soc_codec *codec = wm8994_codec;
struct wm8994_priv *wm8994 = codec->private_data;
+ struct wm8994_pdata *pdata = wm8994->pdata;
unsigned short value;
int error_count = 5;
-// DBG("Enter %s---%d\n",__FUNCTION__,__LINE__);
+// DBG("Enter %s---%d = %d\n",__FUNCTION__,__LINE__,wm8994_current_mode);
switch(wm8994->work_type)
{
case SNDRV_PCM_TRIGGER_STOP:
+ if(wm8994_current_mode > wm8994_FM_to_speakers_and_record)
+ return;
// DBG("wm8994 shutdown\n");
+ mutex_lock(&wm8994->route_lock);
PA_ctrl(GPIO_LOW);
- wm8994_write(0,0);
msleep(50);
- wm8994_write(0x01, 0x0003);
+ wm8994_write(0,0);
msleep(50);
wm8994_write(0x01, 0x0023);
- wm8994_current_mode = null;//Automatically re-set the wake-up time
+ wm8994_current_mode = null;//Automatically re-set the wake-up time
+ mutex_unlock(&wm8994->route_lock);
break;
case SNDRV_PCM_TRIGGER_START:
if(wm8994->First_Poweron == 1)
{
DBG("wm8994 First_Poweron shutup\n");
wm8994->First_Poweron = 0;
+ if(wm8994->kcontrol->private_value != SPEAKER_NORMAL)
+ {
+ // DBG("wm8994->kcontrol->private_value != SPEAKER_NORMAL\n");
+ return;
+ }
wm8994_current_mode = null;
snd_soc_put_route(wm8994->kcontrol,NULL);
}
break;
case SNDRV_PCM_TRIGGER_RESUME:
+ msleep(100);
while(error_count)
{
+ gpio_request(pdata->Power_EN_Pin, NULL);
+ gpio_direction_output(pdata->Power_EN_Pin,GPIO_HIGH);
+ gpio_free(pdata->Power_EN_Pin);
msleep(100);
wm8994_read(0x00, &value);
if(value == 0x8994)
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = socdev->card->codec;
struct wm8994_priv *wm8994 = codec->private_data;
- struct wm8994_pdata *pdata = wm8994->pdata;
+// struct wm8994_pdata *pdata = wm8994->pdata;
DBG("%s----%d\n",__FUNCTION__,__LINE__);
- gpio_request(pdata->Power_EN_Pin, NULL);
- gpio_direction_output(pdata->Power_EN_Pin,GPIO_HIGH);
- gpio_free(pdata->Power_EN_Pin);
+
wm8994->work_type = SNDRV_PCM_TRIGGER_RESUME;
schedule_delayed_work(&wm8994->wm8994_delayed_work, msecs_to_jiffies(0));
int reg;
int value;
struct snd_kcontrol kcontrol;
+// struct wm8994_priv *wm8994 = wm8994_codec->private_data;
+// struct wm8994_pdata *pdata = wm8994->pdata;
cookie_pot = (char *)vmalloc( len );
if (!cookie_pot)
break;
}
- break;
+ break;
default:
DBG("Help for wm8994_ts .\n-->The Cmd list: \n");
DBG("-->'d&&D' Open or close the debug\n");
struct wm8994_priv *wm8994;
struct wm8994_pdata *pdata;
int ret = 0;
+
+
#ifdef WM8994_PROC
wm8994_proc_init();
#endif
codec = wm8994_codec;
wm8994 = codec->private_data;
pdata = wm8994->pdata;
+ //disable power_EN
+ gpio_request(pdata->Power_EN_Pin, NULL);
+ gpio_direction_output(pdata->Power_EN_Pin,GPIO_LOW);
+ gpio_free(pdata->Power_EN_Pin);
/* register pcms */
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
dev_err(codec->dev, "failed to register card: %d\n", ret);
goto card_err;
}
-
+
+ PA_ctrl(GPIO_LOW);
//enable power_EN
+ msleep(50);
gpio_request(pdata->Power_EN_Pin, NULL);
gpio_direction_output(pdata->Power_EN_Pin,GPIO_HIGH);
- gpio_free(pdata->Power_EN_Pin);
-
- gpio_request(pdata->PA_control_pin, NULL); //AUDIO_PA_ON
- gpio_direction_output(pdata->PA_control_pin,GPIO_LOW);
- gpio_free(pdata->PA_control_pin);
+ gpio_free(pdata->Power_EN_Pin);
return ret;
wm8994->BT_call_vol = BT_call_maxvol;
INIT_DELAYED_WORK(&wm8994->wm8994_delayed_work, wm8994_work_fun);
mutex_init(&wm8994->io_lock);
-
+ mutex_init(&wm8994->route_lock);
return wm8994_register(wm8994, SND_SOC_I2C);
}
struct wm8994_pdata *pdata = wm8994->pdata;
DBG("%s----%d\n",__FUNCTION__,__LINE__);
//disable PA
- PA_ctrl(GPIO_LOW);
- wm8994_write(0x00, 0x00);
+ PA_ctrl(GPIO_LOW);
gpio_request(pdata->Power_EN_Pin, NULL);
gpio_direction_output(pdata->Power_EN_Pin,GPIO_LOW);
gpio_free(pdata->Power_EN_Pin);