#define DBG(x...) do { } while (0)
#endif
-#define HOOK_ADC_SAMPLE_TIME 700
-#define HOOK_LEVEL_HIGH 409 //1V*1024/2.5
+#define HOOK_ADC_SAMPLE_TIME 100
+#define HOOK_LEVEL_HIGH 600 //1V*1024/2.5
#define HOOK_LEVEL_LOW 204 //0.5V*1024/2.5
+#define HOOK_DEFAULT_VAL 1024
#define BIT_HEADSET (1 << 0)
#define BIT_HEADSET_NO_MIC (1 << 1)
#define HEADSET_IN 1
#define HEADSET_OUT 0
-#define HOOK_DOWN 0
-#define HOOK_UP 1
+#define HOOK_DOWN 1
+#define HOOK_UP 0
#define enable 1
#define disable 0
#define HEADSET_TIMER 1
#define HOOK_TIMER 2
+#define WAIT 2
+#define BUSY 1
+#define IDLE 0
+
#ifdef CONFIG_SND_SOC_WM8994
-extern int wm8994_set_status(void);
+extern int wm8994_headset_mic_detect(bool headset_status);
+#endif
+
+#ifdef CONFIG_SND_SOC_RT3261
+extern int rt3261_headset_mic_detect(int jack_insert);
#endif
/* headset private data */
struct rk_headset_pdata *pdata;
unsigned int headset_status:1;
unsigned int hook_status:1;
- unsigned int isMic:1;
- unsigned int isHook_irq:1;
+ int isMic;
+ unsigned int heatset_irq_working;// headset interrupt working will not check hook key
int cur_headset_status;
unsigned int irq[2];
unsigned char *keycodes;
struct adc_client *client;
struct timer_list hook_timer;
- int adc_callback_status;
+ unsigned int hook_time;//ms
};
static struct headset_priv *headset_info;
}
EXPORT_SYMBOL_GPL(Headset_isMic);
+//1
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(50));
- return IRQ_HANDLED;
-}
-
-static int headset_change_irqtype(int type,unsigned int irq_type)
-{
- int ret = 0;
- DBG("--------%s----------\n",__FUNCTION__);
- free_irq(headset_info->irq[type],NULL);
-
- switch(type)
- {
- case HEADSET:
- ret = request_irq(headset_info->irq[type], headset_interrupt, irq_type, "headset_hook", NULL);
- break;
- default:
- ret = -1;
- break;
- }
-
- if (ret<0)
- {
- DBG("headset_change_irqtype: request irq failed\n");
- return ret;
- }
- return ret;
-}
-
-static void headsetobserve_work(struct work_struct *work)
-{
- int i,level = 0;
struct rk_headset_pdata *pdata = headset_info->pdata;
static unsigned int old_status = 0;
- DBG("---headsetobserve_work---\n");
- mutex_lock(&headset_info->mutex_lock[HEADSET]);
-
+ int i,level = 0;
+ int adc_value = 0;
+ if(headset_info->heatset_irq_working == BUSY || headset_info->heatset_irq_working == WAIT)
+ return IRQ_HANDLED;
+ DBG("In the headset_interrupt for read headset level\n");
+ headset_info->heatset_irq_working = BUSY;
for(i=0; i<3; i++)
{
level = gpio_get_value(pdata->Headset_gpio);
if(level < 0)
{
printk("%s:get pin level err!\n",__FUNCTION__);
- goto RE_ERROR;
+ goto out;
}
old_status = headset_info->headset_status;
}
if(old_status == headset_info->headset_status)
{
- DBG("old_status == headset_info->headset_status\n");
- goto RE_ERROR;
+ DBG("Read Headset IO level old status == now status\n");
+ goto out;
}
- switch(pdata->headset_in_type)
+ DBG("(headset in is %s)headset status is %s\n",
+ pdata->headset_in_type?"high level":"low level",
+ headset_info->headset_status?"in":"out");
+ if(headset_info->headset_status == HEADSET_IN)
{
- case HEADSET_IN_HIGH:
- if(level > 0)
- {//in--High level
- DBG("--- HEADSET_IN_HIGH headset in HIGH---\n");
- headset_info->cur_headset_status = BIT_HEADSET_NO_MIC;
- headset_change_irqtype(HEADSET,IRQF_TRIGGER_FALLING);//
-
- del_timer(&headset_info->headset_timer);//Start the timer, wait for switch to the headphone channel
- // headset_info->headset_timer.expires = jiffies + 500;
- headset_info->headset_timer.expires = jiffies + 10;
- add_timer(&headset_info->headset_timer);
+ #if 0
+ while(1)
+ {
+ if(adc_sync_read(headset_info->client) > HOOK_DEFAULT_VAL
+ || adc_sync_read(headset_info->client) < 0)
+ {
+ printk("headset is showly inside\n");
+ }
+ else
+ break;
+ msleep(50);
+
+ if(pdata->headset_in_type == HEADSET_IN_HIGH)
+ old_status = headset_info->headset_status = gpio_get_value(pdata->Headset_gpio)?HEADSET_IN:HEADSET_OUT;
+ else
+ old_status = headset_info->headset_status = gpio_get_value(pdata->Headset_gpio)?HEADSET_OUT:HEADSET_IN;
+ if(headset_info->headset_status == HEADSET_OUT)
+ goto out1;
+ msleep(5);
}
- else if(level == 0)
- {//out--Low level
- DBG("---HEADSET_IN_HIGH headset out HIGH---\n");
-
- del_timer(&headset_info->hook_timer);
- headset_info->cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC);
- headset_change_irqtype(HEADSET,IRQF_TRIGGER_RISING);//
- rk28_send_wakeup_key();
- switch_set_state(&headset_info->sdev, headset_info->cur_headset_status);
- DBG("headset_info->cur_headset_status = %d\n",headset_info->cur_headset_status);
+ #endif
+ if(pdata->Hook_adc_chn>=0 && 3>=pdata->Hook_adc_chn)
+ {
+ // wait for find Hook key
+ //#ifdef CONFIG_SND_SOC_RT5625
+ CHECK_AGAIN:
+ //headset_info->isMic = rt5625_headset_mic_detect(true);
+ #ifdef CONFIG_SND_SOC_WM8994
+ wm8994_headset_mic_detect(true);
+ #endif
+ #ifdef CONFIG_SND_SOC_RT3261
+ rt3261_headset_mic_detect(true);
+ #endif
+ //mdelay(400);
+ adc_value = adc_sync_read(headset_info->client);
+ if(adc_value >= 0 && adc_value < HOOK_LEVEL_LOW)
+ {
+ headset_info->isMic= 0;//No microphone
+ #ifdef CONFIG_SND_SOC_WM8994
+ wm8994_headset_mic_detect(false);
+ #endif
+ #ifdef CONFIG_SND_SOC_RT3261
+ rt3261_headset_mic_detect(false);
+ #endif
+ printk("headset->isMic = %d\n",headset_info->isMic);
+ }
+ else if(adc_value >= HOOK_LEVEL_HIGH)
+ {
+ headset_info->isMic = 1;//have mic
+ printk("headset->isMic = %d\n",headset_info->isMic);
+ }
+ if(headset_info->isMic < 0)
+ {
+ printk("codec is error\n");
+ headset_info->heatset_irq_working = WAIT;
+ if(pdata->headset_in_type == HEADSET_IN_HIGH)
+ irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_LOW|IRQF_ONESHOT);
+ else
+ irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_HIGH|IRQF_ONESHOT);
+ schedule_delayed_work(&headset_info->h_delayed_work[HEADSET], msecs_to_jiffies(0));
+ return IRQ_HANDLED;
+ }
+ //adc_value = adc_sync_read(headset_info->client);
+ printk("headset adc value = %d\n",adc_value);
+ if(headset_info->isMic) {
+ if(adc_value > HOOK_DEFAULT_VAL || adc_value < HOOK_LEVEL_HIGH)
+ goto CHECK_AGAIN;
+ mod_timer(&headset_info->hook_timer, jiffies + msecs_to_jiffies(1000));
+ }
+ //#endif
+ headset_info->cur_headset_status = headset_info->isMic ? BIT_HEADSET:BIT_HEADSET_NO_MIC;
}
- break;
- case HEADSET_IN_LOW:
- if(level == 0)
- {//in--High level
- DBG("---HEADSET_IN_LOW headset in LOW ---\n");
+ else
+ {
+ headset_info->isMic= 0;//No microphone
headset_info->cur_headset_status = BIT_HEADSET_NO_MIC;
- headset_change_irqtype(HEADSET,IRQF_TRIGGER_RISING);//
-
- del_timer(&headset_info->headset_timer);//Start the timer, wait for switch to the headphone channel
- // headset_info->headset_timer.expires = jiffies + 500;
- headset_info->headset_timer.expires = jiffies + 10;
- add_timer(&headset_info->headset_timer);
- }
- else if(level > 0)
- {//out--High level
- DBG("---HEADSET_IN_LOW headset out LOW ---\n");
-
- del_timer(&headset_info->hook_timer);
- headset_info->cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC);
- headset_change_irqtype(HEADSET,IRQF_TRIGGER_FALLING);//
- rk28_send_wakeup_key();
- switch_set_state(&headset_info->sdev, headset_info->cur_headset_status);
- DBG("headset_info->cur_headset_status = %d\n",headset_info->cur_headset_status);
}
- break;
- default:
- DBG("---- ERROR: on headset headset_in_type error -----\n");
- break;
+ printk("headset->isMic = %d\n",headset_info->isMic);
+ if(pdata->headset_in_type == HEADSET_IN_HIGH)
+ irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_FALLING);
+ else
+ irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_RISING);
}
-
+ else if(headset_info->headset_status == HEADSET_OUT)
+ {
+ headset_info->cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC);
+ del_timer(&headset_info->hook_timer);
+ if(headset_info->isMic)
+ {
+ headset_info->hook_status = HOOK_UP;
+ #ifdef CONFIG_SND_SOC_WM8994
+ //rt5625_headset_mic_detect(false);
+ wm8994_headset_mic_detect(false);
+ #endif
+ #ifdef CONFIG_SND_SOC_RT3261
+ rt3261_headset_mic_detect(false);
+ #endif
+ }
+ if(pdata->headset_in_type == HEADSET_IN_HIGH)
+ irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_RISING);
+ else
+ irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_FALLING);
+ }
+
+ rk28_send_wakeup_key();
+ switch_set_state(&headset_info->sdev, headset_info->cur_headset_status);
+ DBG("headset notice android headset status = %d\n",headset_info->cur_headset_status);
+
+// schedule_delayed_work(&headset_info->h_delayed_work[HEADSET], msecs_to_jiffies(0));
+out:
+ headset_info->heatset_irq_working = IDLE;
+ return IRQ_HANDLED;
+}
+
+static int headset_change_irqtype(int type,unsigned int irq_type)
+{
+ int ret = 0;
+ free_irq(headset_info->irq[type],NULL);
-RE_ERROR:
- mutex_unlock(&headset_info->mutex_lock[HEADSET]);
+ DBG("%s: type is %s irqtype is %s\n",__FUNCTION__, type?"hook":"headset",(irq_type == IRQF_TRIGGER_RISING)?"RISING":"FALLING");
+// DBG("%s: type is %s irqtype is %s\n",__FUNCTION__, type?"hook":"headset",(irq_type == IRQF_TRIGGER_LOW)?"LOW":"HIGH");
+ switch(type)
+ {
+ case HEADSET:
+ ret = request_threaded_irq(headset_info->irq[type],NULL, headset_interrupt, irq_type, "headset_input", NULL);
+ if (ret<0)
+ DBG("headset_change_irqtype: request irq failed\n");
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+ return ret;
}
+//2
+static void headsetobserve_work(struct work_struct *work)
+{
+ struct rk_headset_pdata *pdata = headset_info->pdata;
+ DBG("In the headsetobserve_work headset_status is %s\n",headset_info->headset_status?"in":"out");
+ if(headset_info->heatset_irq_working == WAIT && headset_info->headset_status == HEADSET_IN)
+ {
+ printk("wait for codec\n");
+ headset_info->heatset_irq_working = IDLE;
+ headset_info->headset_status = HEADSET_OUT;
+
+ free_irq(headset_info->irq[HEADSET],NULL);
+ msleep(100);
+ if(pdata->headset_in_type == HEADSET_IN_HIGH)
+ headset_info->irq_type[HEADSET] = IRQF_TRIGGER_HIGH|IRQF_ONESHOT;
+ else
+ headset_info->irq_type[HEADSET] = IRQF_TRIGGER_LOW|IRQF_ONESHOT;
+ if(request_threaded_irq(headset_info->irq[HEADSET], NULL,headset_interrupt, headset_info->irq_type[HEADSET], "headset_input", NULL) < 0)
+ printk("headset request_threaded_irq error\n");
+ return;
+ }
+/*
+ if(pdata->headset_in_type == HEADSET_IN_HIGH && headset_info->headset_status == HEADSET_IN)
+ headset_change_irqtype(HEADSET,IRQF_TRIGGER_FALLING);
+ else if(pdata->headset_in_type == HEADSET_IN_LOW && headset_info->headset_status == HEADSET_IN)
+ headset_change_irqtype(HEADSET,IRQF_TRIGGER_RISING);
+
+ if(pdata->headset_in_type == HEADSET_IN_HIGH && headset_info->headset_status == HEADSET_OUT)
+ headset_change_irqtype(HEADSET,IRQF_TRIGGER_RISING);
+ else if(pdata->headset_in_type == HEADSET_IN_LOW && headset_info->headset_status == HEADSET_OUT)
+ headset_change_irqtype(HEADSET,IRQF_TRIGGER_FALLING);
+*/
+}
+//4
static void hook_adc_callback(struct adc_client *client, void *client_param, int result)
{
- int level = 0;
+ int level = result;
struct headset_priv *headset = (struct headset_priv *)client_param;
- struct rk_headset_pdata *pdata = headset_info->pdata;
+ struct rk_headset_pdata *pdata = headset->pdata;
static unsigned int old_status = HOOK_UP;
- DBG("---hook_adc_callback---, result = %d, flag = %d\n", result, headset->adc_callback_status);
-
- level = result;
+ DBG("hook_adc_callback read adc value: %d\n",level);
if(level < 0)
{
- printk("%s:get adc level err!\n",__FUNCTION__);
+ printk("%s:get adc level err = %d!\n",__FUNCTION__,level);
return;
}
- switch(headset->adc_callback_status)
+ if(headset->headset_status == HEADSET_OUT
+ || headset->heatset_irq_working == BUSY
+ || headset->heatset_irq_working == WAIT
+ || pdata->headset_in_type?gpio_get_value(pdata->Headset_gpio) == 0:gpio_get_value(pdata->Headset_gpio) > 0)
{
-
- case HEADSET_TIMER:
-
- if(level >= 0 && level < HOOK_LEVEL_LOW)
- {
- headset->isMic= 0;//No microphone
- headset_info->cur_headset_status = BIT_HEADSET_NO_MIC;
- printk("headset->isMic = %d\n",headset->isMic);
- }
- else if(level >= HOOK_LEVEL_HIGH)
- {
- headset->isMic = 1;//have mic
- DBG("enable headset_hook irq\n");
- headset_info->cur_headset_status = BIT_HEADSET;
- mod_timer(&headset_info->hook_timer, jiffies + msecs_to_jiffies(HOOK_ADC_SAMPLE_TIME));
- printk("headset->isMic = %d\n",headset->isMic);
- }
+ DBG("Headset is out or waiting for headset is in or out,after same time check HOOK key\n");
+ return;
+ }
- rk28_send_wakeup_key();
- switch_set_state(&headset_info->sdev, headset_info->cur_headset_status);
- DBG("headset_info->cur_headset_status = %d\n",headset_info->cur_headset_status);
- break;
-
- case HOOK_TIMER:
- mutex_lock(&headset_info->mutex_lock[HOOK]);
- if(headset_info->headset_status == HEADSET_OUT)
- {
- DBG("Headset is out\n");
- goto RE_ERROR;
- }
- #ifdef CONFIG_SND_SOC_WM8994
- if(wm8994_set_status() != 0)
- {
- DBG("wm8994 is not set on heatset channel or suspend\n");
- goto RE_ERROR;
- }
- #endif
+ old_status = headset->hook_status;
+ if(level < HOOK_LEVEL_LOW && level >= 0)
+ headset->hook_status = HOOK_DOWN;
+ else if(level > HOOK_LEVEL_HIGH && level < HOOK_DEFAULT_VAL)
+ headset->hook_status = HOOK_UP;
+ else{
+ DBG("hook_adc_callback read adc value.........outside showly....: %d\n",level);
+ del_timer(&headset->hook_timer);
+ mod_timer(&headset->hook_timer, jiffies + msecs_to_jiffies(500));
+ return;
+ }
- old_status = headset_info->hook_status;
- if(level >= HOOK_LEVEL_HIGH)
- headset_info->hook_status = HOOK_UP;
- else if(level < HOOK_LEVEL_LOW && level >= 0)
- headset_info->hook_status = HOOK_DOWN;
- if(old_status == headset_info->hook_status)
- {
- DBG("old_status == headset_info->hook_status\n");
- goto RE_ERROR;
- }
+ if(old_status == headset->hook_status)
+ {
+ // DBG("Hook adc read old_status == headset->hook_status hook_time = %d\n",headset->hook_time);
+ return;
+ }
- if(level < HOOK_LEVEL_LOW && level >= 0)
- {
- DBG("---HOOK Down ---\n");
- //headset_change_irqtype(HOOK,IRQF_TRIGGER_RISING);//
- input_report_key(headset_info->input_dev,pdata->hook_key_code,headset_info->hook_status);
- input_sync(headset_info->input_dev);
- }
- else if(level >= HOOK_LEVEL_HIGH)
- {
- DBG("---HOOK Up ---\n");
- //headset_change_irqtype(HOOK,IRQF_TRIGGER_FALLING);//
- input_report_key(headset_info->input_dev,pdata->hook_key_code,headset_info->hook_status);
- input_sync(headset_info->input_dev);
- }
- mutex_unlock(&headset_info->mutex_lock[HOOK]);
- break;
- default:
- printk("adc callback flag status error!!! default case\n");
- break;
- }
- return;
-
-RE_ERROR:
- mutex_unlock(&headset_info->mutex_lock[HOOK]);
+ DBG("HOOK status is %s , adc value = %d hook_time = %d\n",headset->hook_status?"down":"up",level,headset->hook_time);
+ if(headset->headset_status == HEADSET_OUT
+ || headset->heatset_irq_working == BUSY
+ || headset->heatset_irq_working == WAIT
+ || (pdata->headset_in_type?gpio_get_value(pdata->Headset_gpio) == 0:gpio_get_value(pdata->Headset_gpio) > 0))
+ DBG("headset is out,HOOK status must discard\n");
+ else
+ {
+ if(headset->hook_status==HOOK_DOWN)
+ DBG("hook_adc_callback read adc ------------HOOK_DOWN\n");
+ else
+ DBG("hook_adc_callback read adc ------------HOOK_UP\n");
+ input_report_key(headset->input_dev,pdata->hook_key_code,headset->hook_status);
+ input_sync(headset->input_dev);
+ }
}
-
+//3
static void hook_timer_callback(unsigned long arg)
{
struct headset_priv *headset = (struct headset_priv *)(arg);
- DBG("hook_timer_callback\n");
- adc_async_read(headset->client);
- headset->adc_callback_status = HOOK_TIMER;
- mod_timer(&headset->hook_timer, jiffies + msecs_to_jiffies(HOOK_ADC_SAMPLE_TIME));
-}
-
-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,headset->headset_status=%d\n",headset->headset_status);
-
- if(headset->headset_status == HEADSET_OUT)
- {
- printk("Headset is out\n");
- goto out;
- }
- #ifdef CONFIG_SND_SOC_WM8994
- if(wm8994_set_status() != 0)
- {
- // printk("wait wm8994 set the MICB2\n");
- // headset_info->headset_timer.expires = jiffies + 500;
- headset_info->headset_timer.expires = jiffies + 10;
- add_timer(&headset_info->headset_timer);
- goto out;
- }
- #endif
-
+// DBG("hook_timer_callback\n");
+ if(headset->headset_status == HEADSET_OUT
+ || headset->heatset_irq_working == BUSY
+ || headset->heatset_irq_working == WAIT)
+ return;
adc_async_read(headset->client);
- headset->adc_callback_status = HEADSET_TIMER;
-out:
- return;
+ mod_timer(&headset->hook_timer, jiffies + msecs_to_jiffies(headset->hook_time));
}
static ssize_t h2w_print_name(struct switch_dev *sdev, char *buf)
if (headset == NULL) {
dev_err(&pdev->dev, "failed to allocate driver data\n");
return -ENOMEM;
- }
+ }
+ headset_info = headset;
headset->pdata = pdev->dev.platform_data;
pdata = headset->pdata;
headset->headset_status = HEADSET_OUT;
+ headset->heatset_irq_working = IDLE;
headset->hook_status = HOOK_UP;
- headset->adc_callback_status = HEADSET_TIMER;
+ headset->hook_time = HOOK_ADC_SAMPLE_TIME;
headset->cur_headset_status = 0;
headset->sdev.name = "h2w";
headset->sdev.print_name = h2w_print_name;
if (ret < 0)
goto failed_free;
- mutex_init(&headset->mutex_lock[HEADSET]);
- mutex_init(&headset->mutex_lock[HOOK]);
+// mutex_init(&headset->mutex_lock[HEADSET]);
+// mutex_init(&headset->mutex_lock[HOOK]);
INIT_DELAYED_WORK(&headset->h_delayed_work[HEADSET], headsetobserve_work);
headset->isMic = 0;
- setup_timer(&headset->headset_timer, headset_timer_callback, (unsigned long)headset);
-
-
+//------------------------------------------------------------------
// Create and register the input driver.
headset->input_dev = input_allocate_device();
if (!headset->input_dev) {
goto failed_free_dev;
}
-
-// headset->input_dev->keycode = headset->keycodes;
-// headset->input_dev->keycodesize = sizeof(unsigned char);
-// headset->input_dev->keycodemax = 2;
-
-// set_bit(KEY_MEDIA, headset->input_dev->keybit);
-// clear_bit(0, headset->input_dev->keybit);
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);
-
-// headset->input_dev->evbit[0] = BIT_MASK(EV_KEY);
-
- headset_info = headset;
- schedule_delayed_work(&headset->h_delayed_work[HEADSET], msecs_to_jiffies(500));
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
- hs_early_suspend.suspend = NULL;
- hs_early_suspend.resume = headset_early_resume;
- hs_early_suspend.level = ~0x0;
- register_early_suspend(&hs_early_suspend);
-#endif
-
- //------------------------------------------------------------------
+//------------------------------------------------------------------
if (pdata->Headset_gpio) {
-
ret = pdata->headset_io_init(pdata->Headset_gpio, pdata->headset_gpio_info.iomux_name, pdata->headset_gpio_info.iomux_mode);
if (ret)
- goto failed_free_dev;
+ goto failed_free;
headset->irq[HEADSET] = gpio_to_irq(pdata->Headset_gpio);
if(pdata->headset_in_type == HEADSET_IN_HIGH)
- headset->irq_type[HEADSET] = IRQF_TRIGGER_RISING;
+ headset->irq_type[HEADSET] = IRQF_TRIGGER_HIGH|IRQF_ONESHOT;
else
- headset->irq_type[HEADSET] = IRQF_TRIGGER_FALLING;
- ret = request_irq(headset->irq[HEADSET], headset_interrupt, headset->irq_type[HEADSET], "headset_input", NULL);
+ headset->irq_type[HEADSET] = IRQF_TRIGGER_LOW|IRQF_ONESHOT;
+ ret = request_threaded_irq(headset->irq[HEADSET], NULL,headset_interrupt, headset->irq_type[HEADSET], "headset_input", NULL);
if (ret)
- goto failed_free_dev;
+ goto failed_free;
enable_irq_wake(headset->irq[HEADSET]);
}
else
- goto failed_free_dev;
+ goto failed_free;
//------------------------------------------------------------------
-
- if(pdata->Hook_adc_chn>=0 && 2>=pdata->Hook_adc_chn)
+ if(pdata->Hook_adc_chn>=0 && 3>=pdata->Hook_adc_chn)
{
- printk("hook adc register\n");
headset->client = adc_register(pdata->Hook_adc_chn, hook_adc_callback, (void *)headset);
if(!headset->client) {
printk("hook adc register error\n");
ret = -EINVAL;
- goto failed_free_dev;
+ goto failed_free;
}
- setup_timer(&headset->hook_timer,
- hook_timer_callback, (unsigned long)headset);
+ setup_timer(&headset->hook_timer,hook_timer_callback, (unsigned long)headset);
+ printk("headset adc default value = %d\n",adc_sync_read(headset->client));
}
-//------------------------------------------------------------------
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ hs_early_suspend.suspend = NULL;
+ hs_early_suspend.resume = headset_early_resume;
+ hs_early_suspend.level = ~0x0;
+ register_early_suspend(&hs_early_suspend);
+#endif
+
return 0;
failed_free_dev:
static int rockchip_headsetobserve_suspend(struct platform_device *pdev, pm_message_t state)
{
DBG("%s----%d\n",__FUNCTION__,__LINE__);
- disable_irq(headset_info->irq[HEADSET]);
+// disable_irq(headset_info->irq[HEADSET]);
+ del_timer(&headset_info->hook_timer);
return 0;
}
static int rockchip_headsetobserve_resume(struct platform_device *pdev)
{
DBG("%s----%d\n",__FUNCTION__,__LINE__);
- enable_irq(headset_info->irq[HEADSET]);
+// enable_irq(headset_info->irq[HEADSET]);
+ if(headset_info->isMic)
+ mod_timer(&headset_info->hook_timer, jiffies + msecs_to_jiffies(1500));
return 0;
}
static struct platform_driver rockchip_headsetobserve_driver = {
.probe = rockchip_headsetobserve_probe,
-// .resume = rockchip_headsetobserve_resume,
-// .suspend = rockchip_headsetobserve_suspend,
+ .resume = rockchip_headsetobserve_resume,
+ .suspend = rockchip_headsetobserve_suspend,
.driver = {
.name = "rk_headsetdet",
.owner = THIS_MODULE,
platform_driver_register(&rockchip_headsetobserve_driver);
return 0;
}
-module_init(rockchip_headsetobserve_init);
+late_initcall(rockchip_headsetobserve_init);
MODULE_DESCRIPTION("Rockchip Headset Driver");
MODULE_LICENSE("GPL");
+
#define VERSION "RT3261_V1.0.0"
+#if defined (CONFIG_SND_SOC_RT5623)
extern void rt5623_on(void);
extern void rt5623_off(void);
+#endif
struct rt3261_init_reg {
u8 reg;
}
/**
- * rt3261_headset_detect - Detect headset.
+ * rt3261_headset_mic_detect - Detect headset.
* @codec: SoC audio codec device.
* @jack_insert: Jack insert or not.
*
*
* Returns detect status.
*/
-int rt3261_headset_detect(struct snd_soc_codec *codec, int jack_insert)
+int rt3261_headset_mic_detect(int jack_insert)
{
int jack_type;
int sclk_src;
if(jack_insert) {
- if (SND_SOC_BIAS_OFF == codec->dapm.bias_level) {
- snd_soc_write(codec, RT3261_PWR_ANLG1, 0x2004);
- snd_soc_write(codec, RT3261_MICBIAS, 0x3830);
- snd_soc_write(codec, RT3261_GEN_CTRL1 , 0x3701);
+ if (SND_SOC_BIAS_OFF == rt3261_codec->dapm.bias_level) {
+ snd_soc_write(rt3261_codec, RT3261_PWR_ANLG1, 0x2004);
+ snd_soc_write(rt3261_codec, RT3261_MICBIAS, 0x3830);
+ snd_soc_write(rt3261_codec, RT3261_GEN_CTRL1 , 0x3701);
}
- sclk_src = snd_soc_read(codec, RT3261_GLB_CLK) &
+ sclk_src = snd_soc_read(rt3261_codec, RT3261_GLB_CLK) &
RT3261_SCLK_SRC_MASK;
- snd_soc_update_bits(codec, RT3261_GLB_CLK,
+ snd_soc_update_bits(rt3261_codec, RT3261_GLB_CLK,
RT3261_SCLK_SRC_MASK, 0x3 << RT3261_SCLK_SRC_SFT);
- snd_soc_update_bits(codec, RT3261_PWR_ANLG1,
+ snd_soc_update_bits(rt3261_codec, RT3261_PWR_ANLG1,
RT3261_PWR_LDO2, RT3261_PWR_LDO2);
- snd_soc_update_bits(codec, RT3261_PWR_ANLG2,
+ snd_soc_update_bits(rt3261_codec, RT3261_PWR_ANLG2,
RT3261_PWR_MB1, RT3261_PWR_MB1);
- snd_soc_update_bits(codec, RT3261_MICBIAS,
+ mdelay(400);
+ snd_soc_update_bits(rt3261_codec, RT3261_MICBIAS,
RT3261_MIC1_OVCD_MASK | RT3261_MIC1_OVTH_MASK |
RT3261_PWR_CLK25M_MASK | RT3261_PWR_MB_MASK,
RT3261_MIC1_OVCD_EN | RT3261_MIC1_OVTH_600UA |
RT3261_PWR_MB_PU | RT3261_PWR_CLK25M_PU);
- snd_soc_update_bits(codec, RT3261_GEN_CTRL1,
+ snd_soc_update_bits(rt3261_codec, RT3261_GEN_CTRL1,
0x1, 0x1);
msleep(100);
- if (snd_soc_read(codec, RT3261_IRQ_CTRL2) & 0x8)
+ if (snd_soc_read(rt3261_codec, RT3261_IRQ_CTRL2) & 0x8)
jack_type = RT3261_HEADPHO_DET;
else
jack_type = RT3261_HEADSET_DET;
- snd_soc_update_bits(codec, RT3261_IRQ_CTRL2,
+ snd_soc_update_bits(rt3261_codec, RT3261_IRQ_CTRL2,
RT3261_MB1_OC_CLR, 0);
- snd_soc_update_bits(codec, RT3261_GLB_CLK,
+ snd_soc_update_bits(rt3261_codec, RT3261_GLB_CLK,
RT3261_SCLK_SRC_MASK, sclk_src);
} else {
- snd_soc_update_bits(codec, RT3261_MICBIAS,
+ snd_soc_update_bits(rt3261_codec, RT3261_MICBIAS,
RT3261_MIC1_OVCD_MASK,
RT3261_MIC1_OVCD_DIS);
return jack_type;
}
-EXPORT_SYMBOL(rt3261_headset_detect);
+EXPORT_SYMBOL(rt3261_headset_mic_detect);
static const char *rt3261_dacr2_src[] = { "TxDC_R", "TxDP_R" };
return 0;
}
+#if defined (CONFIG_SND_SOC_RT5623)
static int rt3261_modem_input_switch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
return 0;
}
+#endif
/* IN1/IN2 Input Type */
static const char *rt3261_input_mode[] = {
static const SOC_ENUM_SINGLE_DECL(rt3261_hp_mute_enum, 0, 0, rt3261_hp_mute_mode);
+#if defined (CONFIG_SND_SOC_RT5623)
static const char *rt3261_modem_input_switch_mode[] = {"off", "on",};
static const SOC_ENUM_SINGLE_DECL(rt3261_modem_input_switch_enum, 0, 0, rt3261_modem_input_switch_mode);
+#endif
#ifdef RT3261_REG_RW
#define REGVAL_MAX 0xffff
SOC_ENUM_EXT("HP mute Switch", rt3261_hp_mute_enum,
rt3261_hp_mute_get, rt3261_hp_mute_put),
+ #if defined (CONFIG_SND_SOC_RT5623)
SOC_ENUM_EXT("Modem Input Switch", rt3261_modem_input_switch_enum,
rt3261_modem_input_switch_get, rt3261_modem_input_switch_put),
+ #endif
};
/**
break;
case SND_SOC_BIAS_PREPARE:
- snd_soc_update_bits(codec, RT3261_PWR_ANLG2,
- RT3261_PWR_MB1 | RT3261_PWR_MB2,
- RT3261_PWR_MB1 | RT3261_PWR_MB2);
break;
case SND_SOC_BIAS_STANDBY:
- snd_soc_update_bits(codec, RT3261_PWR_ANLG2,
- RT3261_PWR_MB1 | RT3261_PWR_MB2, 0);
if (SND_SOC_BIAS_OFF == codec->dapm.bias_level) {
snd_soc_update_bits(codec, RT3261_PWR_ANLG1,
RT3261_PWR_VREF1 | RT3261_PWR_MB |
rt3261_proc_init();
#endif
+ #if defined (CONFIG_SND_SOC_RT5623)
//for rt5623 MCLK use
iis_clk = clk_get_sys("rk29_i2s.2", "i2s");
if (IS_ERR(iis_clk)) {
rk30_mux_api_set(GPIO0D0_I2S22CHCLK_SMCCSN0_NAME, GPIO0D_I2S2_2CH_CLK);
clk_put(iis_clk);
}
+ #endif
rt3261_reset(codec);
snd_soc_update_bits(codec, RT3261_PWR_ANLG1,
if(rt3261->io_init)
rt3261->io_init(pdata->codec_en_gpio, pdata->codec_en_gpio_info.iomux_name, pdata->codec_en_gpio_info.iomux_mode);
+ #if defined (CONFIG_SND_SOC_RT5623)
rt3261->modem_is_open = 0;
+ #endif
i2c_set_clientdata(i2c, rt3261);
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);