Merge remote-tracking branch 'asoc/topic/arizona' into asoc-next

This commit is contained in:
Mark Brown 2012-12-10 00:22:00 +09:00
commit daa5ab9e0d
12 changed files with 586 additions and 58 deletions

View File

@ -72,6 +72,16 @@ config INPUT_AD714X_SPI
To compile this driver as a module, choose M here: the
module will be called ad714x-spi.
config INPUT_ARIZONA_HAPTICS
tristate "Arizona haptics support"
depends on MFD_ARIZONA && SND_SOC
select INPUT_FF_MEMLESS
help
Say Y to enable support for the haptics module in Arizona CODECs.
To compile this driver as a module, choose M here: the
module will be called arizona-haptics.
config INPUT_BMA150
tristate "BMA150/SMB380 acceleration sensor support"
depends on I2C

View File

@ -14,6 +14,7 @@ obj-$(CONFIG_INPUT_ADXL34X) += adxl34x.o
obj-$(CONFIG_INPUT_ADXL34X_I2C) += adxl34x-i2c.o
obj-$(CONFIG_INPUT_ADXL34X_SPI) += adxl34x-spi.o
obj-$(CONFIG_INPUT_APANEL) += apanel.o
obj-$(CONFIG_INPUT_ARIZONA_HAPTICS) += arizona-haptics.o
obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o
obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o
obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o

View File

