#include <linux/mfd/wm8994/pdata.h>
#include <linux/mfd/wm8994/gpio.h>
+#include <linux/clk.h>
+
#define WM8994_PROC
#ifdef WM8994_PROC
#include <linux/proc_fs.h>
/* codec private data */
struct wm8994_priv {
+ struct mutex io_lock;
+
unsigned int sysclk;
struct snd_soc_codec codec;
struct snd_pcm_hw_constraint_list *sysclk_constraints;
struct wm8994_pdata *pdata;
struct delayed_work wm8994_delayed_work;
- int work_type;
+ int work_type;
+ char First_Poweron;
};
static int wm8994_read(unsigned short reg,unsigned short *value)
unsigned short regs=((reg>>8)&0x00FF)|((reg<<8)&0xFF00),values;
char i = 2;
-
+ mutex_lock(&wm8994->io_lock);
// if(wm8994->RW_status == ERROR)return -EIO;
while(i > 0)
if(debug_write_read != 0)
DBG("%s:0x%04x = 0x%04x",__FUNCTION__,reg,*value);
#endif
+ mutex_unlock(&wm8994->io_lock);
return 0;
}
}
wm8994->RW_status = ERROR;
printk("%s---line->%d:Codec read error! reg = 0x%x , value = 0x%x\n",__FUNCTION__,__LINE__,reg,*value);
+ mutex_unlock(&wm8994->io_lock);
return -EIO;
}
unsigned short regs=((reg>>8)&0x00FF)|((reg<<8)&0xFF00),values=((value>>8)&0x00FF)|((value<<8)&0xFF00);
char i = 2;
+
+ mutex_lock(&wm8994->io_lock);
// if(wm8994->RW_status == ERROR)return -EIO;
#ifdef WM8994_PROC
{
i--;
if (reg_send_data(wm8994_client,®s,&values,400000) > 0)
+ {
+ mutex_unlock(&wm8994->io_lock);
return 0;
+ }
}
wm8994->RW_status = ERROR;
printk("%s---line->%d:Codec write error! reg = 0x%x , value = 0x%x\n",__FUNCTION__,__LINE__,reg,value);
+ mutex_unlock(&wm8994->io_lock);
return -EIO;
}
}
}
+static int wm8994_sysclk_config(void)
+{
+ struct wm8994_priv *wm8994 = wm8994_codec->private_data;
+
+ if(wm8994->sysclk == 12288000)
+ return wm8994_SYSCLK_12288M;
+ else if(wm8994->sysclk == 3072000)
+ return wm8994_SYSCLK_3072M;
+
+ return -1;
+}
static void wm8994_set_AIF1DAC_EQ(void)
{
int bank_vol[6] = {0,0,-3,3,-6,3};
void wm8994_codec_set_volume(unsigned char system_type,unsigned char volume)
{
- DBG("%s:: system_type = %d volume = %d \n",__FUNCTION__,system_type,volume);
+// DBG("%s:: system_type = %d volume = %d \n",__FUNCTION__,system_type,volume);
if(system_type == VOICE_CALL)
{
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
- wm8994_write(0x200, 0x0001); // sysclk = MCLK1
+ if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
+ {
+ wm8994_write(0x220, 0x0000);
+ wm8994_write(0x221, 0x0700);
+ wm8994_write(0x222, 0);
+ wm8994_write(0x223, 0x0400);
+ wm8994_write(0x220, 0x0004);
+ wm8994_write(0x220, 0x0005);
+ wm8994_write(0x200, 0x0011); // sysclk = MCLK1
+ }
+ else
+ wm8994_write(0x200, 0x0001); // sysclk = MCLK1
// wm8994_write(0x200, 0x0009); // sysclk = MCLK2
//path
wm8994_write(0x2D, 0x0100);
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
- wm8994_write(0x200, 0x0001); // sysclk = fll (bit4 =1) 0x0011
+ if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
+ {
+ wm8994_write(0x220, 0x0000);
+ wm8994_write(0x221, 0x0700);
+ wm8994_write(0x222, 0);
+ wm8994_write(0x223, 0x0400);
+ wm8994_write(0x220, 0x0004);
+ wm8994_write(0x220, 0x0005);
+ wm8994_write(0x200, 0x0011); // sysclk = MCLK1
+ }
+ else
+ 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
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
- wm8994_write(0x200, 0x0001); // sysclk = MCLK1
+
+ if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
+ {
+ wm8994_write(0x220, 0x0000);
+ wm8994_write(0x221, 0x0700);
+ wm8994_write(0x222, 0);
+ wm8994_write(0x223, 0x0400);
+ wm8994_write(0x220, 0x0004);
+ wm8994_write(0x220, 0x0005);
+ wm8994_write(0x200, 0x0011); // sysclk = MCLK1
+ }
+ else
+ wm8994_write(0x200, 0x0001); // sysclk = MCLK1
+
// wm8994_write(0x200, 0x0009); // sysclk = MCLK2
wm8994_set_channel_vol();
//recorder
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
- wm8994_write(0x200, 0x0001); // sysclk = MCLK1
+ if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
+ {
+ wm8994_write(0x220, 0x0000);
+ wm8994_write(0x221, 0x0700);
+ wm8994_write(0x222, 0);
+ wm8994_write(0x223, 0x0400);
+ wm8994_write(0x220, 0x0004);
+ wm8994_write(0x220, 0x0005);
+ wm8994_write(0x200, 0x0011); // sysclk = MCLK1
+ }
+ else
+ wm8994_write(0x200, 0x0001); // sysclk = MCLK1
//path
wm8994_write(0x22, 0x0000);
wm8994_write(0x23, 0x0100);
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
- wm8994_write(0x200, 0x0001); // sysclk = fll (bit4 =1) 0x0011
+ if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
+ {
+ wm8994_write(0x220, 0x0000);
+ wm8994_write(0x221, 0x0700);
+ wm8994_write(0x222, 0);
+ wm8994_write(0x223, 0x0400);
+ wm8994_write(0x220, 0x0004);
+ wm8994_write(0x220, 0x0005);
+ wm8994_write(0x200, 0x0011); // sysclk = MCLK1
+ }
+ else
+ wm8994_write(0x200, 0x0001); // sysclk = MCLK1
//path
wm8994_write(0x28, 0x0003); //IN1RP_TO_IN1R IN1RN_TO_IN1R
wm8994_write(0x34, 0x0004); //IN1R_TO_LINEOUT1P
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
- wm8994_write(0x200, 0x0001); // sysclk = fll (bit4 =1) 0x0011
+ if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
+ {
+ wm8994_write(0x220, 0x0000);
+ wm8994_write(0x221, 0x0700);
+ wm8994_write(0x222, 0);
+ wm8994_write(0x223, 0x0400);
+ wm8994_write(0x220, 0x0004);
+ wm8994_write(0x220, 0x0005);
+ wm8994_write(0x200, 0x0011); // sysclk = MCLK1
+ }
+ else
+ wm8994_write(0x200, 0x0001); // sysclk = MCLK1
//path
wm8994_write(0x22, 0x0000);
wm8994_write(0x23, 0x0100);
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
- wm8994_write(0x200, 0x0001);
+ if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
+ {
+ wm8994_write(0x220, 0x0000);
+ wm8994_write(0x221, 0x0700);
+ wm8994_write(0x222, 0);
+ wm8994_write(0x223, 0x0400);
+ wm8994_write(0x220, 0x0004);
+ wm8994_write(0x220, 0x0005);
+ wm8994_write(0x200, 0x0011); // sysclk = MCLK1
+ }
+ else
+ wm8994_write(0x200, 0x0001); // sysclk = MCLK1
//AIF2CLK use FLL2
wm8994_write(0x204, 0x0000);
msleep(WM8994_DELAY);
wm8994_write(0x240, 0x0000);
wm8994_write(0x241, 0x2F00);//48
wm8994_write(0x242, 0);
- wm8994_write(0x243, 0x0100);
+ if(wm8994_sysclk_config() == wm8994_SYSCLK_3072M)
+ wm8994_write(0x243, 0x0100);
+ else
+ wm8994_write(0x243, 0x0100);
wm8994_write(0x240, 0x0004);
msleep(10);
wm8994_write(0x240, 0x0005);
char route = kcontrol->private_value & 0xff;
wm8994->kcontrol = kcontrol;//save rount
+
+ if(wm8994->First_Poweron == 1)
+ {
+ PA_ctrl(GPIO_LOW);
+ wm8994_write(0,0);
+ return 0;
+ }
//disable PA
switch(route)
{
PA_ctrl(GPIO_HIGH);
break;
}
-
+
return 0;
}
struct snd_soc_codec *codec = codec_dai->codec;
struct wm8994_priv *wm8994 = codec->private_data;
- DBG("%s----%d\n",__FUNCTION__,__LINE__);
+// DBG("%s----%d\n",__FUNCTION__,__LINE__);
switch (freq) {
case 11289600:
wm8994->sysclk_constraints = &constraints_12;
wm8994->sysclk = freq;
return 0;
+ default:
+ wm8994->sysclk = freq;
+ return 0;
}
return -EINVAL;
}
/* The set of sample rates that can be supported depends on the
* MCLK supplied to the CODEC - enforce this.
*/
-
+ DBG("%s----%d\n",__FUNCTION__,__LINE__);
+/*
if (!wm8994->sysclk) {
dev_err(codec->dev,
"No MCLK configured, call set_sysclk() on init\n");
snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
wm8994->sysclk_constraints);
-
+*/
return 0;
}
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
+/* struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec;
struct wm8994_priv *wm8994 = codec->private_data;
return coeff;
}
params_format(params);
-
+*/
return 0;
}
struct snd_soc_dai *codec_dai = machine->codec_dai;
struct snd_soc_codec *codec = dai->codec;
struct wm8994_priv *wm8994 = codec->private_data;
-
- unsigned int playback_active = codec_dai->playback.active, capture_active = codec_dai->capture.active;
+
+ unsigned int old_playback_active = codec_dai->playback.active, old_capture_active = codec_dai->capture.active;
int i, ret;
else
codec_dai->capture.active = status;
}
-
+ else
+ return 0;
if (!codec_dai->playback.active &&
!codec_dai->capture.active &&
- (playback_active || capture_active))
+ (old_playback_active || old_capture_active))
{//suspend
DBG("It's going to power down wm8994\n");
wm8994->work_type = SNDRV_PCM_TRIGGER_STOP;
u16 *reg_cache = codec->reg_cache;
int i, ret;
- DBG("Enter %s---%d\n",__FUNCTION__,__LINE__);
+// DBG("Enter %s---%d\n",__FUNCTION__,__LINE__);
if(wm8994->work_type == SNDRV_PCM_TRIGGER_STOP)
{
- DBG("wm8994 shutdown\n");
+ // DBG("wm8994 shutdown\n");
PA_ctrl(GPIO_LOW);
wm8994_write(0,0);
- // wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ wm8994_current_mode = null;//Automatically re-set the wake-up time
}
else if(wm8994->work_type == SNDRV_PCM_TRIGGER_START)
{
- DBG("wm8994 shutup\n");
- PA_ctrl(GPIO_LOW);
- wm8994_current_mode = null;
- snd_soc_put_route(wm8994->kcontrol,NULL);
+ if(wm8994->First_Poweron == 1)
+ {
+ DBG("wm8994 First_Poweron shutup\n");
+ wm8994->First_Poweron = 0;
+ wm8994_current_mode = null;
+ snd_soc_put_route(wm8994->kcontrol,NULL);
+ }
}
}
dev_err(codec->dev, "failed to register card: %d\n", ret);
goto card_err;
}
+
+ INIT_DELAYED_WORK(&wm8994->wm8994_delayed_work, wm8994_work_fun);
+ mutex_init(&wm8994->io_lock);
+
//enable power_EN
gpio_request(WM_EN_PIN, NULL);
gpio_direction_output(WM_EN_PIN,GPIO_HIGH);
gpio_free(WM_EN_PIN);
- INIT_DELAYED_WORK(&wm8994->wm8994_delayed_work, wm8994_work_fun);
+ gpio_request(WM_PA_PIN, NULL); //AUDIO_PA_ON
+ gpio_direction_output(WM_PA_PIN,GPIO_LOW);
+ gpio_free(WM_PA_PIN);
+
+ wm8994->First_Poweron = 1;
+// wm8994_write(0,0);
+
return ret;
card_err: