forked from Minki/linux
Merge remote-tracking branches 'asoc/topic/88pm860x', 'asoc/topic/ac97', 'asoc/topic/ak4542', 'asoc/topic/arizona' and 'asoc/topic/atmel' into asoc-next
This commit is contained in:
commit
21af109438
@ -584,6 +584,8 @@ static inline int snd_ac97_update_power(struct snd_ac97 *ac97, int reg,
|
||||
void snd_ac97_suspend(struct snd_ac97 *ac97);
|
||||
void snd_ac97_resume(struct snd_ac97 *ac97);
|
||||
#endif
|
||||
int snd_ac97_reset(struct snd_ac97 *ac97, bool try_warm, unsigned int id,
|
||||
unsigned int id_mask);
|
||||
|
||||
/* quirk types */
|
||||
enum {
|
||||
|
@ -526,7 +526,8 @@ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg,
|
||||
|
||||
#ifdef CONFIG_SND_SOC_AC97_BUS
|
||||
struct snd_ac97 *snd_soc_alloc_ac97_codec(struct snd_soc_codec *codec);
|
||||
struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec);
|
||||
struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
|
||||
unsigned int id, unsigned int id_mask);
|
||||
void snd_soc_free_ac97_codec(struct snd_ac97 *ac97);
|
||||
|
||||
int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops);
|
||||
|
@ -17,6 +17,68 @@
|
||||
#include <linux/string.h>
|
||||
#include <sound/ac97_codec.h>
|
||||
|
||||
/*
|
||||
* snd_ac97_check_id() - Reads and checks the vendor ID of the device
|
||||
* @ac97: The AC97 device to check
|
||||
* @id: The ID to compare to
|
||||
* @id_mask: Mask that is applied to the device ID before comparing to @id
|
||||
*
|
||||
* If @id is 0 this function returns true if the read device vendor ID is
|
||||
* a valid ID. If @id is non 0 this functions returns true if @id
|
||||
* matches the read vendor ID. Otherwise the function returns false.
|
||||
*/
|
||||
static bool snd_ac97_check_id(struct snd_ac97 *ac97, unsigned int id,
|
||||
unsigned int id_mask)
|
||||
{
|
||||
ac97->id = ac97->bus->ops->read(ac97, AC97_VENDOR_ID1) << 16;
|
||||
ac97->id |= ac97->bus->ops->read(ac97, AC97_VENDOR_ID2);
|
||||
|
||||
if (ac97->id == 0x0 || ac97->id == 0xffffffff)
|
||||
return false;
|
||||
|
||||
if (id != 0 && id != (ac97->id & id_mask))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_ac97_reset() - Reset AC'97 device
|
||||
* @ac97: The AC'97 device to reset
|
||||
* @try_warm: Try a warm reset first
|
||||
* @id: Expected device vendor ID
|
||||
* @id_mask: Mask that is applied to the device ID before comparing to @id
|
||||
*
|
||||
* This function resets the AC'97 device. If @try_warm is true the function
|
||||
* first performs a warm reset. If the warm reset is successful the function
|
||||
* returns 1. Otherwise or if @try_warm is false the function issues cold reset
|
||||
* followed by a warm reset. If this is successful the function returns 0,
|
||||
* otherwise a negative error code. If @id is 0 any valid device ID will be
|
||||
* accepted, otherwise only the ID that matches @id and @id_mask is accepted.
|
||||
*/
|
||||
int snd_ac97_reset(struct snd_ac97 *ac97, bool try_warm, unsigned int id,
|
||||
unsigned int id_mask)
|
||||
{
|
||||
struct snd_ac97_bus_ops *ops = ac97->bus->ops;
|
||||
|
||||
if (try_warm && ops->warm_reset) {
|
||||
ops->warm_reset(ac97);
|
||||
if (snd_ac97_check_id(ac97, id, id_mask))
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ops->reset)
|
||||
ops->reset(ac97);
|
||||
if (ops->warm_reset)
|
||||
ops->warm_reset(ac97);
|
||||
|
||||
if (snd_ac97_check_id(ac97, id, id_mask))
|
||||
return 0;
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_ac97_reset);
|
||||
|
||||
/*
|
||||
* Let drivers decide whether they want to support given codec from their
|
||||
* probe method. Drivers have direct access to the struct snd_ac97
|
||||
|
@ -290,7 +290,7 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
|
||||
int dir, dir_mask;
|
||||
int ret;
|
||||
|
||||
pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n",
|
||||
pr_debug("atmel_ssc_startup: SSC_SR=0x%x\n",
|
||||
ssc_readl(ssc_p->ssc->regs, SR));
|
||||
|
||||
/* Enable PMC peripheral clock for this SSC */
|
||||
|
@ -1028,10 +1028,8 @@ static int pm860x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
|
||||
|
||||
if (dir == PM860X_CLK_DIR_OUT)
|
||||
pm860x->dir = PM860X_CLK_DIR_OUT;
|
||||
else {
|
||||
pm860x->dir = PM860X_CLK_DIR_IN;
|
||||
else /* Slave mode is not supported */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -202,19 +202,21 @@ static struct snd_soc_dai_driver ad1980_dai = {
|
||||
.formats = SND_SOC_STD_AC97_FMTS, },
|
||||
};
|
||||
|
||||
#define AD1980_VENDOR_ID 0x41445300
|
||||
#define AD1980_VENDOR_MASK 0xffffff00
|
||||
|
||||
static int ad1980_reset(struct snd_soc_codec *codec, int try_warm)
|
||||
{
|
||||
struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
|
||||
unsigned int retry_cnt = 0;
|
||||
int ret;
|
||||
|
||||
do {
|
||||
if (try_warm && soc_ac97_ops->warm_reset) {
|
||||
soc_ac97_ops->warm_reset(ac97);
|
||||
if (snd_soc_read(codec, AC97_RESET) == 0x0090)
|
||||
return 1;
|
||||
}
|
||||
ret = snd_ac97_reset(ac97, true, AD1980_VENDOR_ID,
|
||||
AD1980_VENDOR_MASK);
|
||||
if (ret >= 0)
|
||||
return 0;
|
||||
|
||||
soc_ac97_ops->reset(ac97);
|
||||
/*
|
||||
* Set bit 16slot in register 74h, then every slot will has only
|
||||
* 16 bits. This command is sent out in 20bit mode, in which
|
||||
@ -223,8 +225,6 @@ static int ad1980_reset(struct snd_soc_codec *codec, int try_warm)
|
||||
*/
|
||||
snd_soc_write(codec, AC97_AD_SERIAL_CFG, 0x9900);
|
||||
|
||||
if (snd_soc_read(codec, AC97_RESET) == 0x0090)
|
||||
return 0;
|
||||
} while (retry_cnt++ < 10);
|
||||
|
||||
dev_err(codec->dev, "Failed to reset: AC97 link error\n");
|
||||
@ -240,7 +240,7 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec)
|
||||
u16 vendor_id2;
|
||||
u16 ext_status;
|
||||
|
||||
ac97 = snd_soc_new_ac97_codec(codec);
|
||||
ac97 = snd_soc_new_ac97_codec(codec, 0, 0);
|
||||
if (IS_ERR(ac97)) {
|
||||
ret = PTR_ERR(ac97);
|
||||
dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret);
|
||||
@ -260,22 +260,10 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec)
|
||||
if (ret < 0)
|
||||
goto reset_err;
|
||||
|
||||
/* Read out vendor ID to make sure it is ad1980 */
|
||||
if (snd_soc_read(codec, AC97_VENDOR_ID1) != 0x4144) {
|
||||
ret = -ENODEV;
|
||||
goto reset_err;
|
||||
}
|
||||
|
||||
vendor_id2 = snd_soc_read(codec, AC97_VENDOR_ID2);
|
||||
|
||||
if (vendor_id2 != 0x5370) {
|
||||
if (vendor_id2 != 0x5374) {
|
||||
ret = -ENODEV;
|
||||
goto reset_err;
|
||||
} else {
|
||||
dev_warn(codec->dev,
|
||||
"Found AD1981 - only 2/2 IN/OUT Channels supported\n");
|
||||
}
|
||||
if (vendor_id2 == 0x5374) {
|
||||
dev_warn(codec->dev,
|
||||
"Found AD1981 - only 2/2 IN/OUT Channels supported\n");
|
||||
}
|
||||
|
||||
/* unmute captures and playbacks volume */
|
||||
|
@ -64,12 +64,15 @@
|
||||
#define FIL1_0 0x1c
|
||||
#define FIL1_1 0x1d
|
||||
#define FIL1_2 0x1e
|
||||
#define FIL1_3 0x1f
|
||||
#define FIL1_3 0x1f /* The maximum valid register for ak4642 */
|
||||
#define PW_MGMT4 0x20
|
||||
#define MD_CTL5 0x21
|
||||
#define LO_MS 0x22
|
||||
#define HP_MS 0x23
|
||||
#define SPK_MS 0x24
|
||||
#define SPK_MS 0x24 /* The maximum valid register for ak4643 */
|
||||
#define EQ_FBEQAB 0x25
|
||||
#define EQ_FBEQCD 0x26
|
||||
#define EQ_FBEQE 0x27 /* The maximum valid register for ak4648 */
|
||||
|
||||
/* PW_MGMT1*/
|
||||
#define PMVCM (1 << 6) /* VCOM Power Management */
|
||||
@ -241,7 +244,7 @@ static const struct snd_soc_dapm_route ak4642_intercon[] = {
|
||||
/*
|
||||
* ak4642 register cache
|
||||
*/
|
||||
static const struct reg_default ak4642_reg[] = {
|
||||
static const struct reg_default ak4643_reg[] = {
|
||||
{ 0, 0x00 }, { 1, 0x00 }, { 2, 0x01 }, { 3, 0x00 },
|
||||
{ 4, 0x02 }, { 5, 0x00 }, { 6, 0x00 }, { 7, 0x00 },
|
||||
{ 8, 0xe1 }, { 9, 0xe1 }, { 10, 0x18 }, { 11, 0x00 },
|
||||
@ -254,6 +257,14 @@ static const struct reg_default ak4642_reg[] = {
|
||||
{ 36, 0x00 },
|
||||
};
|
||||
|
||||
/* The default settings for 0x0 ~ 0x1f registers are the same for ak4642
|
||||
and ak4643. So we reuse the ak4643 reg_default for ak4642.
|
||||
The valid registers for ak4642 are 0x0 ~ 0x1f which is a subset of ak4643,
|
||||
so define NUM_AK4642_REG_DEFAULTS for ak4642.
|
||||
*/
|
||||
#define ak4642_reg ak4643_reg
|
||||
#define NUM_AK4642_REG_DEFAULTS (FIL1_3 + 1)
|
||||
|
||||
static const struct reg_default ak4648_reg[] = {
|
||||
{ 0, 0x00 }, { 1, 0x00 }, { 2, 0x01 }, { 3, 0x00 },
|
||||
{ 4, 0x02 }, { 5, 0x00 }, { 6, 0x00 }, { 7, 0x00 },
|
||||
@ -535,15 +546,23 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4642 = {
|
||||
static const struct regmap_config ak4642_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = ARRAY_SIZE(ak4642_reg) + 1,
|
||||
.max_register = FIL1_3,
|
||||
.reg_defaults = ak4642_reg,
|
||||
.num_reg_defaults = ARRAY_SIZE(ak4642_reg),
|
||||
.num_reg_defaults = NUM_AK4642_REG_DEFAULTS,
|
||||
};
|
||||
|
||||
static const struct regmap_config ak4643_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = SPK_MS,
|
||||
.reg_defaults = ak4643_reg,
|
||||
.num_reg_defaults = ARRAY_SIZE(ak4643_reg),
|
||||
};
|
||||
|
||||
static const struct regmap_config ak4648_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = ARRAY_SIZE(ak4648_reg) + 1,
|
||||
.max_register = EQ_FBEQE,
|
||||
.reg_defaults = ak4648_reg,
|
||||
.num_reg_defaults = ARRAY_SIZE(ak4648_reg),
|
||||
};
|
||||
@ -553,7 +572,7 @@ static const struct ak4642_drvdata ak4642_drvdata = {
|
||||
};
|
||||
|
||||
static const struct ak4642_drvdata ak4643_drvdata = {
|
||||
.regmap_config = &ak4642_regmap,
|
||||
.regmap_config = &ak4643_regmap,
|
||||
};
|
||||
|
||||
static const struct ak4642_drvdata ak4648_drvdata = {
|
||||
|
@ -1504,7 +1504,7 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
|
||||
else
|
||||
rates = &arizona_48k_bclk_rates[0];
|
||||
|
||||
wl = snd_pcm_format_width(params_format(params));
|
||||
wl = params_width(params);
|
||||
|
||||
if (tdm_slots) {
|
||||
arizona_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n",
|
||||
@ -2304,6 +2304,82 @@ const struct snd_kcontrol_new arizona_adsp2_rate_controls[] = {
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(arizona_adsp2_rate_controls);
|
||||
|
||||
static bool arizona_eq_filter_unstable(bool mode, __be16 _a, __be16 _b)
|
||||
{
|
||||
s16 a = be16_to_cpu(_a);
|
||||
s16 b = be16_to_cpu(_b);
|
||||
|
||||
if (!mode) {
|
||||
return abs(a) >= 4096;
|
||||
} else {
|
||||
if (abs(b) >= 4096)
|
||||
return true;
|
||||
|
||||
return (abs((a << 16) / (4096 - b)) >= 4096 << 4);
|
||||
}
|
||||
}
|
||||
|
||||
int arizona_eq_coeff_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
|
||||
struct soc_bytes *params = (void *)kcontrol->private_value;
|
||||
unsigned int val;
|
||||
__be16 *data;
|
||||
int len;
|
||||
int ret;
|
||||
|
||||
len = params->num_regs * regmap_get_val_bytes(arizona->regmap);
|
||||
|
||||
data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data[0] &= cpu_to_be16(ARIZONA_EQ1_B1_MODE);
|
||||
|
||||
if (arizona_eq_filter_unstable(!!data[0], data[1], data[2]) ||
|
||||
arizona_eq_filter_unstable(true, data[4], data[5]) ||
|
||||
arizona_eq_filter_unstable(true, data[8], data[9]) ||
|
||||
arizona_eq_filter_unstable(true, data[12], data[13]) ||
|
||||
arizona_eq_filter_unstable(false, data[16], data[17])) {
|
||||
dev_err(arizona->dev, "Rejecting unstable EQ coefficients\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = regmap_read(arizona->regmap, params->base, &val);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
|
||||
val &= ~ARIZONA_EQ1_B1_MODE;
|
||||
data[0] |= cpu_to_be16(val);
|
||||
|
||||
ret = regmap_raw_write(arizona->regmap, params->base, data, len);
|
||||
|
||||
out:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arizona_eq_coeff_put);
|
||||
|
||||
int arizona_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
|
||||
__be16 *data = (__be16 *)ucontrol->value.bytes.data;
|
||||
s16 val = be16_to_cpu(*data);
|
||||
|
||||
if (abs(val) >= 4096) {
|
||||
dev_err(arizona->dev, "Rejecting unstable LHPF coefficients\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return snd_soc_bytes_put(kcontrol, ucontrol);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arizona_lhpf_coeff_put);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
|
||||
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -194,6 +194,20 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
|
||||
ARIZONA_MIXER_ROUTES(name " Preloader", name "L"), \
|
||||
ARIZONA_MIXER_ROUTES(name " Preloader", name "R")
|
||||
|
||||
#define ARIZONA_EQ_CONTROL(xname, xbase) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \
|
||||
.put = arizona_eq_coeff_put, .private_value = \
|
||||
((unsigned long)&(struct soc_bytes) { .base = xbase, \
|
||||
.num_regs = 20, .mask = ~ARIZONA_EQ1_B1_MODE }) }
|
||||
|
||||
#define ARIZONA_LHPF_CONTROL(xname, xbase) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \
|
||||
.put = arizona_lhpf_coeff_put, .private_value = \
|
||||
((unsigned long)&(struct soc_bytes) { .base = xbase, \
|
||||
.num_regs = 1 }) }
|
||||
|
||||
#define ARIZONA_RATE_ENUM_SIZE 4
|
||||
extern const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE];
|
||||
extern const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE];
|
||||
@ -229,6 +243,11 @@ extern int arizona_hp_ev(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol,
|
||||
int event);
|
||||
|
||||
extern int arizona_eq_coeff_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
extern int arizona_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
|
||||
extern int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
|
||||
int source, unsigned int freq, int dir);
|
||||
|
||||
|
@ -28,6 +28,9 @@
|
||||
|
||||
#include "stac9766.h"
|
||||
|
||||
#define STAC9766_VENDOR_ID 0x83847666
|
||||
#define STAC9766_VENDOR_ID_MASK 0xffffffff
|
||||
|
||||
/*
|
||||
* STAC9766 register cache
|
||||
*/
|
||||
@ -239,45 +242,12 @@ static int stac9766_set_bias_level(struct snd_soc_codec *codec,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stac9766_reset(struct snd_soc_codec *codec, int try_warm)
|
||||
{
|
||||
struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (try_warm && soc_ac97_ops->warm_reset) {
|
||||
soc_ac97_ops->warm_reset(ac97);
|
||||
if (stac9766_ac97_read(codec, 0) == stac9766_reg[0])
|
||||
return 1;
|
||||
}
|
||||
|
||||
soc_ac97_ops->reset(ac97);
|
||||
if (soc_ac97_ops->warm_reset)
|
||||
soc_ac97_ops->warm_reset(ac97);
|
||||
if (stac9766_ac97_read(codec, 0) != stac9766_reg[0])
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stac9766_codec_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
|
||||
u16 id, reset;
|
||||
|
||||
reset = 0;
|
||||
/* give the codec an AC97 warm reset to start the link */
|
||||
reset:
|
||||
if (reset > 5) {
|
||||
dev_err(codec->dev, "Failed to resume\n");
|
||||
return -EIO;
|
||||
}
|
||||
ac97->bus->ops->warm_reset(ac97);
|
||||
id = soc_ac97_ops->read(ac97, AC97_VENDOR_ID2);
|
||||
if (id != 0x4c13) {
|
||||
stac9766_reset(codec, 0);
|
||||
reset++;
|
||||
goto reset;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return snd_ac97_reset(ac97, true, STAC9766_VENDOR_ID,
|
||||
STAC9766_VENDOR_ID_MASK);
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops stac9766_dai_ops_analog = {
|
||||
@ -330,28 +300,15 @@ static struct snd_soc_dai_driver stac9766_dai[] = {
|
||||
static int stac9766_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_ac97 *ac97;
|
||||
int ret = 0;
|
||||
|
||||
ac97 = snd_soc_new_ac97_codec(codec);
|
||||
ac97 = snd_soc_new_ac97_codec(codec, STAC9766_VENDOR_ID,
|
||||
STAC9766_VENDOR_ID_MASK);
|
||||
if (IS_ERR(ac97))
|
||||
return PTR_ERR(ac97);
|
||||
|
||||
snd_soc_codec_set_drvdata(codec, ac97);
|
||||
|
||||
/* do a cold reset for the controller and then try
|
||||
* a warm reset followed by an optional cold reset for codec */
|
||||
stac9766_reset(codec, 0);
|
||||
ret = stac9766_reset(codec, 1);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to reset: AC97 link error\n");
|
||||
goto codec_err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
codec_err:
|
||||
snd_soc_free_ac97_codec(ac97);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stac9766_codec_remove(struct snd_soc_codec *codec)
|
||||
|
@ -788,8 +788,7 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
|
||||
|
||||
SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19),
|
||||
SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0),
|
||||
ARIZONA_EQ_CONTROL("EQ1 Coefficients", ARIZONA_EQ1_2),
|
||||
SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
|
||||
24, 0, eq_tlv),
|
||||
SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
|
||||
@ -801,8 +800,7 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT,
|
||||
SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT,
|
||||
24, 0, eq_tlv),
|
||||
|
||||
SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19),
|
||||
SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0),
|
||||
ARIZONA_EQ_CONTROL("EQ2 Coefficients", ARIZONA_EQ2_2),
|
||||
SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT,
|
||||
24, 0, eq_tlv),
|
||||
SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT,
|
||||
@ -814,8 +812,7 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT,
|
||||
SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT,
|
||||
24, 0, eq_tlv),
|
||||
|
||||
SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19),
|
||||
SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0),
|
||||
ARIZONA_EQ_CONTROL("EQ3 Coefficients", ARIZONA_EQ3_2),
|
||||
SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT,
|
||||
24, 0, eq_tlv),
|
||||
SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT,
|
||||
@ -827,8 +824,7 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT,
|
||||
SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT,
|
||||
24, 0, eq_tlv),
|
||||
|
||||
SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19),
|
||||
SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0),
|
||||
ARIZONA_EQ_CONTROL("EQ4 Coefficients", ARIZONA_EQ4_2),
|
||||
SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT,
|
||||
24, 0, eq_tlv),
|
||||
SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT,
|
||||
@ -851,10 +847,10 @@ ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
|
||||
|
||||
SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1),
|
||||
SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1),
|
||||
SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1),
|
||||
SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1),
|
||||
ARIZONA_LHPF_CONTROL("LHPF1 Coefficients", ARIZONA_HPLPF1_2),
|
||||
ARIZONA_LHPF_CONTROL("LHPF2 Coefficients", ARIZONA_HPLPF2_2),
|
||||
ARIZONA_LHPF_CONTROL("LHPF3 Coefficients", ARIZONA_HPLPF3_2),
|
||||
ARIZONA_LHPF_CONTROL("LHPF4 Coefficients", ARIZONA_HPLPF4_2),
|
||||
|
||||
ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE),
|
||||
@ -1883,7 +1879,7 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec)
|
||||
ret = snd_soc_add_codec_controls(codec,
|
||||
arizona_adsp2_rate_controls, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_adsp2_codec_probe;
|
||||
|
||||
arizona_init_spk(codec);
|
||||
arizona_init_gpio(codec);
|
||||
@ -1893,6 +1889,11 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec)
|
||||
priv->core.arizona->dapm = dapm;
|
||||
|
||||
return 0;
|
||||
|
||||
err_adsp2_codec_probe:
|
||||
wm_adsp2_codec_remove(&priv->core.adsp[0], codec);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wm5102_codec_remove(struct snd_soc_codec *codec)
|
||||
|
@ -247,8 +247,7 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
|
||||
|
||||
SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19),
|
||||
SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0),
|
||||
ARIZONA_EQ_CONTROL("EQ1 Coefficients", ARIZONA_EQ1_2),
|
||||
SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
|
||||
24, 0, eq_tlv),
|
||||
SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
|
||||
@ -260,8 +259,7 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT,
|
||||
SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT,
|
||||
24, 0, eq_tlv),
|
||||
|
||||
SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19),
|
||||
SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0),
|
||||
ARIZONA_EQ_CONTROL("EQ2 Coefficients", ARIZONA_EQ2_2),
|
||||
SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT,
|
||||
24, 0, eq_tlv),
|
||||
SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT,
|
||||
@ -273,8 +271,7 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT,
|
||||
SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT,
|
||||
24, 0, eq_tlv),
|
||||
|
||||
SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19),
|
||||
SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0),
|
||||
ARIZONA_EQ_CONTROL("EQ3 Coefficients", ARIZONA_EQ3_2),
|
||||
SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT,
|
||||
24, 0, eq_tlv),
|
||||
SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT,
|
||||
@ -286,8 +283,7 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT,
|
||||
SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT,
|
||||
24, 0, eq_tlv),
|
||||
|
||||
SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19),
|
||||
SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0),
|
||||
ARIZONA_EQ_CONTROL("EQ4 Coefficients", ARIZONA_EQ4_2),
|
||||
SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT,
|
||||
24, 0, eq_tlv),
|
||||
SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT,
|
||||
@ -314,10 +310,10 @@ ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
|
||||
|
||||
SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1),
|
||||
SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1),
|
||||
SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1),
|
||||
SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1),
|
||||
ARIZONA_LHPF_CONTROL("LHPF1 Coefficients", ARIZONA_HPLPF1_2),
|
||||
ARIZONA_LHPF_CONTROL("LHPF2 Coefficients", ARIZONA_HPLPF2_2),
|
||||
ARIZONA_LHPF_CONTROL("LHPF3 Coefficients", ARIZONA_HPLPF3_2),
|
||||
ARIZONA_LHPF_CONTROL("LHPF4 Coefficients", ARIZONA_HPLPF4_2),
|
||||
|
||||
SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
|
||||
SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
|
||||
@ -1611,18 +1607,24 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec)
|
||||
for (i = 0; i < WM5110_NUM_ADSP; ++i) {
|
||||
ret = wm_adsp2_codec_probe(&priv->core.adsp[i], codec);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_adsp2_codec_probe;
|
||||
}
|
||||
|
||||
ret = snd_soc_add_codec_controls(codec,
|
||||
arizona_adsp2_rate_controls,
|
||||
WM5110_NUM_ADSP);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_adsp2_codec_probe;
|
||||
|
||||
snd_soc_dapm_disable_pin(dapm, "HAPTICS");
|
||||
|
||||
return 0;
|
||||
|
||||
err_adsp2_codec_probe:
|
||||
for (--i; i >= 0; --i)
|
||||
wm_adsp2_codec_remove(&priv->core.adsp[i], codec);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wm5110_codec_remove(struct snd_soc_codec *codec)
|
||||
|
@ -174,8 +174,7 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
|
||||
|
||||
SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19),
|
||||
SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0),
|
||||
ARIZONA_EQ_CONTROL("EQ1 Coefficients", ARIZONA_EQ1_2),
|
||||
SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
|
||||
24, 0, eq_tlv),
|
||||
SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
|
||||
@ -187,8 +186,7 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT,
|
||||
SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT,
|
||||
24, 0, eq_tlv),
|
||||
|
||||
SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19),
|
||||
SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0),
|
||||
ARIZONA_EQ_CONTROL("EQ2 Coefficients", ARIZONA_EQ2_2),
|
||||
SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT,
|
||||
24, 0, eq_tlv),
|
||||
SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT,
|
||||
@ -200,8 +198,7 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT,
|
||||
SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT,
|
||||
24, 0, eq_tlv),
|
||||
|
||||
SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19),
|
||||
SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0),
|
||||
ARIZONA_EQ_CONTROL("EQ3 Coefficients", ARIZONA_EQ3_2),
|
||||
SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT,
|
||||
24, 0, eq_tlv),
|
||||
SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT,
|
||||
@ -213,8 +210,7 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT,
|
||||
SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT,
|
||||
24, 0, eq_tlv),
|
||||
|
||||
SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19),
|
||||
SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0),
|
||||
ARIZONA_EQ_CONTROL("EQ4 Coefficients", ARIZONA_EQ4_2),
|
||||
SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT,
|
||||
24, 0, eq_tlv),
|
||||
SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT,
|
||||
@ -242,10 +238,10 @@ SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
|
||||
SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
|
||||
SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode),
|
||||
|
||||
SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1),
|
||||
SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1),
|
||||
SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1),
|
||||
SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1),
|
||||
ARIZONA_LHPF_CONTROL("LHPF1 Coefficients", ARIZONA_HPLPF1_2),
|
||||
ARIZONA_LHPF_CONTROL("LHPF2 Coefficients", ARIZONA_HPLPF2_2),
|
||||
ARIZONA_LHPF_CONTROL("LHPF3 Coefficients", ARIZONA_HPLPF3_2),
|
||||
ARIZONA_LHPF_CONTROL("LHPF4 Coefficients", ARIZONA_HPLPF4_2),
|
||||
|
||||
SOC_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
|
||||
SOC_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
|
||||
|
@ -22,6 +22,9 @@
|
||||
|
||||
#include "wm9705.h"
|
||||
|
||||
#define WM9705_VENDOR_ID 0x574d4c05
|
||||
#define WM9705_VENDOR_ID_MASK 0xffffffff
|
||||
|
||||
/*
|
||||
* WM9705 register cache
|
||||
*/
|
||||
@ -293,21 +296,6 @@ static struct snd_soc_dai_driver wm9705_dai[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static int wm9705_reset(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (soc_ac97_ops->reset) {
|
||||
soc_ac97_ops->reset(ac97);
|
||||
if (ac97_read(codec, 0) == wm9705_reg[0])
|
||||
return 0; /* Success */
|
||||
}
|
||||
|
||||
dev_err(codec->dev, "Failed to reset: AC97 link error\n");
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wm9705_soc_suspend(struct snd_soc_codec *codec)
|
||||
{
|
||||
@ -324,7 +312,8 @@ static int wm9705_soc_resume(struct snd_soc_codec *codec)
|
||||
int i, ret;
|
||||
u16 *cache = codec->reg_cache;
|
||||
|
||||
ret = wm9705_reset(codec);
|
||||
ret = snd_ac97_reset(ac97, true, WM9705_VENDOR_ID,
|
||||
WM9705_VENDOR_ID_MASK);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -342,30 +331,17 @@ static int wm9705_soc_resume(struct snd_soc_codec *codec)
|
||||
static int wm9705_soc_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_ac97 *ac97;
|
||||
int ret = 0;
|
||||
|
||||
ac97 = snd_soc_alloc_ac97_codec(codec);
|
||||
ac97 = snd_soc_new_ac97_codec(codec, WM9705_VENDOR_ID,
|
||||
WM9705_VENDOR_ID_MASK);
|
||||
if (IS_ERR(ac97)) {
|
||||
ret = PTR_ERR(ac97);
|
||||
dev_err(codec->dev, "Failed to register AC97 codec\n");
|
||||
return ret;
|
||||
return PTR_ERR(ac97);
|
||||
}
|
||||
|
||||
ret = wm9705_reset(codec);
|
||||
if (ret)
|
||||
goto err_put_device;
|
||||
|
||||
ret = device_add(&ac97->dev);
|
||||
if (ret)
|
||||
goto err_put_device;
|
||||
|
||||
snd_soc_codec_set_drvdata(codec, ac97);
|
||||
|
||||
return 0;
|
||||
|
||||
err_put_device:
|
||||
put_device(&ac97->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wm9705_soc_remove(struct snd_soc_codec *codec)
|
||||
|
@ -23,6 +23,9 @@
|
||||
#include <sound/tlv.h>
|
||||
#include "wm9712.h"
|
||||
|
||||
#define WM9712_VENDOR_ID 0x574d4c12
|
||||
#define WM9712_VENDOR_ID_MASK 0xffffffff
|
||||
|
||||
struct wm9712_priv {
|
||||
struct snd_ac97 *ac97;
|
||||
unsigned int hp_mixer[2];
|
||||
@ -613,35 +616,14 @@ static int wm9712_set_bias_level(struct snd_soc_codec *codec,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm9712_reset(struct snd_soc_codec *codec, int try_warm)
|
||||
{
|
||||
struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (try_warm && soc_ac97_ops->warm_reset) {
|
||||
soc_ac97_ops->warm_reset(wm9712->ac97);
|
||||
if (ac97_read(codec, 0) == wm9712_reg[0])
|
||||
return 1;
|
||||
}
|
||||
|
||||
soc_ac97_ops->reset(wm9712->ac97);
|
||||
if (soc_ac97_ops->warm_reset)
|
||||
soc_ac97_ops->warm_reset(wm9712->ac97);
|
||||
if (ac97_read(codec, 0) != wm9712_reg[0])
|
||||
goto err;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
dev_err(codec->dev, "Failed to reset: AC97 link error\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int wm9712_soc_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec);
|
||||
int i, ret;
|
||||
u16 *cache = codec->reg_cache;
|
||||
|
||||
ret = wm9712_reset(codec, 1);
|
||||
ret = snd_ac97_reset(wm9712->ac97, true, WM9712_VENDOR_ID,
|
||||
WM9712_VENDOR_ID_MASK);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -663,31 +645,20 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec)
|
||||
static int wm9712_soc_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
wm9712->ac97 = snd_soc_alloc_ac97_codec(codec);
|
||||
wm9712->ac97 = snd_soc_new_ac97_codec(codec, WM9712_VENDOR_ID,
|
||||
WM9712_VENDOR_ID_MASK);
|
||||
if (IS_ERR(wm9712->ac97)) {
|
||||
ret = PTR_ERR(wm9712->ac97);
|
||||
dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = wm9712_reset(codec, 0);
|
||||
if (ret < 0)
|
||||
goto err_put_device;
|
||||
|
||||
ret = device_add(&wm9712->ac97->dev);
|
||||
if (ret)
|
||||
goto err_put_device;
|
||||
|
||||
/* set alc mux to none */
|
||||
ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000);
|
||||
|
||||
return 0;
|
||||
|
||||
err_put_device:
|
||||
put_device(&wm9712->ac97->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wm9712_soc_remove(struct snd_soc_codec *codec)
|
||||
|
@ -29,6 +29,9 @@
|
||||
|
||||
#include "wm9713.h"
|
||||
|
||||
#define WM9713_VENDOR_ID 0x574d4c13
|
||||
#define WM9713_VENDOR_ID_MASK 0xffffffff
|
||||
|
||||
struct wm9713_priv {
|
||||
struct snd_ac97 *ac97;
|
||||
u32 pll_in; /* PLL input frequency */
|
||||
@ -1123,28 +1126,6 @@ static struct snd_soc_dai_driver wm9713_dai[] = {
|
||||
},
|
||||
};
|
||||
|
||||
int wm9713_reset(struct snd_soc_codec *codec, int try_warm)
|
||||
{
|
||||
struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (try_warm && soc_ac97_ops->warm_reset) {
|
||||
soc_ac97_ops->warm_reset(wm9713->ac97);
|
||||
if (ac97_read(codec, 0) == wm9713_reg[0])
|
||||
return 1;
|
||||
}
|
||||
|
||||
soc_ac97_ops->reset(wm9713->ac97);
|
||||
if (soc_ac97_ops->warm_reset)
|
||||
soc_ac97_ops->warm_reset(wm9713->ac97);
|
||||
if (ac97_read(codec, 0) != wm9713_reg[0]) {
|
||||
dev_err(codec->dev, "Failed to reset: AC97 link error\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wm9713_reset);
|
||||
|
||||
static int wm9713_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
@ -1196,7 +1177,8 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec)
|
||||
int i, ret;
|
||||
u16 *cache = codec->reg_cache;
|
||||
|
||||
ret = wm9713_reset(codec, 1);
|
||||
ret = snd_ac97_reset(wm9713->ac97, true, WM9713_VENDOR_ID,
|
||||
WM9713_VENDOR_ID_MASK);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -1222,32 +1204,18 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec)
|
||||
static int wm9713_soc_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret = 0, reg;
|
||||
int reg;
|
||||
|
||||
wm9713->ac97 = snd_soc_alloc_ac97_codec(codec);
|
||||
wm9713->ac97 = snd_soc_new_ac97_codec(codec, WM9713_VENDOR_ID,
|
||||
WM9713_VENDOR_ID_MASK);
|
||||
if (IS_ERR(wm9713->ac97))
|
||||
return PTR_ERR(wm9713->ac97);
|
||||
|
||||
/* do a cold reset for the controller and then try
|
||||
* a warm reset followed by an optional cold reset for codec */
|
||||
wm9713_reset(codec, 0);
|
||||
ret = wm9713_reset(codec, 1);
|
||||
if (ret < 0)
|
||||
goto err_put_device;
|
||||
|
||||
ret = device_add(&wm9713->ac97->dev);
|
||||
if (ret)
|
||||
goto err_put_device;
|
||||
|
||||
/* unmute the adc - move to kcontrol */
|
||||
reg = ac97_read(codec, AC97_CD) & 0x7fff;
|
||||
ac97_write(codec, AC97_CD, reg);
|
||||
|
||||
return 0;
|
||||
|
||||
err_put_device:
|
||||
put_device(&wm9713->ac97->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wm9713_soc_remove(struct snd_soc_codec *codec)
|
||||
|
@ -45,6 +45,4 @@
|
||||
#define WM9713_DAI_AC97_AUX 1
|
||||
#define WM9713_DAI_PCM_VOICE 2
|
||||
|
||||
int wm9713_reset(struct snd_soc_codec *codec, int try_warm);
|
||||
|
||||
#endif
|
||||
|
@ -85,10 +85,19 @@ EXPORT_SYMBOL(snd_soc_alloc_ac97_codec);
|
||||
/**
|
||||
* snd_soc_new_ac97_codec - initailise AC97 device
|
||||
* @codec: audio codec
|
||||
* @id: The expected device ID
|
||||
* @id_mask: Mask that is applied to the device ID before comparing with @id
|
||||
*
|
||||
* Initialises AC97 codec resources for use by ad-hoc devices only.
|
||||
*
|
||||
* If @id is not 0 this function will reset the device, then read the ID from
|
||||
* the device and check if it matches the expected ID. If it doesn't match an
|
||||
* error will be returned and device will not be registered.
|
||||
*
|
||||
* Returns: A PTR_ERR() on failure or a valid snd_ac97 struct on success.
|
||||
*/
|
||||
struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec)
|
||||
struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
|
||||
unsigned int id, unsigned int id_mask)
|
||||
{
|
||||
struct snd_ac97 *ac97;
|
||||
int ret;
|
||||
@ -97,13 +106,24 @@ struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec)
|
||||
if (IS_ERR(ac97))
|
||||
return ac97;
|
||||
|
||||
ret = device_add(&ac97->dev);
|
||||
if (ret) {
|
||||
put_device(&ac97->dev);
|
||||
return ERR_PTR(ret);
|
||||
if (id) {
|
||||
ret = snd_ac97_reset(ac97, false, id, id_mask);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to reset AC97 device: %d\n",
|
||||
ret);
|
||||
goto err_put_device;
|
||||
}
|
||||
}
|
||||
|
||||
ret = device_add(&ac97->dev);
|
||||
if (ret)
|
||||
goto err_put_device;
|
||||
|
||||
return ac97;
|
||||
|
||||
err_put_device:
|
||||
put_device(&ac97->dev);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user