--- /dev/null
+/* arch/arm/mach-rockchip/rk28_headset.c
+ *
+ * Copyright (C) 2009 Rockchip Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/sysdev.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/hrtimer.h>
+#include <linux/switch.h>
+#include <linux/input.h>
+#include <linux/debugfs.h>
+#include <linux/wakelock.h>
+#include <asm/gpio.h>
+#include <asm/atomic.h>
+#include <asm/mach-types.h>
+#include "rk_headset.h"
+#include <linux/earlysuspend.h>
+
+/* Debug */
+#if 1
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...) do { } while (0)
+#endif
+
+#define BIT_HEADSET (1 << 0)
+#define BIT_HEADSET_NO_MIC (1 << 1)
+
+struct rk2818_headset_dev{
+ struct switch_dev sdev;
+ int cur_headset_status;
+ int pre_headset_status;
+ struct mutex mutex_lock;
+};
+
+static struct rk2818_headset_dev Headset_dev;
+static struct delayed_work g_headsetobserve_work;
+static struct rk2818_headset_data *prk2818_headset_info;
+#if defined(CONFIG_MACH_BENGO_V2) || defined(CONFIG_MACH_BENGO) || defined(CONFIG_MACH_Z5) || defined(CONFIG_MACH_Z5_V2) || defined(CONFIG_MACH_A22)
+extern void detect_HSMic(void);
+#endif
+
+int headset_status(void)
+{
+ if(Headset_dev.cur_headset_status & BIT_HEADSET)
+ return 1;
+ else
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(headset_status);
+
+static irqreturn_t headset_interrupt(int irq, void *dev_id)
+{
+// DBG("---headset_interrupt---\n");
+ schedule_delayed_work(&g_headsetobserve_work, msecs_to_jiffies(20));
+ return IRQ_HANDLED;
+}
+
+static int headset_change_irqtype(unsigned int irq_type)
+{
+ int ret = 0;
+// DBG("--------%s----------\n",__FUNCTION__);
+ free_irq(prk2818_headset_info->irq,NULL);
+
+ ret = request_irq(prk2818_headset_info->irq, headset_interrupt, irq_type, NULL, NULL);
+ if (ret)
+ {
+ DBG("headsetobserve: request irq failed\n");
+ return ret;
+ }
+ return ret;
+}
+
+static void headsetobserve_work(struct work_struct *work)
+{
+ int i,level = 0;
+
+// DBG("---headsetobserve_work---\n");
+ mutex_lock(&Headset_dev.mutex_lock);
+
+ for(i=0; i<3; i++)
+ {
+ level = gpio_get_value(prk2818_headset_info->gpio);
+ if(level < 0)
+ {
+ printk("%s:get pin level again,pin=%d,i=%d\n",__FUNCTION__,prk2818_headset_info->gpio,i);
+ msleep(1);
+ continue;
+ }
+ else
+ break;
+ }
+ if(level < 0)
+ {
+ printk("%s:get pin level err!\n",__FUNCTION__);
+ return;
+ }
+
+ switch(prk2818_headset_info->headset_in_type)
+ {
+ case HEADSET_IN_HIGH:
+ if(level > 0)
+ {//in--High level
+ DBG("--- HEADSET_IN_HIGH headset in---\n");
+ Headset_dev.cur_headset_status = BIT_HEADSET;
+ headset_change_irqtype(IRQF_TRIGGER_FALLING);//
+ }
+ else if(level == 0)
+ {//out--Low level
+ DBG("---HEADSET_IN_HIGH headset out---\n");
+ Headset_dev.cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC);
+ headset_change_irqtype(IRQF_TRIGGER_RISING);//
+ }
+ break;
+ case HEADSET_IN_LOW:
+ if(level == 0)
+ {//in--High level
+ DBG("---HEADSET_IN_LOW headset in---\n");
+ Headset_dev.cur_headset_status = BIT_HEADSET;
+ headset_change_irqtype(IRQF_TRIGGER_RISING);//
+ }
+ else if(level > 0)
+ {//out--High level
+ DBG("---HEADSET_IN_LOW headset out---\n");
+ Headset_dev.cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC);
+ headset_change_irqtype(IRQF_TRIGGER_FALLING);//
+ }
+ break;
+ default:
+ DBG("---- ERROR: on headset headset_in_type error -----\n");
+ break;
+ }
+
+ if(Headset_dev.cur_headset_status != Headset_dev.pre_headset_status)
+ {
+ Headset_dev.pre_headset_status = Headset_dev.cur_headset_status;
+ switch_set_state(&Headset_dev.sdev, Headset_dev.cur_headset_status);
+ DBG("Headset_dev.cur_headset_status = %d\n",Headset_dev.cur_headset_status);
+#if defined(CONFIG_MACH_BENGO_V2) || defined(CONFIG_MACH_BENGO) || defined(CONFIG_MACH_Z5) || defined(CONFIG_MACH_Z5_V2) || defined(CONFIG_MACH_A22)
+ detect_HSMic();
+#endif
+ }
+ mutex_unlock(&Headset_dev.mutex_lock);
+}
+
+static ssize_t h2w_print_name(struct switch_dev *sdev, char *buf)
+{
+ return sprintf(buf, "Headset\n");
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void headset_early_resume(struct early_suspend *h)
+{
+ schedule_delayed_work(&g_headsetobserve_work, msecs_to_jiffies(10));
+ //DBG(">>>>>headset_early_resume\n");
+}
+
+static struct early_suspend hs_early_suspend;
+#endif
+
+static int rockchip_headsetobserve_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ DBG("RockChip headset observe driver\n");
+ prk2818_headset_info = pdev->dev.platform_data;
+
+ Headset_dev.cur_headset_status = 0;
+ Headset_dev.pre_headset_status = 0;
+ Headset_dev.sdev.name = "h2w";
+ Headset_dev.sdev.print_name = h2w_print_name;
+ mutex_init(&Headset_dev.mutex_lock);
+
+ ret = switch_dev_register(&Headset_dev.sdev);
+ if (ret < 0)
+ return ret;
+
+ INIT_DELAYED_WORK(&g_headsetobserve_work, headsetobserve_work);
+
+ ret = gpio_request(prk2818_headset_info->gpio, "headset_det");
+ if (ret)
+ {
+ DBG("headsetobserve: request gpio_request failed\n");
+ return ret;
+ }
+ gpio_pull_updown(prk2818_headset_info->gpio, GPIONormal);
+ gpio_direction_input(prk2818_headset_info->gpio);
+ prk2818_headset_info->irq = gpio_to_irq(prk2818_headset_info->gpio);
+
+ if(prk2818_headset_info->headset_in_type == HEADSET_IN_HIGH)
+ prk2818_headset_info->irq_type = IRQF_TRIGGER_RISING;
+ else
+ prk2818_headset_info->irq_type = IRQF_TRIGGER_FALLING;
+ ret = request_irq(prk2818_headset_info->irq, headset_interrupt, prk2818_headset_info->irq_type, NULL, NULL);
+ if (ret)
+ {
+ DBG("headsetobserve: request irq failed\n");
+ return ret;
+ }
+
+ schedule_delayed_work(&g_headsetobserve_work, 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
+
+ return 0;
+}
+
+static struct platform_driver rockchip_headsetobserve_driver = {
+ .probe = rockchip_headsetobserve_probe,
+ .driver = {
+ .name = "rk2818_headsetdet",
+ .owner = THIS_MODULE,
+ },
+};
+
+
+static int __init rockchip_headsetobserve_init(void)
+{
+ platform_driver_register(&rockchip_headsetobserve_driver);
+ return 0;
+}
+module_init(rockchip_headsetobserve_init);
+MODULE_DESCRIPTION("Rockchip Headset Driver");
+MODULE_LICENSE("GPL");
};
#ifdef WM8994_PROC
-char wm8994_current_route = SPEAKER_NORMAL;
char debug_write_read = 0;
#endif
bool wm8994_set_status(void)
{
- return isWM8994SetChannel;
+ return isWM8994SetChannel;
}
EXPORT_SYMBOL_GPL(wm8994_set_status);
if(vol<=0){
wm8994_write(0x31, (((-vol)/3)<<3)+(-vol)/3);
}else if(vol <= 9){
- // wm8994_write(0x25, ((vol*10/15)<<3)+vol*10/15);
+ wm8994_write(0x25, ((vol*10/15)<<3)+vol*10/15);
}else{
- // wm8994_write(0x25, 0x003F);
+ wm8994_write(0x25, 0x003F);
}
break;
struct wm8994_pdata *pdata = wm8994->pdata;
char route = kcontrol->private_value & 0xff;
-#ifdef WM8994_PROC
- wm8994_current_route = route;
-#endif
isWM8994SetChannel = true;
switch(route)
{
}
return 0;
}
+
+#if 1
/*
* WM8994 Controls
*/
-
static const char *bass_boost_txt[] = {"Linear Control", "Adaptive Boost"};
static const struct soc_enum bass_boost =
SOC_ENUM_SINGLE(WM8994_BASS, 7, 2, bass_boost_txt);
{12000000, 96000, 125, 0xe, 0x1},
};
-
static inline int get_coeff(int mclk, int rate)
{
int i;
codec->bias_level = level;
return 0;
}
-
+#endif
#define WM8994_RATES SNDRV_PCM_RATE_48000
#define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
int reg;
int value;
- char procadd = 0;
- unsigned short eqvol;
- unsigned char wm8994_proc_mode;
- wm8994_codec_fnc_t **wm8994_fnc_ptr = wm8994_codec_sequence;
-
cookie_pot = (char *)vmalloc( len );
if (!cookie_pot)
{
switch(cookie_pot[0])
{
- case 'n':
- case 'N':
- if(*(cookie_pot+1)=='+'){
- procadd = 3;
- }else if(*(cookie_pot+1)=='-'){
- procadd = -3;
- }else{
- printk("Please press '+' or '-' follow 'n'!\n");
- return -1;
- }
- switch(wm8994_current_route){
- case HEADSET_NORMAL:
- if(procadd == 3)
- headset_normal_vol += 3;
- else
- headset_normal_vol -= 3;
-
- if(headset_normal_vol > 6)
- headset_normal_vol = 6;
- else if(headset_normal_vol < -57)
- headset_normal_vol = -57;
-
- printk("headset_normal_vol = %ddB \n",headset_normal_vol);
- break;
-
- case SPEAKER_NORMAL:
- case EARPIECE_NORMAL:
- case SPEAKER_RINGTONE:
- case EARPIECE_RINGTONE:
- case BLUETOOTH_SCO_INCALL:
- if(procadd == 3)
- speaker_normal_vol += 3;
- else
- speaker_normal_vol -= 3;
-
- if(speaker_normal_vol > 6)
- speaker_normal_vol = 6;
- else if(speaker_normal_vol < -57)
- speaker_normal_vol = -57;
-
- printk("speaker_normal_vol = %ddB \n",speaker_normal_vol);
- break;
-
- case HEADSET_RINGTONE:
- if(procadd == 3){
- headset_normal_vol += 3;
- speaker_normal_vol += 3;
- }else{
- headset_normal_vol -= 3;
- speaker_normal_vol -= 3;
- }
-
- if(speaker_normal_vol > 6)
- speaker_normal_vol = 6;
- else if(speaker_normal_vol < -57)
- speaker_normal_vol = -57;
- if(headset_normal_vol > 6)
- headset_normal_vol = 6;
- else if(headset_normal_vol < -57)
- headset_normal_vol = -57;
-
- printk("headset_normal_vol = %ddB \n",headset_normal_vol);
- printk("speaker_normal_vol = %ddB \n",speaker_normal_vol);
- break;
-
- default:
- printk("Current channel does not match to normal mode!\n");
- return -1;
- }
- break;
- case 'i':
- case 'I':
- if(*(cookie_pot+1)=='+'){
- procadd = 3;
- }else if(*(cookie_pot+1)=='-'){
- procadd = -3;
- }else{
- printk("Please press '+' or '-' follow 'i'!\n");
- return -1;
- }
-
- switch(wm8994_current_route){
- case HEADSET_INCALL:
- if(procadd == 3)
- headset_incall_vol += 3;
- else
- headset_incall_vol -= 3;
-
- if(headset_incall_vol > 6)
- headset_incall_vol = 6;
- else if(headset_incall_vol < -12)
- headset_incall_vol = -12;
-
- printk("headset_incall_vol = %ddB \n",headset_incall_vol);
- break;
-
- case EARPIECE_INCALL:
- if(procadd == 3)
- earpiece_incall_vol += 3;
- else
- earpiece_incall_vol -= 3;
-
- if(earpiece_incall_vol>6)
- earpiece_incall_vol = 6;
- else if(earpiece_incall_vol<-21)
- earpiece_incall_vol = -21;
-
- printk("earpiece_incall_vol = %ddB \n",earpiece_incall_vol);
- break;
-
- case SPEAKER_INCALL:
- if(procadd == 3)
- speaker_incall_vol += 3;
- else
- speaker_incall_vol -= 3;
-
- if(speaker_incall_vol > 12)
- speaker_incall_vol = 12;
- else if(speaker_incall_vol < -21)
- speaker_incall_vol = -21;
-
- printk("speaker_incall_vol = %ddB \n",speaker_incall_vol);
- break;
-
- case BLUETOOTH_SCO_INCALL:
- if(procadd == 3)
- BT_incall_vol += 3;
- else
- BT_incall_vol -= 3;
-
- if(BT_incall_vol > 30)
- BT_incall_vol = 30;
- else if(BT_incall_vol < -16)
- BT_incall_vol = -16;
-
- printk("BT_incall_vol = %ddB \n",BT_incall_vol);
- break;
-
- default:
- printk("Current channel does not match to incall mode!\n");
- return -1;
- }
- break;
- case 'm':
- case 'M':
- if(*(cookie_pot+1)=='+'){
- procadd = 3;
- }else if(*(cookie_pot+1)=='-'){
- procadd = -3;
- }else{
- printk("Please press '+' or '-' follow 'm'!\n");
- return -1;
- }
- switch(wm8994_current_route){
- case HEADSET_INCALL:
- if(procadd == 3)
- headset_incall_mic_vol += 3;
- else
- headset_incall_mic_vol -= 3;
-
- if(speaker_incall_mic_vol > 30)
- speaker_incall_mic_vol = 30;
- else if(speaker_incall_mic_vol < -22)
- speaker_incall_mic_vol = -22;
-
- printk("speaker_incall_mic_vol = %ddB \n",speaker_incall_mic_vol);
- break;
-
- case EARPIECE_INCALL:
- if(procadd == 3)
- speaker_incall_mic_vol += 3;
- else
- speaker_incall_mic_vol -= 3;
-
- if(speaker_incall_mic_vol > 30)
- speaker_incall_mic_vol = 30;
- else if(speaker_incall_mic_vol < -22)
- speaker_incall_mic_vol = -22;
-
- printk("speaker_incall_mic_vol = %ddB \n",speaker_incall_mic_vol);
- break;
-
- case SPEAKER_INCALL:
- if(procadd == 3)
- speaker_incall_mic_vol += 3;
- else
- speaker_incall_mic_vol -= 3;
-
- if(speaker_incall_mic_vol > 30)
- speaker_incall_mic_vol = 30;
- else if(speaker_incall_mic_vol < -22)
- speaker_incall_mic_vol = -22;
-
- printk("speaker_incall_mic_vol = %ddB \n",speaker_incall_mic_vol);
- break;
-
- case BLUETOOTH_SCO_INCALL:
- if(procadd == 3)
- BT_incall_mic_vol += 3;
- else
- BT_incall_mic_vol -= 3;
-
- if(BT_incall_mic_vol > 6)
- BT_incall_mic_vol = 6;
- else if(BT_incall_mic_vol < -57)
- BT_incall_mic_vol = -57;
-
- printk("BT_incall_mic_vol = %ddB \n",BT_incall_mic_vol);
- break;
-
- case MIC_CAPTURE:
- if(procadd == 3)
- recorder_vol += 3;
- else
- recorder_vol -= 3;
-
- if(recorder_vol > 60)
- recorder_vol = 60;
- else if(recorder_vol < -16)
- recorder_vol = -16;
-
- printk("recorder_vol = %ddB \n",recorder_vol);
- break;
-
- default:
- printk("Current channel does not match to mic mode!\n");
- return -1;
- }
- break;
- case 'l':
- case 'L':
- {
- printk("headset_normal_vol = %ddB \n",headset_normal_vol);
- printk("speaker_normal_vol = %ddB \n",speaker_normal_vol);
- printk("headset_incall_vol = %ddB \n",headset_incall_vol);
- printk("earpiece_incall_vol = %ddB \n",earpiece_incall_vol);
- printk("speaker_incall_vol = %ddB \n",speaker_incall_vol);
- printk("BT_incall_vol = %ddB \n",BT_incall_vol);
- printk("headset_incall_mic_vol = %ddB \n",headset_incall_mic_vol);
- printk("speaker_incall_mic_vol = %ddB \n",speaker_incall_mic_vol);
- printk("BT_incall_mic_vol = %ddB \n",BT_incall_mic_vol);
- printk("recorder_vol = %ddB \n",recorder_vol);
- printk("bank_vol[1] = %ddB \n",bank_vol[1]);
- printk("bank_vol[2] = %ddB \n",bank_vol[2]);
- printk("bank_vol[3] = %ddB \n",bank_vol[3]);
- printk("bank_vol[4] = %ddB \n",bank_vol[4]);
- printk("bank_vol[5] = %ddB \n",bank_vol[5]);
- }
- return 0;
- break;
- case 'c':
- case 'C':
- if(((*(cookie_pot+1) == 't') || (*(cookie_pot+1) == 'T')) &&
- ((*(cookie_pot+2) == 'a') || (*(cookie_pot+2) == 'A'))){
- if(earpiece_vol_table[5] == 0x013D){
- earpiece_vol_table[0] = 0x0127;//for cta
- earpiece_vol_table[1] = 0x012D;
- earpiece_vol_table[2] = 0x0130;
- earpiece_vol_table[3] = 0x0135;
- earpiece_vol_table[4] = 0x0137;
- earpiece_vol_table[5] = 0x0135;
- printk("CTA on,earpiece table value is:0x0127,0x012D,0x0130,0x0135,0x0137,0x0135\n");
- }
- return 0;
- break;
- }
- isWM8994SetChannel = true;
- if(*(cookie_pot+1) == '+'){
- wm8994_proc_mode = wm8994_current_mode+1;
-
- if(wm8994_proc_mode > wm8994_BT_baseband)
- wm8994_proc_mode = wm8994_AP_to_headset;
- }else if(*(cookie_pot+1) == '-'){
- wm8994_proc_mode = wm8994_current_mode-1;
-
- if(wm8994_proc_mode == null || wm8994_proc_mode > wm8994_BT_baseband)
- wm8994_proc_mode = wm8994_BT_baseband;
- }else{
- wm8994_proc_mode = wm8994_current_mode;
- wm8994_current_mode = null;
- }
-
- wm8994_fnc_ptr += wm8994_proc_mode;
- (*wm8994_fnc_ptr)();
- isWM8994SetChannel = false;
- return 0;
- break;
- case 'e':
- case 'E':
- if(*(cookie_pot+1)=='+'){
- procadd = 3;
- }else if(*(cookie_pot+1)=='-'){
- procadd = -3;
- }else if(*(cookie_pot+1)=='c'){
- wm8994_write(0x0480, 0x0000);
- return 0;
- }else if(*(cookie_pot+1)=='o'){
- wm8994_write(0x0480, 0x0001|((bank_vol[1]+12)<<11)|
- ((bank_vol[2]+12)<<6)|((bank_vol[3]+12)<<1));
- wm8994_write(0x0481, 0x0000|((bank_vol[4]+12)<<11)|
- ((bank_vol[5]+12)<<6));
- return 0;
- }else{
- printk("Please press '+' '-' 'o' 'c' follow 'e'!\n");
- return -1;
- }
-
- switch(*(cookie_pot+2)){
- case '1':
- if(procadd == 3)
- bank_vol[1] += 3;
- else
- bank_vol[1] -= 3;
-
- if(bank_vol[1] > 12)bank_vol[1] = 12;
- if(bank_vol[1] < -12)bank_vol[1] = -12;
-
- wm8994_read(0x0480, &eqvol);
- wm8994_write(0x0480, (eqvol&0x07FF)|((bank_vol[1]+12)<<11));
-
- printk("bank_vol[1] = %ddB \n",bank_vol[1]);
- break;
-
- case '2':
- if(procadd == 3)
- bank_vol[2] += 3;
- else
- bank_vol[2] -= 3;
-
- if(bank_vol[2] > 12)bank_vol[2] = 12;
- if(bank_vol[2] < -12)bank_vol[2] = -12;
-
- wm8994_read(0x0480, &eqvol);
- wm8994_write(0x0480, (eqvol&0xF83F)|((bank_vol[2]+12)<<6));
-
- printk("bank_vol[2] = %ddB \n",bank_vol[2]);
- break;
-
- case '3':
- if(procadd == 3)
- bank_vol[3] += 3;
- else
- bank_vol[3] -= 3;
-
- if(bank_vol[3] > 12)bank_vol[3] = 12;
- if(bank_vol[3] < -12)bank_vol[3] = -12;
-
- wm8994_read(0x0480, &eqvol);
- wm8994_write(0x0480, (eqvol&0xFFC1)|((bank_vol[3]+12)<<1));
-
- printk("bank_vol[3] = %ddB \n",bank_vol[3]);
- break;
-
- case '4':
- if(procadd == 3)
- bank_vol[4] += 3;
- else
- bank_vol[4] -= 3;
-
- if(bank_vol[4] > 12)bank_vol[4] = 12;
- if(bank_vol[4] < -12)bank_vol[4] = -12;
-
- wm8994_read(0x0481, &eqvol);
- wm8994_write(0x0481, (eqvol&0x07FF)|((bank_vol[4]+12)<<11));
-
- printk("bank_vol[4] = %ddB \n",bank_vol[4]);
- break;
-
- case '5':
- if(procadd == 3)
- bank_vol[5] += 3;
- else
- bank_vol[5] -= 3;
-
- if(bank_vol[5] > 12)bank_vol[5] = 12;
- if(bank_vol[5] < -12)bank_vol[5] = -12;
-
- wm8994_read(0x0481, &eqvol);
- wm8994_write(0x0481, (eqvol&0xF83F)|((bank_vol[5]+12)<<6));
-
- printk("bank_vol[5] = %ddB \n",bank_vol[5]);
- break;
-
- default:
- printk("Please press bank '1' to '5' follow 'e+' or 'e-'!\n");
- return -1;
- }
- return 0;
- break;
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
case 'd':
case 'D':
debug_write_read ++;
break;
}
- wm8994_set_channel_vol();
return len;
}
}
#endif
+
static int wm8994_probe(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);