@ -0,0 +1,255 @@
/*
* Arizona haptics driver
*
* Copyright 2012 Wolfson Microelectronics plc
*
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/slab.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <linux/mfd/arizona/core.h>
#include <linux/mfd/arizona/pdata.h>
#include <linux/mfd/arizona/registers.h>
struct arizona_haptics {
struct arizona *arizona;
struct input_dev *input_dev;
struct work_struct work;
struct mutex mutex;
u8 intensity;
};
static void arizona_haptics_work(struct work_struct *work)
{
struct arizona_haptics *haptics = container_of(work,
struct arizona_haptics,
work);
struct arizona *arizona = haptics->arizona;
struct mutex *dapm_mutex = &arizona->dapm->card->dapm_mutex;
int ret;
if (!haptics->arizona->dapm) {
dev_err(arizona->dev, "No DAPM context\n");
return;
}
if (haptics->intensity) {
ret = regmap_update_bits(arizona->regmap,
ARIZONA_HAPTICS_PHASE_2_INTENSITY,
ARIZONA_PHASE2_INTENSITY_MASK,
haptics->intensity);
if (ret != 0) {
dev_err(arizona->dev, "Failed to set intensity: %d\n",
ret);
return;
}
/* This enable sequence will be a noop if already enabled */
ret = regmap_update_bits(arizona->regmap,
ARIZONA_HAPTICS_CONTROL_1,
ARIZONA_HAP_CTRL_MASK,
1 << ARIZONA_HAP_CTRL_SHIFT);
if (ret != 0) {
dev_err(arizona->dev, "Failed to start haptics: %d\n",
ret);
return;
}
mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS");
if (ret != 0) {
dev_err(arizona->dev, "Failed to start HAPTICS: %d\n",
ret);
mutex_unlock(dapm_mutex);
return;
}
ret = snd_soc_dapm_sync(arizona->dapm);
if (ret != 0) {
dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
ret);
mutex_unlock(dapm_mutex);
return;
}
mutex_unlock(dapm_mutex);
} else {
/* This disable sequence will be a noop if already enabled */
mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS");
if (ret != 0) {
dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n",
ret);
mutex_unlock(dapm_mutex);
return;
}
ret = snd_soc_dapm_sync(arizona->dapm);
if (ret != 0) {
dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
ret);
mutex_unlock(dapm_mutex);
return;
}
mutex_unlock(dapm_mutex);
ret = regmap_update_bits(arizona->regmap,
ARIZONA_HAPTICS_CONTROL_1,
ARIZONA_HAP_CTRL_MASK,
1 << ARIZONA_HAP_CTRL_SHIFT);
if (ret != 0) {
dev_err(arizona->dev, "Failed to stop haptics: %d\n",
ret);
return;
}
}
}
static int arizona_haptics_play(struct input_dev *input, void *data,
struct ff_effect *effect)
{
struct arizona_haptics *haptics = input_get_drvdata(input);
struct arizona *arizona = haptics->arizona;
if (!arizona->dapm) {
dev_err(arizona->dev, "No DAPM context\n");
return -EBUSY;
}
if (effect->u.rumble.strong_magnitude) {
/* Scale the magnitude into the range the device supports */
if (arizona->pdata.hap_act) {
haptics->intensity =
effect->u.rumble.strong_magnitude >> 9;
if (effect->direction < 0x8000)
haptics->intensity += 0x7f;
} else {
haptics->intensity =
effect->u.rumble.strong_magnitude >> 8;
}
} else {
haptics->intensity = 0;
}
schedule_work(&haptics->work);
return 0;
}
static void arizona_haptics_close(struct input_dev *input)
{
struct arizona_haptics *haptics = input_get_drvdata(input);
struct mutex *dapm_mutex = &haptics->arizona->dapm->card->dapm_mutex;
cancel_work_sync(&haptics->work);
mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
if (haptics->arizona->dapm)
snd_soc_dapm_disable_pin(haptics->arizona->dapm, "HAPTICS");
mutex_unlock(dapm_mutex);
}
static int arizona_haptics_probe(struct platform_device *pdev)
{
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
struct arizona_haptics *haptics;
int ret;
haptics = devm_kzalloc(&pdev->dev, sizeof(*haptics), GFP_KERNEL);
if (!haptics)
return -ENOMEM;
haptics->arizona = arizona;
ret = regmap_update_bits(arizona->regmap, ARIZONA_HAPTICS_CONTROL_1,
ARIZONA_HAP_ACT, arizona->pdata.hap_act);
if (ret != 0) {
dev_err(arizona->dev, "Failed to set haptics actuator: %d\n",
ret);
return ret;
}
INIT_WORK(&haptics->work, arizona_haptics_work);
haptics->input_dev = input_allocate_device();
if (haptics->input_dev == NULL) {
dev_err(arizona->dev, "Failed to allocate input device\n");
return -ENOMEM;
}
input_set_drvdata(haptics->input_dev, haptics);
haptics->input_dev->name = "arizona:haptics";
haptics->input_dev->dev.parent = pdev->dev.parent;
haptics->input_dev->close = arizona_haptics_close;
__set_bit(FF_RUMBLE, haptics->input_dev->ffbit);
ret = input_ff_create_memless(haptics->input_dev, NULL,
arizona_haptics_play);
if (ret < 0) {
dev_err(arizona->dev, "input_ff_create_memless() failed: %d\n",
ret);
goto err_ialloc;
}
ret = input_register_device(haptics->input_dev);
if (ret < 0) {
dev_err(arizona->dev, "couldn't register input device: %d\n",
ret);
goto err_iff;
}
platform_set_drvdata(pdev, haptics);
return 0;
err_iff:
if (haptics->input_dev)
input_ff_destroy(haptics->input_dev);
err_ialloc:
input_free_device(haptics->input_dev);
return ret;
}
static int arizona_haptics_remove(struct platform_device *pdev)
{
struct arizona_haptics *haptics = platform_get_drvdata(pdev);
input_unregister_device(haptics->input_dev);
return 0;
}
static struct platform_driver arizona_haptics_driver = {
.probe = arizona_haptics_probe,
.remove = arizona_haptics_remove,
.driver = {
.name = "arizona-haptics",
.owner = THIS_MODULE,
},
};
module_platform_driver(arizona_haptics_driver);
MODULE_ALIAS("platform:arizona-haptics");
MODULE_DESCRIPTION("Arizona haptics driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");

View File

