summaryrefslogtreecommitdiff
path: root/sound/soc/codecs/tlv320aic326x.c
diff options
context:
space:
mode:
authorManoj Gangwal <mgangwal@nvidia.com>2012-11-22 11:42:15 +0530
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 12:43:43 -0700
commitb9032c84376ba817177f4c86d0dcd1302441a55b (patch)
treea00a21571074752c216a49ab5809502175bad617 /sound/soc/codecs/tlv320aic326x.c
parentc8b94411619331629eaa36b998f63e02192e282c (diff)
asoc: aic326x codec: Add TI codec support
Added support for TI aic326x codec for K3.4 Bug 1179798 Change-Id: Ib9efcf67c7b99cc9c7cfc1d6150aa587b88bd3cd Signed-off-by: Manoj Gangwal <mgangwal@nvidia.com> Reviewed-on: http://git-master/r/165611 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Vijay Mali <vmali@nvidia.com> Reviewed-by: Scott Peterson <speterson@nvidia.com>
Diffstat (limited to 'sound/soc/codecs/tlv320aic326x.c')
-rw-r--r--sound/soc/codecs/tlv320aic326x.c1494
1 files changed, 869 insertions, 625 deletions
diff --git a/sound/soc/codecs/tlv320aic326x.c b/sound/soc/codecs/tlv320aic326x.c
index 5b0be9bb642e..a8cde73363bf 100644
--- a/sound/soc/codecs/tlv320aic326x.c
+++ b/sound/soc/codecs/tlv320aic326x.c
@@ -37,9 +37,9 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
#include <linux/spi/spi.h>
#include <linux/platform_device.h>
-#include <linux/switch.h>
#include <sound/jack.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
@@ -56,30 +56,29 @@
#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include <linux/mfd/tlv320aic3262-registers.h>
-#include <linux/mfd/tlv320aic3262-core.h>
-#include "aic3xxx_cfw.h"
-#include "aic3xxx_cfw_ops.h"
+#include <linux/mfd/tlv320aic3xxx-core.h>
+#include "aic3xxx/aic3xxx_cfw.h"
+#include "aic3xxx/aic3xxx_cfw_ops.h"
#include "tlv320aic326x.h"
-#include "aic3262_codec_ops.h"
-#include "tlv320aic3262_default_fw.h"
-#define SOC_DOUBLE_R_SX_TLV3262(xname, xreg_left, xreg_right, xshift,\
- xmin, xmax, tlv_array) \
+
+#define SOC_DOUBLE_R_SX_TLV3262(xname, xreg_left, xreg_right, xshift, \
+ xmin, xmax, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
- SNDRV_CTL_ELEM_ACCESS_READWRITE, \
+ SNDRV_CTL_ELEM_ACCESS_READWRITE, \
.tlv.p = (tlv_array), \
.info = snd_soc_info_volsw_2r_sx, \
.get = snd_soc_get_volsw_2r_sx, \
.put = snd_soc_put_volsw_2r_sx_aic3262, \
- .private_value = (unsigned long) &(struct soc_mixer_control) \
- {.reg = xreg_left, \
- .rreg = xreg_right, .shift = xshift, \
- .min = xmin, .max = xmax} }
+ .private_value = (unsigned long)&(struct soc_mixer_control) \
+ {.reg = xreg_left, \
+ .rreg = xreg_right, .shift = xshift, \
+ .min = xmin, .max = xmax} }
-/*****************************************************************************
+/******************************************************************************
Macros
******************************************************************************
@@ -93,9 +92,6 @@ static int aic3262_hw_params(struct snd_pcm_substream *substream,
static int aic3262_mute(struct snd_soc_dai *dai, int mute);
-static int aic3262_set_dai_sysclk(struct snd_soc_dai *codec_dai,
- int clk_id, unsigned int freq, int dir);
-
static int aic3262_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt);
static int aic3262_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
@@ -111,33 +107,37 @@ static int aic3262_set_mode_put(struct snd_kcontrol *kcontrol,
static int aic326x_adc_dsp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
+static int aic3262_get_runstate(struct snd_soc_codec *codec);
+static int aic3262_dsp_pwrdwn_status(struct snd_soc_codec *codec);
+static int aic3262_dsp_pwrup(struct snd_soc_codec *codec, int state);
+static int aic3262_restart_dsps_sync(struct snd_soc_codec *codec, int rs);
-static long debug_level;
-module_param(debug_level, long, 0);
-MODULE_PARM_DESC(debug_level, "Debug level for printing");
+static inline unsigned int dsp_non_sync_mode(unsigned int state)
+ { return (!((state & 0x03) && (state & 0x30))); }
/**
* snd_soc_put_volsw_2r_sx - double with tlv and variable data size
- * mixer put callback
+ * mixer put callback
* @kcontrol: mixer control
* @uinfo: control element information
*
* Returns 0 for success.
*/
int snd_soc_put_volsw_2r_sx_aic3262(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+ struct snd_ctl_elem_value *ucontrol)
{
struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
+ (struct soc_mixer_control *)kcontrol->private_value;
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- unsigned int mask = (1 << mc->shift) - 1;
+ unsigned int mask = (1<<mc->shift)-1;
int min = mc->min;
int ret;
unsigned int val, valr;
- val = ((ucontrol->value.integer.value[0] + min) & 0xff);
+
+ val = ((ucontrol->value.integer.value[0]+min) & 0xff);
val &= mask;
- valr = ((ucontrol->value.integer.value[1] + min) & 0xff);
+ valr = ((ucontrol->value.integer.value[1]+min) & 0xff);
valr &= mask;
ret = 0;
@@ -150,27 +150,6 @@ int snd_soc_put_volsw_2r_sx_aic3262(struct snd_kcontrol *kcontrol,
return 0;
}
-static ssize_t debug_level_show(struct device *dev,
- struct device_attribute *attr,
- char *buf, size_t count)
-{
- return sprintf(buf, "%ld\n", debug_level);
-}
-
-static ssize_t debug_level_set(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- int ret;
-
- ret = kstrtol(buf, 10, &debug_level);
- if (ret)
- return ret;
- return count;
-}
-
-static DEVICE_ATTR(debug_level, 0644, debug_level_show, debug_level_set);
-
static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6350, 50, 0);
static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1200, 50, 0);
static const DECLARE_TLV_DB_SCALE(spk_gain_tlv, 600, 600, 0);
@@ -284,7 +263,6 @@ static const struct snd_kcontrol_new aic3262_snd_controls[] = {
struct snd_soc_dai_ops aic3262_asi1_dai_ops = {
.hw_params = aic3262_hw_params,
.digital_mute = aic3262_mute,
- .set_sysclk = aic3262_set_dai_sysclk,
.set_fmt = aic3262_set_dai_fmt,
.set_pll = aic3262_dai_set_pll,
};
@@ -292,7 +270,6 @@ struct snd_soc_dai_ops aic3262_asi1_dai_ops = {
struct snd_soc_dai_ops aic3262_asi2_dai_ops = {
.hw_params = aic3262_hw_params,
.digital_mute = aic3262_mute,
- .set_sysclk = aic3262_set_dai_sysclk,
.set_fmt = aic3262_set_dai_fmt,
.set_pll = aic3262_dai_set_pll,
};
@@ -300,7 +277,6 @@ struct snd_soc_dai_ops aic3262_asi2_dai_ops = {
struct snd_soc_dai_ops aic3262_asi3_dai_ops = {
.hw_params = aic3262_hw_params,
.digital_mute = aic3262_mute,
- .set_sysclk = aic3262_set_dai_sysclk,
.set_fmt = aic3262_set_dai_fmt,
.set_pll = aic3262_dai_set_pll,
};
@@ -311,14 +287,14 @@ struct snd_soc_dai_driver aic326x_dai_driver[] = {
.playback = {
.stream_name = "ASI1 Playback",
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 8,
.rates = AIC3262_RATES,
.formats = AIC3262_FORMATS,
},
.capture = {
.stream_name = "ASI1 Capture",
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 8,
.rates = AIC3262_RATES,
.formats = AIC3262_FORMATS,
},
@@ -363,148 +339,150 @@ struct snd_soc_dai_driver aic326x_dai_driver[] = {
};
-
static const unsigned int adc_ma_tlv[] = {
- TLV_DB_RANGE_HEAD(4),
- 0, 29, TLV_DB_SCALE_ITEM(-1450, 500, 0),
- 30, 35, TLV_DB_SCALE_ITEM(-2060, 1000, 0),
- 36, 38, TLV_DB_SCALE_ITEM(-2660, 2000, 0),
- 39, 40, TLV_DB_SCALE_ITEM(-3610, 5000, 0),
+ TLV_DB_RANGE_HEAD(7),
+ 1, 1, TLV_DB_SCALE_ITEM(-3610, 0, 0),
+ 2, 2, TLV_DB_SCALE_ITEM(-3010, 0, 0),
+ 3, 3, TLV_DB_SCALE_ITEM(-2660, 0, 0),
+ 4, 4, TLV_DB_SCALE_ITEM(-2410, 0, 0),
+ 5, 7, TLV_DB_SCALE_ITEM(-2210, 1500, 0),
+ 8, 11, TLV_DB_SCALE_ITEM(-1810, 1000, 0),
+ 12, 41 , TLV_DB_SCALE_ITEM(-1450, 500, 0)
};
static const DECLARE_TLV_DB_SCALE(lo_hp_tlv, -7830, 50, 0);
static const struct snd_kcontrol_new mal_pga_mixer_controls[] = {
- SOC_DAPM_SINGLE("IN1L Switch", AIC3262_MA_CNTL, 5, 1, 0),
+ SOC_DAPM_SINGLE("IN1 Left Capture Switch", AIC3262_MA_CNTL, 5, 1, 0),
SOC_DAPM_SINGLE_TLV("Left MicPGA Volume", AIC3262_LADC_PGA_MAL_VOL,
0, 0x3f, 1, adc_ma_tlv),
};
static const struct snd_kcontrol_new mar_pga_mixer_controls[] = {
- SOC_DAPM_SINGLE("IN1R Switch", AIC3262_MA_CNTL, 4, 1, 0),
+ SOC_DAPM_SINGLE("IN1 Right Capture Switch", AIC3262_MA_CNTL, 4, 1, 0),
SOC_DAPM_SINGLE_TLV("Right MicPGA Volume", AIC3262_RADC_PGA_MAR_VOL,
0, 0x3f, 1, adc_ma_tlv),
};
/* Left HPL Mixer */
static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
- SOC_DAPM_SINGLE("MAL Switch", AIC3262_HP_AMP_CNTL_R1, 7, 1,
+ SOC_DAPM_SINGLE("MA Left Playback Switch", AIC3262_HP_AMP_CNTL_R1, 7, 1,
0),
- SOC_DAPM_SINGLE("LDAC Switch", AIC3262_HP_AMP_CNTL_R1,
+ SOC_DAPM_SINGLE("Left DAC Playback Switch", AIC3262_HP_AMP_CNTL_R1,
5, 1, 0),
- SOC_DAPM_SINGLE_TLV("LOL-B1 Volume",
+ SOC_DAPM_SINGLE_TLV("LO Left-B1 Playback Volume",
AIC3262_HP_AMP_CNTL_R2, 0, 0x7f, 1, lo_hp_tlv),
};
/* Right HPR Mixer */
static const struct snd_kcontrol_new hpr_output_mixer_controls[] = {
- SOC_DAPM_SINGLE_TLV("LOR-B1 Volume",
+ SOC_DAPM_SINGLE_TLV("LO Right-B1 Playback Volume",
AIC3262_HP_AMP_CNTL_R3, 0, 0x7f, 1, lo_hp_tlv),
- SOC_DAPM_SINGLE("LDAC Switch", AIC3262_HP_AMP_CNTL_R1,
+ SOC_DAPM_SINGLE("Left DAC Playback Switch", AIC3262_HP_AMP_CNTL_R1,
2, 1, 0),
- SOC_DAPM_SINGLE("RDAC Switch", AIC3262_HP_AMP_CNTL_R1,
+ SOC_DAPM_SINGLE("Right DAC Playback Switch", AIC3262_HP_AMP_CNTL_R1,
4, 1, 0),
- SOC_DAPM_SINGLE("MAR Switch", AIC3262_HP_AMP_CNTL_R1,
+ SOC_DAPM_SINGLE("MA Right Playback Switch", AIC3262_HP_AMP_CNTL_R1,
6, 1, 0),
};
/* Left LOL Mixer */
static const struct snd_kcontrol_new lol_output_mixer_controls[] = {
- SOC_DAPM_SINGLE("MAL Switch", AIC3262_LINE_AMP_CNTL_R2,
+ SOC_DAPM_SINGLE("MA Left Playback Switch", AIC3262_LINE_AMP_CNTL_R2,
7, 1, 0),
- SOC_DAPM_SINGLE("IN1L-B Switch", AIC3262_LINE_AMP_CNTL_R2,
+ SOC_DAPM_SINGLE("IN1 Left-B Capture Switch", AIC3262_LINE_AMP_CNTL_R2,
3, 1, 0),
- SOC_DAPM_SINGLE("LDAC Switch", AIC3262_LINE_AMP_CNTL_R1,
+ SOC_DAPM_SINGLE("Left DAC Playback Switch", AIC3262_LINE_AMP_CNTL_R1,
7, 1, 0),
- SOC_DAPM_SINGLE("RDAC Switch", AIC3262_LINE_AMP_CNTL_R1,
+ SOC_DAPM_SINGLE("Right DAC Playback Switch", AIC3262_LINE_AMP_CNTL_R1,
5, 1, 0),
};
/* Right LOR Mixer */
static const struct snd_kcontrol_new lor_output_mixer_controls[] = {
- SOC_DAPM_SINGLE("LOL Switch", AIC3262_LINE_AMP_CNTL_R1,
+ SOC_DAPM_SINGLE("LO Left Playback Switch", AIC3262_LINE_AMP_CNTL_R1,
2, 1, 0),
- SOC_DAPM_SINGLE("RDAC Switch", AIC3262_LINE_AMP_CNTL_R1,
+ SOC_DAPM_SINGLE("Right DAC Playback Switch", AIC3262_LINE_AMP_CNTL_R1,
6, 1, 0),
- SOC_DAPM_SINGLE("MAR Switch", AIC3262_LINE_AMP_CNTL_R2,
+ SOC_DAPM_SINGLE("MA Right Playback Switch", AIC3262_LINE_AMP_CNTL_R2,
6, 1, 0),
- SOC_DAPM_SINGLE("IN1R-B Switch", AIC3262_LINE_AMP_CNTL_R2,
+ SOC_DAPM_SINGLE("IN1 Right-B Capture Switch", AIC3262_LINE_AMP_CNTL_R2,
0, 1, 0),
};
/* Left SPKL Mixer */
static const struct snd_kcontrol_new spkl_output_mixer_controls[] = {
- SOC_DAPM_SINGLE("MAL Switch", AIC3262_SPK_AMP_CNTL_R1,
+ SOC_DAPM_SINGLE("MA Left Playback Switch", AIC3262_SPK_AMP_CNTL_R1,
7, 1, 0),
- SOC_DAPM_SINGLE_TLV("LOL Volume",
+ SOC_DAPM_SINGLE_TLV("LO Left Playback Volume",
AIC3262_SPK_AMP_CNTL_R2, 0, 0x7f, 1, lo_hp_tlv),
SOC_DAPM_SINGLE("SPR_IN Switch", AIC3262_SPK_AMP_CNTL_R1, 2, 1, 0),
};
/* Right SPKR Mixer */
static const struct snd_kcontrol_new spkr_output_mixer_controls[] = {
- SOC_DAPM_SINGLE_TLV("LOR Volume",
+ SOC_DAPM_SINGLE_TLV("LO Right Playback Volume",
AIC3262_SPK_AMP_CNTL_R3, 0, 0x7f, 1, lo_hp_tlv),
- SOC_DAPM_SINGLE("MAR Switch",
+ SOC_DAPM_SINGLE("MA Right Playback Switch",
AIC3262_SPK_AMP_CNTL_R1, 6, 1, 0),
};
/* REC Mixer */
static const struct snd_kcontrol_new rec_output_mixer_controls[] = {
- SOC_DAPM_SINGLE_TLV("LOL-B2 Volume",
+ SOC_DAPM_SINGLE_TLV("LO Left-B2 Playback Volume",
AIC3262_RAMP_CNTL_R1, 0, 0x7f, 1, lo_hp_tlv),
- SOC_DAPM_SINGLE_TLV("IN1L Volume",
+ SOC_DAPM_SINGLE_TLV("IN1 Left Capture Volume",
AIC3262_IN1L_SEL_RM, 0, 0x7f, 1, lo_hp_tlv),
- SOC_DAPM_SINGLE_TLV("IN1R Volume",
+ SOC_DAPM_SINGLE_TLV("IN1 Right Capture Volume",
AIC3262_IN1R_SEL_RM, 0, 0x7f, 1, lo_hp_tlv),
- SOC_DAPM_SINGLE_TLV("LOR-B2 Volume",
+ SOC_DAPM_SINGLE_TLV("LO Right-B2 Playback Volume",
AIC3262_RAMP_CNTL_R2, 0, 0x7f, 1, lo_hp_tlv),
};
/* Left Input Mixer */
static const struct snd_kcontrol_new left_input_mixer_controls[] = {
- SOC_DAPM_SINGLE("IN1L Switch", AIC3262_LMIC_PGA_PIN,
+ SOC_DAPM_SINGLE("IN1 Left Capture Switch", AIC3262_LMIC_PGA_PIN,
6, 3, 0),
- SOC_DAPM_SINGLE("IN2L Switch", AIC3262_LMIC_PGA_PIN,
+ SOC_DAPM_SINGLE("IN2 Left Capture Switch", AIC3262_LMIC_PGA_PIN,
4, 3, 0),
- SOC_DAPM_SINGLE("IN3L Switch", AIC3262_LMIC_PGA_PIN,
+ SOC_DAPM_SINGLE("IN3 Left Capture Switch", AIC3262_LMIC_PGA_PIN,
2, 3, 0),
- SOC_DAPM_SINGLE("IN4L Switch", AIC3262_LMIC_PGA_PM_IN4,
+ SOC_DAPM_SINGLE("IN4 Left Capture Switch", AIC3262_LMIC_PGA_PM_IN4,
5, 1, 0),
- SOC_DAPM_SINGLE("IN1R Switch", AIC3262_LMIC_PGA_PIN,
+ SOC_DAPM_SINGLE("IN1 Right Capture Switch", AIC3262_LMIC_PGA_PIN,
0, 3, 0),
- SOC_DAPM_SINGLE("IN2R Switch", AIC3262_LMIC_PGA_MIN,
+ SOC_DAPM_SINGLE("IN2 Right Capture Switch", AIC3262_LMIC_PGA_MIN,
4, 3, 0),
- SOC_DAPM_SINGLE("IN3R Switch", AIC3262_LMIC_PGA_MIN,
+ SOC_DAPM_SINGLE("IN3 Right Capture Switch", AIC3262_LMIC_PGA_MIN,
2, 3, 0),
- SOC_DAPM_SINGLE("IN4R Switch", AIC3262_LMIC_PGA_PM_IN4,
+ SOC_DAPM_SINGLE("IN4 Right Capture Switch", AIC3262_LMIC_PGA_PM_IN4,
4, 1, 0),
- SOC_DAPM_SINGLE("CM2L Switch", AIC3262_LMIC_PGA_MIN,
+ SOC_DAPM_SINGLE("CM2 Left Capture Switch", AIC3262_LMIC_PGA_MIN,
0, 3, 0),
- SOC_DAPM_SINGLE("CM1L Switch", AIC3262_LMIC_PGA_MIN,
+ SOC_DAPM_SINGLE("CM1 Left Capture Switch", AIC3262_LMIC_PGA_MIN,
6, 3, 0),
};
/* Right Input Mixer */
static const struct snd_kcontrol_new right_input_mixer_controls[] = {
- SOC_DAPM_SINGLE("IN1R Switch", AIC3262_RMIC_PGA_PIN,
+ SOC_DAPM_SINGLE("IN1 Right Capture Switch", AIC3262_RMIC_PGA_PIN,
6, 3, 0),
- SOC_DAPM_SINGLE("IN2R Switch", AIC3262_RMIC_PGA_PIN,
+ SOC_DAPM_SINGLE("IN2 Right Capture Switch", AIC3262_RMIC_PGA_PIN,
4, 3, 0),
- SOC_DAPM_SINGLE("IN3R Switch", AIC3262_RMIC_PGA_PIN,
+ SOC_DAPM_SINGLE("IN3 Right Capture Switch", AIC3262_RMIC_PGA_PIN,
2, 3, 0),
- SOC_DAPM_SINGLE("IN4R Switch", AIC3262_RMIC_PGA_PM_IN4,
+ SOC_DAPM_SINGLE("IN4 Right Capture Switch", AIC3262_RMIC_PGA_PM_IN4,
5, 1, 0),
- SOC_DAPM_SINGLE("IN2L Switch", AIC3262_RMIC_PGA_PIN,
+ SOC_DAPM_SINGLE("IN2 Left Capture Switch", AIC3262_RMIC_PGA_PIN,
0, 3, 0),
- SOC_DAPM_SINGLE("IN1L Switch", AIC3262_RMIC_PGA_MIN,
+ SOC_DAPM_SINGLE("IN1 Left Capture Switch", AIC3262_RMIC_PGA_MIN,
4, 3, 0),
- SOC_DAPM_SINGLE("IN3L Switch", AIC3262_RMIC_PGA_MIN,
+ SOC_DAPM_SINGLE("IN3 Left Capture Switch", AIC3262_RMIC_PGA_MIN,
2, 3, 0),
- SOC_DAPM_SINGLE("IN4L Switch", AIC3262_RMIC_PGA_PM_IN4,
+ SOC_DAPM_SINGLE("IN4 Left Capture Switch", AIC3262_RMIC_PGA_PM_IN4,
4, 1, 0),
- SOC_DAPM_SINGLE("CM1R Switch", AIC3262_RMIC_PGA_MIN,
+ SOC_DAPM_SINGLE("CM1 Right Capture Switch", AIC3262_RMIC_PGA_MIN,
6, 3, 0),
- SOC_DAPM_SINGLE("CM2R Switch", AIC3262_RMIC_PGA_MIN,
+ SOC_DAPM_SINGLE("CM2 Right Capture Switch", AIC3262_RMIC_PGA_MIN,
0, 3, 0),
};
@@ -720,31 +698,69 @@ static int aic326x_hp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
int reg_mask = 0;
+ int mute_reg = 0;
int ret_wbits = 0;
+ u8 hpl_hpr;
- if (w->shift == 1)
- reg_mask = AIC3262_HPL_POWER_MASK;
- if (w->shift == 0)
- reg_mask = AIC3262_HPR_POWER_MASK;
+ if (w->shift == 1) {
+ reg_mask = AIC3262_HPL_POWER_STATUS_MASK;
+ mute_reg = AIC3262_HPL_VOL;
+ }
+ if (w->shift == 0) {
+ reg_mask = AIC3262_HPR_POWER_STATUS_MASK;
+ mute_reg = AIC3262_HPR_VOL;
+ }
switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(w->codec, AIC3262_CHARGE_PUMP_CNTL,
+ AIC3262_DYNAMIC_OFFSET_CALIB_MASK,
+ AIC3262_DYNAMIC_OFFSET_CALIB);
+ snd_soc_write(w->codec, mute_reg, 0x80);
+ snd_soc_update_bits(w->codec, AIC3262_HP_CTL,
+ AIC3262_HP_STAGE_MASK ,
+ AIC3262_HP_STAGE_25 << AIC3262_HP_STAGE_SHIFT);
+ break;
+
case SND_SOC_DAPM_POST_PMU:
- ret_wbits = aic3262_wait_bits(w->codec->control_data,
+ ret_wbits = aic3xxx_wait_bits(w->codec->control_data,
AIC3262_HP_FLAG, reg_mask,
- reg_mask, TIME_DELAY,
- DELAY_COUNTER);
+ reg_mask, AIC326X_TIME_DELAY,
+ AIC326X_DELAY_COUNTER);
if (!ret_wbits) {
dev_err(w->codec->dev, "HP POST_PMU timedout\n");
return -1;
}
+ snd_soc_update_bits(w->codec, AIC3262_HP_CTL,
+ AIC3262_HP_STAGE_MASK ,
+ AIC3262_HP_STAGE_100 << AIC3262_HP_STAGE_SHIFT);
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(w->codec, AIC3262_HP_CTL,
+ AIC3262_HP_STAGE_MASK ,
+ AIC3262_HP_STAGE_25 << AIC3262_HP_STAGE_SHIFT);
+ hpl_hpr = snd_soc_read(w->codec, AIC3262_HP_AMP_CNTL_R1);
+ if ((hpl_hpr & 0x3) == 0x3) {
+ snd_soc_update_bits(w->codec, AIC3262_HP_AMP_CNTL_R1,
+ AIC3262_HPL_POWER_MASK, 0x0);
+ mdelay(1);
+ snd_soc_update_bits(w->codec, AIC3262_HP_AMP_CNTL_R1,
+ AIC3262_HPR_POWER_MASK, 0x0);
+ }
break;
+
case SND_SOC_DAPM_POST_PMD:
- ret_wbits = aic3262_wait_bits(w->codec->control_data,
+ ret_wbits = aic3xxx_wait_bits(w->codec->control_data,
AIC3262_HP_FLAG, reg_mask, 0,
- TIME_DELAY, DELAY_COUNTER);
+ AIC326X_TIME_DELAY,
+ AIC326X_DELAY_COUNTER);
if (!ret_wbits) {
dev_err(w->codec->dev, "HP POST_PMD timedout\n");
return -1;
}
+ snd_soc_write(w->codec, mute_reg, 0xb9);
+ snd_soc_write(w->codec, AIC3262_POWER_CONF,
+ snd_soc_read(w->codec, AIC3262_POWER_CONF));
break;
default:
BUG();
@@ -773,29 +789,31 @@ static int aic326x_dac_event(struct snd_soc_dapm_widget *w,
int other_dsp = 0, run_state = 0;
if (w->shift == 7) {
- reg_mask = AIC3262_LDAC_POWER_MASK;
- run_state_mask = AIC3262_COPS_MDSP_D_L;
+ reg_mask = AIC3262_LDAC_POWER_STATUS_MASK;
+ run_state_mask = AIC3XXX_COPS_MDSP_D_L;
}
if (w->shift == 6) {
- reg_mask = AIC3262_RDAC_POWER_MASK;
- run_state_mask = AIC3262_COPS_MDSP_D_R;
+ reg_mask = AIC3262_RDAC_POWER_STATUS_MASK;
+ run_state_mask = AIC3XXX_COPS_MDSP_D_R;
}
switch (event) {
case SND_SOC_DAPM_POST_PMU:
- ret_wbits = aic3262_wait_bits(w->codec->control_data,
+ ret_wbits = aic3xxx_wait_bits(w->codec->control_data,
AIC3262_DAC_FLAG, reg_mask,
- reg_mask, TIME_DELAY,
- DELAY_COUNTER);
+ reg_mask, AIC326X_TIME_DELAY,
+ AIC326X_DELAY_COUNTER);
- sync_needed = SYNC_STATE(aic3262);
- non_sync_state = DSP_NON_SYNC_MODE(aic3262->dsp_runstate);
- other_dsp = aic3262->dsp_runstate & AIC3262_COPS_MDSP_A;
+ sync_needed = aic3xxx_reg_read(w->codec->control_data,
+ AIC3262_DAC_PRB);
+ non_sync_state = dsp_non_sync_mode(aic3262->dsp_runstate);
+ other_dsp = aic3262->dsp_runstate & AIC3XXX_COPS_MDSP_A;
if (sync_needed && non_sync_state && other_dsp) {
- run_state = get_runstate(aic3262->codec->control_data);
- aic3262_dsp_pwrdwn_status(aic3262);
- aic3262_dsp_pwrup(aic3262, run_state);
+ run_state = aic3262_get_runstate(
+ aic3262->codec);
+ aic3262_dsp_pwrdwn_status(aic3262->codec);
+ aic3262_dsp_pwrup(aic3262->codec, run_state);
}
aic3262->dsp_runstate |= run_state_mask;
@@ -806,9 +824,10 @@ static int aic326x_dac_event(struct snd_soc_dapm_widget *w,
break;
case SND_SOC_DAPM_POST_PMD:
- ret_wbits = aic3262_wait_bits(w->codec->control_data,
+ ret_wbits = aic3xxx_wait_bits(w->codec->control_data,
AIC3262_DAC_FLAG, reg_mask, 0,
- TIME_DELAY, DELAY_COUNTER);
+ AIC326X_TIME_DELAY,
+ AIC326X_DELAY_COUNTER);
aic3262->dsp_runstate = (aic3262->dsp_runstate &
~run_state_mask);
@@ -839,9 +858,9 @@ static int aic326x_spk_event(struct snd_soc_dapm_widget *w,
int reg_mask;
if (w->shift == 1)
- reg_mask = AIC3262_SPKL_POWER_MASK;
+ reg_mask = AIC3262_SPKL_POWER_STATUS_MASK;
if (w->shift == 0)
- reg_mask = AIC3262_SPKR_POWER_MASK;
+ reg_mask = AIC3262_SPKR_POWER_STATUS_MASK;
switch (event) {
case SND_SOC_DAPM_POST_PMU:
mdelay(1);
@@ -914,7 +933,6 @@ static int aic3262_set_mode_put(struct snd_kcontrol *kcontrol,
else
ret = aic3xxx_cfw_setmode_cfg(priv_ds->cfw_p,
next_mode, next_cfg);
-
return ret;
}
@@ -939,25 +957,27 @@ static int aic326x_adc_dsp_event(struct snd_soc_dapm_widget *w,
if (w->shift == 7) {
reg_mask = AIC3262_LADC_POWER_MASK;
- run_state_mask = AIC3262_COPS_MDSP_A_L;
+ run_state_mask = AIC3XXX_COPS_MDSP_A_L;
}
if (w->shift == 6) {
reg_mask = AIC3262_RADC_POWER_MASK;
- run_state_mask = AIC3262_COPS_MDSP_A_R;
+ run_state_mask = AIC3XXX_COPS_MDSP_A_R;
}
switch (event) {
case SND_SOC_DAPM_POST_PMU:
- ret_wbits = aic3262_wait_bits(w->codec->control_data,
+ ret_wbits = aic3xxx_wait_bits(w->codec->control_data,
AIC3262_ADC_FLAG, reg_mask,
- reg_mask, TIME_DELAY,
- DELAY_COUNTER);
- sync_needed = SYNC_STATE(aic3262);
- non_sync_state = DSP_NON_SYNC_MODE(aic3262->dsp_runstate);
- other_dsp = aic3262->dsp_runstate & AIC3262_COPS_MDSP_D;
+ reg_mask, AIC326X_TIME_DELAY,
+ AIC326X_DELAY_COUNTER);
+ sync_needed = aic3xxx_reg_read(w->codec->control_data,
+ AIC3262_DAC_PRB);
+ non_sync_state = dsp_non_sync_mode(aic3262->dsp_runstate);
+ other_dsp = aic3262->dsp_runstate & AIC3XXX_COPS_MDSP_D;
if (sync_needed && non_sync_state && other_dsp) {
- run_state = get_runstate(aic3262->codec->control_data);
- aic3262_dsp_pwrdwn_status(aic3262);
- aic3262_dsp_pwrup(aic3262, run_state);
+ run_state = aic3262_get_runstate(
+ aic3262->codec);
+ aic3262_dsp_pwrdwn_status(aic3262->codec);
+ aic3262_dsp_pwrup(aic3262->codec, run_state);
}
aic3262->dsp_runstate |= run_state_mask;
if (!ret_wbits) {
@@ -966,9 +986,10 @@ static int aic326x_adc_dsp_event(struct snd_soc_dapm_widget *w,
}
break;
case SND_SOC_DAPM_POST_PMD:
- ret_wbits = aic3262_wait_bits(w->codec->control_data,
+ ret_wbits = aic3xxx_wait_bits(w->codec->control_data,
AIC3262_ADC_FLAG, reg_mask, 0,
- TIME_DELAY, DELAY_COUNTER);
+ AIC326X_TIME_DELAY,
+ AIC326X_DELAY_COUNTER);
aic3262->dsp_runstate = (aic3262->dsp_runstate &
~run_state_mask);
if (!ret_wbits) {
@@ -984,6 +1005,7 @@ static int aic326x_adc_dsp_event(struct snd_soc_dapm_widget *w,
}
static const struct snd_soc_dapm_widget aic3262_dapm_widgets[] = {
+ /* TODO: Can we switch these off ? */
SND_SOC_DAPM_AIF_IN("DIN1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_IN("DIN2", "ASI2 Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_IN("DIN3", "ASI3 Playback", 0, SND_SOC_NOPM, 0, 0),
@@ -996,68 +1018,65 @@ static const struct snd_soc_dapm_widget aic3262_dapm_widgets[] = {
SND_SOC_DAPM_POST_PMD),
/* dapm widget (path domain) for HPL Output Mixer */
- SND_SOC_DAPM_MIXER("HPL Output Mixer", SND_SOC_NOPM, 0, 0,
- &hpl_output_mixer_controls[0],
- ARRAY_SIZE(hpl_output_mixer_controls)),
+ SND_SOC_DAPM_MIXER("HP Left Mixer", SND_SOC_NOPM, 0, 0,
+ &hpl_output_mixer_controls[0],
+ ARRAY_SIZE(hpl_output_mixer_controls)),
/* dapm widget (path domain) for HPR Output Mixer */
- SND_SOC_DAPM_MIXER("HPR Output Mixer", SND_SOC_NOPM, 0, 0,
- &hpr_output_mixer_controls[0],
- ARRAY_SIZE(hpr_output_mixer_controls)),
-
-
- SND_SOC_DAPM_PGA_E("HPL Driver", AIC3262_HP_AMP_CNTL_R1,
- 1, 0, NULL, 0, aic326x_hp_event,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_PGA_E("HPR Driver", AIC3262_HP_AMP_CNTL_R1,
- 0, 0, NULL, 0, aic326x_hp_event,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
+ SND_SOC_DAPM_MIXER("HP Right Mixer", SND_SOC_NOPM, 0, 0,
+ &hpr_output_mixer_controls[0],
+ ARRAY_SIZE(hpr_output_mixer_controls)),
+
+ SND_SOC_DAPM_PGA_S("HP Left Playback Driver", 3,
+ AIC3262_HP_AMP_CNTL_R1, 1, 0, aic326x_hp_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_S("HP Right Playback Driver", 3,
+ AIC3262_HP_AMP_CNTL_R1, 0, 0, aic326x_hp_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
/* dapm widget (path domain) for LOL Output Mixer */
- SND_SOC_DAPM_MIXER("LOL Output Mixer", SND_SOC_NOPM, 0, 0,
- &lol_output_mixer_controls[0],
- ARRAY_SIZE(lol_output_mixer_controls)),
+ SND_SOC_DAPM_MIXER("LO Left Mixer", SND_SOC_NOPM, 0, 0,
+ &lol_output_mixer_controls[0],
+ ARRAY_SIZE(lol_output_mixer_controls)),
/* dapm widget (path domain) for LOR Output Mixer mixer */
- SND_SOC_DAPM_MIXER("LOR Output Mixer", SND_SOC_NOPM, 0, 0,
- &lor_output_mixer_controls[0],
- ARRAY_SIZE(lor_output_mixer_controls)),
-
- SND_SOC_DAPM_PGA("LOL Driver", AIC3262_LINE_AMP_CNTL_R1,
- 1, 0, NULL, 0),
- SND_SOC_DAPM_PGA("LOR Driver", AIC3262_LINE_AMP_CNTL_R1,
- 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("LO Right Mixer", SND_SOC_NOPM, 0, 0,
+ &lor_output_mixer_controls[0],
+ ARRAY_SIZE(lor_output_mixer_controls)),
+ SND_SOC_DAPM_PGA_S("LO Left Playback Driver", 2,
+ AIC3262_LINE_AMP_CNTL_R1, 1, 0, NULL, 0),
+ SND_SOC_DAPM_PGA_S("LO Right Playback Driver", 2,
+ AIC3262_LINE_AMP_CNTL_R1, 0, 0, NULL, 0),
/* dapm widget (path domain) for SPKL Output Mixer */
- SND_SOC_DAPM_MIXER("SPKL Output Mixer", SND_SOC_NOPM, 0, 0,
- &spkl_output_mixer_controls[0],
- ARRAY_SIZE(spkl_output_mixer_controls)),
+ SND_SOC_DAPM_MIXER("SPK Left Mixer", SND_SOC_NOPM, 0, 0,
+ &spkl_output_mixer_controls[0],
+ ARRAY_SIZE(spkl_output_mixer_controls)),
/* dapm widget (path domain) for SPKR Output Mixer */
- SND_SOC_DAPM_MIXER("SPKR Output Mixer", SND_SOC_NOPM, 0, 0,
- &spkr_output_mixer_controls[0],
- ARRAY_SIZE(spkr_output_mixer_controls)),
-
- SND_SOC_DAPM_PGA_E("SPKL Driver", AIC3262_SPK_AMP_CNTL_R1,
- 1, 0, NULL, 0, aic326x_spk_event,
- SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
- SND_SOC_DAPM_PGA_E("SPKR Driver", AIC3262_SPK_AMP_CNTL_R1,
- 0, 0, NULL, 0, aic326x_spk_event,
- SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_MIXER("SPK Right Mixer", SND_SOC_NOPM, 0, 0,
+ &spkr_output_mixer_controls[0],
+ ARRAY_SIZE(spkr_output_mixer_controls)),
+ SND_SOC_DAPM_PGA_S("SPK Left Playback Driver", 3,
+ AIC3262_SPK_AMP_CNTL_R1, 1, 0, aic326x_spk_event,
+ SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PGA_S("SPK Right Playback Driver", 3,
+ AIC3262_SPK_AMP_CNTL_R1, 0, 0, aic326x_spk_event,
+ SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
/* dapm widget (path domain) for SPKR Output Mixer */
- SND_SOC_DAPM_MIXER("REC Output Mixer", SND_SOC_NOPM, 0, 0,
- &rec_output_mixer_controls[0],
- ARRAY_SIZE(rec_output_mixer_controls)),
-
- SND_SOC_DAPM_PGA("RECP Driver", AIC3262_REC_AMP_CNTL_R5,
- 7, 0, NULL, 0),
- SND_SOC_DAPM_PGA("RECM Driver", AIC3262_REC_AMP_CNTL_R5,
- 6, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("REC Mixer", SND_SOC_NOPM, 0, 0,
+ &rec_output_mixer_controls[0],
+ ARRAY_SIZE(rec_output_mixer_controls)),
+ SND_SOC_DAPM_PGA_S("RECP Playback Driver", 3, AIC3262_REC_AMP_CNTL_R5,
+ 7, 0, NULL, 0),
+ SND_SOC_DAPM_PGA_S("RECM Playback Driver", 3, AIC3262_REC_AMP_CNTL_R5,
+ 6, 0, NULL, 0),
SND_SOC_DAPM_MUX("ASI1LIN Route",
SND_SOC_NOPM, 0, 0, &asi1lin_control),
@@ -1097,10 +1116,10 @@ static const struct snd_soc_dapm_widget aic3262_dapm_widgets[] = {
SND_SOC_NOPM, 0, 0, &adcdacroute_control),
SND_SOC_DAPM_PGA("CM", SND_SOC_NOPM, 0, 0, NULL, 0),
- SND_SOC_DAPM_PGA("CM1L", SND_SOC_NOPM, 0, 0, NULL, 0),
- SND_SOC_DAPM_PGA("CM2L", SND_SOC_NOPM, 0, 0, NULL, 0),
- SND_SOC_DAPM_PGA("CM1R", SND_SOC_NOPM, 0, 0, NULL, 0),
- SND_SOC_DAPM_PGA("CM2R", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("CM1 Left Capture", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("CM2 Left Capture", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("CM1 Right Capture", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("CM2 Right Capture", SND_SOC_NOPM, 0, 0, NULL, 0),
/* TODO: Can we switch these off ? */
SND_SOC_DAPM_AIF_OUT("DOUT1", "ASI1 Capture", 0, SND_SOC_NOPM, 0, 0),
@@ -1131,9 +1150,6 @@ static const struct snd_soc_dapm_widget aic3262_dapm_widgets[] = {
SND_SOC_DAPM_PGA("ADC MiniDSP OUT2", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("ADC MiniDSP OUT3", SND_SOC_NOPM, 0, 0, NULL, 0),
-/* SND_SOC_DAPM_MUX("DMICDAT Input Route",
- SND_SOC_NOPM, 0, 0, &dmicinput_control),*/
-
SND_SOC_DAPM_MUX("Left ADC Route", SND_SOC_NOPM, 0, 0, &adcl_mux),
SND_SOC_DAPM_MUX("Right ADC Route", SND_SOC_NOPM, 0, 0, &adcr_mux),
@@ -1144,72 +1160,80 @@ static const struct snd_soc_dapm_widget aic3262_dapm_widgets[] = {
aic326x_adc_dsp_event, SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_PGA("Left MicPGA", AIC3262_MICL_PGA, 7, 1, NULL, 0),
- SND_SOC_DAPM_PGA("Right MicPGA", AIC3262_MICR_PGA, 7, 1, NULL, 0),
+ SND_SOC_DAPM_PGA_S("Left MicPGA", 0, AIC3262_MICL_PGA, 7, 1, NULL, 0),
+ SND_SOC_DAPM_PGA_S("Right MicPGA", 0, AIC3262_MICR_PGA, 7, 1, NULL, 0),
- SND_SOC_DAPM_PGA("MAL PGA", AIC3262_MA_CNTL,
- 3, 0, NULL, 0),
- SND_SOC_DAPM_PGA("MAR PGA", AIC3262_MA_CNTL,
- 2, 0, NULL, 0),
+ SND_SOC_DAPM_PGA_S("MA Left Playback PGA", 1, AIC3262_MA_CNTL,
+ 3, 0, NULL, 0),
+ SND_SOC_DAPM_PGA_S("MA Right Playback PGA", 1, AIC3262_MA_CNTL,
+ 2, 0, NULL, 0),
/* dapm widget for MAL PGA Mixer */
- SND_SOC_DAPM_MIXER("MAL PGA Mixer", SND_SOC_NOPM, 0, 0,
- &mal_pga_mixer_controls[0],
- ARRAY_SIZE(mal_pga_mixer_controls)),
+ SND_SOC_DAPM_MIXER("MA Left PGA Mixer", SND_SOC_NOPM, 0, 0,
+ &mal_pga_mixer_controls[0],
+ ARRAY_SIZE(mal_pga_mixer_controls)),
/* dapm widget for MAR PGA Mixer */
- SND_SOC_DAPM_MIXER("MAR PGA Mixer", SND_SOC_NOPM, 0, 0,
- &mar_pga_mixer_controls[0],
- ARRAY_SIZE(mar_pga_mixer_controls)),
+ SND_SOC_DAPM_MIXER("MA Right PGA Mixer", SND_SOC_NOPM, 0, 0,
+ &mar_pga_mixer_controls[0],
+ ARRAY_SIZE(mar_pga_mixer_controls)),
/* dapm widget for Left Input Mixer */
SND_SOC_DAPM_MIXER("Left Input Mixer", SND_SOC_NOPM, 0, 0,
- &left_input_mixer_controls[0],
- ARRAY_SIZE(left_input_mixer_controls)),
+ &left_input_mixer_controls[0],
+ ARRAY_SIZE(left_input_mixer_controls)),
/* dapm widget for Right Input Mixer */
SND_SOC_DAPM_MIXER("Right Input Mixer", SND_SOC_NOPM, 0, 0,
- &right_input_mixer_controls[0],
- ARRAY_SIZE(right_input_mixer_controls)),
-
- SND_SOC_DAPM_OUTPUT("HPL"),
- SND_SOC_DAPM_OUTPUT("HPR"),
- SND_SOC_DAPM_OUTPUT("LOL"),
- SND_SOC_DAPM_OUTPUT("LOR"),
- SND_SOC_DAPM_OUTPUT("SPKL"),
- SND_SOC_DAPM_OUTPUT("SPKR"),
- SND_SOC_DAPM_OUTPUT("RECP"),
- SND_SOC_DAPM_OUTPUT("RECM"),
-
- SND_SOC_DAPM_INPUT("IN1L"),
- SND_SOC_DAPM_INPUT("IN2L"),
- SND_SOC_DAPM_INPUT("IN3L"),
- SND_SOC_DAPM_INPUT("IN4L"),
- SND_SOC_DAPM_INPUT("IN1R"),
- SND_SOC_DAPM_INPUT("IN2R"),
- SND_SOC_DAPM_INPUT("IN3R"),
- SND_SOC_DAPM_INPUT("IN4R"),
- SND_SOC_DAPM_INPUT("Left DMIC"),
- SND_SOC_DAPM_INPUT("Right DMIC"),
+ &right_input_mixer_controls[0],
+ ARRAY_SIZE(right_input_mixer_controls)),
+
+ SND_SOC_DAPM_OUTPUT("HP Left Playback"),
+ SND_SOC_DAPM_OUTPUT("HP Right Playback"),
+ SND_SOC_DAPM_OUTPUT("LO Left Playback"),
+ SND_SOC_DAPM_OUTPUT("LO Right Playback"),
+ SND_SOC_DAPM_OUTPUT("SPK Left Playback"),
+ SND_SOC_DAPM_OUTPUT("SPK Right Playback"),
+ SND_SOC_DAPM_OUTPUT("RECP Playback"),
+ SND_SOC_DAPM_OUTPUT("RECM Playback"),
+
+ SND_SOC_DAPM_INPUT("IN1 Left Capture"),
+ SND_SOC_DAPM_INPUT("IN2 Left Capture"),
+ SND_SOC_DAPM_INPUT("IN3 Left Capture"),
+ SND_SOC_DAPM_INPUT("IN4 Left Capture"),
+ SND_SOC_DAPM_INPUT("IN1 Right Capture"),
+ SND_SOC_DAPM_INPUT("IN2 Right Capture"),
+ SND_SOC_DAPM_INPUT("IN3 Right Capture"),
+ SND_SOC_DAPM_INPUT("IN4 Right Capture"),
+ SND_SOC_DAPM_INPUT("Left DMIC Capture"),
+ SND_SOC_DAPM_INPUT("Right DMIC Capture"),
SND_SOC_DAPM_MICBIAS("Mic Bias Ext", AIC3262_MIC_BIAS_CNTL, 6, 0),
SND_SOC_DAPM_MICBIAS("Mic Bias Int", AIC3262_MIC_BIAS_CNTL, 2, 0),
- SND_SOC_DAPM_SUPPLY("PLLCLK", AIC3262_PLL_PR_POW_REG, 7, 0,
+ SND_SOC_DAPM_SUPPLY_S("PLLCLK", 0, AIC3262_PLL_PR_POW_REG, 7, 0,
pll_power_on_event, SND_SOC_DAPM_POST_PMU),
- SND_SOC_DAPM_SUPPLY("DACCLK", AIC3262_NDAC_DIV_POW_REG, 7, 0, NULL, 0),
- SND_SOC_DAPM_SUPPLY("CODEC_CLK_IN", SND_SOC_NOPM, 0, 0, NULL, 0),
- SND_SOC_DAPM_SUPPLY("DAC_MOD_CLK", AIC3262_MDAC_DIV_POW_REG,
- 7, 0, NULL, 0),
- SND_SOC_DAPM_SUPPLY("ADCCLK", AIC3262_NADC_DIV_POW_REG, 7, 0, NULL, 0),
- SND_SOC_DAPM_SUPPLY("ADC_MOD_CLK", AIC3262_MADC_DIV_POW_REG,
- 7, 0, NULL, 0),
- SND_SOC_DAPM_SUPPLY("ASI1_BCLK", AIC3262_ASI1_BCLK_N, 7, 0, NULL, 0),
- SND_SOC_DAPM_SUPPLY("ASI1_WCLK", AIC3262_ASI1_WCLK_N, 7, 0, NULL, 0),
- SND_SOC_DAPM_SUPPLY("ASI2_BCLK", AIC3262_ASI2_BCLK_N, 7, 0, NULL, 0),
- SND_SOC_DAPM_SUPPLY("ASI2_WCLK", AIC3262_ASI2_WCLK_N, 7, 0, NULL, 0),
- SND_SOC_DAPM_SUPPLY("ASI3_BCLK", AIC3262_ASI3_BCLK_N, 7, 0, NULL, 0),
- SND_SOC_DAPM_SUPPLY("ASI3_WCLK", AIC3262_ASI3_WCLK_N, 7, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("DACCLK", 2, AIC3262_NDAC_DIV_POW_REG, 7, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("CODEC_CLK_IN", 1, SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("DAC_MOD_CLK", 3, AIC3262_MDAC_DIV_POW_REG,
+ 7, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("ADCCLK", 2, AIC3262_NADC_DIV_POW_REG,
+ 7, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("ADC_MOD_CLK", 3, AIC3262_MADC_DIV_POW_REG,
+ 7, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("ASI1_BCLK", 4, AIC3262_ASI1_BCLK_N,
+ 7, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("ASI1_WCLK", 4, AIC3262_ASI1_WCLK_N,
+ 7, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("ASI2_BCLK", 4, AIC3262_ASI2_BCLK_N,
+ 7, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("ASI2_WCLK", 4, AIC3262_ASI2_WCLK_N,
+ 7, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("ASI3_BCLK", 4, AIC3262_ASI3_BCLK_N,
+ 7, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("ASI3_WCLK", 4, AIC3262_ASI3_WCLK_N,
+ 7, 0, NULL, 0),
SND_SOC_DAPM_MUX("ASI1_BCLK Route",
SND_SOC_NOPM, 0, 0, &asi1bclk_control),
SND_SOC_DAPM_MUX("ASI2_BCLK Route",
@@ -1249,122 +1273,89 @@ static const struct snd_soc_dapm_route aic3262_dapm_routes[] = {
{"ASI1_BCLK", NULL, "ASI1_BCLK Route"},
{"ASI2_BCLK", NULL, "ASI2_BCLK Route"},
{"ASI3_BCLK", NULL, "ASI3_BCLK Route"},
-
- {"DIN1", NULL, "PLLCLK"},
- {"DIN1", NULL, "DACCLK"},
- {"DIN1", NULL, "ADCCLK"},
- {"DIN1", NULL, "DAC_MOD_CLK"},
- {"DIN1", NULL, "ADC_MOD_CLK"},
-
- {"DOUT1", NULL, "PLLCLK"},
- {"DOUT1", NULL, "DACCLK"},
- {"DOUT1", NULL, "ADCCLK"},
- {"DOUT1", NULL, "DAC_MOD_CLK"},
- {"DOUT1", NULL, "ADC_MOD_CLK"},
#ifdef AIC3262_ASI1_MASTER
{"DIN1", NULL, "ASI1_BCLK"},
{"DOUT1", NULL, "ASI1_BCLK"},
{"DIN1", NULL, "ASI1_WCLK"},
{"DOUT1", NULL, "ASI1_WCLK"},
-#else
-
#endif
- {"DIN2", NULL, "PLLCLK"},
- {"DIN2", NULL, "DACCLK"},
- {"DIN2", NULL, "ADCCLK"},
- {"DIN2", NULL, "DAC_MOD_CLK"},
- {"DIN2", NULL, "ADC_MOD_CLK"},
-
- {"DOUT2", NULL, "PLLCLK"},
- {"DOUT2", NULL, "DACCLK"},
- {"DOUT2", NULL, "ADCCLK"},
- {"DOUT2", NULL, "DAC_MOD_CLK"},
- {"DOUT2", NULL, "ADC_MOD_CLK"},
-
#ifdef AIC3262_ASI2_MASTER
{"DIN2", NULL, "ASI2_BCLK"},
{"DOUT2", NULL, "ASI2_BCLK"},
{"DIN2", NULL, "ASI2_WCLK"},
{"DOUT2", NULL, "ASI2_WCLK"},
-#else
-
#endif
- {"DIN3", NULL, "PLLCLK"},
- {"DIN3", NULL, "DACCLK"},
- {"DIN3", NULL, "ADCCLK"},
- {"DIN3", NULL, "DAC_MOD_CLK"},
- {"DIN3", NULL, "ADC_MOD_CLK"},
-
- {"DOUT3", NULL, "PLLCLK"},
- {"DOUT3", NULL, "DACCLK"},
- {"DOUT3", NULL, "ADCCLK"},
- {"DOUT3", NULL, "DAC_MOD_CLK"},
- {"DOUT3", NULL, "ADC_MOD_CLK"},
-
#ifdef AIC3262_ASI3_MASTER
{"DIN3", NULL, "ASI3_BCLK"},
{"DOUT3", NULL, "ASI3_BCLK"},
{"DIN3", NULL, "ASI3_WCLK"},
{"DOUT3", NULL, "ASI3_WCLK"},
-#else
-
#endif
+ {"Left DAC", NULL, "DAC_MOD_CLK"},
+ {"Right DAC", NULL, "DAC_MOD_CLK"},
+ /* When we are master, ASI bclk and wclk are generated by
+ * DAC_MOD_CLK, so we put them as dependency for ADC too.
+ */
+ {"Left ADC", NULL, "DAC_MOD_CLK"},
+ {"Right ADC", NULL, "DAC_MOD_CLK"},
+ {"Left ADC", NULL, "ADC_MOD_CLK"},
+ {"Right ADC", NULL, "ADC_MOD_CLK"},
/* Playback (DAC) Portion */
- {"HPL Output Mixer", "LDAC Switch", "Left DAC"},
- {"HPL Output Mixer", "MAL Switch", "MAL PGA"},
- {"HPL Output Mixer", "LOL-B1 Volume", "LOL"},
-
- {"HPR Output Mixer", "LOR-B1 Volume", "LOR"},
- {"HPR Output Mixer", "LDAC Switch", "Left DAC"},
- {"HPR Output Mixer", "RDAC Switch", "Right DAC"},
- {"HPR Output Mixer", "MAR Switch", "MAR PGA"},
+ {"HP Left Mixer", "Left DAC Playback Switch", "Left DAC"},
+ {"HP Left Mixer", "MA Left Playback Switch", "MA Left Playback PGA"},
+ {"HP Left Mixer", "LO Left-B1 Playback Volume", "LO Left Playback"},
- {"HPL Driver", NULL, "HPL Output Mixer"},
- {"HPR Driver", NULL, "HPR Output Mixer"},
+ {"HP Right Mixer", "LO Right-B1 Playback Volume", "LO Right Playback"},
+ {"HP Right Mixer", "Left DAC Playback Switch", "Left DAC"},
+ {"HP Right Mixer", "Right DAC Playback Switch", "Right DAC"},
+ {"HP Right Mixer", "MA Right Playback Switch", "MA Right Playback PGA"},
- {"HPL", NULL, "HPL Driver"},
- {"HPR", NULL, "HPR Driver"},
+ {"HP Left Playback Driver", NULL, "HP Left Mixer"},
+ {"HP Right Playback Driver", NULL, "HP Right Mixer"},
- {"LOL Output Mixer", "MAL Switch", "MAL PGA"},
- {"LOL Output Mixer", "IN1L-B Switch", "IN1L"},
- {"LOL Output Mixer", "LDAC Switch", "Left DAC"},
- {"LOL Output Mixer", "RDAC Switch", "Right DAC"},
+ {"HP Left Playback", NULL, "HP Left Playback Driver"},
+ {"HP Right Playback", NULL, "HP Right Playback Driver"},
- {"LOR Output Mixer", "LOL Switch", "LOL"},
- {"LOR Output Mixer", "RDAC Switch", "Right DAC"},
- {"LOR Output Mixer", "MAR Switch", "MAR PGA"},
- {"LOR Output Mixer", "IN1R-B Switch", "IN1R"},
+ {"LO Left Mixer", "MA Left Playback Switch", "MA Left Playback PGA"},
+ {"LO Left Mixer", "IN1 Left-B Capture Switch", "IN1 Left Capture"},
+ {"LO Left Mixer", "Left DAC Playback Switch", "Left DAC"},
+ {"LO Left Mixer", "Right DAC Playback Switch", "Right DAC"},
- {"LOL Driver", NULL, "LOL Output Mixer"},
- {"LOR Driver", NULL, "LOR Output Mixer"},
+ {"LO Right Mixer", "LO Left Playback Switch", "LO Left Playback"},
+ {"LO Right Mixer", "Right DAC Playback Switch", "Right DAC"},
+ {"LO Right Mixer", "MA Right Playback Switch", "MA Right Playback PGA"},
+ {"LO Right Mixer", "IN1 Right-B Capture Switch", "IN1 Right Capture"},
- {"LOL", NULL, "LOL Driver"},
- {"LOR", NULL, "LOR Driver"},
+ {"LO Left Playback Driver", NULL, "LO Left Mixer"},
+ {"LO Right Playback Driver", NULL, "LO Right Mixer"},
- {"REC Output Mixer", "LOL-B2 Volume", "LOL"},
- {"REC Output Mixer", "IN1L Volume", "IN1L"},
- {"REC Output Mixer", "IN1R Volume", "IN1R"},
- {"REC Output Mixer", "LOR-B2 Volume", "LOR"},
+ {"LO Left Playback", NULL, "LO Left Playback Driver"},
+ {"LO Right Playback", NULL, "LO Right Playback Driver"},
- {"RECP Driver", NULL, "REC Output Mixer"},
- {"RECM Driver", NULL, "REC Output Mixer"},
+ {"REC Mixer", "LO Left-B2 Playback Volume", "LO Left Playback"},
+ {"REC Mixer", "IN1 Left Capture Volume", "IN1 Left Capture"},
+ {"REC Mixer", "IN1 Right Capture Volume", "IN1 Right Capture"},
+ {"REC Mixer", "LO Right-B2 Playback Volume", "LO Right Playback"},
- {"RECP", NULL, "RECP Driver"},
- {"RECM", NULL, "RECM Driver"},
+ {"RECP Playback Driver", NULL, "REC Mixer"},
+ {"RECM Playback Driver", NULL, "REC Mixer"},
- {"SPKL Output Mixer", "MAL Switch", "MAL PGA"},
- {"SPKL Output Mixer", "LOL Volume", "LOL"},
- {"SPKL Output Mixer", "SPR_IN Switch", "SPKR Output Mixer"},
+ {"RECP Playback", NULL, "RECP Playback Driver"},
+ {"RECM Playback", NULL, "RECM Playback Driver"},
- {"SPKR Output Mixer", "LOR Volume", "LOR"},
- {"SPKR Output Mixer", "MAR Switch", "MAR PGA"},
+ {"SPK Left Mixer", "MA Left Playback Switch", "MA Left Playback PGA"},
+ {"SPK Left Mixer", "LO Left Playback Volume", "LO Left Playback"},
+ {"SPK Left Mixer", "SPR_IN Switch", "SPK Right Mixer"},
+ {"SPK Right Mixer", "LO Right Playback Volume", "LO Right Playback"},
+ {"SPK Right Mixer", "MA Right Playback Switch",
+ "MA Right Playback PGA"},
- {"SPKL Driver", NULL, "SPKL Output Mixer"},
- {"SPKR Driver", NULL, "SPKR Output Mixer"},
+ {"SPK Left Playback Driver", NULL, "SPK Left Mixer"},
+ {"SPK Right Playback Driver", NULL, "SPK Right Mixer"},
- {"SPKL", NULL, "SPKL Driver"},
- {"SPKR", NULL, "SPKR Driver"},
+ {"SPK Left Playback", NULL, "SPK Left Playback Driver"},
+ {"SPK Right Playback", NULL, "SPK Right Playback Driver"},
/* ASI Input routing */
{"ASI1LIN", NULL, "DIN1"},
{"ASI1RIN", NULL, "DIN1"},
@@ -1428,18 +1419,15 @@ static const struct snd_soc_dapm_route aic3262_dapm_routes[] = {
{"Right DAC", "NULL", "DAC MiniDSP IN3 Route"},
/* Mixer Amplifier */
+ {"MA Left PGA Mixer", "IN1 Left Capture Switch", "IN1 Left Capture"},
+ {"MA Left PGA Mixer", "Left MicPGA Volume", "Left MicPGA"},
- {"MAL PGA Mixer", "IN1L Switch", "IN1L"},
- {"MAL PGA Mixer", "Left MicPGA Volume", "Left MicPGA"},
-
- {"MAL PGA", NULL, "MAL PGA Mixer"},
-
+ {"MA Left Playback PGA", NULL, "MA Left PGA Mixer"},
- {"MAR PGA Mixer", "IN1R Switch", "IN1R"},
- {"MAR PGA Mixer", "Right MicPGA Volume", "Right MicPGA"},
-
- {"MAR PGA", NULL, "MAR PGA Mixer"},
+ {"MA Right PGA Mixer", "IN1 Right Capture Switch", "IN1 Right Capture"},
+ {"MA Right PGA Mixer", "Right MicPGA Volume", "Right MicPGA"},
+ {"MA Right Playback PGA", NULL, "MA Right PGA Mixer"},
/* Virtual connection between DAC and ADC for miniDSP IPC */
{"ADC DAC Route", "On", "Left ADC"},
@@ -1450,46 +1438,44 @@ static const struct snd_soc_dapm_route aic3262_dapm_routes[] = {
/* Capture (ADC) portions */
/* Left Positive PGA input */
- {"Left Input Mixer", "IN1L Switch", "IN1L"},
- {"Left Input Mixer", "IN2L Switch", "IN2L"},
- {"Left Input Mixer", "IN3L Switch", "IN3L"},
- {"Left Input Mixer", "IN4L Switch", "IN4L"},
- {"Left Input Mixer", "IN1R Switch", "IN1R"},
+ {"Left Input Mixer", "IN1 Left Capture Switch", "IN1 Left Capture"},
+ {"Left Input Mixer", "IN2 Left Capture Switch", "IN2 Left Capture"},
+ {"Left Input Mixer", "IN3 Left Capture Switch", "IN3 Left Capture"},
+ {"Left Input Mixer", "IN4 Left Capture Switch", "IN4 Left Capture"},
+ {"Left Input Mixer", "IN1 Right Capture Switch", "IN1 Right Capture"},
/* Left Negative PGA input */
- {"Left Input Mixer", "IN2R Switch", "IN2R"},
- {"Left Input Mixer", "IN3R Switch", "IN3R"},
- {"Left Input Mixer", "IN4R Switch", "IN4R"},
- {"Left Input Mixer", "CM2L Switch", "CM2L"},
- {"Left Input Mixer", "CM1L Switch", "CM1L"},
-
+ {"Left Input Mixer", "IN2 Right Capture Switch", "IN2 Right Capture"},
+ {"Left Input Mixer", "IN3 Right Capture Switch", "IN3 Right Capture"},
+ {"Left Input Mixer", "IN4 Right Capture Switch", "IN4 Right Capture"},
+ {"Left Input Mixer", "CM2 Left Capture Switch", "CM2 Left Capture"},
+ {"Left Input Mixer", "CM1 Left Capture Switch", "CM1 Left Capture"},
/* Right Positive PGA Input */
- {"Right Input Mixer", "IN1R Switch", "IN1R"},
- {"Right Input Mixer", "IN2R Switch", "IN2R"},
- {"Right Input Mixer", "IN3R Switch", "IN3R"},
- {"Right Input Mixer", "IN4R Switch", "IN4R"},
- {"Right Input Mixer", "IN2L Switch", "IN2L"},
+ {"Right Input Mixer", "IN1 Right Capture Switch", "IN1 Right Capture"},
+ {"Right Input Mixer", "IN2 Right Capture Switch", "IN2 Right Capture"},
+ {"Right Input Mixer", "IN3 Right Capture Switch", "IN3 Right Capture"},
+ {"Right Input Mixer", "IN4 Right Capture Switch", "IN4 Right Capture"},
+ {"Right Input Mixer", "IN2 Left Capture Switch", "IN2 Left Capture"},
/* Right Negative PGA Input */
- {"Right Input Mixer", "IN1L Switch", "IN1L"},
- {"Right Input Mixer", "IN3L Switch", "IN3L"},
- {"Right Input Mixer", "IN4L Switch", "IN4L"},
- {"Right Input Mixer", "CM1R Switch", "CM1R"},
- {"Right Input Mixer", "CM2R Switch", "CM2R"},
-
+ {"Right Input Mixer", "IN1 Left Capture Switch", "IN1 Left Capture"},
+ {"Right Input Mixer", "IN3 Left Capture Switch", "IN3 Left Capture"},
+ {"Right Input Mixer", "IN4 Left Capture Switch", "IN4 Left Capture"},
+ {"Right Input Mixer", "CM1 Right Capture Switch", "CM1 Right Capture"},
+ {"Right Input Mixer", "CM2 Right Capture Switch", "CM2 Right Capture"},
- {"CM1L", NULL, "CM"},
- {"CM2L", NULL, "CM"},
- {"CM1R", NULL, "CM"},
- {"CM2R", NULL, "CM"},
+ {"CM1 Left Capture", NULL, "CM"},
+ {"CM2 Left Capture", NULL, "CM"},
+ {"CM1 Right Capture", NULL, "CM"},
+ {"CM2 Right Capture", NULL, "CM"},
{"Left MicPGA", NULL, "Left Input Mixer"},
{"Right MicPGA", NULL, "Right Input Mixer"},
{"Left ADC Route", "Analog", "Left MicPGA"},
- {"Left ADC Route", "Digital", "Left DMIC"},
+ {"Left ADC Route", "Digital", "Left DMIC Capture"},
{"Right ADC Route", "Analog", "Right MicPGA"},
- {"Right ADC Route", "Digital", "Right DMIC"},
+ {"Right ADC Route", "Digital", "Right DMIC Capture"},
{"Left ADC", NULL, "Left ADC Route"},
{"Right ADC", NULL, "Right ADC Route"},
@@ -1555,7 +1541,7 @@ static const struct snd_soc_dapm_route aic3262_dapm_routes[] = {
*
* Returns 0 for success.
*/
-void aic3262_firmware_load(const struct firmware *fw, void *context)
+static void aic3262_firmware_load(const struct firmware *fw, void *context)
{
struct snd_soc_codec *codec = context;
struct aic3262_priv *private_ds = snd_soc_codec_get_drvdata(codec);
@@ -1569,37 +1555,35 @@ void aic3262_firmware_load(const struct firmware *fw, void *context)
if (fw != NULL) {
dev_dbg(codec->dev, "Firmware binary load\n");
private_ds->cur_fw = (void *)fw;
- ret = aic3xxx_cfw_reload(private_ds->cfw_p,
- (void *)fw->data, fw->size);
- if (ret < 0) { /* reload failed */
+ ret = aic3xxx_cfw_reload(private_ds->cfw_p, (void *)fw->data,
+ fw->size);
+ if (ret < 0) { /* reload failed */
dev_err(codec->dev, "Firmware binary load failed\n");
release_firmware(private_ds->cur_fw);
private_ds->cur_fw = NULL;
fw = NULL;
- } else
- private_ds->isdefault_fw = 0;
+ }
+ } else {
+ /* request_firmware failed*/
+ /* could not locate file tlv320aic3262_fw_v1.bin
+ under /vendor/firmare
+ */
+ dev_err(codec->dev, "request_firmware failed\n");
+ ret = -1;
}
- if (fw == NULL) {
- /* either request_firmware or reload failed */
- dev_dbg(codec->dev, "Default firmware load\n");
- ret = aic3xxx_cfw_reload(private_ds->cfw_p, default_firmware,
- sizeof(default_firmware));
- if (ret < 0)
- dev_err(codec->dev, "Default firmware load failed\n");
- else
- private_ds->isdefault_fw = 1;
- }
aic3xxx_cfw_lock(private_ds->cfw_p, 0);
if (ret >= 0) {
- /* init function for transition */
+ /*init function for transition */
aic3xxx_cfw_transition(private_ds->cfw_p, "INIT");
- if (!private_ds->isdefault_fw) {
- aic3xxx_cfw_add_modes(codec, private_ds->cfw_p);
- aic3xxx_cfw_add_controls(codec, private_ds->cfw_p);
- }
+ /* add firmware modes */
+ aic3xxx_cfw_add_modes(codec, private_ds->cfw_p);
+ /* add runtime controls */
+ aic3xxx_cfw_add_controls(codec, private_ds->cfw_p);
+ /* set the default firmware mode */
aic3xxx_cfw_setmode_cfg(private_ds->cfw_p, 0, 0);
}
+
}
/*=========================================================
@@ -1608,6 +1592,12 @@ void aic3262_firmware_load(const struct firmware *fw, void *context)
========================================================*/
+enum headset_accessory_state {
+ BIT_NO_ACCESSORY = 0,
+ BIT_HEADSET = (1 << 0),
+ BIT_HEADPHONE = (1 << 1),
+};
+
/**
* aic3262_hs_jack_report: Report jack notication to upper layor
* @codec: pointer variable to codec having information related to codec
@@ -1620,28 +1610,30 @@ static void aic3262_hs_jack_report(struct snd_soc_codec *codec,
struct snd_soc_jack *jack, int report)
{
struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
- int status, state = 0;
+ int status, state = 0, switch_state = BIT_NO_ACCESSORY;
mutex_lock(&aic3262->mutex);
/* Sync status */
status = snd_soc_read(codec, AIC3262_DAC_FLAG);
-
+ /* We will check only stereo MIC and headphone */
switch (status & AIC3262_JACK_TYPE_MASK) {
case AIC3262_JACK_WITH_MIC:
state |= SND_JACK_HEADSET;
break;
case AIC3262_JACK_WITHOUT_MIC:
state |= SND_JACK_HEADPHONE;
- break;
- default:
- break;
}
mutex_unlock(&aic3262->mutex);
snd_soc_jack_report(jack, state, report);
+ if ((state & SND_JACK_HEADSET) == SND_JACK_HEADSET)
+ switch_state |= BIT_HEADSET;
+ else if (state & SND_JACK_HEADPHONE)
+ switch_state |= BIT_HEADPHONE;
+
}
/**
@@ -1697,19 +1689,337 @@ static irqreturn_t aic3262_audio_handler(int irq, void *data)
return IRQ_HANDLED;
}
-static irqreturn_t aic3262_button_handler(int irq, void *data)
+/**
+ * Methods for CFW Operations
+ *
+ * Due to incompatibilites between structures used by MFD and CFW
+ * we need to transform the register format before linking to
+ * CFW operations.
+ */
+static inline unsigned int aic3262_ops_cfw2reg(unsigned int reg)
+{
+ union cfw_register *c = (union cfw_register *) &reg;
+ union aic3xxx_reg_union mreg;
+
+ mreg.aic3xxx_register.offset = c->offset;
+ mreg.aic3xxx_register.page = c->page;
+ mreg.aic3xxx_register.book = c->book;
+ mreg.aic3xxx_register.reserved = 0;
+
+ return mreg.aic3xxx_register_int;
+}
+static int aic3262_ops_reg_read(struct snd_soc_codec *codec, unsigned int reg)
+{
+ return aic3xxx_reg_read(codec->control_data, aic3262_ops_cfw2reg(reg));
+}
+
+static int aic3262_ops_reg_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned char val)
{
- struct snd_soc_codec *codec = data;
- struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
- input_report_key(aic3262->idev, KEY_MEDIA, 1);
- mdelay(50);
- input_report_key(aic3262->idev, KEY_MEDIA, 0);
- input_sync(aic3262->idev);
+ return aic3xxx_reg_write(codec->control_data,
+ aic3262_ops_cfw2reg(reg), val);
+}
- return IRQ_HANDLED;
+static int aic3262_ops_set_bits(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned char mask, unsigned char val)
+{
+ return aic3xxx_set_bits(codec->control_data,
+ aic3262_ops_cfw2reg(reg), mask, val);
+
+}
+
+static int aic3262_ops_bulk_read(struct snd_soc_codec *codec, unsigned int reg,
+ int count, u8 *buf)
+{
+ return aic3xxx_bulk_read(codec->control_data,
+ aic3262_ops_cfw2reg(reg), count, buf);
+}
+
+static int aic3262_ops_bulk_write(struct snd_soc_codec *codec, unsigned int reg,
+ int count, const u8 *buf)
+{
+ return aic3xxx_bulk_write(codec->control_data,
+ aic3262_ops_cfw2reg(reg), count, buf);
}
/**
+ * aic3262_ops_dlock_lock: To Read the run state of the DAC and ADC
+ * by reading the codec and returning the run state
+ * @pv: pointer argument to the codec
+ *
+ * Run state Bit format
+ *
+ * ------------------------------------------------------
+ * D31|..........| D7 | D6| D5 | D4 | D3 | D2 | D1 | D0 |
+ * R R R LADC RADC R R LDAC RDAC
+ * ------------------------------------------------------
+ *
+ * R- Reserved
+ * LDAC- Left DAC
+ * RDAC- Right DAC
+ *
+ * Return value : Integer
+ */
+static int aic3262_ops_lock(struct snd_soc_codec *codec)
+{
+ mutex_lock(&codec->mutex);
+
+ /* Reading the run state of adc and dac */
+ return aic3262_get_runstate(codec);
+
+}
+
+/**
+ * aic3262_ops_dlock_unlock: To unlock the mutex acqiured for reading
+ * run state of the codec
+ * @pv: pointer argument to the codec
+ *
+ * Return Value: integer returning 0
+ */
+static int aic3262_ops_unlock(struct snd_soc_codec *codec)
+{
+ /*Releasing the lock of mutex */
+ mutex_unlock(&codec->mutex);
+ return 0;
+}
+
+/**
+ * aic3262_ops_dlock_stop:
+ * @pv: pointer Argument to the codec
+ * @mask: tells us the bit format of the codec running state
+ *
+ * Bit Format:
+ * ------------------------------------------------------
+ * D31|..........| D7 | D6| D5 | D4 | D3 | D2 | D1 | D0 |
+ * R R R AL AR R R DL DR
+ * ------------------------------------------------------
+ * R - Reserved
+ * A - minidsp_A
+ * D - minidsp_D
+ *
+ * Return: return run state
+ */
+static int aic3262_ops_stop(struct snd_soc_codec *codec, int mask)
+{
+ int run_state = 0;
+
+ run_state = aic3262_get_runstate(codec);
+
+ if (mask & AIC3XXX_COPS_MDSP_A)
+ aic3xxx_set_bits(codec->control_data,
+ AIC3262_ADC_DATAPATH_SETUP, 0xC0, 0);
+
+ if (mask & AIC3XXX_COPS_MDSP_D)
+ aic3xxx_set_bits(codec->control_data,
+ AIC3262_DAC_DATAPATH_SETUP, 0xC0, 0);
+
+ if ((mask & AIC3XXX_COPS_MDSP_A) &&
+ !aic3xxx_wait_bits(codec->control_data,
+ AIC3262_ADC_FLAG, AIC3262_ADC_POWER_MASK,
+ 0, AIC326X_TIME_DELAY,
+ AIC326X_DELAY_COUNTER))
+ goto err;
+
+ if ((mask & AIC3XXX_COPS_MDSP_D) &&
+ !aic3xxx_wait_bits(codec->control_data,
+ AIC3262_DAC_FLAG, AIC3262_DAC_POWER_MASK,
+ 0, AIC326X_TIME_DELAY,
+ AIC326X_DELAY_COUNTER))
+ goto err;
+
+ return run_state;
+err:
+ dev_err(codec->dev, "Unable to turn off ADCs or DACs at [%s:%d]",
+ __FILE__, __LINE__);
+ return -EINVAL;
+}
+
+/**
+ * aic3262_ops_dlock_restore: To unlock the mutex acqiured for reading
+ * @pv: pointer argument to the codec,run_state
+ * @run_state: run state of the codec and to restore the states of the dsp
+ *
+ * Return Value : integer returning 0
+ */
+
+static int aic3262_ops_restore(struct snd_soc_codec *codec, int run_state)
+{
+ int sync_state;
+
+ /* This is for read the sync mode register state */
+ sync_state = aic3xxx_reg_read(codec->control_data, AIC3262_DAC_PRB);
+
+ /*checking whether the sync mode has been set or
+ not and checking the current state */
+ if (((run_state & 0x30) && (run_state & 0x03)) && (sync_state & 0x80))
+ aic3262_restart_dsps_sync(codec, run_state);
+ else
+ aic3262_dsp_pwrup(codec, run_state);
+
+ return 0;
+}
+
+/**
+ * aic3262_ops_adaptivebuffer_swap: To swap the coefficient buffers
+ * of minidsp according to mask
+ * @pv: pointer argument to the codec,
+ * @mask: tells us which dsp has to be chosen for swapping
+ *
+ * Return Value : returning 0 on success
+ */
+int aic3262_ops_adaptivebuffer_swap(struct snd_soc_codec *codec, int mask)
+{
+ const int sbuf[][2] = {
+ { AIC3XXX_ABUF_MDSP_A, AIC3262_ADC_ADAPTIVE_CRAM_REG },
+ { AIC3XXX_ABUF_MDSP_D1, AIC3262_DAC_ADAPTIVE_BANK1_REG },
+ { AIC3XXX_ABUF_MDSP_D2, AIC3262_DAC_ADAPTIVE_BANK2_REG },
+ };
+ int i;
+
+ for (i = 0; i < sizeof(sbuf)/sizeof(sbuf[0]); ++i) {
+ if (!(mask & sbuf[i][0]))
+ continue;
+ aic3xxx_set_bits(codec->control_data, sbuf[i][1], 0x1, 0x1);
+ if (!aic3xxx_wait_bits(codec->control_data,
+ sbuf[i][1], 0x1, 0, 15, 1))
+ goto err;
+ }
+ return 0;
+err:
+ dev_err(codec->dev, "miniDSP buffer swap failure at [%s:%d]",
+ __FILE__, __LINE__);
+ return -EINVAL;
+}
+
+/**
+ * get_runstate: To read the current state of the dac's and adc's
+ * @ps: pointer argument to the codec
+ *
+ * Return Value : returning the runstate
+ */
+static int aic3262_get_runstate(struct snd_soc_codec *codec)
+{
+ unsigned int dac, adc;
+ /* Read the run state */
+ dac = aic3xxx_reg_read(codec->control_data, AIC3262_DAC_FLAG);
+ adc = aic3xxx_reg_read(codec->control_data, AIC3262_ADC_FLAG);
+
+ return (((adc>>6)&1)<<5) |
+ (((adc>>2)&1)<<4) |
+ (((dac>>7)&1)<<1) |
+ (((dac>>3)&1)<<0);
+}
+
+/**
+ * aic3262_dsp_pwrdwn_status: To read the status of dsp's
+ * @pv: pointer argument to the codec , cur_state of dac's and adc's
+ *
+ * Return Value : integer returning 0
+ */
+static int aic3262_dsp_pwrdwn_status(struct snd_soc_codec *codec)
+{
+
+ aic3xxx_set_bits(codec->control_data,
+ AIC3262_ADC_DATAPATH_SETUP, 0XC0, 0);
+ aic3xxx_set_bits(codec->control_data,
+ AIC3262_DAC_DATAPATH_SETUP, 0XC0, 0);
+
+ if (!aic3xxx_wait_bits(codec->control_data, AIC3262_ADC_FLAG,
+ AIC3262_ADC_POWER_MASK, 0, AIC326X_TIME_DELAY,
+ AIC326X_DELAY_COUNTER))
+ goto err;
+ if (!aic3xxx_wait_bits(codec->control_data, AIC3262_DAC_FLAG,
+ AIC3262_DAC_POWER_MASK, 0, AIC326X_TIME_DELAY,
+ AIC326X_DELAY_COUNTER))
+ goto err;
+
+ return 0;
+err:
+ dev_err(codec->dev, "DAC/ADC Power down timedout at [%s:%d]",
+ __FILE__, __LINE__);
+ return -EINVAL;
+}
+static int aic3262_dsp_pwrup(struct snd_soc_codec *codec, int state)
+{
+ int adc_reg_mask = 0;
+ int adc_power_mask = 0;
+ int dac_reg_mask = 0;
+ int dac_power_mask = 0;
+ int ret_wbits;
+
+ if (state & AIC3XXX_COPS_MDSP_A_L) {
+ adc_reg_mask |= 0x80;
+ adc_power_mask |= AIC3262_LADC_POWER_MASK;
+ }
+ if (state & AIC3XXX_COPS_MDSP_A_R) {
+ adc_reg_mask |= 0x40;
+ adc_power_mask |= AIC3262_RADC_POWER_MASK;
+ }
+
+ if (state & AIC3XXX_COPS_MDSP_A)
+ aic3xxx_set_bits(codec->control_data,
+ AIC3262_ADC_DATAPATH_SETUP, 0XC0,
+ adc_reg_mask);
+
+ if (state & AIC3XXX_COPS_MDSP_D_L) {
+ dac_reg_mask |= 0x80;
+ dac_power_mask |= AIC3262_LDAC_POWER_STATUS_MASK;
+ }
+ if (state & AIC3XXX_COPS_MDSP_D_R) {
+ dac_reg_mask |= 0x40;
+ dac_power_mask |= AIC3262_RDAC_POWER_STATUS_MASK;
+ }
+
+ if (state & AIC3XXX_COPS_MDSP_D)
+ aic3xxx_set_bits(codec->control_data,
+ AIC3262_DAC_DATAPATH_SETUP, 0XC0,
+ dac_reg_mask);
+
+ if (state & AIC3XXX_COPS_MDSP_A) {
+ ret_wbits = aic3xxx_wait_bits(codec->control_data,
+ AIC3262_ADC_FLAG, AIC3262_ADC_POWER_MASK,
+ adc_power_mask, AIC326X_TIME_DELAY,
+ AIC326X_DELAY_COUNTER);
+ if (!ret_wbits)
+ dev_err(codec->dev, "ADC Power down timedout\n");
+ }
+
+ if (state & AIC3XXX_COPS_MDSP_D) {
+ ret_wbits = aic3xxx_wait_bits(codec->control_data,
+ AIC3262_DAC_FLAG, AIC3262_DAC_POWER_MASK,
+ dac_power_mask, AIC326X_TIME_DELAY,
+ AIC326X_DELAY_COUNTER);
+ if (!ret_wbits)
+ dev_err(codec->dev, "ADC Power down timedout\n");
+ }
+
+ return 0;
+}
+
+static int aic3262_restart_dsps_sync(struct snd_soc_codec *codec, int run_state)
+{
+
+ aic3262_dsp_pwrdwn_status(codec);
+ aic3262_dsp_pwrup(codec, run_state);
+
+ return 0;
+}
+
+static const struct aic3xxx_codec_ops aic3262_cfw_codec_ops = {
+ .reg_read = aic3262_ops_reg_read,
+ .reg_write = aic3262_ops_reg_write,
+ .set_bits = aic3262_ops_set_bits,
+ .bulk_read = aic3262_ops_bulk_read,
+ .bulk_write = aic3262_ops_bulk_write,
+ .lock = aic3262_ops_lock,
+ .unlock = aic3262_ops_unlock,
+ .stop = aic3262_ops_stop,
+ .restore = aic3262_ops_restore,
+ .bswap = aic3262_ops_adaptivebuffer_swap,
+};
+
+
+/**
* aic3262_codec_read: provide read api to read aic3262 registe space
* @codec: pointer variable to codec having codec information,
* @reg: register address,
@@ -1721,11 +2031,11 @@ unsigned int aic3262_codec_read(struct snd_soc_codec *codec, unsigned int reg)
u8 value;
- union aic326x_reg_union *aic_reg = (union aic326x_reg_union *) &reg;
- value = aic3262_reg_read(codec->control_data, reg);
+ union aic3xxx_reg_union *aic_reg = (union aic3xxx_reg_union *) &reg;
+ value = aic3xxx_reg_read(codec->control_data, reg);
dev_dbg(codec->dev, "p %d , r 30 %x %x\n",
- aic_reg->aic326x_register.page,
- aic_reg->aic326x_register.offset, value);
+ aic_reg->aic3xxx_register.page,
+ aic_reg->aic3xxx_register.offset, value);
return value;
}
@@ -1740,40 +2050,11 @@ unsigned int aic3262_codec_read(struct snd_soc_codec *codec, unsigned int reg)
int aic3262_codec_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
- union aic326x_reg_union *aic_reg = (union aic326x_reg_union *) &reg;
+ union aic3xxx_reg_union *aic_reg = (union aic3xxx_reg_union *) &reg;
dev_dbg(codec->dev, "p %d, w 30 %x %x\n",
- aic_reg->aic326x_register.page,
- aic_reg->aic326x_register.offset, value);
- return aic3262_reg_write(codec->control_data, reg, value);
-}
-
-/**
- * aic3262_add_widget: This function is to add the dapm widgets
- * The following are the main widgets supported
- * # Left DAC to Left Outputs
- * # Right DAC to Right Outputs
- * # Left Inputs to Left ADC
- * # Right Inputs to Right ADC
- * @codec: pointer variable to codec having informaton related to codec,
- *
- * Return: return 0 on success.
- */
-static int aic3262_add_widgets(struct snd_soc_codec *codec)
-{
-
- snd_soc_dapm_new_controls(&codec->dapm, aic3262_dapm_widgets,
- ARRAY_SIZE(aic3262_dapm_widgets));
- /* set up audio path interconnects */
- dev_dbg(codec->dev, "#Completed adding new dapm widget"
- " controls size=%d\n", ARRAY_SIZE(aic3262_dapm_widgets));
-
- snd_soc_dapm_add_routes(&codec->dapm, aic3262_dapm_routes,
- ARRAY_SIZE(aic3262_dapm_routes));
- dev_dbg(codec->dev, "#Completed adding DAPM routes\n");
- snd_soc_dapm_new_widgets(&codec->dapm);
- dev_dbg(codec->dev, "#Completed updating dapm\n");
-
- return 0;
+ aic_reg->aic3xxx_register.page,
+ aic_reg->aic3xxx_register.offset, value);
+ return aic3xxx_reg_write(codec->control_data, reg, value);
}
/**
@@ -1785,7 +2066,7 @@ static int aic3262_add_widgets(struct snd_soc_codec *codec)
* Return: On success return 0.
*/
static int aic3262_set_interface_fmt(struct snd_soc_dai *dai, unsigned int fmt,
- unsigned int channel)
+ unsigned int channel)
{
int aif_interface_reg;
int aif_bclk_offset_reg;
@@ -1816,19 +2097,14 @@ static int aic3262_set_interface_fmt(struct snd_soc_dai *dai, unsigned int fmt,
iface_val = 0;
break;
case SND_SOC_DAIFMT_DSP_A:
- dsp_a_val = 0x1; /* Intentionally falling back
- to following case */
+ dsp_a_val = 0x1; /* Intentionally falling through */
case SND_SOC_DAIFMT_DSP_B:
- switch (channel) {
- case 1:
+ if (channel == 1)
iface_val = 0x80; /* Choose mono PCM */
- break;
- case 2:
- iface_val = 0x20;
- break;
- default:
+ else if (channel <= 8)
+ iface_val = 0x20; /* choose multichannel PCM */
+ else
return -EINVAL;
- }
break;
case SND_SOC_DAIFMT_RIGHT_J:
iface_val = 0x40;
@@ -1841,9 +2117,9 @@ static int aic3262_set_interface_fmt(struct snd_soc_dai *dai, unsigned int fmt,
return -EINVAL;
}
snd_soc_update_bits(codec, aif_interface_reg,
- AIC3262_ASI_INTERFACE_MASK, iface_val);
+ AIC3262_ASI_INTERFACE_MASK, iface_val);
snd_soc_update_bits(codec, aif_bclk_offset_reg,
- AIC3262_BCLK_OFFSET_MASK, dsp_a_val);
+ AIC3262_BCLK_OFFSET_MASK, dsp_a_val);
return 0;
}
@@ -1860,13 +2136,15 @@ static int aic3262_set_interface_fmt(struct snd_soc_dai *dai, unsigned int fmt,
* Return: Return 0 on success.
*/
int aic3262_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec;
struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
- int asi_reg;
- u8 data = 0;
+ int asi_reg, ret = 0;
+ u8 data = 0, value = 0, val = 0, wclk_div = 0, bclk_div = 0;
+ unsigned int channels = params_channels(params);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
aic3262->stream_status = 1;
@@ -1902,11 +2180,52 @@ int aic3262_hw_params(struct snd_pcm_substream *substream,
break;
}
+ /* Configure TDM for multi chennels */
+ switch (channels) {
+ case 4:
+ value = value | 0x40;
+ bclk_div = 0x03;
+ wclk_div = 0x40;
+ break;
+ case 6:
+ bclk_div = 0x02;
+ wclk_div = 0x60;
+ value = value | 0x80;
+ break;
+ case 8:
+ bclk_div = 0x01;
+ wclk_div = 0x00;
+ value = value | 0xC0;
+ break;
+ default:
+ bclk_div = 0x04;
+ wclk_div = 0x20;
+ }
+
+ snd_soc_update_bits(codec, AIC3262_ASI1_CHNL_SETUP,
+ AIC3262_ASI1_CHNL_MASK, value);
+
+ snd_soc_update_bits(codec, AIC3262_ASI1_BCLK_N,
+ AIC3262_ASI1_BCLK_N_MASK, bclk_div);
+
+ snd_soc_update_bits(codec, AIC3262_ASI1_WCLK_N,
+ AIC3262_ASI1_WCLK_N_MASK, wclk_div);
+
+
+ val = snd_soc_read(codec, AIC3262_ASI1_BUS_FMT);
+ val = snd_soc_read(codec, AIC3262_ASI1_CHNL_SETUP);
+
/* configure the respective Registers for the above configuration */
snd_soc_update_bits(codec, asi_reg,
AIC3262_ASI_DATA_WORD_LENGTH_MASK, data);
- return aic3262_set_interface_fmt(dai, aic3262->asi_fmt[dai->id],
- params_channels(params));
+ ret = aic3262_set_interface_fmt(dai, aic3262->asi_fmt[dai->id],
+ channels);
+ if (ret < 0) {
+ dev_err(codec->dev, "failed to set hardware params for AIC3262\n");
+ return ret;
+ }
+
+ return 0;
}
/**
@@ -1947,50 +2266,6 @@ static int aic3262_mute(struct snd_soc_dai *dai, int mute)
return 0;
}
-/**
- * aic3262_set_dai_sysclk: This function is to set the DAI system clock
- * @codec_dai: ponter to dai Holds runtime data for a DAI,
- * @freq: system clock to be set,
- * @dir: integer dir,
- *
- * Return: return 0 on success.
- */
-static int aic3262_set_dai_sysclk(struct snd_soc_dai *codec_dai,
- int clk_id, unsigned int freq, int dir)
-{
- struct aic3262_priv *aic3262;
- struct snd_soc_codec *codec;
-
- codec = codec_dai->codec;
- aic3262 = snd_soc_codec_get_drvdata(codec);
- switch (freq) {
- case AIC3262_FREQ_12000000:
- aic3262->sysclk = freq;
- return 0;
- case AIC3262_FREQ_24000000:
- aic3262->sysclk = freq;
- return 0;
- break;
- case AIC3262_FREQ_19200000:
- aic3262->sysclk = freq;
- return 0;
- break;
- case AIC3262_FREQ_38400000:
- aic3262->sysclk = freq;
- dev_dbg(codec->dev, "codec: sysclk = %d\n", aic3262->sysclk);
- return 0;
- break;
- case AIC3262_FREQ_12288000:
- aic3262->sysclk = freq;
- dev_dbg(codec->dev, "codec: sysclk = %d\n", aic3262->sysclk);
- return 0;
- break;
-
- }
- dev_err(codec->dev, "Invalid frequency to set DAI system clock\n");
-
- return -EINVAL;
-}
/**
* aic3262_set_dai_fmt: This function is to set the DAI format
@@ -2035,7 +2310,7 @@ static int aic3262_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
case SND_SOC_DAIFMT_CBS_CFS:
aic3262->master = 0;
break;
- case SND_SOC_DAIFMT_CBS_CFM: /* new case..just for debugging */
+ case SND_SOC_DAIFMT_CBS_CFM: /* new case..for debug purpose */
master |= (AIC3262_WCLK_OUT_MASK);
aic3262->master = 0;
break;
@@ -2108,6 +2383,7 @@ static int aic3262_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
/* TODO: How to select low/high clock range? */
aic3xxx_cfw_set_pll(aic3262->cfw_p, dai->id);
+
return 0;
}
@@ -2144,6 +2420,7 @@ static int aic3262_set_bias_level(struct snd_soc_codec *codec,
*/
dev_dbg(codec->dev, "set_bias_stby\n");
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ pm_runtime_get_sync(codec->dev);
snd_soc_update_bits(codec, AIC3262_POWER_CONF,
(AIC3262_AVDD_TO_DVDD_MASK |
AIC3262_EXT_ANALOG_SUPPLY_MASK),
@@ -2152,21 +2429,26 @@ static int aic3262_set_bias_level(struct snd_soc_codec *codec,
AIC3262_CHIP_REF_PWR_ON_MASK,
AIC3262_CHIP_REF_PWR_ON);
mdelay(40);
- }
+ snd_soc_update_bits(codec, AIC3262_CHARGE_PUMP_CNTL,
+ AIC3262_DYNAMIC_OFFSET_CALIB_MASK,
+ AIC3262_DYNAMIC_OFFSET_CALIB);
+ }
break;
/* Off, without power */
case SND_SOC_BIAS_OFF:
dev_dbg(codec->dev, "set_bias_off\n");
+ /* force all power off */
if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
snd_soc_update_bits(codec, AIC3262_REF_PWR_DLY,
- AIC3262_CHIP_REF_PWR_ON_MASK, 0x0);
+ AIC3262_CHIP_REF_PWR_ON_MASK, 0x0);
snd_soc_update_bits(codec, AIC3262_POWER_CONF,
- (AIC3262_AVDD_TO_DVDD_MASK |
- AIC3262_EXT_ANALOG_SUPPLY_MASK),
- (AIC3262_AVDD_TO_DVDD |
- AIC3262_EXT_ANALOG_SUPPLY_OFF));
+ (AIC3262_AVDD_TO_DVDD_MASK |
+ AIC3262_EXT_ANALOG_SUPPLY_MASK),
+ (AIC3262_AVDD_TO_DVDD |
+ AIC3262_EXT_ANALOG_SUPPLY_OFF));
+ pm_runtime_put(codec->dev);
}
break;
}
@@ -2175,25 +2457,25 @@ static int aic3262_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-/*
- *----------------------------------------------------------------------------
- * Function : aic3262_suspend
- * Purpose : This function is to suspend the AIC3262 driver.
+/**
*
- *----------------------------------------------------------------------------
+ * aic3262_suspend; This function is to suspend the AIC3262 driver.
+ * @codec: pointer variable to codec having informaton related to codec,
+ *
+ * Return: Return 0 on success.
*/
-static int aic3262_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int aic3262_suspend(struct snd_soc_codec *codec)
{
aic3262_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-/*
- *----------------------------------------------------------------------------
- * Function : aic3262_resume
- * Purpose : This function is to resume the AIC3262 driver
+/**
+ * aic3262_resume: This function is to resume the AIC3262 driver
+ * from off state to standby
+ * @codec: pointer variable to codec having informaton related to codec,
*
- *----------------------------------------------------------------------------
+ * Return: Return 0 on success.
*/
static int aic3262_resume(struct snd_soc_codec *codec)
{
@@ -2202,20 +2484,17 @@ static int aic3262_resume(struct snd_soc_codec *codec)
return 0;
}
-/*
- *----------------------------------------------------------------------------
- * Function : aic3262_probe
- * Purpose : This is first driver function called by the SoC core driver.
+/**
+ * aic3262_probe: This is first driver function called by the SoC core driver.
+ * @codec: pointer variable to codec having informaton related to codec,
*
- *----------------------------------------------------------------------------
+ * Return: Return 0 on success.
*/
static int aic3262_codec_probe(struct snd_soc_codec *codec)
{
int ret = 0;
- int ret_btn = 0;
- struct aic3262 *control;
+ struct aic3xxx *control;
struct aic3262_priv *aic3262;
- struct aic3262_jack_data *jack;
if (codec == NULL)
dev_err(codec->dev, "codec pointer is NULL.\n");
@@ -2230,56 +2509,37 @@ static int aic3262_codec_probe(struct snd_soc_codec *codec)
aic3262->pdata = dev_get_platdata(codec->dev->parent);
aic3262->codec = codec;
aic3262->cur_fw = NULL;
- aic3262->isdefault_fw = 0;
aic3262->cfw_p = &(aic3262->cfw_ps);
- aic3xxx_cfw_init(aic3262->cfw_p, &aic3262_cfw_codec_ops, aic3262);
+ aic3xxx_cfw_init(aic3262->cfw_p, &aic3262_cfw_codec_ops,
+ aic3262->codec);
aic3262->workqueue = create_singlethread_workqueue("aic3262-codec");
if (!aic3262->workqueue) {
ret = -ENOMEM;
goto work_err;
}
- ret = device_create_file(codec->dev, &dev_attr_debug_level);
- if (ret)
- dev_info(codec->dev, "Failed to add debug_level sysfs\n");
INIT_DELAYED_WORK(&aic3262->delayed_work, aic3262_accessory_work);
mutex_init(&aic3262->mutex);
mutex_init(&codec->mutex);
mutex_init(&aic3262->cfw_mutex);
- aic3262->dsp_runstate = 0;
- /* use switch-class based headset reporting if platform requires it */
- jack = &aic3262->hs_jack;
- aic3262->idev = input_allocate_device();
- if (aic3262->idev <= 0)
- printk(KERN_ERR, "Allocate failed\n");
-
- input_set_capability(aic3262->idev, EV_KEY, KEY_MEDIA);
- ret = input_register_device(aic3262->idev);
- if (ret < 0) {
- dev_err(codec->dev, "register input dev fail\n");
- goto input_dev_err;
- }
+ pm_runtime_enable(codec->dev);
+ pm_runtime_resume(codec->dev);
+ aic3262->dsp_runstate = 0;
if (control->irq) {
- ret = aic3262_request_irq(codec->control_data,
- AIC3262_IRQ_HEADSET_DETECT,
- aic3262_audio_handler, 0,
- "aic3262_irq_headset", codec);
+ ret = aic3xxx_request_irq(codec->control_data,
+ AIC3262_IRQ_HEADSET_DETECT,
+ aic3262_audio_handler,
+ IRQF_NO_SUSPEND,
+ "aic3262_irq_headset", codec);
- if (ret) {
+ if (ret) {
dev_err(codec->dev, "HEADSET detect irq request"
"failed: %d\n", ret);
goto irq_err;
- }
-
- ret = aic3262_request_irq(codec->control_data,
- AIC3262_IRQ_BUTTON_PRESS,
- aic3262_button_handler, 0, "aic3262_irq_button",
- codec);
-
- if (ret) {
- dev_err(codec->dev, "button press irq request"
- "failed: %d\n", ret);
- goto irq_err;
+ } else {
+ /* Dynamic Headset Detection Enabled */
+ snd_soc_update_bits(codec, AIC3262_HP_DETECT,
+ AIC3262_HEADSET_IN_MASK, AIC3262_HEADSET_IN_MASK);
}
}
/* Keep the reference voltage ON while in$
@@ -2289,74 +2549,63 @@ static int aic3262_codec_probe(struct snd_soc_codec *codec)
AIC3262_CHIP_REF_PWR_ON_MASK,
AIC3262_CHIP_REF_PWR_ON);
mdelay(40);
- aic3262_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- ret = snd_soc_add_codec_controls(codec, aic3262_snd_controls,
- ARRAY_SIZE(aic3262_snd_controls));
- if(ret)
- {
- printk(KERN_INFO "%s failed\n", __func__);
- }
+ snd_soc_update_bits(codec, AIC3262_CHARGE_PUMP_CNTL,
+ AIC3262_DYNAMIC_OFFSET_CALIB_MASK,
+ AIC3262_DYNAMIC_OFFSET_CALIB);
- aic3262->mute_asi = 0;
+ aic3262_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- aic3262_add_widgets(codec);
+ aic3262->mute_asi = 0;
-#ifdef AIC3262_TiLoad
- ret = aic3262_driver_init(codec);
- if (ret < 0)
- dev_err(codec->dev, "\nTiLoad Initialization failed\n");
-#endif
- /* force loading the default firmware */
- aic3262_firmware_load(NULL, codec);
- request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+ ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
"tlv320aic3262_fw_v1.bin", codec->dev,
GFP_KERNEL, codec, aic3262_firmware_load);
+ if (ret < 0) {
+ dev_err(codec->dev, "Firmware request failed\n");
+ goto firm_err;
+ }
return 0;
+firm_err:
+ aic3xxx_free_irq(control,
+ AIC3262_IRQ_HEADSET_DETECT, codec);
irq_err:
- input_unregister_device(aic3262->idev);
- input_free_device(aic3262->idev);
-input_dev_err:
-reg_err:
+ destroy_workqueue(aic3262->workqueue);
work_err:
kfree(aic3262);
return 0;
}
/*
-* aic3262_remove: Cleans up and Remove aic3262 soc device
-* @codec: pointer variable to codec having informaton related to codec,
-*
-* Return: Return 0 on success.
-*/
+ * aic3262_remove: Cleans up and Remove aic3262 soc device
+ * @codec: pointer variable to codec having informaton related to codec,
+ *
+ * Return: Return 0 on success.
+ */
static int aic3262_codec_remove(struct snd_soc_codec *codec)
{
/* power down chip */
struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
- struct aic3262 *control = codec->control_data;
- struct aic3262_jack_data *jack = &aic3262->hs_jack;
+ struct aic3xxx *control = codec->control_data;
aic3262_set_bias_level(codec, SND_SOC_BIAS_OFF);
/* free_irq if any */
switch (control->type) {
case TLV320AIC3262:
- if (control->irq) {
- aic3262_free_irq(control, AIC3262_IRQ_HEADSET_DETECT,
- codec);
- aic3262_free_irq(control, AIC3262_IRQ_BUTTON_PRESS,
- codec);
- }
+ if (control->irq)
+ aic3xxx_free_irq(control,
+ AIC3262_IRQ_HEADSET_DETECT, codec);
break;
+ default:
+ dev_info(codec->dev, "Coded is not TLV320AIC3262\n");
}
/* release firmware if any */
if (aic3262->cur_fw != NULL)
release_firmware(aic3262->cur_fw);
/* destroy workqueue for jac dev */
destroy_workqueue(aic3262->workqueue);
- input_unregister_device(aic3262->idev);
- input_free_device(aic3262->idev);
kfree(aic3262);
@@ -2370,6 +2619,12 @@ static struct snd_soc_codec_driver soc_codec_driver_aic326x = {
.resume = aic3262_resume,
.read = aic3262_codec_read,
.write = aic3262_codec_write,
+ .controls = aic3262_snd_controls,
+ .num_controls = ARRAY_SIZE(aic3262_snd_controls),
+ .dapm_widgets = aic3262_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(aic3262_dapm_widgets),
+ .dapm_routes = aic3262_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(aic3262_dapm_routes),
.set_bias_level = aic3262_set_bias_level,
.reg_cache_size = 0,
.reg_word_size = sizeof(u8),
@@ -2390,42 +2645,31 @@ static int aic326x_remove(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id aic3262_of_match[] = {
+ { .compatible = "ti,aic3262", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, aic3262_of_match);
+
+static const struct platform_device_id aic3262_i2c_id[] = {
+ { "tlv320aic3262-codec", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, aic3262_i2c_id);
+
static struct platform_driver aic326x_codec_driver = {
.driver = {
- .name = "tlv320aic3262-codec",
- .owner = THIS_MODULE,
- },
+ .name = "tlv320aic3262-codec",
+ .owner = THIS_MODULE,
+ .of_match_table = aic3262_of_match,
+ },
.probe = aic326x_probe,
.remove = aic326x_remove,
+ .id_table = aic3262_i2c_id,
};
-/*
-*----------------------------------------------------------------------------
-* Function : tlv320aic3262_modinit
-* Purpose : module init function. First function to run.
-*
-*----------------------------------------------------------------------------
-*/
-static int __init tlv320aic3262_modinit(void)
-{
- return platform_driver_register(&aic326x_codec_driver);
-}
-module_init(tlv320aic3262_modinit);
-
-/*
-*----------------------------------------------------------------------------
-* Function : tlv320aic3262_exit
-* Purpose : module init function. First function to run.
-*
-*----------------------------------------------------------------------------
-*/
-static void __exit tlv320aic3262_exit(void)
-{
- platform_driver_unregister(&aic326x_codec_driver);
-
-}
+module_platform_driver(aic326x_codec_driver);
-module_exit(tlv320aic3262_exit);
MODULE_ALIAS("platform:tlv320aic3262-codec");
MODULE_DESCRIPTION("ASoC TLV320AIC3262 codec driver");
MODULE_AUTHOR("Y Preetam Sashank Reddy ");