@ -272,6 +272,7 @@ static struct mfd_cell early_devs[] = {
static struct mfd_cell wm5102_devs[] = {
{ .name = "arizona-extcon" },
{ .name = "arizona-gpio" },
{ .name = "arizona-haptics" },
{ .name = "arizona-micsupp" },
{ .name = "arizona-pwm" },
{ .name = "wm5102-codec" },
@ -280,6 +281,7 @@ static struct mfd_cell wm5102_devs[] = {
static struct mfd_cell wm5110_devs[] = {
{ .name = "arizona-extcon" },
{ .name = "arizona-gpio" },
{ .name = "arizona-haptics" },
{ .name = "arizona-micsupp" },
{ .name = "arizona-pwm" },
{ .name = "wm5110-codec" },

View File

@ -78,6 +78,8 @@ enum arizona_type {
#define ARIZONA_NUM_IRQ 50
struct snd_soc_dapm_context;
struct arizona {
struct regmap *regmap;
struct device *dev;
@ -98,6 +100,8 @@ struct arizona {
struct mutex clk_lock;
int clk32k_ref;
struct snd_soc_dapm_context *dapm;
};
int arizona_clk32k_enable(struct arizona *arizona);

View File

@ -62,6 +62,9 @@
#define ARIZONA_MAX_OUTPUT 6
#define ARIZONA_HAP_ACT_ERM 0
#define ARIZONA_HAP_ACT_LRA 2
#define ARIZONA_MAX_PDM_SPK 2
struct regulator_init_data;
@ -114,6 +117,9 @@ struct arizona_pdata {
/** PDM speaker format */
unsigned int spk_fmt[ARIZONA_MAX_PDM_SPK];
/** Haptic actuator type */
unsigned int hap_act;
};
#endif

View File

@ -148,7 +148,9 @@ config SND_SOC_WM_HUBS
config SND_SOC_WM_ADSP
tristate
default y if SND_SOC_WM5102=y
default y if SND_SOC_WM2200=y
default m if SND_SOC_WM5102=m
default m if SND_SOC_WM2200=m
config SND_SOC_AB8500_CODEC

View File

@ -226,6 +226,31 @@ EXPORT_SYMBOL_GPL(arizona_mixer_values);
const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
static const char *arizona_vol_ramp_text[] = {
"0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
"15ms/6dB", "30ms/6dB",
};
const struct soc_enum arizona_in_vd_ramp =
SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
ARIZONA_IN_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
EXPORT_SYMBOL_GPL(arizona_in_vd_ramp);
const struct soc_enum arizona_in_vi_ramp =
SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
ARIZONA_IN_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
EXPORT_SYMBOL_GPL(arizona_in_vi_ramp);
const struct soc_enum arizona_out_vd_ramp =
SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
ARIZONA_OUT_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
EXPORT_SYMBOL_GPL(arizona_out_vd_ramp);
const struct soc_enum arizona_out_vi_ramp =
SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
ARIZONA_OUT_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
EXPORT_SYMBOL_GPL(arizona_out_vi_ramp);
static const char *arizona_lhpf_mode_text[] = {
"Low-pass", "High-pass"
};
@ -380,6 +405,18 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
case 49152000:
val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT;
break;
case 67737600:
case 73728000:
val |= 4 << ARIZONA_SYSCLK_FREQ_SHIFT;
break;
case 90316800:
case 98304000:
val |= 5 << ARIZONA_SYSCLK_FREQ_SHIFT;
break;
case 135475200:
case 147456000:
val |= 6 << ARIZONA_SYSCLK_FREQ_SHIFT;
break;
default:
return -EINVAL;
}
@ -737,6 +774,9 @@ static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
return -EBUSY;
}
dev_dbg(codec->dev, "Setting AIF%d to %s\n", dai->id + 1,
arizona_dai_clk_str(clk_id));
memset(&routes, 0, sizeof(routes));
routes[0].sink = dai->driver->capture.stream_name;
routes[1].sink = dai->driver->playback.stream_name;
@ -749,6 +789,8 @@ static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
routes[1].source = arizona_dai_clk_str(clk_id);
snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
dai_priv->clk = clk_id;
return snd_soc_dapm_sync(&codec->dapm);
}
@ -925,6 +967,9 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
bool ena;
int ret;
if (fll->fref == Fref && fll->fout == Fout)
return 0;
ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
if (ret != 0) {
arizona_fll_err(fll, "Failed to read current state: %d\n",
@ -970,6 +1015,9 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
if (ena)
pm_runtime_put_autosuspend(arizona->dev);
fll->fref = Fref;
fll->fout = Fout;
return 0;
}
@ -998,10 +1046,13 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
ARIZONA_FLL1_SYNC_ENA);
ret = wait_for_completion_timeout(&fll->ok,
msecs_to_jiffies(25));
msecs_to_jiffies(250));
if (ret == 0)
arizona_fll_warn(fll, "Timed out waiting for lock\n");
fll->fref = Fref;
fll->fout = Fout;
return 0;
}
EXPORT_SYMBOL_GPL(arizona_set_fll);

View File

@ -17,6 +17,8 @@
#include <sound/soc.h>
#include "wm_adsp.h"
#define ARIZONA_CLK_SYSCLK 1
#define ARIZONA_CLK_ASYNCCLK 2
#define ARIZONA_CLK_OPCLK 3
@ -46,15 +48,18 @@
#define ARIZONA_MIXER_VOL_SHIFT 1
#define ARIZONA_MIXER_VOL_WIDTH 7
#define ARIZONA_MAX_DAI 3
#define ARIZONA_MAX_DAI 4
#define ARIZONA_MAX_ADSP 4
struct arizona;
struct wm_adsp;
struct arizona_dai_priv {
int clk;
};
struct arizona_priv {
struct wm_adsp adsp[ARIZONA_MAX_ADSP];
struct arizona *arizona;
int sysclk;
int asyncclk;
@ -89,19 +94,30 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
const struct snd_kcontrol_new name##_mux = \
SOC_DAPM_VALUE_ENUM("Route", name##_enum)
#define ARIZONA_MUX_ENUMS(name, base_reg) \
static ARIZONA_MUX_ENUM_DECL(name##_enum, base_reg); \
static ARIZONA_MUX_CTL_DECL(name)
#define ARIZONA_MIXER_ENUMS(name, base_reg) \
static ARIZONA_MUX_ENUM_DECL(name##_in1_enum, base_reg); \
static ARIZONA_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2); \
static ARIZONA_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4); \
static ARIZONA_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6); \
static ARIZONA_MUX_CTL_DECL(name##_in1); \
static ARIZONA_MUX_CTL_DECL(name##_in2); \
static ARIZONA_MUX_CTL_DECL(name##_in3); \
static ARIZONA_MUX_CTL_DECL(name##_in4)
ARIZONA_MUX_ENUMS(name##_in1, base_reg); \
ARIZONA_MUX_ENUMS(name##_in2, base_reg + 2); \
ARIZONA_MUX_ENUMS(name##_in3, base_reg + 4); \
ARIZONA_MUX_ENUMS(name##_in4, base_reg + 6)
#define ARIZONA_DSP_AUX_ENUMS(name, base_reg) \
ARIZONA_MUX_ENUMS(name##_aux1, base_reg); \
ARIZONA_MUX_ENUMS(name##_aux2, base_reg + 8); \
ARIZONA_MUX_ENUMS(name##_aux3, base_reg + 16); \
ARIZONA_MUX_ENUMS(name##_aux4, base_reg + 24); \
ARIZONA_MUX_ENUMS(name##_aux5, base_reg + 32); \
ARIZONA_MUX_ENUMS(name##_aux6, base_reg + 40)
#define ARIZONA_MUX(name, ctrl) \
SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
#define ARIZONA_MUX_WIDGETS(name, name_str) \
ARIZONA_MUX(name_str " Input", &name##_mux)
#define ARIZONA_MIXER_WIDGETS(name, name_str) \
ARIZONA_MUX(name_str " Input 1", &name##_in1_mux), \
ARIZONA_MUX(name_str " Input 2", &name##_in2_mux), \
@ -109,6 +125,19 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
ARIZONA_MUX(name_str " Input 4", &name##_in4_mux), \
SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
#define ARIZONA_DSP_WIDGETS(name, name_str) \
ARIZONA_MIXER_WIDGETS(name##L, name_str "L"), \
ARIZONA_MIXER_WIDGETS(name##R, name_str "R"), \
ARIZONA_MUX(name_str " Aux 1", &name##_aux1_mux), \
ARIZONA_MUX(name_str " Aux 2", &name##_aux2_mux), \
ARIZONA_MUX(name_str " Aux 3", &name##_aux3_mux), \
ARIZONA_MUX(name_str " Aux 4", &name##_aux4_mux), \
ARIZONA_MUX(name_str " Aux 5", &name##_aux5_mux), \
ARIZONA_MUX(name_str " Aux 6", &name##_aux6_mux)
#define ARIZONA_MUX_ROUTES(name) \
ARIZONA_MIXER_INPUT_ROUTES(name " Input")
#define ARIZONA_MIXER_ROUTES(widget, name) \
{ widget, NULL, name " Mixer" }, \
{ name " Mixer", NULL, name " Input 1" }, \
@ -120,6 +149,28 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
ARIZONA_MIXER_INPUT_ROUTES(name " Input 3"), \
ARIZONA_MIXER_INPUT_ROUTES(name " Input 4")
#define ARIZONA_DSP_ROUTES(name) \
{ name, NULL, name " Aux 1" }, \
{ name, NULL, name " Aux 2" }, \
{ name, NULL, name " Aux 3" }, \
{ name, NULL, name " Aux 4" }, \
{ name, NULL, name " Aux 5" }, \
{ name, NULL, name " Aux 6" }, \
ARIZONA_MIXER_INPUT_ROUTES(name " Aux 1"), \
ARIZONA_MIXER_INPUT_ROUTES(name " Aux 2"), \
ARIZONA_MIXER_INPUT_ROUTES(name " Aux 3"), \
ARIZONA_MIXER_INPUT_ROUTES(name " Aux 4"), \
ARIZONA_MIXER_INPUT_ROUTES(name " Aux 5"), \
ARIZONA_MIXER_INPUT_ROUTES(name " Aux 6"), \
ARIZONA_MIXER_ROUTES(name, name "L"), \
ARIZONA_MIXER_ROUTES(name, name "R")
extern const struct soc_enum arizona_in_vi_ramp;
extern const struct soc_enum arizona_in_vd_ramp;
extern const struct soc_enum arizona_out_vi_ramp;
extern const struct soc_enum arizona_out_vd_ramp;
extern const struct soc_enum arizona_lhpf1_mode;
extern const struct soc_enum arizona_lhpf2_mode;
extern const struct soc_enum arizona_lhpf3_mode;
@ -146,6 +197,8 @@ struct arizona_fll {
unsigned int vco_mult;
struct completion lock;
struct completion ok;
unsigned int fref;
unsigned int fout;
char lock_name[ARIZONA_FLL_NAME_LEN];
char clock_ok_name[ARIZONA_FLL_NAME_LEN];

View File

@ -31,6 +31,7 @@
#include "arizona.h"
#include "wm5102.h"
#include "wm_adsp.h"
struct wm5102_priv {
struct arizona_priv core;
@ -42,6 +43,13 @@ static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0);
static const struct wm_adsp_region wm5102_dsp1_regions[] = {
{ .type = WMFW_ADSP2_PM, .base = 0x100000 },
{ .type = WMFW_ADSP2_ZM, .base = 0x180000 },
{ .type = WMFW_ADSP2_XM, .base = 0x190000 },
{ .type = WMFW_ADSP2_YM, .base = 0x1a8000 },
};
static const struct reg_default wm5102_sysclk_reva_patch[] = {
{ 0x3000, 0x2225 },
{ 0x3001, 0x3a03 },
@ -627,11 +635,23 @@ SOC_DOUBLE_R_TLV("IN3 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_3L,
ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_DIG_VOL_SHIFT,
0xbf, 0, digital_tlv),
SOC_ENUM("Input Ramp Up", arizona_in_vi_ramp),
SOC_ENUM("Input Ramp Down", arizona_in_vd_ramp),
ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE),
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_MASK("EQ1 Coefficeints", ARIZONA_EQ1_1, 21,
ARIZONA_EQ1_ENA_MASK),
SND_SOC_BYTES_MASK("EQ2 Coefficeints", ARIZONA_EQ2_1, 21,
ARIZONA_EQ2_ENA_MASK),
SND_SOC_BYTES_MASK("EQ3 Coefficeints", ARIZONA_EQ3_1, 21,
ARIZONA_EQ3_ENA_MASK),
SND_SOC_BYTES_MASK("EQ4 Coefficeints", ARIZONA_EQ4_1, 21,
ARIZONA_EQ4_ENA_MASK),
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,
@ -687,6 +707,14 @@ 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_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE),
SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
@ -708,14 +736,6 @@ ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE),
SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L,
ARIZONA_OUT1_OSR_SHIFT, 1, 0),
SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L,
ARIZONA_OUT2_OSR_SHIFT, 1, 0),
SOC_SINGLE("EPOUT High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L,
ARIZONA_OUT3_OSR_SHIFT, 1, 0),
SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L,
ARIZONA_OUT4_OSR_SHIFT, 1, 0),
SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L,
ARIZONA_OUT5_OSR_SHIFT, 1, 0),
@ -745,16 +765,8 @@ SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L,
ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT,
0xbf, 0, digital_tlv),
SOC_DOUBLE_R_RANGE_TLV("HPOUT1 Volume", ARIZONA_OUTPUT_PATH_CONFIG_1L,
ARIZONA_OUTPUT_PATH_CONFIG_1R,
ARIZONA_OUT1L_PGA_VOL_SHIFT,
0x34, 0x40, 0, ana_tlv),
SOC_DOUBLE_R_RANGE_TLV("OUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L,
ARIZONA_OUTPUT_PATH_CONFIG_2R,
ARIZONA_OUT2L_PGA_VOL_SHIFT,
0x34, 0x40, 0, ana_tlv),
SOC_SINGLE_RANGE_TLV("EPOUT Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L,
ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv),
SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
ARIZONA_SPK1R_MUTE_SHIFT, 1, 1),
@ -819,11 +831,15 @@ ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
ARIZONA_MUX_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(DSP1L, ARIZONA_DSP1LMIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(DSP1R, ARIZONA_DSP1RMIX_INPUT_1_SOURCE);
ARIZONA_DSP_AUX_ENUMS(DSP1, ARIZONA_DSP1AUX1MIX_INPUT_1_SOURCE);
static const char *wm5102_aec_loopback_texts[] = {
"HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "EPOUT",
@ -864,6 +880,7 @@ SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0),
SND_SOC_DAPM_SIGGEN("TONE"),
SND_SOC_DAPM_SIGGEN("NOISE"),
SND_SOC_DAPM_SIGGEN("HAPTICS"),
SND_SOC_DAPM_INPUT("IN1L"),
SND_SOC_DAPM_INPUT("IN1R"),
@ -894,9 +911,9 @@ SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT,
SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1,
ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2,
ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
ARIZONA_MICB2_ENA_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("MICBIAS3", ARIZONA_MIC_BIAS_CTRL_3,
ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
ARIZONA_MICB3_ENA_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_PGA("Noise Generator", ARIZONA_COMFORT_NOISE_GENERATOR,
ARIZONA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0),
@ -996,6 +1013,8 @@ SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0),
ARIZONA_DSP_WIDGETS(DSP1, "DSP1"),
SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5102_aec_loopback_mux),
@ -1071,10 +1090,12 @@ ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"),
ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"),
ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"),
ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"),
ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"),
ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"),
ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"),
ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"),
WM_ADSP2("DSP1", 0),
SND_SOC_DAPM_OUTPUT("HPOUT1L"),
SND_SOC_DAPM_OUTPUT("HPOUT1R"),
@ -1094,6 +1115,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"),
{ name, "Noise Generator", "Noise Generator" }, \
{ name, "Tone Generator 1", "Tone Generator 1" }, \
{ name, "Tone Generator 2", "Tone Generator 2" }, \
{ name, "Haptics", "HAPTICS" }, \
{ name, "AEC", "AEC Loopback" }, \
{ name, "IN1L", "IN1L PGA" }, \
{ name, "IN1R", "IN1R PGA" }, \
@ -1127,7 +1149,13 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"),
{ name, "ASRC1L", "ASRC1L" }, \
{ name, "ASRC1R", "ASRC1R" }, \
{ name, "ASRC2L", "ASRC2L" }, \
{ name, "ASRC2R", "ASRC2R" }
{ name, "ASRC2R", "ASRC2R" }, \
{ name, "DSP1.1", "DSP1" }, \
{ name, "DSP1.2", "DSP1" }, \
{ name, "DSP1.3", "DSP1" }, \
{ name, "DSP1.4", "DSP1" }, \
{ name, "DSP1.5", "DSP1" }, \
{ name, "DSP1.6", "DSP1" }
static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
{ "AIF2 Capture", NULL, "DBVDD2" },
@ -1213,6 +1241,11 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
{ "IN3L PGA", NULL, "IN3L" },
{ "IN3R PGA", NULL, "IN3R" },
{ "ASRC1L", NULL, "ASRC1L Input" },
{ "ASRC1R", NULL, "ASRC1R Input" },
{ "ASRC2L", NULL, "ASRC2L Input" },
{ "ASRC2R", NULL, "ASRC2R Input" },
ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"),
ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"),
ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"),
@ -1255,10 +1288,12 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"),
ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"),
ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"),
ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"),
ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"),
ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"),
ARIZONA_MUX_ROUTES("ASRC1L"),
ARIZONA_MUX_ROUTES("ASRC1R"),
ARIZONA_MUX_ROUTES("ASRC2L"),
ARIZONA_MUX_ROUTES("ASRC2R"),
ARIZONA_DSP_ROUTES("DSP1"),
{ "AEC Loopback", "HPOUT1L", "OUT1L" },
{ "AEC Loopback", "HPOUT1R", "OUT1R" },
@ -1377,9 +1412,28 @@ static struct snd_soc_dai_driver wm5102_dai[] = {
static int wm5102_codec_probe(struct snd_soc_codec *codec)
{
struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
int ret;
codec->control_data = priv->core.arizona->regmap;
return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
if (ret != 0)
return ret;
snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
priv->core.arizona->dapm = &codec->dapm;
return 0;
}
static int wm5102_codec_remove(struct snd_soc_codec *codec)
{
struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
priv->core.arizona->dapm = NULL;
return 0;
}
#define WM5102_DIG_VU 0x0200
@ -1406,6 +1460,7 @@ static unsigned int wm5102_digital_vu[] = {
static struct snd_soc_codec_driver soc_codec_dev_wm5102 = {
.probe = wm5102_codec_probe,
.remove = wm5102_codec_remove,
.idle_bias_off = true,
@ -1424,7 +1479,7 @@ static int __devinit wm5102_probe(struct platform_device *pdev)
{
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
struct wm5102_priv *wm5102;
int i;
int i, ret;
wm5102 = devm_kzalloc(&pdev->dev, sizeof(struct wm5102_priv),
GFP_KERNEL);
@ -1434,6 +1489,19 @@ static int __devinit wm5102_probe(struct platform_device *pdev)
wm5102->core.arizona = arizona;
wm5102->core.adsp[0].part = "wm5102";
wm5102->core.adsp[0].num = 1;
wm5102->core.adsp[0].type = WMFW_ADSP2;
wm5102->core.adsp[0].base = ARIZONA_DSP1_CONTROL_1;
wm5102->core.adsp[0].dev = arizona->dev;
wm5102->core.adsp[0].regmap = arizona->regmap;
wm5102->core.adsp[0].mem = wm5102_dsp1_regions;
wm5102->core.adsp[0].num_mems = ARRAY_SIZE(wm5102_dsp1_regions);
ret = wm_adsp2_init(&wm5102->core.adsp[0], true);
if (ret != 0)
return ret;
for (i = 0; i < ARRAY_SIZE(wm5102->fll); i++)
wm5102->fll[i].vco_mult = 1;

View File

@ -84,11 +84,23 @@ SOC_DOUBLE_R_TLV("IN4 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_4L,
ARIZONA_ADC_DIGITAL_VOLUME_4R, ARIZONA_IN4L_DIG_VOL_SHIFT,
0xbf, 0, digital_tlv),
SOC_ENUM("Input Ramp Up", arizona_in_vi_ramp),
SOC_ENUM("Input Ramp Down", arizona_in_vd_ramp),
ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE),
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_MASK("EQ1 Coefficeints", ARIZONA_EQ1_1, 21,
ARIZONA_EQ1_ENA_MASK),
SND_SOC_BYTES_MASK("EQ2 Coefficeints", ARIZONA_EQ2_1, 21,
ARIZONA_EQ2_ENA_MASK),
SND_SOC_BYTES_MASK("EQ3 Coefficeints", ARIZONA_EQ3_1, 21,
ARIZONA_EQ3_ENA_MASK),
SND_SOC_BYTES_MASK("EQ4 Coefficeints", ARIZONA_EQ4_1, 21,
ARIZONA_EQ4_ENA_MASK),
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,
@ -148,6 +160,11 @@ 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),
SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
@ -243,6 +260,9 @@ SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT,
ARIZONA_SPK2R_MUTE_SHIFT, 1, 1),
SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
ARIZONA_MIXER_CONTROLS("AIF1TX1", ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("AIF1TX2", ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("AIF1TX3", ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE),
@ -308,10 +328,10 @@ ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
ARIZONA_MUX_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
static const char *wm5110_aec_loopback_texts[] = {
"HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R",
@ -352,6 +372,7 @@ SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0),
SND_SOC_DAPM_SIGGEN("TONE"),
SND_SOC_DAPM_SIGGEN("NOISE"),
SND_SOC_DAPM_SIGGEN("HAPTICS"),
SND_SOC_DAPM_INPUT("IN1L"),
SND_SOC_DAPM_INPUT("IN1R"),
@ -585,10 +606,10 @@ ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"),
ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"),
ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"),
ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"),
ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"),
ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"),
ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"),
ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"),
SND_SOC_DAPM_OUTPUT("HPOUT1L"),
SND_SOC_DAPM_OUTPUT("HPOUT1R"),
@ -610,6 +631,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT2R"),
{ name, "Noise Generator", "Noise Generator" }, \
{ name, "Tone Generator 1", "Tone Generator 1" }, \
{ name, "Tone Generator 2", "Tone Generator 2" }, \
{ name, "Haptics", "HAPTICS" }, \
{ name, "AEC", "AEC Loopback" }, \
{ name, "IN1L", "IN1L PGA" }, \
{ name, "IN1R", "IN1R PGA" }, \
@ -786,10 +808,10 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"),
ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"),
ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"),
ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"),
ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"),
ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"),
ARIZONA_MUX_ROUTES("ASRC1L"),
ARIZONA_MUX_ROUTES("ASRC1R"),
ARIZONA_MUX_ROUTES("ASRC2L"),
ARIZONA_MUX_ROUTES("ASRC2R"),
{ "HPOUT1L", NULL, "OUT1L" },
{ "HPOUT1R", NULL, "OUT1R" },
@ -902,9 +924,29 @@ static struct snd_soc_dai_driver wm5110_dai[] = {
static int wm5110_codec_probe(struct snd_soc_codec *codec)
{
struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
int ret;
codec->control_data = priv->core.arizona->regmap;
return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
priv->core.arizona->dapm = &codec->dapm;
ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
if (ret != 0)
return ret;
snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
priv->core.arizona->dapm = &codec->dapm;
return 0;
}
static int wm5110_codec_remove(struct snd_soc_codec *codec)
{
struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
priv->core.arizona->dapm = NULL;
return 0;
}
#define WM5110_DIG_VU 0x0200
@ -935,6 +977,7 @@ static unsigned int wm5110_digital_vu[] = {
static struct snd_soc_codec_driver soc_codec_dev_wm5110 = {
.probe = wm5110_codec_probe,
.remove = wm5110_codec_remove,
.idle_bias_off = true,

View File

@ -544,6 +544,28 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
switch (event) {
case SND_SOC_DAPM_POST_PMU:
/*
* For simplicity set the DSP clock rate to be the
* SYSCLK rate rather than making it configurable.
*/
ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val);
if (ret != 0) {
adsp_err(dsp, "Failed to read SYSCLK state: %d\n",
ret);
return ret;
}
val = (val & ARIZONA_SYSCLK_FREQ_MASK)
>> ARIZONA_SYSCLK_FREQ_SHIFT;
ret = regmap_update_bits(dsp->regmap,
dsp->base + ADSP2_CLOCKING,
ADSP2_CLK_SEL_MASK, val);
if (ret != 0) {
adsp_err(dsp, "Failed to set clock rate: %d\n",
ret);
return ret;
}
if (dsp->dvfs) {
ret = regmap_read(dsp->regmap,
dsp->base + ADSP2_CLOCKING, &val);
@ -631,6 +653,17 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
{
int ret;
/*
* Disable the DSP memory by default when in reset for a small
* power saving.
*/
ret = regmap_update_bits(adsp->regmap, adsp->base + ADSP2_CONTROL,
ADSP2_MEM_ENA, 0);
if (ret != 0) {
adsp_err(adsp, "Failed to clear memory retention: %d\n", ret);
return ret;
}
if (dvfs) {
adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");
if (IS_ERR(adsp->dvfs)) {