ASoC: Updates for v3.20

More updates for v3.20:
 
  - Lots of refactoring from Lars-Peter Clausen, moving drivers to more
    data driven initialization and rationalizing a lot of DAPM usage.
  - Much improved handling of CDCLK clocks on Samsung I2S controllers.
  - Lots of driver specific cleanups and feature improvements.
  - CODEC support for TI PCM514x and TLV320AIC3104 devices.
  - Board support for Tegra systems with Realtek RT5677.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJU0ok8AAoJECTWi3JdVIfQ3ccH/2zb+b477H4GNhUw5AEzdHtC
 L7CI+5Q9VOGJQmZTjayRdUcPUHx4sTpYdQVTI56Q6CJk0OFljKNJcRrbzPqNgJ46
 yOrMTIpNvzFEv46f7rX2uKfvAFOVRAA2f+gl34AMLXqxL5aydbZZBtoe2jP9lL8z
 fIZ/s7qXHn3xnvxqNwOz3pnu6wFDrxbG34lXZaTaFQOueZ3fsthWLsz0xtO6a7aI
 J9tA+wejd9qf+D3i6svsi+MhB6OehYMh9Fbm+ODj6NMWZGCIA3SJ/PD+gbCg318+
 Xo0FNOyiw0fSAeBcHrEcfoaWBJrswxXjXaNbrIXc1/0gTj8AOJHCRus3w0OQU+Q=
 =Yw2l
 -----END PGP SIGNATURE-----

Merge tag 'asoc-v3.20-2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-next

ASoC: Updates for v3.20

More updates for v3.20:

 - Lots of refactoring from Lars-Peter Clausen, moving drivers to more
   data driven initialization and rationalizing a lot of DAPM usage.
 - Much improved handling of CDCLK clocks on Samsung I2S controllers.
 - Lots of driver specific cleanups and feature improvements.
 - CODEC support for TI PCM514x and TLV320AIC3104 devices.
 - Board support for Tegra systems with Realtek RT5677.

Conflicts:
	sound/soc/intel/sst-mfld-platform-pcm.c
This commit is contained in:
Takashi Iwai 2015-02-05 07:08:35 +01:00
commit a3ae255e37
187 changed files with 5296 additions and 2083 deletions

View File

@ -0,0 +1,18 @@
Bindings for I2S controller built into xtfpga Xtensa bitstreams.
Required properties:
- compatible: shall be "cdns,xtfpga-i2s".
- reg: memory region (address and length) with device registers.
- interrupts: interrupt for the device.
- clocks: phandle to the clk used as master clock. I2S bus clock
is derived from it.
Examples:
i2s0: xtfpga-i2s@0d080000 {
#sound-dai-cells = <0>;
compatible = "cdns,xtfpga-i2s";
reg = <0x0d080000 0x40>;
interrupts = <2 1>;
clocks = <&cdce706 4>;
};

View File

@ -0,0 +1,31 @@
DesignWare I2S controller
Required properties:
- compatible : Must be "snps,designware-i2s"
- reg : Must contain the I2S core's registers location and length
- clocks : Pairs of phandle and specifier referencing the controller's
clocks. The controller expects one clock: the clock used as the sampling
rate reference clock sample.
- clock-names : "i2sclk" for the sample rate reference clock.
- dmas: Pairs of phandle and specifier for the DMA channels that are used by
the core. The core expects one or two dma channels: one for transmit and
one for receive.
- dma-names : "tx" for the transmit channel, "rx" for the receive channel.
For more details on the 'dma', 'dma-names', 'clock' and 'clock-names'
properties please check:
* resource-names.txt
* clock/clock-bindings.txt
* dma/dma.txt
Example:
soc_i2s: i2s@7ff90000 {
compatible = "snps,designware-i2s";
reg = <0x0 0x7ff90000 0x0 0x1000>;
clocks = <&scpi_i2sclk 0>;
clock-names = "i2sclk";
#sound-dai-cells = <0>;
dmas = <&dma0 5>;
dma-names = "tx";
};

View File

@ -0,0 +1,67 @@
NVIDIA Tegra audio complex, with RT5677 CODEC
Required properties:
- compatible : "nvidia,tegra-audio-rt5677"
- clocks : Must contain an entry for each entry in clock-names.
See ../clocks/clock-bindings.txt for details.
- clock-names : Must include the following entries:
- pll_a
- pll_a_out0
- mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
- nvidia,model : The user-visible name of this sound complex.
- nvidia,audio-routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources and
sinks are the RT5677's pins (as documented in its binding), and the jacks
on the board:
* Headphone
* Speaker
* Headset Mic
* Internal Mic 1
* Internal Mic 2
- nvidia,i2s-controller : The phandle of the Tegra I2S controller that's
connected to the CODEC.
- nvidia,audio-codec : The phandle of the RT5677 audio codec. This binding
assumes that AIF1 on the CODEC is connected to Tegra.
Optional properties:
- nvidia,hp-det-gpios : The GPIO that detects headphones are plugged in
- nvidia,hp-en-gpios : The GPIO that enables headphone amplifier
- nvidia,mic-present-gpios: The GPIO that mic jack is plugged in
- nvidia,dmic-clk-en-gpios : The GPIO that gates DMIC clock signal
Example:
sound {
compatible = "nvidia,tegra-audio-rt5677-ryu",
"nvidia,tegra-audio-rt5677";
nvidia,model = "NVIDIA Tegra Ryu";
nvidia,audio-routing =
"Headphone", "LOUT2",
"Headphone", "LOUT1",
"Headset Mic", "MICBIAS1",
"IN1P", "Headset Mic",
"IN1N", "Headset Mic",
"DMIC L1", "Internal Mic 1",
"DMIC R1", "Internal Mic 1",
"DMIC L2", "Internal Mic 2",
"DMIC R2", "Internal Mic 2",
"Speaker", "PDM1L",
"Speaker", "PDM1R";
nvidia,i2s-controller = <&tegra_i2s1>;
nvidia,audio-codec = <&rt5677>;
nvidia,hp-det-gpios = <&gpio TEGRA_GPIO(R, 7) GPIO_ACTIVE_HIGH>;
nvidia,mic-present-gpios = <&gpio TEGRA_GPIO(O, 5) GPIO_ACTIVE_LOW>;
nvidia,hp-en-gpios = <&rt5677 1 GPIO_ACTIVE_HIGH>;
nvidia,dmic-clk-en-gpios = <&rt5677 2 GPIO_ACTIVE_HIGH>;
clocks = <&tegra_car TEGRA124_CLK_PLL_A>,
<&tegra_car TEGRA124_CLK_PLL_A_OUT0>,
<&tegra_car TEGRA124_CLK_EXTERN1>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};

View File

@ -17,9 +17,16 @@ Required properties:
Optional properties:
- clocks : A clock specifier for the clock connected as SCLK. If this
is absent the device will be configured to clock from BCLK.
is absent the device will be configured to clock from BCLK. If pll-in
and pll-out are specified in addition to a clock, the device is
configured to accept clock input on a specified gpio pin.
Example:
- pll-in, pll-out : gpio pins used to connect the pll using <1>
through <6>. The device will be configured for clock input on the
given pll-in pin and PLL output on the given pll-out pin. An
external connection from the pll-out pin to the SCLK pin is assumed.
Examples:
pcm5122: pcm5122@4c {
compatible = "ti,pcm5122";
@ -29,3 +36,17 @@ Example:
DVDD-supply = <&reg_1v8>;
CPVDD-supply = <&reg_3v3>;
};
pcm5142: pcm5142@4c {
compatible = "ti,pcm5142";
reg = <0x4c>;
AVDD-supply = <&reg_3v3_analog>;
DVDD-supply = <&reg_1v8>;
CPVDD-supply = <&reg_3v3>;
clocks = <&sck>;
pll-in = <3>;
pll-out = <6>;
};

View File

@ -33,6 +33,25 @@ Required SoC Specific Properties:
"iis" is the i2s bus clock and i2s_opclk0, i2s_opclk1 are sources of the root
clk. i2s0 has internal mux to select the source of root clk and i2s1 and i2s2
doesn't have any such mux.
- #clock-cells: should be 1, this property must be present if the I2S device
is a clock provider in terms of the common clock bindings, described in
../clock/clock-bindings.txt.
- clock-output-names: from the common clock bindings, names of the CDCLK
I2S output clocks, suggested values are "i2s_cdclk0", "i2s_cdclk1",
"i2s_cdclk3" for the I2S0, I2S1, I2S2 devices recpectively.
There are following clocks available at the I2S device nodes:
CLK_I2S_CDCLK - the CDCLK (CODECLKO) gate clock,
CLK_I2S_RCLK_PSR - the RCLK prescaler divider clock (corresponding to the
IISPSR register),
CLK_I2S_RCLK_SRC - the RCLKSRC mux clock (corresponding to RCLKSRC bit in
IISMOD register).
Refer to the SoC datasheet for availability of the above clocks.
The CLK_I2S_RCLK_PSR and CLK_I2S_RCLK_SRC clocks are usually only available
in the IIS Multi Audio Interface (I2S0).
Note: Old DTs may not have the #clock-cells, clock-output-names properties
and then not use the I2S node as a clock supplier.
Optional SoC Specific Properties:
@ -41,6 +60,7 @@ Optional SoC Specific Properties:
- pinctrl-0: Should specify pin control groups used for this controller.
- pinctrl-names: Should contain only one value - "default".
Example:
i2s0: i2s@03830000 {
@ -54,6 +74,8 @@ i2s0: i2s@03830000 {
<&clock_audss EXYNOS_I2S_BUS>,
<&clock_audss EXYNOS_SCLK_I2S>;
clock-names = "iis", "i2s_opclk0", "i2s_opclk1";
#clock-cells;
clock-output-names = "i2s_cdclk0";
samsung,idma-addr = <0x03000000>;
pinctrl-names = "default";
pinctrl-0 = <&i2s0_bus>;

View File

@ -75,6 +75,11 @@ Optional CPU/CODEC subnodes properties:
it can be specified via "clocks" if system has
clock node (= common clock), or "system-clock-frequency"
(if system doens't support common clock)
If a clock is specified, it is
enabled with clk_prepare_enable()
in dai startup() and disabled with
clk_disable_unprepare() in dai
shutdown().
Example 1 - single DAI link:

View File

@ -0,0 +1,92 @@
STA32X audio CODEC
The driver for this device only supports I2C.
Required properties:
- compatible: "st,sta32x"
- reg: the I2C address of the device for I2C
- reset-gpios: a GPIO spec for the reset pin. If specified, it will be
deasserted before communication to the codec starts.
- power-down-gpios: a GPIO spec for the power down pin. If specified,
it will be deasserted before communication to the codec
starts.
- Vdda-supply: regulator spec, providing 3.3V
- Vdd3-supply: regulator spec, providing 3.3V
- Vcc-supply: regulator spec, providing 5V - 26V
Optional properties:
- st,output-conf: number, Selects the output configuration:
0: 2-channel (full-bridge) power, 2-channel data-out
1: 2 (half-bridge). 1 (full-bridge) on-board power
2: 2 Channel (Full-Bridge) Power, 1 Channel FFX
3: 1 Channel Mono-Parallel
If parameter is missing, mode 0 will be enabled.
This property has to be specified as '/bits/ 8' value.
- st,ch1-output-mapping: Channel 1 output mapping
- st,ch2-output-mapping: Channel 2 output mapping
- st,ch3-output-mapping: Channel 3 output mapping
0: Channel 1
1: Channel 2
2: Channel 3
If parameter is missing, channel 1 is chosen.
This properties have to be specified as '/bits/ 8' values.
- st,thermal-warning-recover:
If present, thermal warning recovery is enabled.
- st,thermal-warning-adjustment:
If present, thermal warning adjustment is enabled.
- st,fault-detect-recovery:
If present, then fault recovery will be enabled.
- st,drop-compensation-ns: number
Only required for "st,ffx-power-output-mode" ==
"variable-drop-compensation".
Specifies the drop compensation in nanoseconds.
The value must be in the range of 0..300, and only
multiples of 20 are allowed. Default is 140ns.
- st,max-power-use-mpcc:
If present, then MPCC bits are used for MPC coefficients,
otherwise standard MPC coefficients are used.
- st,max-power-corr:
If present, power bridge correction for THD reduction near maximum
power output is enabled.
- st,am-reduction-mode:
If present, FFX mode runs in AM reduction mode, otherwise normal
FFX mode is used.
- st,odd-pwm-speed-mode:
If present, PWM speed mode run on odd speed mode (341.3 kHz) on all
channels. If not present, normal PWM spped mode (384 kHz) will be used.
- st,invalid-input-detect-mute:
If present, automatic invalid input detect mute is enabled.
Example:
codec: sta32x@38 {
compatible = "st,sta32x";
reg = <0x1c>;
reset-gpios = <&gpio1 19 0>;
power-down-gpios = <&gpio1 16 0>;
st,output-conf = /bits/ 8 <0x3>; // set output to 2-channel
// (full-bridge) power,
// 2-channel data-out
st,ch1-output-mapping = /bits/ 8 <0>; // set channel 1 output ch 1
st,ch2-output-mapping = /bits/ 8 <0>; // set channel 2 output ch 1
st,ch3-output-mapping = /bits/ 8 <0>; // set channel 3 output ch 1
st,max-power-correction; // enables power bridge
// correction for THD reduction
// near maximum power output
st,invalid-input-detect-mute; // mute if no valid digital
// audio signal is provided.
};

View File

@ -9,6 +9,7 @@ Required properties:
"ti,tlv320aic33" - TLV320AIC33
"ti,tlv320aic3007" - TLV320AIC3007
"ti,tlv320aic3106" - TLV320AIC3106
"ti,tlv320aic3104" - TLV320AIC3104
- reg - <int> - I2C slave address
@ -18,6 +19,7 @@ Optional properties:
- gpio-reset - gpio pin number used for codec reset
- ai3x-gpio-func - <array of 2 int> - AIC3X_GPIO1 & AIC3X_GPIO2 Functionality
- Not supported on tlv320aic3104
- ai3x-micbias-vg - MicBias Voltage required.
1 - MICBIAS output is powered to 2.0V,
2 - MICBIAS output is powered to 2.5V,
@ -36,7 +38,13 @@ CODEC output pins:
* HPLCOM
* HPRCOM
CODEC input pins:
CODEC input pins for TLV320AIC3104:
* MIC2L
* MIC2R
* LINE1L
* LINE1R
CODEC input pins for other compatible codecs:
* MIC3L
* MIC3R
* LINE1L

View File

@ -13,6 +13,11 @@ Required properties:
- interrupt-parent: The parent interrupt controller
- interrupts: Interrupt number for /INT pin from the 227e
Optional properies:
- ti,micbias: Intended MICBIAS voltage (datasheet section 9.6.7).
Select 0/1/2/3/4/5/6/7 to specify MACBIAS voltage
2.1V/2.2V/2.3V/2.4V/2.5V/2.6V/2.7V/2.8V
Default value is "1" (2.2V).
Examples:

View File

@ -3,7 +3,7 @@ WM8904 audio CODEC
This device supports I2C only.
Required properties:
- compatible: "wlf,wm8904"
- compatible: "wlf,wm8904" or "wlf,wm8912"
- reg: the I2C address of the device.
- clock-names: "mclk"
- clocks: reference to

View File

@ -4953,6 +4953,16 @@ F: Documentation/input/multi-touch-protocol.txt
F: drivers/input/input-mt.c
K: \b(ABS|SYN)_MT_
INTEL ASoC BDW/HSW DRIVERS
M: Jie Yang <yang.jie@linux.intel.com>
L: alsa-devel@alsa-project.org
S: Supported
F: sound/soc/intel/sst-haswell*
F: sound/soc/intel/sst-dsp*
F: sound/soc/intel/sst-firmware.c
F: sound/soc/intel/broadwell.c
F: sound/soc/intel/haswell.c
INTEL C600 SERIES SAS CONTROLLER DRIVER
M: Intel SCU Linux support <intel-linux-scu@intel.com>
M: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
@ -10659,6 +10669,7 @@ M: Max Filippov <jcmvbkbc@gmail.com>
L: linux-xtensa@linux-xtensa.org
S: Maintained
F: drivers/spi/spi-xtensa-xtfpga.c
F: sound/soc/xtensa/xtfpga-i2s.c
YAM DRIVER FOR AX.25
M: Jean-Paul Roubelat <jpr@f6fbb.org>

View File

@ -0,0 +1,8 @@
#ifndef _DT_BINDINGS_SAMSUNG_I2S_H
#define _DT_BINDINGS_SAMSUNG_I2S_H
#define CLK_I2S_CDCLK 0
#define CLK_I2S_RCLK_SRC 1
#define CLK_I2S_RCLK_PSR 2
#endif /* _DT_BINDINGS_SAMSUNG_I2S_H */

View File

@ -273,6 +273,12 @@ struct snd_pcm_hw_constraint_list {
unsigned int mask;
};
struct snd_pcm_hw_constraint_ranges {
unsigned int count;
const struct snd_interval *ranges;
unsigned int mask;
};
struct snd_pcm_hwptr_log;
struct snd_pcm_runtime {
@ -907,6 +913,8 @@ void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,
const struct snd_interval *b, struct snd_interval *c);
int snd_interval_list(struct snd_interval *i, unsigned int count,
const unsigned int *list, unsigned int mask);
int snd_interval_ranges(struct snd_interval *i, unsigned int count,
const struct snd_interval *list, unsigned int mask);
int snd_interval_ratnum(struct snd_interval *i,
unsigned int rats_count, struct snd_ratnum *rats,
unsigned int *nump, unsigned int *denp);
@ -931,6 +939,10 @@ int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime,
unsigned int cond,
snd_pcm_hw_param_t var,
const struct snd_pcm_hw_constraint_list *l);
int snd_pcm_hw_constraint_ranges(struct snd_pcm_runtime *runtime,
unsigned int cond,
snd_pcm_hw_param_t var,
const struct snd_pcm_hw_constraint_ranges *r);
int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime,
unsigned int cond,
snd_pcm_hw_param_t var,

View File

@ -55,6 +55,7 @@ struct rsnd_ssi_platform_info {
struct rsnd_src_platform_info {
u32 convert_rate; /* sampling rate convert */
int dma_id; /* for Gen2 SCU */
int irq;
};
/*

View File

@ -37,6 +37,9 @@ struct rt5677_platform_data {
OFF, GPIO4, GPIO5 and GPIO6 respectively */
unsigned int jd2_gpio;
unsigned int jd3_gpio;
/* Set MICBIAS1 VDD 1v8 or 3v3 */
bool micbias1_vdd_3v3;
};
#endif

View File

@ -20,6 +20,7 @@ struct asoc_simple_dai {
unsigned int sysclk;
int slots;
int slot_width;
struct clk *clk;
};
struct asoc_simple_card_info {

View File

@ -405,7 +405,7 @@ int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm,
struct snd_soc_dapm_update *update);
/* dapm sys fs - used by the core */
int snd_soc_dapm_sys_add(struct device *dev);
extern struct attribute *soc_dapm_dev_attrs[];
void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
struct dentry *parent);
@ -525,7 +525,6 @@ struct snd_soc_dapm_widget {
enum snd_soc_dapm_type id;
const char *name; /* widget name */
const char *sname; /* stream name */
struct snd_soc_codec *codec;
struct list_head list;
struct snd_soc_dapm_context *dapm;

View File

@ -429,6 +429,9 @@ bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd);
void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream);
void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream);
int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd,
unsigned int dai_fmt);
/* Utility functions to get clock rates from various things */
int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params);
@ -498,6 +501,7 @@ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg,
unsigned int mask, unsigned int value);
#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);
void snd_soc_free_ac97_codec(struct snd_ac97 *ac97);

View File

@ -24,12 +24,20 @@
#define STA32X_THERMAL_RECOVERY_ENABLE 2
struct sta32x_platform_data {
int output_conf;
int ch1_output_mapping;
int ch2_output_mapping;
int ch3_output_mapping;
int thermal_conf;
u8 output_conf;
u8 ch1_output_mapping;
u8 ch2_output_mapping;
u8 ch3_output_mapping;
int needs_esd_watchdog;
u8 drop_compensation_ns;
unsigned int thermal_warning_recovery:1;
unsigned int thermal_warning_adjustment:1;
unsigned int fault_detect_recovery:1;
unsigned int max_power_use_mpcc:1;
unsigned int max_power_correction:1;
unsigned int am_reduction_mode:1;
unsigned int odd_pwm_speed_mode:1;
unsigned int invalid_input_detect_mute:1;
};
#endif /* __LINUX_SND__STA32X_H */

View File

@ -1015,6 +1015,60 @@ int snd_interval_list(struct snd_interval *i, unsigned int count,
EXPORT_SYMBOL(snd_interval_list);
/**
* snd_interval_ranges - refine the interval value from the list of ranges
* @i: the interval value to refine
* @count: the number of elements in the list of ranges
* @ranges: the ranges list
* @mask: the bit-mask to evaluate
*
* Refines the interval value from the list of ranges.
* When mask is non-zero, only the elements corresponding to bit 1 are
* evaluated.
*
* Return: Positive if the value is changed, zero if it's not changed, or a
* negative error code.
*/
int snd_interval_ranges(struct snd_interval *i, unsigned int count,
const struct snd_interval *ranges, unsigned int mask)
{
unsigned int k;
struct snd_interval range_union;
struct snd_interval range;
if (!count) {
snd_interval_none(i);
return -EINVAL;
}
snd_interval_any(&range_union);
range_union.min = UINT_MAX;
range_union.max = 0;
for (k = 0; k < count; k++) {
if (mask && !(mask & (1 << k)))
continue;
snd_interval_copy(&range, &ranges[k]);
if (snd_interval_refine(&range, i) < 0)
continue;
if (snd_interval_empty(&range))
continue;
if (range.min < range_union.min) {
range_union.min = range.min;
range_union.openmin = 1;
}
if (range.min == range_union.min && !range.openmin)
range_union.openmin = 0;
if (range.max > range_union.max) {
range_union.max = range.max;
range_union.openmax = 1;
}
if (range.max == range_union.max && !range.openmax)
range_union.openmax = 0;
}
return snd_interval_refine(i, &range_union);
}
EXPORT_SYMBOL(snd_interval_ranges);
static int snd_interval_step(struct snd_interval *i, unsigned int step)
{
unsigned int n;
@ -1221,6 +1275,37 @@ int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime,
EXPORT_SYMBOL(snd_pcm_hw_constraint_list);
static int snd_pcm_hw_rule_ranges(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{
struct snd_pcm_hw_constraint_ranges *r = rule->private;
return snd_interval_ranges(hw_param_interval(params, rule->var),
r->count, r->ranges, r->mask);
}
/**
* snd_pcm_hw_constraint_ranges - apply list of range constraints to a parameter
* @runtime: PCM runtime instance
* @cond: condition bits
* @var: hw_params variable to apply the list of range constraints
* @r: ranges
*
* Apply the list of range constraints to an interval parameter.
*
* Return: Zero if successful, or a negative error code on failure.
*/
int snd_pcm_hw_constraint_ranges(struct snd_pcm_runtime *runtime,
unsigned int cond,
snd_pcm_hw_param_t var,
const struct snd_pcm_hw_constraint_ranges *r)
{
return snd_pcm_hw_rule_add(runtime, cond, var,
snd_pcm_hw_rule_ranges, (void *)r,
var, -1);
}
EXPORT_SYMBOL(snd_pcm_hw_constraint_ranges);
static int snd_pcm_hw_rule_ratnums(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{

View File

@ -55,6 +55,7 @@ source "sound/soc/spear/Kconfig"
source "sound/soc/tegra/Kconfig"
source "sound/soc/txx9/Kconfig"
source "sound/soc/ux500/Kconfig"
source "sound/soc/xtensa/Kconfig"
# Supported codecs
source "sound/soc/codecs/Kconfig"

View File

@ -36,3 +36,4 @@ obj-$(CONFIG_SND_SOC) += spear/
obj-$(CONFIG_SND_SOC) += tegra/
obj-$(CONFIG_SND_SOC) += txx9/
obj-$(CONFIG_SND_SOC) += ux500/
obj-$(CONFIG_SND_SOC) += xtensa/

View File

@ -45,7 +45,7 @@ config SND_ATMEL_SOC_WM8904
config SND_AT91_SOC_SAM9X5_WM8731
tristate "SoC Audio support for WM8731-based at91sam9x5 board"
depends on ATMEL_SSC && SND_ATMEL_SOC && SOC_AT91SAM9X5
depends on ARCH_AT91 && ATMEL_SSC && SND_ATMEL_SOC
select SND_ATMEL_SOC_SSC
select SND_ATMEL_SOC_DMA
select SND_SOC_WM8731

View File

@ -105,13 +105,11 @@ static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream,
return ret;
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
slave_config->dst_addr = ssc->phybase + SSC_THR;
slave_config->dst_maxburst = 1;
} else {
slave_config->src_addr = ssc->phybase + SSC_RHR;
slave_config->src_maxburst = 1;
}
slave_config->dst_addr = ssc->phybase + SSC_THR;
slave_config->dst_maxburst = 1;
slave_config->src_addr = ssc->phybase + SSC_RHR;
slave_config->src_maxburst = 1;
prtd->dma_intr_handler = atmel_pcm_dma_irq;

View File

@ -204,6 +204,13 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n",
ssc_readl(ssc_p->ssc->regs, SR));
/* Enable PMC peripheral clock for this SSC */
pr_debug("atmel_ssc_dai: Starting clock\n");
clk_enable(ssc_p->ssc->clk);
/* Reset the SSC to keep it at a clean status */
ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
dir = 0;
dir_mask = SSC_DIR_MASK_PLAYBACK;
@ -250,11 +257,6 @@ static void atmel_ssc_shutdown(struct snd_pcm_substream *substream,
dma_params = ssc_p->dma_params[dir];
if (dma_params != NULL) {
ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable);
pr_debug("atmel_ssc_shutdown: %s disabled SSC_SR=0x%08x\n",
(dir ? "receive" : "transmit"),
ssc_readl(ssc_p->ssc->regs, SR));
dma_params->ssc = NULL;
dma_params->substream = NULL;
ssc_p->dma_params[dir] = NULL;
@ -266,10 +268,6 @@ static void atmel_ssc_shutdown(struct snd_pcm_substream *substream,
ssc_p->dir_mask &= ~dir_mask;
if (!ssc_p->dir_mask) {
if (ssc_p->initialized) {
/* Shutdown the SSC clock. */
pr_debug("atmel_ssc_dai: Stopping clock\n");
clk_disable(ssc_p->ssc->clk);
free_irq(ssc_p->ssc->irq, ssc_p);
ssc_p->initialized = 0;
}
@ -280,6 +278,10 @@ static void atmel_ssc_shutdown(struct snd_pcm_substream *substream,
ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0;
}
spin_unlock_irq(&ssc_p->lock);
/* Shutdown the SSC clock. */
pr_debug("atmel_ssc_dai: Stopping clock\n");
clk_disable(ssc_p->ssc->clk);
}
@ -348,7 +350,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
struct atmel_pcm_dma_params *dma_params;
int dir, channels, bits;
u32 tfmr, rfmr, tcmr, rcmr;
int start_event;
int ret;
int fslen, fslen_ext;
@ -451,25 +452,10 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
break;
case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
/*
* I2S format, CODEC supplies BCLK and LRC clocks.
*
* The SSC transmit clock is obtained from the BCLK signal on
* on the TK line, and the SSC receive clock is
* generated from the transmit clock.
*
* For single channel data, one sample is transferred
* on the falling edge of the LRC clock.
* For two channel data, one sample is
* transferred on both edges of the LRC clock.
*/
start_event = ((channels == 1)
? SSC_START_FALLING_RF
: SSC_START_EDGE_RF);
/* I2S format, CODEC supplies BCLK and LRC clocks. */
rcmr = SSC_BF(RCMR_PERIOD, 0)
| SSC_BF(RCMR_STTDLY, START_DELAY)
| SSC_BF(RCMR_START, start_event)
| SSC_BF(RCMR_START, SSC_START_FALLING_RF)
| SSC_BF(RCMR_CKI, SSC_CKI_RISING)
| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
| SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ?
@ -478,14 +464,14 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
| SSC_BF(RFMR_FSOS, SSC_FSOS_NONE)
| SSC_BF(RFMR_FSLEN, 0)
| SSC_BF(RFMR_DATNB, 0)
| SSC_BF(RFMR_DATNB, (channels - 1))
| SSC_BIT(RFMR_MSBF)
| SSC_BF(RFMR_LOOP, 0)
| SSC_BF(RFMR_DATLEN, (bits - 1));
tcmr = SSC_BF(TCMR_PERIOD, 0)
| SSC_BF(TCMR_STTDLY, START_DELAY)
| SSC_BF(TCMR_START, start_event)
| SSC_BF(TCMR_START, SSC_START_FALLING_RF)
| SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
| SSC_BF(TCMR_CKO, SSC_CKO_NONE)
| SSC_BF(TCMR_CKS, ssc->clk_from_rk_pin ?
@ -495,7 +481,55 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
| SSC_BF(TFMR_FSDEN, 0)
| SSC_BF(TFMR_FSOS, SSC_FSOS_NONE)
| SSC_BF(TFMR_FSLEN, 0)
| SSC_BF(TFMR_DATNB, 0)
| SSC_BF(TFMR_DATNB, (channels - 1))
| SSC_BIT(TFMR_MSBF)
| SSC_BF(TFMR_DATDEF, 0)
| SSC_BF(TFMR_DATLEN, (bits - 1));
break;
case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFS:
/* I2S format, CODEC supplies BCLK, SSC supplies LRCLK. */
if (bits > 16 && !ssc->pdata->has_fslen_ext) {
dev_err(dai->dev,
"sample size %d is too large for SSC device\n",
bits);
return -EINVAL;
}
fslen_ext = (bits - 1) / 16;
fslen = (bits - 1) % 16;
rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
| SSC_BF(RCMR_STTDLY, START_DELAY)
| SSC_BF(RCMR_START, SSC_START_FALLING_RF)
| SSC_BF(RCMR_CKI, SSC_CKI_RISING)
| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
| SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ?
SSC_CKS_PIN : SSC_CKS_CLOCK);
rfmr = SSC_BF(RFMR_FSLEN_EXT, fslen_ext)
| SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
| SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE)
| SSC_BF(RFMR_FSLEN, fslen)
| SSC_BF(RFMR_DATNB, (channels - 1))
| SSC_BIT(RFMR_MSBF)
| SSC_BF(RFMR_LOOP, 0)
| SSC_BF(RFMR_DATLEN, (bits - 1));
tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period)
| SSC_BF(TCMR_STTDLY, START_DELAY)
| SSC_BF(TCMR_START, SSC_START_FALLING_RF)
| SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
| SSC_BF(TCMR_CKO, SSC_CKO_NONE)
| SSC_BF(TCMR_CKS, ssc->clk_from_rk_pin ?
SSC_CKS_CLOCK : SSC_CKS_PIN);
tfmr = SSC_BF(TFMR_FSLEN_EXT, fslen_ext)
| SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_NEGATIVE)
| SSC_BF(TFMR_FSDEN, 0)
| SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE)
| SSC_BF(TFMR_FSLEN, fslen)
| SSC_BF(TFMR_DATNB, (channels - 1))
| SSC_BIT(TFMR_MSBF)
| SSC_BF(TFMR_DATDEF, 0)
| SSC_BF(TFMR_DATLEN, (bits - 1));
@ -512,7 +546,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
| SSC_BF(RCMR_STTDLY, 1)
| SSC_BF(RCMR_START, SSC_START_RISING_RF)
| SSC_BF(RCMR_CKI, SSC_CKI_RISING)
| SSC_BF(RCMR_CKI, SSC_CKI_FALLING)
| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
| SSC_BF(RCMR_CKS, SSC_CKS_DIV);
@ -527,7 +561,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period)
| SSC_BF(TCMR_STTDLY, 1)
| SSC_BF(TCMR_START, SSC_START_RISING_RF)
| SSC_BF(TCMR_CKI, SSC_CKI_RISING)
| SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
| SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
| SSC_BF(TCMR_CKS, SSC_CKS_DIV);
@ -545,10 +579,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
/*
* DSP/PCM Mode A format, CODEC supplies BCLK and LRC clocks.
*
* The SSC transmit clock is obtained from the BCLK signal on
* on the TK line, and the SSC receive clock is
* generated from the transmit clock.
*
* Data is transferred on first BCLK after LRC pulse rising
* edge.If stereo, the right channel data is contiguous with
* the left channel data.
@ -556,7 +586,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
rcmr = SSC_BF(RCMR_PERIOD, 0)
| SSC_BF(RCMR_STTDLY, START_DELAY)
| SSC_BF(RCMR_START, SSC_START_RISING_RF)
| SSC_BF(RCMR_CKI, SSC_CKI_RISING)
| SSC_BF(RCMR_CKI, SSC_CKI_FALLING)
| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
| SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ?
SSC_CKS_PIN : SSC_CKS_CLOCK);
@ -597,23 +627,17 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
rcmr, rfmr, tcmr, tfmr);
if (!ssc_p->initialized) {
if (!ssc_p->ssc->pdata->use_dma) {
ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0);
ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0);
ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0);
ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0);
/* Enable PMC peripheral clock for this SSC */
pr_debug("atmel_ssc_dai: Starting clock\n");
clk_enable(ssc_p->ssc->clk);
/* Reset the SSC and its PDC registers */
ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0);
ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0);
ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0);
ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0);
ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0);
ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0);
ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0);
ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0);
ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0);
ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0);
ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0);
ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0);
}
ret = request_irq(ssc_p->ssc->irq, atmel_ssc_interrupt, 0,
ssc_p->name, ssc_p);

View File

@ -47,7 +47,6 @@
#include <sound/soc.h>
#include <asm/mach-types.h>
#include <mach/hardware.h>
#include "../codecs/wm8731.h"
#include "atmel-pcm.h"
@ -64,33 +63,6 @@
static struct clk *mclk;
static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int ret;
/* set codec DAI configuration */
ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
if (ret < 0)
return ret;
/* set cpu DAI configuration */
ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
if (ret < 0)
return ret;
return 0;
}
static struct snd_soc_ops at91sam9g20ek_ops = {
.hw_params = at91sam9g20ek_hw_params,
};
static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level)
@ -173,7 +145,8 @@ static struct snd_soc_dai_link at91sam9g20ek_dai = {
.init = at91sam9g20ek_wm8731_init,
.platform_name = "at91rm9200_ssc.0",
.codec_name = "wm8731.0-001b",
.ops = &at91sam9g20ek_ops,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM,
};
static struct snd_soc_card snd_soc_at91sam9g20ek = {

View File

@ -91,27 +91,12 @@ static int db1200_i2s_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int ret;
/* WM8731 has its own 12MHz crystal */
snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL,
12000000, SND_SOC_CLOCK_IN);
/* codec is bitclock and lrclk master */
ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
if (ret < 0)
goto out;
ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_LEFT_J |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
if (ret < 0)
goto out;
ret = 0;
out:
return ret;
return 0;
}
static struct snd_soc_ops db1200_i2s_wm8731_ops = {
@ -125,6 +110,8 @@ static struct snd_soc_dai_link db1200_i2s_dai = {
.cpu_dai_name = "au1xpsc_i2s.1",
.platform_name = "au1xpsc-pcm.1",
.codec_name = "wm8731.0-001b",
.dai_fmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM,
.ops = &db1200_i2s_wm8731_ops,
};

View File

@ -315,11 +315,6 @@ static struct snd_pcm_ops au1xpsc_pcm_ops = {
.pointer = au1xpsc_pcm_pointer,
};
static void au1xpsc_pcm_free_dma_buffers(struct snd_pcm *pcm)
{
snd_pcm_lib_preallocate_free_for_all(pcm);
}
static int au1xpsc_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
@ -335,7 +330,6 @@ static int au1xpsc_pcm_new(struct snd_soc_pcm_runtime *rtd)
static struct snd_soc_platform_driver au1xpsc_soc_platform = {
.ops = &au1xpsc_pcm_ops,
.pcm_new = au1xpsc_pcm_new,
.pcm_free = au1xpsc_pcm_free_dma_buffers,
};
static int au1xpsc_pcm_drvprobe(struct platform_device *pdev)

View File

@ -287,11 +287,6 @@ static struct snd_pcm_ops alchemy_pcm_ops = {
.pointer = alchemy_pcm_pointer,
};
static void alchemy_pcm_free_dma_buffers(struct snd_pcm *pcm)
{
snd_pcm_lib_preallocate_free_for_all(pcm);
}
static int alchemy_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_pcm *pcm = rtd->pcm;
@ -305,7 +300,6 @@ static int alchemy_pcm_new(struct snd_soc_pcm_runtime *rtd)
static struct snd_soc_platform_driver alchemy_pcm_soc_platform = {
.ops = &alchemy_pcm_ops,
.pcm_new = alchemy_pcm_new,
.pcm_free = alchemy_pcm_free_dma_buffers,
};
static int alchemy_pcm_drvprobe(struct platform_device *pdev)

View File

@ -386,7 +386,7 @@ static int snd_soc_put_volsw_2r_out(struct snd_kcontrol *kcontrol,
static int pm860x_rsync_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
/*
* In order to avoid current on the load, mute power-on and power-off
@ -403,7 +403,7 @@ static int pm860x_rsync_event(struct snd_soc_dapm_widget *w,
static int pm860x_dac_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
unsigned int dac = 0;
int data;

View File

@ -525,7 +525,7 @@ config SND_SOC_RT5677
config SND_SOC_RT5677_SPI
tristate
default SND_SOC_RT5677
default SND_SOC_RT5677 && SPI
#Freescale sgtl5000 codec
config SND_SOC_SGTL5000
@ -580,7 +580,9 @@ config SND_SOC_SSM4567
depends on I2C
config SND_SOC_STA32X
tristate
tristate "STA326, STA328 and STA329 speaker amplifier"
depends on I2C
select REGMAP_I2C
config SND_SOC_STA350
tristate "STA350 speaker amplifier"

View File

@ -333,8 +333,8 @@ static int ad193x_codec_probe(struct snd_soc_codec *codec)
regmap_write(ad193x->regmap, AD193X_DAC_CHNL_MUTE, 0x0);
/* de-emphasis: 48kHz, powedown dac */
regmap_write(ad193x->regmap, AD193X_DAC_CTRL2, 0x1A);
/* powerdown dac, dac in tdm mode */
regmap_write(ad193x->regmap, AD193X_DAC_CTRL0, 0x41);
/* dac in tdm mode */
regmap_write(ad193x->regmap, AD193X_DAC_CTRL0, 0x40);
/* high-pass filter enable */
regmap_write(ad193x->regmap, AD193X_ADC_CTRL0, 0x3);
/* sata delay=1, adc aux mode */

View File

@ -163,7 +163,7 @@ static const struct snd_kcontrol_new ak4671_snd_controls[] = {
static int ak4671_out2_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:

View File

@ -55,18 +55,20 @@ static inline int alc5623_reset(struct snd_soc_codec *codec)
static int amp_mixer_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
/* to power-on/off class-d amp generators/speaker */
/* need to write to 'index-46h' register : */
/* so write index num (here 0x46) to reg 0x6a */
/* and then 0xffff/0 to reg 0x6c */
snd_soc_write(w->codec, ALC5623_HID_CTRL_INDEX, 0x46);
snd_soc_write(codec, ALC5623_HID_CTRL_INDEX, 0x46);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
snd_soc_write(w->codec, ALC5623_HID_CTRL_DATA, 0xFFFF);
snd_soc_write(codec, ALC5623_HID_CTRL_DATA, 0xFFFF);
break;
case SND_SOC_DAPM_POST_PMD:
snd_soc_write(w->codec, ALC5623_HID_CTRL_DATA, 0);
snd_soc_write(codec, ALC5623_HID_CTRL_DATA, 0);
break;
}

View File

@ -116,18 +116,20 @@ static inline int alc5632_reset(struct regmap *map)
static int amp_mixer_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
/* to power-on/off class-d amp generators/speaker */
/* need to write to 'index-46h' register : */
/* so write index num (here 0x46) to reg 0x6a */
/* and then 0xffff/0 to reg 0x6c */
snd_soc_write(w->codec, ALC5632_HID_CTRL_INDEX, 0x46);
snd_soc_write(codec, ALC5632_HID_CTRL_INDEX, 0x46);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
snd_soc_write(w->codec, ALC5632_HID_CTRL_DATA, 0xFFFF);
snd_soc_write(codec, ALC5632_HID_CTRL_DATA, 0xFFFF);
break;
case SND_SOC_DAPM_POST_PMD:
snd_soc_write(w->codec, ALC5632_HID_CTRL_DATA, 0);
snd_soc_write(codec, ALC5632_HID_CTRL_DATA, 0);
break;
}
@ -1066,7 +1068,7 @@ static int alc5632_probe(struct snd_soc_codec *codec)
return 0;
}
static struct snd_soc_codec_driver soc_codec_device_alc5632 = {
static const struct snd_soc_codec_driver soc_codec_device_alc5632 = {
.probe = alc5632_probe,
.resume = alc5632_resume,
.set_bias_level = alc5632_set_bias_level,
@ -1080,7 +1082,7 @@ static struct snd_soc_codec_driver soc_codec_device_alc5632 = {
.num_dapm_routes = ARRAY_SIZE(alc5632_dapm_routes),
};
static struct regmap_config alc5632_regmap = {
static const struct regmap_config alc5632_regmap = {
.reg_bits = 8,
.val_bits = 16,

View File

@ -84,7 +84,7 @@ static int arizona_spk_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
bool manual_ena = false;
@ -692,7 +692,8 @@ static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena)
int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
int event)
{
struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec);
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
unsigned int reg;
if (w->shift % 2)
@ -705,25 +706,25 @@ int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
priv->in_pending++;
break;
case SND_SOC_DAPM_POST_PMU:
snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE, 0);
snd_soc_update_bits(codec, reg, ARIZONA_IN1L_MUTE, 0);
/* If this is the last input pending then allow VU */
priv->in_pending--;
if (priv->in_pending == 0) {
msleep(1);
arizona_in_set_vu(w->codec, 1);
arizona_in_set_vu(codec, 1);
}
break;
case SND_SOC_DAPM_PRE_PMD:
snd_soc_update_bits(w->codec, reg,
snd_soc_update_bits(codec, reg,
ARIZONA_IN1L_MUTE | ARIZONA_IN_VU,
ARIZONA_IN1L_MUTE | ARIZONA_IN_VU);
break;
case SND_SOC_DAPM_POST_PMD:
/* Disable volume updates if no inputs are enabled */
reg = snd_soc_read(w->codec, ARIZONA_INPUT_ENABLES);
reg = snd_soc_read(codec, ARIZONA_INPUT_ENABLES);
if (reg == 0)
arizona_in_set_vu(w->codec, 0);
arizona_in_set_vu(codec, 0);
}
return 0;
@ -734,7 +735,25 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
switch (w->shift) {
case ARIZONA_OUT1L_ENA_SHIFT:
case ARIZONA_OUT1R_ENA_SHIFT:
case ARIZONA_OUT2L_ENA_SHIFT:
case ARIZONA_OUT2R_ENA_SHIFT:
case ARIZONA_OUT3L_ENA_SHIFT:
case ARIZONA_OUT3R_ENA_SHIFT:
priv->out_up_pending++;
priv->out_up_delay += 17;
break;
default:
break;
}
break;
case SND_SOC_DAPM_POST_PMU:
switch (w->shift) {
case ARIZONA_OUT1L_ENA_SHIFT:
@ -743,13 +762,50 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w,
case ARIZONA_OUT2R_ENA_SHIFT:
case ARIZONA_OUT3L_ENA_SHIFT:
case ARIZONA_OUT3R_ENA_SHIFT:
msleep(17);
priv->out_up_pending--;
if (!priv->out_up_pending) {
msleep(priv->out_up_delay);
priv->out_up_delay = 0;
}
break;
default:
break;
}
break;
case SND_SOC_DAPM_PRE_PMD:
switch (w->shift) {
case ARIZONA_OUT1L_ENA_SHIFT:
case ARIZONA_OUT1R_ENA_SHIFT:
case ARIZONA_OUT2L_ENA_SHIFT:
case ARIZONA_OUT2R_ENA_SHIFT:
case ARIZONA_OUT3L_ENA_SHIFT:
case ARIZONA_OUT3R_ENA_SHIFT:
priv->out_down_pending++;
priv->out_down_delay++;
break;
default:
break;
}
break;
case SND_SOC_DAPM_POST_PMD:
switch (w->shift) {
case ARIZONA_OUT1L_ENA_SHIFT:
case ARIZONA_OUT1R_ENA_SHIFT:
case ARIZONA_OUT2L_ENA_SHIFT:
case ARIZONA_OUT2R_ENA_SHIFT:
case ARIZONA_OUT3L_ENA_SHIFT:
case ARIZONA_OUT3R_ENA_SHIFT:
priv->out_down_pending--;
if (!priv->out_down_pending) {
msleep(priv->out_down_delay);
priv->out_down_delay = 0;
}
break;
default:
break;
}
break;
}
return 0;
@ -760,7 +816,8 @@ int arizona_hp_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec);
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
struct arizona *arizona = priv->arizona;
unsigned int mask = 1 << w->shift;
unsigned int val;
@ -772,6 +829,9 @@ int arizona_hp_ev(struct snd_soc_dapm_widget *w,
case SND_SOC_DAPM_PRE_PMD:
val = 0;
break;
case SND_SOC_DAPM_PRE_PMU:
case SND_SOC_DAPM_POST_PMD:
return arizona_out_ev(w, kcontrol, event);
default:
return -EINVAL;
}

View File

@ -77,6 +77,11 @@ struct arizona_priv {
int num_inputs;
unsigned int in_pending;
unsigned int out_up_pending;
unsigned int out_up_delay;
unsigned int out_down_pending;
unsigned int out_down_delay;
unsigned int spk_ena:2;
unsigned int spk_ena_pending:1;
};

View File

@ -86,5 +86,5 @@ static struct platform_driver bt_sco_driver = {
module_platform_driver(bt_sco_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("ASoC generic bluethooth sco link driver");
MODULE_DESCRIPTION("ASoC generic bluetooth sco link driver");
MODULE_LICENSE("GPL");

View File

@ -264,7 +264,7 @@ static int cs35l32_codec_set_sysclk(struct snd_soc_codec *codec,
CS35L32_MCLK_DIV2_MASK | CS35L32_MCLK_RATIO_MASK, val);
}
static struct snd_soc_codec_driver soc_codec_dev_cs35l32 = {
static const struct snd_soc_codec_driver soc_codec_dev_cs35l32 = {
.set_sysclk = cs35l32_codec_set_sysclk,
.dapm_widgets = cs35l32_dapm_widgets,
@ -288,7 +288,7 @@ static const struct reg_default cs35l32_monitor_patch[] = {
{ 0x00, 0x00 },
};
static struct regmap_config cs35l32_regmap = {
static const struct regmap_config cs35l32_regmap = {
.reg_bits = 8,
.val_bits = 8,

View File

@ -1103,7 +1103,7 @@ static int cs42l52_remove(struct snd_soc_codec *codec)
return 0;
}
static struct snd_soc_codec_driver soc_codec_dev_cs42l52 = {
static const struct snd_soc_codec_driver soc_codec_dev_cs42l52 = {
.probe = cs42l52_probe,
.remove = cs42l52_remove,
.set_bias_level = cs42l52_set_bias_level,
@ -1130,7 +1130,7 @@ static const struct reg_default cs42l52_threshold_patch[] = {
};
static struct regmap_config cs42l52_regmap = {
static const struct regmap_config cs42l52_regmap = {
.reg_bits = 8,
.val_bits = 8,

View File

@ -1164,7 +1164,7 @@ static int cs42l56_remove(struct snd_soc_codec *codec)
return 0;
}
static struct snd_soc_codec_driver soc_codec_dev_cs42l56 = {
static const struct snd_soc_codec_driver soc_codec_dev_cs42l56 = {
.probe = cs42l56_probe,
.remove = cs42l56_remove,
.set_bias_level = cs42l56_set_bias_level,
@ -1179,7 +1179,7 @@ static struct snd_soc_codec_driver soc_codec_dev_cs42l56 = {
.num_controls = ARRAY_SIZE(cs42l56_snd_controls),
};
static struct regmap_config cs42l56_regmap = {
static const struct regmap_config cs42l56_regmap = {
.reg_bits = 8,
.val_bits = 8,

View File

@ -1347,7 +1347,7 @@ static int cs42l73_probe(struct snd_soc_codec *codec)
return 0;
}
static struct snd_soc_codec_driver soc_codec_dev_cs42l73 = {
static const struct snd_soc_codec_driver soc_codec_dev_cs42l73 = {
.probe = cs42l73_probe,
.set_bias_level = cs42l73_set_bias_level,
.suspend_bias_off = true,
@ -1361,7 +1361,7 @@ static struct snd_soc_codec_driver soc_codec_dev_cs42l73 = {
.num_controls = ARRAY_SIZE(cs42l73_snd_controls),
};
static struct regmap_config cs42l73_regmap = {
static const struct regmap_config cs42l73_regmap = {
.reg_bits = 8,
.val_bits = 8,

View File

@ -609,7 +609,7 @@ static const struct snd_kcontrol_new da732x_snd_controls[] = {
static int da732x_adc_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
@ -663,7 +663,7 @@ static int da732x_adc_event(struct snd_soc_dapm_widget *w,
static int da732x_out_pga_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:

View File

@ -328,16 +328,16 @@ static int mc13783_set_tdm_slot_dac(struct snd_soc_dai *dai,
}
switch (rx_mask) {
case 0xfffffffc:
case 0x03:
val |= SSI_NETWORK_DAC_RXSLOT_0_1;
break;
case 0xfffffff3:
case 0x0c:
val |= SSI_NETWORK_DAC_RXSLOT_2_3;
break;
case 0xffffffcf:
case 0x30:
val |= SSI_NETWORK_DAC_RXSLOT_4_5;
break;
case 0xffffff3f:
case 0xc0:
val |= SSI_NETWORK_DAC_RXSLOT_6_7;
break;
default:
@ -360,7 +360,7 @@ static int mc13783_set_tdm_slot_codec(struct snd_soc_dai *dai,
if (slots != 4)
return -EINVAL;
if (tx_mask != 0xfffffffc)
if (tx_mask != 0x3)
return -EINVAL;
val |= (0x00 << 2); /* primary timeslot RX/TX(?) is 0 */

View File

@ -32,7 +32,7 @@ static int pcm3008_dac_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct pcm3008_setup_data *setup = codec->dev->platform_data;
gpio_set_value_cansleep(setup->pdda_pin,
@ -45,7 +45,7 @@ static int pcm3008_adc_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct pcm3008_setup_data *setup = codec->dev->platform_data;
gpio_set_value_cansleep(setup->pdad_pin,

File diff suppressed because it is too large Load Diff

View File

@ -37,6 +37,10 @@
#define PCM512x_DSP_GPIO_INPUT (PCM512x_PAGE_BASE(0) + 10)
#define PCM512x_MASTER_MODE (PCM512x_PAGE_BASE(0) + 12)
#define PCM512x_PLL_REF (PCM512x_PAGE_BASE(0) + 13)
#define PCM512x_DAC_REF (PCM512x_PAGE_BASE(0) + 14)
#define PCM512x_GPIO_DACIN (PCM512x_PAGE_BASE(0) + 16)
#define PCM512x_GPIO_PLLIN (PCM512x_PAGE_BASE(0) + 18)
#define PCM512x_SYNCHRONIZE (PCM512x_PAGE_BASE(0) + 19)
#define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_BASE(0) + 20)
#define PCM512x_PLL_COEFF_1 (PCM512x_PAGE_BASE(0) + 21)
#define PCM512x_PLL_COEFF_2 (PCM512x_PAGE_BASE(0) + 22)
@ -77,6 +81,7 @@
#define PCM512x_RATE_DET_2 (PCM512x_PAGE_BASE(0) + 92)
#define PCM512x_RATE_DET_3 (PCM512x_PAGE_BASE(0) + 93)
#define PCM512x_RATE_DET_4 (PCM512x_PAGE_BASE(0) + 94)
#define PCM512x_CLOCK_STATUS (PCM512x_PAGE_BASE(0) + 95)
#define PCM512x_ANALOG_MUTE_DET (PCM512x_PAGE_BASE(0) + 108)
#define PCM512x_GPIN (PCM512x_PAGE_BASE(0) + 119)
#define PCM512x_DIGITAL_MUTE_DET (PCM512x_PAGE_BASE(0) + 120)
@ -91,7 +96,10 @@
#define PCM512x_CRAM_CTRL (PCM512x_PAGE_BASE(44) + 1)
#define PCM512x_MAX_REGISTER (PCM512x_PAGE_BASE(44) + 1)
#define PCM512x_FLEX_A (PCM512x_PAGE_BASE(253) + 63)
#define PCM512x_FLEX_B (PCM512x_PAGE_BASE(253) + 64)
#define PCM512x_MAX_REGISTER (PCM512x_PAGE_BASE(253) + 64)
/* Page 0, Register 1 - reset */
#define PCM512x_RSTR (1 << 0)
@ -108,8 +116,8 @@
#define PCM512x_RQML_SHIFT 4
/* Page 0, Register 4 - PLL */
#define PCM512x_PLCE (1 << 0)
#define PCM512x_RLCE_SHIFT 0
#define PCM512x_PLLE (1 << 0)
#define PCM512x_PLLE_SHIFT 0
#define PCM512x_PLCK (1 << 4)
#define PCM512x_PLCK_SHIFT 4
@ -119,8 +127,66 @@
#define PCM512x_DEMP (1 << 4)
#define PCM512x_DEMP_SHIFT 4
/* Page 0, Register 8 - GPIO output enable */
#define PCM512x_G1OE (1 << 0)
#define PCM512x_G2OE (1 << 1)
#define PCM512x_G3OE (1 << 2)
#define PCM512x_G4OE (1 << 3)
#define PCM512x_G5OE (1 << 4)
#define PCM512x_G6OE (1 << 5)
/* Page 0, Register 9 - BCK, LRCLK configuration */
#define PCM512x_LRKO (1 << 0)
#define PCM512x_LRKO_SHIFT 0
#define PCM512x_BCKO (1 << 4)
#define PCM512x_BCKO_SHIFT 4
#define PCM512x_BCKP (1 << 5)
#define PCM512x_BCKP_SHIFT 5
/* Page 0, Register 12 - Master mode BCK, LRCLK reset */
#define PCM512x_RLRK (1 << 0)
#define PCM512x_RLRK_SHIFT 0
#define PCM512x_RBCK (1 << 1)
#define PCM512x_RBCK_SHIFT 1
/* Page 0, Register 13 - PLL reference */
#define PCM512x_SREF (1 << 4)
#define PCM512x_SREF (7 << 4)
#define PCM512x_SREF_SHIFT 4
#define PCM512x_SREF_SCK (0 << 4)
#define PCM512x_SREF_BCK (1 << 4)
#define PCM512x_SREF_GPIO (3 << 4)
/* Page 0, Register 14 - DAC reference */
#define PCM512x_SDAC (7 << 4)
#define PCM512x_SDAC_SHIFT 4
#define PCM512x_SDAC_MCK (0 << 4)
#define PCM512x_SDAC_PLL (1 << 4)
#define PCM512x_SDAC_SCK (3 << 4)
#define PCM512x_SDAC_BCK (4 << 4)
#define PCM512x_SDAC_GPIO (5 << 4)
/* Page 0, Register 16, 18 - GPIO source for DAC, PLL */
#define PCM512x_GREF (7 << 0)
#define PCM512x_GREF_SHIFT 0
#define PCM512x_GREF_GPIO1 (0 << 0)
#define PCM512x_GREF_GPIO2 (1 << 0)
#define PCM512x_GREF_GPIO3 (2 << 0)
#define PCM512x_GREF_GPIO4 (3 << 0)
#define PCM512x_GREF_GPIO5 (4 << 0)
#define PCM512x_GREF_GPIO6 (5 << 0)
/* Page 0, Register 19 - synchronize */
#define PCM512x_RQSY (1 << 0)
#define PCM512x_RQSY_RESUME (0 << 0)
#define PCM512x_RQSY_HALT (1 << 0)
/* Page 0, Register 34 - fs speed mode */
#define PCM512x_FSSP (3 << 0)
#define PCM512x_FSSP_SHIFT 0
#define PCM512x_FSSP_48KHZ (0 << 0)
#define PCM512x_FSSP_96KHZ (1 << 0)
#define PCM512x_FSSP_192KHZ (2 << 0)
#define PCM512x_FSSP_384KHZ (3 << 0)
/* Page 0, Register 37 - Error detection */
#define PCM512x_IPLK (1 << 0)
@ -131,6 +197,20 @@
#define PCM512x_IDBK (1 << 5)
#define PCM512x_IDFS (1 << 6)
/* Page 0, Register 40 - I2S configuration */
#define PCM512x_ALEN (3 << 0)
#define PCM512x_ALEN_SHIFT 0
#define PCM512x_ALEN_16 (0 << 0)
#define PCM512x_ALEN_20 (1 << 0)
#define PCM512x_ALEN_24 (2 << 0)
#define PCM512x_ALEN_32 (3 << 0)
#define PCM512x_AFMT (3 << 4)
#define PCM512x_AFMT_SHIFT 4
#define PCM512x_AFMT_I2S (0 << 4)
#define PCM512x_AFMT_DSP (1 << 4)
#define PCM512x_AFMT_RTJ (2 << 4)
#define PCM512x_AFMT_LTJ (3 << 4)
/* Page 0, Register 42 - DAC routing */
#define PCM512x_AUPR_SHIFT 0
#define PCM512x_AUPL_SHIFT 4
@ -152,7 +232,26 @@
/* Page 0, Register 65 - Digital mute enables */
#define PCM512x_ACTL_SHIFT 2
#define PCM512x_AMLE_SHIFT 1
#define PCM512x_AMLR_SHIFT 0
#define PCM512x_AMRE_SHIFT 0
/* Page 0, Register 80-85, GPIO output selection */
#define PCM512x_GxSL (31 << 0)
#define PCM512x_GxSL_SHIFT 0
#define PCM512x_GxSL_OFF (0 << 0)
#define PCM512x_GxSL_DSP (1 << 0)
#define PCM512x_GxSL_REG (2 << 0)
#define PCM512x_GxSL_AMUTB (3 << 0)
#define PCM512x_GxSL_AMUTL (4 << 0)
#define PCM512x_GxSL_AMUTR (5 << 0)
#define PCM512x_GxSL_CLKI (6 << 0)
#define PCM512x_GxSL_SDOUT (7 << 0)
#define PCM512x_GxSL_ANMUL (8 << 0)
#define PCM512x_GxSL_ANMUR (9 << 0)
#define PCM512x_GxSL_PLLLK (10 << 0)
#define PCM512x_GxSL_CPCLK (11 << 0)
#define PCM512x_GxSL_UV0_7 (14 << 0)
#define PCM512x_GxSL_UV0_3 (15 << 0)
#define PCM512x_GxSL_PLLCK (16 << 0)
/* Page 1, Register 2 - analog volume control */
#define PCM512x_RAGN_SHIFT 0

View File

@ -403,7 +403,8 @@ EXPORT_SYMBOL_GPL(rt286_mic_detect);
static int is_mclk_mode(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(source->codec);
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
if (rt286->clk_id == RT286_SCLK_S_MCLK)
return 1;
@ -417,6 +418,8 @@ static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0);
static const struct snd_kcontrol_new rt286_snd_controls[] = {
SOC_DOUBLE_R_TLV("DAC0 Playback Volume", RT286_DACL_GAIN,
RT286_DACR_GAIN, 0, 0x7f, 0, out_vol_tlv),
SOC_DOUBLE_R("ADC0 Capture Switch", RT286_ADCL_GAIN,
RT286_ADCR_GAIN, 7, 1, 1),
SOC_DOUBLE_R_TLV("ADC0 Capture Volume", RT286_ADCL_GAIN,
RT286_ADCR_GAIN, 0, 0x7f, 0, out_vol_tlv),
SOC_SINGLE_TLV("AMIC Volume", RT286_MIC_GAIN,
@ -500,7 +503,7 @@ SOC_DAPM_ENUM("SPO source", rt286_spo_enum);
static int rt286_spk_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
@ -522,7 +525,7 @@ static int rt286_spk_event(struct snd_soc_dapm_widget *w,
static int rt286_set_dmic1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
@ -538,36 +541,10 @@ static int rt286_set_dmic1_event(struct snd_soc_dapm_widget *w,
return 0;
}
static int rt286_adc_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
unsigned int nid;
nid = (w->reg >> 20) & 0xff;
switch (event) {
case SND_SOC_DAPM_POST_PMU:
snd_soc_update_bits(codec,
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0),
0x7080, 0x7000);
break;
case SND_SOC_DAPM_PRE_PMD:
snd_soc_update_bits(codec,
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0),
0x7080, 0x7080);
break;
default:
return 0;
}
return 0;
}
static int rt286_vref_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
@ -585,7 +562,7 @@ static int rt286_vref_event(struct snd_soc_dapm_widget *w,
static int rt286_ldo2_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
@ -604,7 +581,7 @@ static int rt286_ldo2_event(struct snd_soc_dapm_widget *w,
static int rt286_mic1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
@ -667,12 +644,10 @@ static const struct snd_soc_dapm_widget rt286_dapm_widgets[] = {
SND_SOC_DAPM_ADC("ADC 1", NULL, SND_SOC_NOPM, 0, 0),
/* ADC Mux */
SND_SOC_DAPM_MUX_E("ADC 0 Mux", RT286_SET_POWER(RT286_ADC_IN1), 0, 1,
&rt286_adc0_mux, rt286_adc_event, SND_SOC_DAPM_PRE_PMD |
SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_MUX_E("ADC 1 Mux", RT286_SET_POWER(RT286_ADC_IN2), 0, 1,
&rt286_adc1_mux, rt286_adc_event, SND_SOC_DAPM_PRE_PMD |
SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_MUX("ADC 0 Mux", RT286_SET_POWER(RT286_ADC_IN1), 0, 1,
&rt286_adc0_mux),
SND_SOC_DAPM_MUX("ADC 1 Mux", RT286_SET_POWER(RT286_ADC_IN2), 0, 1,
&rt286_adc1_mux),
/* Audio Interface */
SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),

View File

@ -287,70 +287,78 @@ static const struct snd_kcontrol_new rt5631_snd_controls[] = {
static int check_sysclk1_source(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
unsigned int reg;
reg = snd_soc_read(source->codec, RT5631_GLOBAL_CLK_CTRL);
reg = snd_soc_read(codec, RT5631_GLOBAL_CLK_CTRL);
return reg & RT5631_SYSCLK_SOUR_SEL_PLL;
}
static int check_dmic_used(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(source->codec);
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
return rt5631->dmic_used_flag;
}
static int check_dacl_to_outmixl(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
unsigned int reg;
reg = snd_soc_read(source->codec, RT5631_OUTMIXER_L_CTRL);
reg = snd_soc_read(codec, RT5631_OUTMIXER_L_CTRL);
return !(reg & RT5631_M_DAC_L_TO_OUTMIXER_L);
}
static int check_dacr_to_outmixr(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
unsigned int reg;
reg = snd_soc_read(source->codec, RT5631_OUTMIXER_R_CTRL);
reg = snd_soc_read(codec, RT5631_OUTMIXER_R_CTRL);
return !(reg & RT5631_M_DAC_R_TO_OUTMIXER_R);
}
static int check_dacl_to_spkmixl(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
unsigned int reg;
reg = snd_soc_read(source->codec, RT5631_SPK_MIXER_CTRL);
reg = snd_soc_read(codec, RT5631_SPK_MIXER_CTRL);
return !(reg & RT5631_M_DAC_L_TO_SPKMIXER_L);
}
static int check_dacr_to_spkmixr(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
unsigned int reg;
reg = snd_soc_read(source->codec, RT5631_SPK_MIXER_CTRL);
reg = snd_soc_read(codec, RT5631_SPK_MIXER_CTRL);
return !(reg & RT5631_M_DAC_R_TO_SPKMIXER_R);
}
static int check_adcl_select(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
unsigned int reg;
reg = snd_soc_read(source->codec, RT5631_ADC_REC_MIXER);
reg = snd_soc_read(codec, RT5631_ADC_REC_MIXER);
return !(reg & RT5631_M_MIC1_TO_RECMIXER_L);
}
static int check_adcr_select(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
unsigned int reg;
reg = snd_soc_read(source->codec, RT5631_ADC_REC_MIXER);
reg = snd_soc_read(codec, RT5631_ADC_REC_MIXER);
return !(reg & RT5631_M_MIC2_TO_RECMIXER_R);
}
@ -556,7 +564,7 @@ static void depop_seq_mute_stage(struct snd_soc_codec *codec, int enable)
static int hp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -590,7 +598,7 @@ static int hp_event(struct snd_soc_dapm_widget *w,
static int set_dmic_params(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
switch (rt5631->rx_rate) {

View File

@ -458,7 +458,7 @@ static const struct snd_kcontrol_new rt5640_specific_snd_controls[] = {
static int set_dmic_clk(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
int idx = -EINVAL;
@ -475,9 +475,10 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
unsigned int val;
val = snd_soc_read(source->codec, RT5640_GLB_CLK);
val = snd_soc_read(codec, RT5640_GLB_CLK);
val &= RT5640_SCLK_SRC_MASK;
if (val == RT5640_SCLK_SRC_PLL1)
return 1;
@ -963,7 +964,7 @@ static void rt5640_pmu_depop(struct snd_soc_codec *codec)
static int rt5640_hp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -987,7 +988,7 @@ static int rt5640_hp_event(struct snd_soc_dapm_widget *w,
static int rt5640_hp_power_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
@ -1003,7 +1004,7 @@ static int rt5640_hp_power_event(struct snd_soc_dapm_widget *w,
static int rt5640_hp_post_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -2124,6 +2125,7 @@ MODULE_DEVICE_TABLE(of, rt5640_of_match);
static struct acpi_device_id rt5640_acpi_match[] = {
{ "INT33CA", 0 },
{ "10EC5640", 0 },
{ "10EC5642", 0 },
{ },
};
MODULE_DEVICE_TABLE(acpi, rt5640_acpi_match);

View File

@ -31,6 +31,7 @@
#include "rt5645.h"
#define RT5645_DEVICE_ID 0x6308
#define RT5650_DEVICE_ID 0x6419
#define RT5645_PR_RANGE_BASE (0xff + 1)
#define RT5645_PR_SPACING 0x100
@ -59,6 +60,10 @@ static const struct reg_default init_list[] = {
};
#define RT5645_INIT_REG_LEN ARRAY_SIZE(init_list)
static const struct reg_default rt5650_init_list[] = {
{0xf6, 0x0100},
};
static const struct reg_default rt5645_reg[] = {
{ 0x00, 0x0000 },
{ 0x01, 0xc8c8 },
@ -86,6 +91,7 @@ static const struct reg_default rt5645_reg[] = {
{ 0x2a, 0x5656 },
{ 0x2b, 0x5454 },
{ 0x2c, 0xaaa0 },
{ 0x2d, 0x0000 },
{ 0x2f, 0x1002 },
{ 0x31, 0x5000 },
{ 0x32, 0x0000 },
@ -193,6 +199,8 @@ static const struct reg_default rt5645_reg[] = {
{ 0xdb, 0x0003 },
{ 0xdc, 0x0049 },
{ 0xdd, 0x001b },
{ 0xdf, 0x0008 },
{ 0xe0, 0x4000 },
{ 0xe6, 0x8000 },
{ 0xe7, 0x0200 },
{ 0xec, 0xb300 },
@ -242,6 +250,7 @@ static bool rt5645_volatile_register(struct device *dev, unsigned int reg)
case RT5645_IRQ_CTRL3:
case RT5645_INT_IRQ_ST:
case RT5645_IL_CMD:
case RT5650_4BTN_IL_CMD1:
case RT5645_VENDOR_ID:
case RT5645_VENDOR_ID1:
case RT5645_VENDOR_ID2:
@ -287,6 +296,7 @@ static bool rt5645_readable_register(struct device *dev, unsigned int reg)
case RT5645_STO_DAC_MIXER:
case RT5645_MONO_DAC_MIXER:
case RT5645_DIG_MIXER:
case RT5650_A_DAC_SOUR:
case RT5645_DIG_INF1_DATA:
case RT5645_PDM_OUT_CTRL:
case RT5645_REC_L1_MIXER:
@ -378,6 +388,8 @@ static bool rt5645_readable_register(struct device *dev, unsigned int reg)
case RT5645_IL_CMD:
case RT5645_IL_CMD2:
case RT5645_IL_CMD3:
case RT5650_4BTN_IL_CMD1:
case RT5650_4BTN_IL_CMD2:
case RT5645_DRC1_HL_CTRL1:
case RT5645_DRC2_HL_CTRL1:
case RT5645_ADC_MONO_HP_CTRL1:
@ -527,7 +539,7 @@ static const struct snd_kcontrol_new rt5645_snd_controls[] = {
static int set_dmic_clk(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
int idx = -EINVAL;
@ -544,9 +556,10 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
unsigned int val;
val = snd_soc_read(source->codec, RT5645_GLB_CLK);
val = snd_soc_read(codec, RT5645_GLB_CLK);
val &= RT5645_SCLK_SRC_MASK;
if (val == RT5645_SCLK_SRC_PLL1)
return 1;
@ -557,6 +570,7 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
static int is_using_asrc(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
unsigned int reg, shift, val;
switch (source->shift) {
@ -588,7 +602,7 @@ static int is_using_asrc(struct snd_soc_dapm_widget *source,
return 0;
}
val = (snd_soc_read(source->codec, reg) >> shift) & 0xf;
val = (snd_soc_read(codec, reg) >> shift) & 0xf;
switch (val) {
case 1:
case 2:
@ -1007,6 +1021,44 @@ static SOC_ENUM_SINGLE_DECL(
static const struct snd_kcontrol_new rt5645_if1_adc_in_mux =
SOC_DAPM_ENUM("IF1 ADC IN source", rt5645_if1_adc_in_enum);
/* MX-2d [3] [2] */
static const char * const rt5650_a_dac1_src[] = {
"DAC1", "Stereo DAC Mixer"
};
static SOC_ENUM_SINGLE_DECL(
rt5650_a_dac1_l_enum, RT5650_A_DAC_SOUR,
RT5650_A_DAC1_L_IN_SFT, rt5650_a_dac1_src);
static const struct snd_kcontrol_new rt5650_a_dac1_l_mux =
SOC_DAPM_ENUM("A DAC1 L source", rt5650_a_dac1_l_enum);
static SOC_ENUM_SINGLE_DECL(
rt5650_a_dac1_r_enum, RT5650_A_DAC_SOUR,
RT5650_A_DAC1_R_IN_SFT, rt5650_a_dac1_src);
static const struct snd_kcontrol_new rt5650_a_dac1_r_mux =
SOC_DAPM_ENUM("A DAC1 R source", rt5650_a_dac1_r_enum);
/* MX-2d [1] [0] */
static const char * const rt5650_a_dac2_src[] = {
"Stereo DAC Mixer", "Mono DAC Mixer"
};
static SOC_ENUM_SINGLE_DECL(
rt5650_a_dac2_l_enum, RT5650_A_DAC_SOUR,
RT5650_A_DAC2_L_IN_SFT, rt5650_a_dac2_src);
static const struct snd_kcontrol_new rt5650_a_dac2_l_mux =
SOC_DAPM_ENUM("A DAC2 L source", rt5650_a_dac2_l_enum);
static SOC_ENUM_SINGLE_DECL(
rt5650_a_dac2_r_enum, RT5650_A_DAC_SOUR,
RT5650_A_DAC2_R_IN_SFT, rt5650_a_dac2_src);
static const struct snd_kcontrol_new rt5650_a_dac2_r_mux =
SOC_DAPM_ENUM("A DAC2 R source", rt5650_a_dac2_r_enum);
/* MX-2F [13:12] */
static const char * const rt5645_if2_adc_in_src[] = {
"IF_ADC1", "IF_ADC2", "VAD_ADC"
@ -1144,18 +1196,23 @@ static void hp_amp_power(struct snd_soc_codec *codec, int on)
static int rt5645_hp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
hp_amp_power(codec, 1);
/* headphone unmute sequence */
snd_soc_update_bits(codec, RT5645_DEPOP_M3, RT5645_CP_FQ1_MASK |
RT5645_CP_FQ2_MASK | RT5645_CP_FQ3_MASK,
(RT5645_CP_FQ_192_KHZ << RT5645_CP_FQ1_SFT) |
(RT5645_CP_FQ_12_KHZ << RT5645_CP_FQ2_SFT) |
(RT5645_CP_FQ_192_KHZ << RT5645_CP_FQ3_SFT));
if (rt5645->codec_type == CODEC_TYPE_RT5650) {
snd_soc_write(codec, RT5645_DEPOP_M3, 0x0737);
} else {
snd_soc_update_bits(codec, RT5645_DEPOP_M3,
RT5645_CP_FQ1_MASK | RT5645_CP_FQ2_MASK |
RT5645_CP_FQ3_MASK,
(RT5645_CP_FQ_192_KHZ << RT5645_CP_FQ1_SFT) |
(RT5645_CP_FQ_12_KHZ << RT5645_CP_FQ2_SFT) |
(RT5645_CP_FQ_192_KHZ << RT5645_CP_FQ3_SFT));
}
regmap_write(rt5645->regmap,
RT5645_PR_BASE + RT5645_MAMP_INT_REG2, 0xfc00);
snd_soc_update_bits(codec, RT5645_DEPOP_M1,
@ -1175,12 +1232,16 @@ static int rt5645_hp_event(struct snd_soc_dapm_widget *w,
case SND_SOC_DAPM_PRE_PMD:
/* headphone mute sequence */
snd_soc_update_bits(codec, RT5645_DEPOP_M3,
RT5645_CP_FQ1_MASK | RT5645_CP_FQ2_MASK |
RT5645_CP_FQ3_MASK,
(RT5645_CP_FQ_96_KHZ << RT5645_CP_FQ1_SFT) |
(RT5645_CP_FQ_12_KHZ << RT5645_CP_FQ2_SFT) |
(RT5645_CP_FQ_96_KHZ << RT5645_CP_FQ3_SFT));
if (rt5645->codec_type == CODEC_TYPE_RT5650) {
snd_soc_write(codec, RT5645_DEPOP_M3, 0x0737);
} else {
snd_soc_update_bits(codec, RT5645_DEPOP_M3,
RT5645_CP_FQ1_MASK | RT5645_CP_FQ2_MASK |
RT5645_CP_FQ3_MASK,
(RT5645_CP_FQ_96_KHZ << RT5645_CP_FQ1_SFT) |
(RT5645_CP_FQ_12_KHZ << RT5645_CP_FQ2_SFT) |
(RT5645_CP_FQ_96_KHZ << RT5645_CP_FQ3_SFT));
}
regmap_write(rt5645->regmap,
RT5645_PR_BASE + RT5645_MAMP_INT_REG2, 0xfc00);
snd_soc_update_bits(codec, RT5645_DEPOP_M1,
@ -1205,7 +1266,7 @@ static int rt5645_hp_event(struct snd_soc_dapm_widget *w,
static int rt5645_spk_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
@ -1232,7 +1293,7 @@ static int rt5645_spk_event(struct snd_soc_dapm_widget *w,
static int rt5645_lout_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
@ -1262,7 +1323,7 @@ static int rt5645_lout_event(struct snd_soc_dapm_widget *w,
static int rt5645_bst2_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
@ -1574,6 +1635,17 @@ static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("SPOR"),
};
static const struct snd_soc_dapm_widget rt5650_specific_dapm_widgets[] = {
SND_SOC_DAPM_MUX("A DAC1 L Mux", SND_SOC_NOPM,
0, 0, &rt5650_a_dac1_l_mux),
SND_SOC_DAPM_MUX("A DAC1 R Mux", SND_SOC_NOPM,
0, 0, &rt5650_a_dac1_r_mux),
SND_SOC_DAPM_MUX("A DAC2 L Mux", SND_SOC_NOPM,
0, 0, &rt5650_a_dac2_l_mux),
SND_SOC_DAPM_MUX("A DAC2 R Mux", SND_SOC_NOPM,
0, 0, &rt5650_a_dac2_r_mux),
};
static const struct snd_soc_dapm_route rt5645_dapm_routes[] = {
{ "adc stereo1 filter", NULL, "ADC STO1 ASRC", is_using_asrc },
{ "adc stereo2 filter", NULL, "ADC STO2 ASRC", is_using_asrc },
@ -1779,13 +1851,9 @@ static const struct snd_soc_dapm_route rt5645_dapm_routes[] = {
{ "DAC MIXR", "DAC R2 Switch", "DAC R2 Volume" },
{ "DAC MIXR", "DAC L2 Switch", "DAC L2 Volume" },
{ "DAC L1", NULL, "Stereo DAC MIXL" },
{ "DAC L1", NULL, "PLL1", is_sys_clk_from_pll },
{ "DAC R1", NULL, "Stereo DAC MIXR" },
{ "DAC R1", NULL, "PLL1", is_sys_clk_from_pll },
{ "DAC L2", NULL, "Mono DAC MIXL" },
{ "DAC L2", NULL, "PLL1", is_sys_clk_from_pll },
{ "DAC R2", NULL, "Mono DAC MIXR" },
{ "DAC R2", NULL, "PLL1", is_sys_clk_from_pll },
{ "SPK MIXL", "BST1 Switch", "BST1" },
@ -1874,6 +1942,30 @@ static const struct snd_soc_dapm_route rt5645_dapm_routes[] = {
{ "SPOR", NULL, "SPK amp" },
};
static const struct snd_soc_dapm_route rt5650_specific_dapm_routes[] = {
{ "A DAC1 L Mux", "DAC1", "DAC1 MIXL"},
{ "A DAC1 L Mux", "Stereo DAC Mixer", "Stereo DAC MIXL"},
{ "A DAC1 R Mux", "DAC1", "DAC1 MIXR"},
{ "A DAC1 R Mux", "Stereo DAC Mixer", "Stereo DAC MIXR"},
{ "A DAC2 L Mux", "Stereo DAC Mixer", "Stereo DAC MIXL"},
{ "A DAC2 L Mux", "Mono DAC Mixer", "Mono DAC MIXL"},
{ "A DAC2 R Mux", "Stereo DAC Mixer", "Stereo DAC MIXR"},
{ "A DAC2 R Mux", "Mono DAC Mixer", "Mono DAC MIXR"},
{ "DAC L1", NULL, "A DAC1 L Mux" },
{ "DAC R1", NULL, "A DAC1 R Mux" },
{ "DAC L2", NULL, "A DAC2 L Mux" },
{ "DAC R2", NULL, "A DAC2 R Mux" },
};
static const struct snd_soc_dapm_route rt5645_specific_dapm_routes[] = {
{ "DAC L1", NULL, "Stereo DAC MIXL" },
{ "DAC R1", NULL, "Stereo DAC MIXR" },
{ "DAC L2", NULL, "Mono DAC MIXL" },
{ "DAC R2", NULL, "Mono DAC MIXR" },
};
static int rt5645_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
@ -2293,6 +2385,22 @@ static int rt5645_probe(struct snd_soc_codec *codec)
rt5645->codec = codec;
switch (rt5645->codec_type) {
case CODEC_TYPE_RT5645:
snd_soc_dapm_add_routes(&codec->dapm,
rt5645_specific_dapm_routes,
ARRAY_SIZE(rt5645_specific_dapm_routes));
break;
case CODEC_TYPE_RT5650:
snd_soc_dapm_new_controls(&codec->dapm,
rt5650_specific_dapm_widgets,
ARRAY_SIZE(rt5650_specific_dapm_widgets));
snd_soc_dapm_add_routes(&codec->dapm,
rt5650_specific_dapm_routes,
ARRAY_SIZE(rt5650_specific_dapm_routes));
break;
}
rt5645_set_bias_level(codec, SND_SOC_BIAS_OFF);
snd_soc_update_bits(codec, RT5645_CHARGE_PUMP, 0x0300, 0x0200);
@ -2424,6 +2532,7 @@ static const struct regmap_config rt5645_regmap = {
static const struct i2c_device_id rt5645_i2c_id[] = {
{ "rt5645", 0 },
{ "rt5650", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt5645_i2c_id);
@ -2456,9 +2565,18 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
}
regmap_read(rt5645->regmap, RT5645_VENDOR_ID2, &val);
if (val != RT5645_DEVICE_ID) {
switch (val) {
case RT5645_DEVICE_ID:
rt5645->codec_type = CODEC_TYPE_RT5645;
break;
case RT5650_DEVICE_ID:
rt5645->codec_type = CODEC_TYPE_RT5650;
break;
default:
dev_err(&i2c->dev,
"Device with ID register %x is not rt5645\n", val);
"Device with ID register %x is not rt5645 or rt5650\n",
val);
return -ENODEV;
}
@ -2469,6 +2587,14 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
if (ret != 0)
dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret);
if (rt5645->codec_type == CODEC_TYPE_RT5650) {
ret = regmap_register_patch(rt5645->regmap, rt5650_init_list,
ARRAY_SIZE(rt5650_init_list));
if (ret != 0)
dev_warn(&i2c->dev, "Apply rt5650 patch failed: %d\n",
ret);
}
if (rt5645->pdata.in2_diff)
regmap_update_bits(rt5645->regmap, RT5645_IN2_CTRL,
RT5645_IN_DF2, RT5645_IN_DF2);

View File

@ -47,6 +47,7 @@
#define RT5645_STO_DAC_MIXER 0x2a
#define RT5645_MONO_DAC_MIXER 0x2b
#define RT5645_DIG_MIXER 0x2c
#define RT5650_A_DAC_SOUR 0x2d
#define RT5645_DIG_INF1_DATA 0x2f
/* Mixer - PDM */
#define RT5645_PDM_OUT_CTRL 0x31
@ -150,6 +151,8 @@
#define RT5645_IL_CMD 0xdb
#define RT5645_IL_CMD2 0xdc
#define RT5645_IL_CMD3 0xdd
#define RT5650_4BTN_IL_CMD1 0xdf
#define RT5650_4BTN_IL_CMD2 0xe0
#define RT5645_DRC1_HL_CTRL1 0xe7
#define RT5645_DRC2_HL_CTRL1 0xe9
#define RT5645_MUTI_DRC_CTRL1 0xea
@ -472,6 +475,12 @@
#define RT5645_DAC_L2_DAC_R_VOL_MASK (0x1 << 4)
#define RT5645_DAC_L2_DAC_R_VOL_SFT 4
/* Analog DAC1/2 Input Source Control (0x2d) */
#define RT5650_A_DAC1_L_IN_SFT 3
#define RT5650_A_DAC1_R_IN_SFT 2
#define RT5650_A_DAC2_L_IN_SFT 1
#define RT5650_A_DAC2_R_IN_SFT 0
/* Digital Interface Data Control (0x2f) */
#define RT5645_IF1_ADC2_IN_SEL (0x1 << 15)
#define RT5645_IF1_ADC2_IN_SFT 15
@ -2175,6 +2184,11 @@ enum {
RT5645_DMIC_DATA_GPIO11,
};
enum {
CODEC_TYPE_RT5645,
CODEC_TYPE_RT5650,
};
struct rt5645_priv {
struct snd_soc_codec *codec;
struct rt5645_platform_data pdata;
@ -2184,6 +2198,7 @@ struct rt5645_priv {
struct snd_soc_jack *mic_jack;
struct delayed_work jack_detect_work;
int codec_type;
int sysclk;
int sysclk_src;
int lrck[RT5645_AIFS];

View File

@ -376,7 +376,7 @@ static const struct snd_kcontrol_new rt5651_snd_controls[] = {
static int set_dmic_clk(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
int idx = -EINVAL;
@ -394,9 +394,10 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
static int is_sysclk_from_pll(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
unsigned int val;
val = snd_soc_read(source->codec, RT5651_GLB_CLK);
val = snd_soc_read(codec, RT5651_GLB_CLK);
val &= RT5651_SCLK_SRC_MASK;
if (val == RT5651_SCLK_SRC_PLL1)
return 1;
@ -731,7 +732,7 @@ static const struct snd_kcontrol_new rt5651_pdm_r_mux =
static int rt5651_amp_power_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -769,7 +770,7 @@ static int rt5651_amp_power_event(struct snd_soc_dapm_widget *w,
static int rt5651_hp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -813,7 +814,8 @@ static int rt5651_hp_event(struct snd_soc_dapm_widget *w,
static int rt5651_hp_post_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -833,7 +835,7 @@ static int rt5651_hp_post_event(struct snd_soc_dapm_widget *w,
static int rt5651_bst1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
@ -856,7 +858,7 @@ static int rt5651_bst1_event(struct snd_soc_dapm_widget *w,
static int rt5651_bst2_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
@ -879,7 +881,7 @@ static int rt5651_bst2_event(struct snd_soc_dapm_widget *w,
static int rt5651_bst3_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:

View File

@ -500,7 +500,7 @@ static const struct snd_kcontrol_new rt5670_snd_controls[] = {
static int set_dmic_clk(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
int idx = -EINVAL;
@ -517,9 +517,10 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
unsigned int val;
val = snd_soc_read(source->codec, RT5670_GLB_CLK);
val = snd_soc_read(codec, RT5670_GLB_CLK);
val &= RT5670_SCLK_SRC_MASK;
if (val == RT5670_SCLK_SRC_PLL1)
return 1;
@ -530,6 +531,7 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
static int is_using_asrc(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
unsigned int reg, shift, val;
switch (source->shift) {
@ -565,7 +567,7 @@ static int is_using_asrc(struct snd_soc_dapm_widget *source,
return 0;
}
val = (snd_soc_read(source->codec, reg) >> shift) & 0xf;
val = (snd_soc_read(codec, reg) >> shift) & 0xf;
switch (val) {
case 1:
case 2:
@ -590,6 +592,89 @@ static int can_use_asrc(struct snd_soc_dapm_widget *source,
return 0;
}
/**
* rt5670_sel_asrc_clk_src - select ASRC clock source for a set of filters
* @codec: SoC audio codec device.
* @filter_mask: mask of filters.
* @clk_src: clock source
*
* The ASRC function is for asynchronous MCLK and LRCK. Also, since RT5670 can
* only support standard 32fs or 64fs i2s format, ASRC should be enabled to
* support special i2s clock format such as Intel's 100fs(100 * sampling rate).
* ASRC function will track i2s clock and generate a corresponding system clock
* for codec. This function provides an API to select the clock source for a
* set of filters specified by the mask. And the codec driver will turn on ASRC
* for these filters if ASRC is selected as their clock source.
*/
int rt5670_sel_asrc_clk_src(struct snd_soc_codec *codec,
unsigned int filter_mask, unsigned int clk_src)
{
unsigned int asrc2_mask = 0, asrc2_value = 0;
unsigned int asrc3_mask = 0, asrc3_value = 0;
if (clk_src > RT5670_CLK_SEL_SYS3)
return -EINVAL;
if (filter_mask & RT5670_DA_STEREO_FILTER) {
asrc2_mask |= RT5670_DA_STO_CLK_SEL_MASK;
asrc2_value = (asrc2_value & ~RT5670_DA_STO_CLK_SEL_MASK)
| (clk_src << RT5670_DA_STO_CLK_SEL_SFT);
}
if (filter_mask & RT5670_DA_MONO_L_FILTER) {
asrc2_mask |= RT5670_DA_MONOL_CLK_SEL_MASK;
asrc2_value = (asrc2_value & ~RT5670_DA_MONOL_CLK_SEL_MASK)
| (clk_src << RT5670_DA_MONOL_CLK_SEL_SFT);
}
if (filter_mask & RT5670_DA_MONO_R_FILTER) {
asrc2_mask |= RT5670_DA_MONOR_CLK_SEL_MASK;
asrc2_value = (asrc2_value & ~RT5670_DA_MONOR_CLK_SEL_MASK)
| (clk_src << RT5670_DA_MONOR_CLK_SEL_SFT);
}
if (filter_mask & RT5670_AD_STEREO_FILTER) {
asrc2_mask |= RT5670_AD_STO1_CLK_SEL_MASK;
asrc2_value = (asrc2_value & ~RT5670_AD_STO1_CLK_SEL_MASK)
| (clk_src << RT5670_AD_STO1_CLK_SEL_SFT);
}
if (filter_mask & RT5670_AD_MONO_L_FILTER) {
asrc3_mask |= RT5670_AD_MONOL_CLK_SEL_MASK;
asrc3_value = (asrc3_value & ~RT5670_AD_MONOL_CLK_SEL_MASK)
| (clk_src << RT5670_AD_MONOL_CLK_SEL_SFT);
}
if (filter_mask & RT5670_AD_MONO_R_FILTER) {
asrc3_mask |= RT5670_AD_MONOR_CLK_SEL_MASK;
asrc3_value = (asrc3_value & ~RT5670_AD_MONOR_CLK_SEL_MASK)
| (clk_src << RT5670_AD_MONOR_CLK_SEL_SFT);
}
if (filter_mask & RT5670_UP_RATE_FILTER) {
asrc3_mask |= RT5670_UP_CLK_SEL_MASK;
asrc3_value = (asrc3_value & ~RT5670_UP_CLK_SEL_MASK)
| (clk_src << RT5670_UP_CLK_SEL_SFT);
}
if (filter_mask & RT5670_DOWN_RATE_FILTER) {
asrc3_mask |= RT5670_DOWN_CLK_SEL_MASK;
asrc3_value = (asrc3_value & ~RT5670_DOWN_CLK_SEL_MASK)
| (clk_src << RT5670_DOWN_CLK_SEL_SFT);
}
if (asrc2_mask)
snd_soc_update_bits(codec, RT5670_ASRC_2,
asrc2_mask, asrc2_value);
if (asrc3_mask)
snd_soc_update_bits(codec, RT5670_ASRC_3,
asrc3_mask, asrc3_value);
return 0;
}
EXPORT_SYMBOL_GPL(rt5670_sel_asrc_clk_src);
/* Digital Mixer */
static const struct snd_kcontrol_new rt5670_sto1_adc_l_mix[] = {
SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO1_ADC_MIXER,
@ -1148,7 +1233,7 @@ static const struct snd_kcontrol_new rt5670_vad_adc_mux =
static int rt5670_hp_power_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -1184,7 +1269,7 @@ static int rt5670_hp_power_event(struct snd_soc_dapm_widget *w,
static int rt5670_hp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -1234,7 +1319,7 @@ static int rt5670_hp_event(struct snd_soc_dapm_widget *w,
static int rt5670_bst1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
@ -1257,7 +1342,7 @@ static int rt5670_bst1_event(struct snd_soc_dapm_widget *w,
static int rt5670_bst2_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:

View File

@ -1023,50 +1023,33 @@
#define RT5670_DMIC_2_M_NOR (0x0 << 8)
#define RT5670_DMIC_2_M_ASYN (0x1 << 8)
/* ASRC clock source selection (0x84, 0x85) */
#define RT5670_CLK_SEL_SYS (0x0)
#define RT5670_CLK_SEL_I2S1_ASRC (0x1)
#define RT5670_CLK_SEL_I2S2_ASRC (0x2)
#define RT5670_CLK_SEL_I2S3_ASRC (0x3)
#define RT5670_CLK_SEL_SYS2 (0x5)
#define RT5670_CLK_SEL_SYS3 (0x6)
/* ASRC Control 2 (0x84) */
#define RT5670_MDA_L_M_MASK (0x1 << 15)
#define RT5670_MDA_L_M_SFT 15
#define RT5670_MDA_L_M_NOR (0x0 << 15)
#define RT5670_MDA_L_M_ASYN (0x1 << 15)
#define RT5670_MDA_R_M_MASK (0x1 << 14)
#define RT5670_MDA_R_M_SFT 14
#define RT5670_MDA_R_M_NOR (0x0 << 14)
#define RT5670_MDA_R_M_ASYN (0x1 << 14)
#define RT5670_MAD_L_M_MASK (0x1 << 13)
#define RT5670_MAD_L_M_SFT 13
#define RT5670_MAD_L_M_NOR (0x0 << 13)
#define RT5670_MAD_L_M_ASYN (0x1 << 13)
#define RT5670_MAD_R_M_MASK (0x1 << 12)
#define RT5670_MAD_R_M_SFT 12
#define RT5670_MAD_R_M_NOR (0x0 << 12)
#define RT5670_MAD_R_M_ASYN (0x1 << 12)
#define RT5670_ADC_M_MASK (0x1 << 11)
#define RT5670_ADC_M_SFT 11
#define RT5670_ADC_M_NOR (0x0 << 11)
#define RT5670_ADC_M_ASYN (0x1 << 11)
#define RT5670_STO_DAC_M_MASK (0x1 << 5)
#define RT5670_STO_DAC_M_SFT 5
#define RT5670_STO_DAC_M_NOR (0x0 << 5)
#define RT5670_STO_DAC_M_ASYN (0x1 << 5)
#define RT5670_I2S1_R_D_MASK (0x1 << 4)
#define RT5670_I2S1_R_D_SFT 4
#define RT5670_I2S1_R_D_DIS (0x0 << 4)
#define RT5670_I2S1_R_D_EN (0x1 << 4)
#define RT5670_I2S2_R_D_MASK (0x1 << 3)
#define RT5670_I2S2_R_D_SFT 3
#define RT5670_I2S2_R_D_DIS (0x0 << 3)
#define RT5670_I2S2_R_D_EN (0x1 << 3)
#define RT5670_PRE_SCLK_MASK (0x3)
#define RT5670_PRE_SCLK_SFT 0
#define RT5670_PRE_SCLK_512 (0x0)
#define RT5670_PRE_SCLK_1024 (0x1)
#define RT5670_PRE_SCLK_2048 (0x2)
#define RT5670_DA_STO_CLK_SEL_MASK (0xf << 12)
#define RT5670_DA_STO_CLK_SEL_SFT 12
#define RT5670_DA_MONOL_CLK_SEL_MASK (0xf << 8)
#define RT5670_DA_MONOL_CLK_SEL_SFT 8
#define RT5670_DA_MONOR_CLK_SEL_MASK (0xf << 4)
#define RT5670_DA_MONOR_CLK_SEL_SFT 4
#define RT5670_AD_STO1_CLK_SEL_MASK (0xf << 0)
#define RT5670_AD_STO1_CLK_SEL_SFT 0
/* ASRC Control 3 (0x85) */
#define RT5670_I2S1_RATE_MASK (0xf << 12)
#define RT5670_I2S1_RATE_SFT 12
#define RT5670_I2S2_RATE_MASK (0xf << 8)
#define RT5670_I2S2_RATE_SFT 8
#define RT5670_UP_CLK_SEL_MASK (0xf << 12)
#define RT5670_UP_CLK_SEL_SFT 12
#define RT5670_DOWN_CLK_SEL_MASK (0xf << 8)
#define RT5670_DOWN_CLK_SEL_SFT 8
#define RT5670_AD_MONOL_CLK_SEL_MASK (0xf << 4)
#define RT5670_AD_MONOL_CLK_SEL_SFT 4
#define RT5670_AD_MONOR_CLK_SEL_MASK (0xf << 0)
#define RT5670_AD_MONOR_CLK_SEL_SFT 0
/* ASRC Control 4 (0x89) */
#define RT5670_I2S1_PD_MASK (0x7 << 12)
@ -1983,6 +1966,21 @@ enum {
RT5670_DMIC_DATA_GPIO5,
};
/* filter mask */
enum {
RT5670_DA_STEREO_FILTER = 0x1,
RT5670_DA_MONO_L_FILTER = (0x1 << 1),
RT5670_DA_MONO_R_FILTER = (0x1 << 2),
RT5670_AD_STEREO_FILTER = (0x1 << 3),
RT5670_AD_MONO_L_FILTER = (0x1 << 4),
RT5670_AD_MONO_R_FILTER = (0x1 << 5),
RT5670_UP_RATE_FILTER = (0x1 << 6),
RT5670_DOWN_RATE_FILTER = (0x1 << 7),
};
int rt5670_sel_asrc_clk_src(struct snd_soc_codec *codec,
unsigned int filter_mask, unsigned int clk_src);
struct rt5670_priv {
struct snd_soc_codec *codec;
struct rt5670_platform_data pdata;

View File

@ -702,6 +702,9 @@ static int rt5677_set_dsp_vad(struct snd_soc_codec *codec, bool on)
static bool activity;
int ret;
if (!IS_ENABLED(CONFIG_SND_SOC_RT5677_SPI))
return -ENXIO;
if (on && !activity) {
activity = true;
@ -896,7 +899,7 @@ static const struct snd_kcontrol_new rt5677_snd_controls[] = {
static int set_dmic_clk(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
int idx = rl6231_calc_dmic_clk(rt5677->sysclk);
@ -911,7 +914,8 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(source->codec);
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
unsigned int val;
regmap_read(rt5677->regmap, RT5677_GLB_CLK1, &val);
@ -925,6 +929,8 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
static int is_using_asrc(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
unsigned int reg, shift, val;
if (source->reg == RT5677_ASRC_1) {
@ -991,7 +997,9 @@ static int is_using_asrc(struct snd_soc_dapm_widget *source,
}
}
val = (snd_soc_read(source->codec, reg) >> shift) & 0xf;
regmap_read(rt5677->regmap, reg, &val);
val = (val >> shift) & 0xf;
switch (val) {
case 1 ... 6:
return 1;
@ -2122,7 +2130,7 @@ static const struct snd_kcontrol_new rt5677_if2_dac7_tdm_sel_mux =
static int rt5677_bst1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -2146,7 +2154,7 @@ static int rt5677_bst1_event(struct snd_soc_dapm_widget *w,
static int rt5677_bst2_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -2170,7 +2178,7 @@ static int rt5677_bst2_event(struct snd_soc_dapm_widget *w,
static int rt5677_set_pll1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -2192,7 +2200,7 @@ static int rt5677_set_pll1_event(struct snd_soc_dapm_widget *w,
static int rt5677_set_pll2_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -2214,7 +2222,7 @@ static int rt5677_set_pll2_event(struct snd_soc_dapm_widget *w,
static int rt5677_set_micbias1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -2241,7 +2249,7 @@ static int rt5677_set_micbias1_event(struct snd_soc_dapm_widget *w,
static int rt5677_if1_adc_tdm_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
unsigned int value;
@ -2264,7 +2272,7 @@ static int rt5677_if1_adc_tdm_event(struct snd_soc_dapm_widget *w,
static int rt5677_if2_adc_tdm_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
unsigned int value;
@ -2287,7 +2295,7 @@ static int rt5677_if2_adc_tdm_event(struct snd_soc_dapm_widget *w,
static int rt5677_vref_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -4098,7 +4106,8 @@ static int rt5677_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
unsigned int rx_mask, int slots, int slot_width)
{
struct snd_soc_codec *codec = dai->codec;
unsigned int val = 0;
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
unsigned int val = 0, slot_width_25 = 0;
if (rx_mask || tx_mask)
val |= (1 << 12);
@ -4122,6 +4131,8 @@ static int rt5677_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
case 20:
val |= (1 << 8);
break;
case 25:
slot_width_25 = 0x8080;
case 24:
val |= (2 << 8);
break;
@ -4135,10 +4146,16 @@ static int rt5677_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
switch (dai->id) {
case RT5677_AIF1:
snd_soc_update_bits(codec, RT5677_TDM1_CTRL1, 0x1f00, val);
regmap_update_bits(rt5677->regmap, RT5677_TDM1_CTRL1, 0x1f00,
val);
regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x8000,
slot_width_25);
break;
case RT5677_AIF2:
snd_soc_update_bits(codec, RT5677_TDM2_CTRL1, 0x1f00, val);
regmap_update_bits(rt5677->regmap, RT5677_TDM2_CTRL1, 0x1f00,
val);
regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x80,
slot_width_25);
break;
default:
break;
@ -4923,6 +4940,11 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
RT5677_GPIO5_DIR_OUT);
}
if (rt5677->pdata.micbias1_vdd_3v3)
regmap_update_bits(rt5677->regmap, RT5677_MICBIAS,
RT5677_MICBIAS1_CTRL_VDD_MASK,
RT5677_MICBIAS1_CTRL_VDD_3_3V);
rt5677_init_gpio(i2c);
rt5677_init_irq(i2c);

View File

@ -155,18 +155,19 @@ struct sgtl5000_priv {
static int mic_bias_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(w->codec);
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
/* change mic bias resistor */
snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL,
snd_soc_update_bits(codec, SGTL5000_CHIP_MIC_CTRL,
SGTL5000_BIAS_R_MASK,
sgtl5000->micbias_resistor << SGTL5000_BIAS_R_SHIFT);
break;
case SND_SOC_DAPM_PRE_PMD:
snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL,
snd_soc_update_bits(codec, SGTL5000_CHIP_MIC_CTRL,
SGTL5000_BIAS_R_MASK, 0);
break;
}
@ -181,11 +182,12 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w,
static int power_vag_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
const u32 mask = SGTL5000_DAC_POWERUP | SGTL5000_ADC_POWERUP;
switch (event) {
case SND_SOC_DAPM_POST_PMU:
snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER,
snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP);
break;
@ -195,9 +197,9 @@ static int power_vag_event(struct snd_soc_dapm_widget *w,
* operational to prevent inadvertently starving the
* other one of them.
*/
if ((snd_soc_read(w->codec, SGTL5000_CHIP_ANA_POWER) &
if ((snd_soc_read(codec, SGTL5000_CHIP_ANA_POWER) &
mask) != mask) {
snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER,
snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
SGTL5000_VAG_POWERUP, 0);
msleep(400);
}
@ -483,21 +485,21 @@ static int sgtl5000_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
/* setting i2s data format */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_DSP_A:
i2sctl |= SGTL5000_I2S_MODE_PCM;
i2sctl |= SGTL5000_I2S_MODE_PCM << SGTL5000_I2S_MODE_SHIFT;
break;
case SND_SOC_DAIFMT_DSP_B:
i2sctl |= SGTL5000_I2S_MODE_PCM;
i2sctl |= SGTL5000_I2S_MODE_PCM << SGTL5000_I2S_MODE_SHIFT;
i2sctl |= SGTL5000_I2S_LRALIGN;
break;
case SND_SOC_DAIFMT_I2S:
i2sctl |= SGTL5000_I2S_MODE_I2S_LJ;
i2sctl |= SGTL5000_I2S_MODE_I2S_LJ << SGTL5000_I2S_MODE_SHIFT;
break;
case SND_SOC_DAIFMT_RIGHT_J:
i2sctl |= SGTL5000_I2S_MODE_RJ;
i2sctl |= SGTL5000_I2S_MODE_RJ << SGTL5000_I2S_MODE_SHIFT;
i2sctl |= SGTL5000_I2S_LRPOL;
break;
case SND_SOC_DAIFMT_LEFT_J:
i2sctl |= SGTL5000_I2S_MODE_I2S_LJ;
i2sctl |= SGTL5000_I2S_MODE_I2S_LJ << SGTL5000_I2S_MODE_SHIFT;
i2sctl |= SGTL5000_I2S_LRALIGN;
break;
default:
@ -1462,6 +1464,9 @@ static int sgtl5000_i2c_probe(struct i2c_client *client,
if (ret)
return ret;
/* Need 8 clocks before I2C accesses */
udelay(1);
/* read chip information */
ret = regmap_read(sgtl5000->regmap, SGTL5000_CHIP_ID, &reg);
if (ret)

View File

@ -233,16 +233,18 @@ static int sn95031_set_vaud_bias(struct snd_soc_codec *codec,
static int sn95031_vhs_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
if (SND_SOC_DAPM_EVENT_ON(event)) {
pr_debug("VHS SND_SOC_DAPM_EVENT_ON doing rail startup now\n");
/* power up the rail */
snd_soc_write(w->codec, SN95031_VHSP, 0x3D);
snd_soc_write(w->codec, SN95031_VHSN, 0x3F);
snd_soc_write(codec, SN95031_VHSP, 0x3D);
snd_soc_write(codec, SN95031_VHSN, 0x3F);
msleep(1);
} else if (SND_SOC_DAPM_EVENT_OFF(event)) {
pr_debug("VHS SND_SOC_DAPM_EVENT_OFF doing rail shutdown\n");
snd_soc_write(w->codec, SN95031_VHSP, 0xC4);
snd_soc_write(w->codec, SN95031_VHSN, 0x04);
snd_soc_write(codec, SN95031_VHSP, 0xC4);
snd_soc_write(codec, SN95031_VHSN, 0x04);
}
return 0;
}
@ -250,14 +252,16 @@ static int sn95031_vhs_event(struct snd_soc_dapm_widget *w,
static int sn95031_vihf_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
if (SND_SOC_DAPM_EVENT_ON(event)) {
pr_debug("VIHF SND_SOC_DAPM_EVENT_ON doing rail startup now\n");
/* power up the rail */
snd_soc_write(w->codec, SN95031_VIHF, 0x27);
snd_soc_write(codec, SN95031_VIHF, 0x27);
msleep(1);
} else if (SND_SOC_DAPM_EVENT_OFF(event)) {
pr_debug("VIHF SND_SOC_DAPM_EVENT_OFF doing rail shutdown\n");
snd_soc_write(w->codec, SN95031_VIHF, 0x24);
snd_soc_write(codec, SN95031_VIHF, 0x24);
}
return 0;
}
@ -265,6 +269,7 @@ static int sn95031_vihf_event(struct snd_soc_dapm_widget *w,
static int sn95031_dmic12_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
unsigned int ldo = 0, clk_dir = 0, data_dir = 0;
if (SND_SOC_DAPM_EVENT_ON(event)) {
@ -273,15 +278,16 @@ static int sn95031_dmic12_event(struct snd_soc_dapm_widget *w,
data_dir = BIT(7);
}
/* program DMIC LDO, clock and set clock */
snd_soc_update_bits(w->codec, SN95031_MICBIAS, BIT(5)|BIT(4), ldo);
snd_soc_update_bits(w->codec, SN95031_DMICBUF0123, BIT(0), clk_dir);
snd_soc_update_bits(w->codec, SN95031_DMICBUF0123, BIT(7), data_dir);
snd_soc_update_bits(codec, SN95031_MICBIAS, BIT(5)|BIT(4), ldo);
snd_soc_update_bits(codec, SN95031_DMICBUF0123, BIT(0), clk_dir);
snd_soc_update_bits(codec, SN95031_DMICBUF0123, BIT(7), data_dir);
return 0;
}
static int sn95031_dmic34_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
unsigned int ldo = 0, clk_dir = 0, data_dir = 0;
if (SND_SOC_DAPM_EVENT_ON(event)) {
@ -290,22 +296,23 @@ static int sn95031_dmic34_event(struct snd_soc_dapm_widget *w,
data_dir = BIT(1);
}
/* program DMIC LDO, clock and set clock */
snd_soc_update_bits(w->codec, SN95031_MICBIAS, BIT(5)|BIT(4), ldo);
snd_soc_update_bits(w->codec, SN95031_DMICBUF0123, BIT(2), clk_dir);
snd_soc_update_bits(w->codec, SN95031_DMICBUF45, BIT(1), data_dir);
snd_soc_update_bits(codec, SN95031_MICBIAS, BIT(5)|BIT(4), ldo);
snd_soc_update_bits(codec, SN95031_DMICBUF0123, BIT(2), clk_dir);
snd_soc_update_bits(codec, SN95031_DMICBUF45, BIT(1), data_dir);
return 0;
}
static int sn95031_dmic56_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
unsigned int ldo = 0;
if (SND_SOC_DAPM_EVENT_ON(event))
ldo = BIT(7)|BIT(6);
/* program DMIC LDO */
snd_soc_update_bits(w->codec, SN95031_MICBIAS, BIT(7)|BIT(6), ldo);
snd_soc_update_bits(codec, SN95031_MICBIAS, BIT(7)|BIT(6), ldo);
return 0;
}

View File

@ -24,8 +24,11 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/gpio/consumer.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <sound/core.h>
@ -102,6 +105,35 @@ static const struct reg_default sta32x_regs[] = {
{ 0x2c, 0x0c },
};
static const struct regmap_range sta32x_write_regs_range[] = {
regmap_reg_range(STA32X_CONFA, STA32X_AUTO2),
regmap_reg_range(STA32X_C1CFG, STA32X_FDRC2),
};
static const struct regmap_range sta32x_read_regs_range[] = {
regmap_reg_range(STA32X_CONFA, STA32X_AUTO2),
regmap_reg_range(STA32X_C1CFG, STA32X_FDRC2),
};
static const struct regmap_range sta32x_volatile_regs_range[] = {
regmap_reg_range(STA32X_CFADDR2, STA32X_CFUD),
};
static const struct regmap_access_table sta32x_write_regs = {
.yes_ranges = sta32x_write_regs_range,
.n_yes_ranges = ARRAY_SIZE(sta32x_write_regs_range),
};
static const struct regmap_access_table sta32x_read_regs = {
.yes_ranges = sta32x_read_regs_range,
.n_yes_ranges = ARRAY_SIZE(sta32x_read_regs_range),
};
static const struct regmap_access_table sta32x_volatile_regs = {
.yes_ranges = sta32x_volatile_regs_range,
.n_yes_ranges = ARRAY_SIZE(sta32x_volatile_regs_range),
};
/* regulator power supply names */
static const char *sta32x_supply_names[] = {
"Vdda", /* analog supply, 3.3VV */
@ -122,6 +154,8 @@ struct sta32x_priv {
u32 coef_shadow[STA32X_COEF_COUNT];
struct delayed_work watchdog_work;
int shutdown;
struct gpio_desc *gpiod_nreset;
struct mutex coeff_lock;
};
static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1);
@ -155,37 +189,32 @@ static const char *sta32x_limiter_release_rate[] = {
"0.5116", "0.1370", "0.0744", "0.0499", "0.0360", "0.0299",
"0.0264", "0.0208", "0.0198", "0.0172", "0.0147", "0.0137",
"0.0134", "0.0117", "0.0110", "0.0104" };
static const unsigned int sta32x_limiter_ac_attack_tlv[] = {
TLV_DB_RANGE_HEAD(2),
static DECLARE_TLV_DB_RANGE(sta32x_limiter_ac_attack_tlv,
0, 7, TLV_DB_SCALE_ITEM(-1200, 200, 0),
8, 16, TLV_DB_SCALE_ITEM(300, 100, 0),
};
);
static const unsigned int sta32x_limiter_ac_release_tlv[] = {
TLV_DB_RANGE_HEAD(5),
static DECLARE_TLV_DB_RANGE(sta32x_limiter_ac_release_tlv,
0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0),
1, 1, TLV_DB_SCALE_ITEM(-2900, 0, 0),
2, 2, TLV_DB_SCALE_ITEM(-2000, 0, 0),
3, 8, TLV_DB_SCALE_ITEM(-1400, 200, 0),
8, 16, TLV_DB_SCALE_ITEM(-700, 100, 0),
};
);
static const unsigned int sta32x_limiter_drc_attack_tlv[] = {
TLV_DB_RANGE_HEAD(3),
static DECLARE_TLV_DB_RANGE(sta32x_limiter_drc_attack_tlv,
0, 7, TLV_DB_SCALE_ITEM(-3100, 200, 0),
8, 13, TLV_DB_SCALE_ITEM(-1600, 100, 0),
14, 16, TLV_DB_SCALE_ITEM(-1000, 300, 0),
};
);
static const unsigned int sta32x_limiter_drc_release_tlv[] = {
TLV_DB_RANGE_HEAD(5),
static DECLARE_TLV_DB_RANGE(sta32x_limiter_drc_release_tlv,
0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0),
1, 2, TLV_DB_SCALE_ITEM(-3800, 200, 0),
3, 4, TLV_DB_SCALE_ITEM(-3300, 200, 0),
5, 12, TLV_DB_SCALE_ITEM(-3000, 200, 0),
13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0),
};
);
static SOC_ENUM_SINGLE_DECL(sta32x_drc_ac_enum,
STA32X_CONFD, STA32X_CONFD_DRC_SHIFT,
@ -244,29 +273,42 @@ static int sta32x_coefficient_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
int numcoef = kcontrol->private_value >> 16;
int index = kcontrol->private_value & 0xffff;
unsigned int cfud;
int i;
unsigned int cfud, val;
int i, ret = 0;
mutex_lock(&sta32x->coeff_lock);
/* preserve reserved bits in STA32X_CFUD */
cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0;
/* chip documentation does not say if the bits are self clearing,
* so do it explicitly */
snd_soc_write(codec, STA32X_CFUD, cfud);
regmap_read(sta32x->regmap, STA32X_CFUD, &cfud);
cfud &= 0xf0;
/*
* chip documentation does not say if the bits are self clearing,
* so do it explicitly
*/
regmap_write(sta32x->regmap, STA32X_CFUD, cfud);
snd_soc_write(codec, STA32X_CFADDR2, index);
if (numcoef == 1)
snd_soc_write(codec, STA32X_CFUD, cfud | 0x04);
else if (numcoef == 5)
snd_soc_write(codec, STA32X_CFUD, cfud | 0x08);
else
return -EINVAL;
for (i = 0; i < 3 * numcoef; i++)
ucontrol->value.bytes.data[i] =
snd_soc_read(codec, STA32X_B1CF1 + i);
regmap_write(sta32x->regmap, STA32X_CFADDR2, index);
if (numcoef == 1) {
regmap_write(sta32x->regmap, STA32X_CFUD, cfud | 0x04);
} else if (numcoef == 5) {
regmap_write(sta32x->regmap, STA32X_CFUD, cfud | 0x08);
} else {
ret = -EINVAL;
goto exit_unlock;
}
return 0;
for (i = 0; i < 3 * numcoef; i++) {
regmap_read(sta32x->regmap, STA32X_B1CF1 + i, &val);
ucontrol->value.bytes.data[i] = val;
}
exit_unlock:
mutex_unlock(&sta32x->coeff_lock);
return ret;
}
static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol,
@ -280,24 +322,27 @@ static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol,
int i;
/* preserve reserved bits in STA32X_CFUD */
cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0;
/* chip documentation does not say if the bits are self clearing,
* so do it explicitly */
snd_soc_write(codec, STA32X_CFUD, cfud);
regmap_read(sta32x->regmap, STA32X_CFUD, &cfud);
cfud &= 0xf0;
/*
* chip documentation does not say if the bits are self clearing,
* so do it explicitly
*/
regmap_write(sta32x->regmap, STA32X_CFUD, cfud);
snd_soc_write(codec, STA32X_CFADDR2, index);
regmap_write(sta32x->regmap, STA32X_CFADDR2, index);
for (i = 0; i < numcoef && (index + i < STA32X_COEF_COUNT); i++)
sta32x->coef_shadow[index + i] =
(ucontrol->value.bytes.data[3 * i] << 16)
| (ucontrol->value.bytes.data[3 * i + 1] << 8)
| (ucontrol->value.bytes.data[3 * i + 2]);
for (i = 0; i < 3 * numcoef; i++)
snd_soc_write(codec, STA32X_B1CF1 + i,
ucontrol->value.bytes.data[i]);
regmap_write(sta32x->regmap, STA32X_B1CF1 + i,
ucontrol->value.bytes.data[i]);
if (numcoef == 1)
snd_soc_write(codec, STA32X_CFUD, cfud | 0x01);
regmap_write(sta32x->regmap, STA32X_CFUD, cfud | 0x01);
else if (numcoef == 5)
snd_soc_write(codec, STA32X_CFUD, cfud | 0x02);
regmap_write(sta32x->regmap, STA32X_CFUD, cfud | 0x02);
else
return -EINVAL;
@ -311,20 +356,23 @@ static int sta32x_sync_coef_shadow(struct snd_soc_codec *codec)
int i;
/* preserve reserved bits in STA32X_CFUD */
cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0;
regmap_read(sta32x->regmap, STA32X_CFUD, &cfud);
cfud &= 0xf0;
for (i = 0; i < STA32X_COEF_COUNT; i++) {
snd_soc_write(codec, STA32X_CFADDR2, i);
snd_soc_write(codec, STA32X_B1CF1,
(sta32x->coef_shadow[i] >> 16) & 0xff);
snd_soc_write(codec, STA32X_B1CF2,
(sta32x->coef_shadow[i] >> 8) & 0xff);
snd_soc_write(codec, STA32X_B1CF3,
(sta32x->coef_shadow[i]) & 0xff);
/* chip documentation does not say if the bits are
* self-clearing, so do it explicitly */
snd_soc_write(codec, STA32X_CFUD, cfud);
snd_soc_write(codec, STA32X_CFUD, cfud | 0x01);
regmap_write(sta32x->regmap, STA32X_CFADDR2, i);
regmap_write(sta32x->regmap, STA32X_B1CF1,
(sta32x->coef_shadow[i] >> 16) & 0xff);
regmap_write(sta32x->regmap, STA32X_B1CF2,
(sta32x->coef_shadow[i] >> 8) & 0xff);
regmap_write(sta32x->regmap, STA32X_B1CF3,
(sta32x->coef_shadow[i]) & 0xff);
/*
* chip documentation does not say if the bits are
* self-clearing, so do it explicitly
*/
regmap_write(sta32x->regmap, STA32X_CFUD, cfud);
regmap_write(sta32x->regmap, STA32X_CFUD, cfud | 0x01);
}
return 0;
}
@ -336,11 +384,11 @@ static int sta32x_cache_sync(struct snd_soc_codec *codec)
int rc;
/* mute during register sync */
mute = snd_soc_read(codec, STA32X_MMUTE);
snd_soc_write(codec, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE);
regmap_read(sta32x->regmap, STA32X_MMUTE, &mute);
regmap_write(sta32x->regmap, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE);
sta32x_sync_coef_shadow(codec);
rc = regcache_sync(sta32x->regmap);
snd_soc_write(codec, STA32X_MMUTE, mute);
regmap_write(sta32x->regmap, STA32X_MMUTE, mute);
return rc;
}
@ -508,17 +556,12 @@ static struct {
};
/* MCLK to fs clock ratios */
static struct {
int ratio;
int mcs;
} mclk_ratios[3][7] = {
{ { 768, 0 }, { 512, 1 }, { 384, 2 }, { 256, 3 },
{ 128, 4 }, { 576, 5 }, { 0, 0 } },
{ { 384, 2 }, { 256, 3 }, { 192, 4 }, { 128, 5 }, {64, 0 }, { 0, 0 } },
{ { 384, 2 }, { 256, 3 }, { 192, 4 }, { 128, 5 }, {64, 0 }, { 0, 0 } },
static int mcs_ratio_table[3][7] = {
{ 768, 512, 384, 256, 128, 576, 0 },
{ 384, 256, 192, 128, 64, 0 },
{ 384, 256, 192, 128, 64, 0 },
};
/**
* sta32x_set_dai_sysclk - configure MCLK
* @codec_dai: the codec DAI
@ -543,46 +586,10 @@ static int sta32x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
{
struct snd_soc_codec *codec = codec_dai->codec;
struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
int i, j, ir, fs;
unsigned int rates = 0;
unsigned int rate_min = -1;
unsigned int rate_max = 0;
pr_debug("mclk=%u\n", freq);
dev_dbg(codec->dev, "mclk=%u\n", freq);
sta32x->mclk = freq;
if (sta32x->mclk) {
for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) {
ir = interpolation_ratios[i].ir;
fs = interpolation_ratios[i].fs;
for (j = 0; mclk_ratios[ir][j].ratio; j++) {
if (mclk_ratios[ir][j].ratio * fs == freq) {
rates |= snd_pcm_rate_to_rate_bit(fs);
if (fs < rate_min)
rate_min = fs;
if (fs > rate_max)
rate_max = fs;
break;
}
}
}
/* FIXME: soc should support a rate list */
rates &= ~SNDRV_PCM_RATE_KNOT;
if (!rates) {
dev_err(codec->dev, "could not find a valid sample rate\n");
return -EINVAL;
}
} else {
/* enable all possible rates */
rates = STA32X_RATES;
rate_min = 32000;
rate_max = 192000;
}
codec_dai->driver->playback.rates = rates;
codec_dai->driver->playback.rate_min = rate_min;
codec_dai->driver->playback.rate_max = rate_max;
return 0;
}
@ -599,10 +606,7 @@ static int sta32x_set_dai_fmt(struct snd_soc_dai *codec_dai,
{
struct snd_soc_codec *codec = codec_dai->codec;
struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
u8 confb = snd_soc_read(codec, STA32X_CONFB);
pr_debug("\n");
confb &= ~(STA32X_CONFB_C1IM | STA32X_CONFB_C2IM);
u8 confb = 0;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
@ -632,8 +636,8 @@ static int sta32x_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL;
}
snd_soc_write(codec, STA32X_CONFB, confb);
return 0;
return regmap_update_bits(sta32x->regmap, STA32X_CONFB,
STA32X_CONFB_C1IM | STA32X_CONFB_C2IM, confb);
}
/**
@ -651,39 +655,55 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_codec *codec = dai->codec;
struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
unsigned int rate;
int i, mcs = -1, ir = -1;
u8 confa, confb;
int i, mcs = -EINVAL, ir = -EINVAL;
unsigned int confa, confb;
unsigned int rate, ratio;
int ret;
if (!sta32x->mclk) {
dev_err(codec->dev,
"sta32x->mclk is unset. Unable to determine ratio\n");
return -EIO;
}
rate = params_rate(params);
pr_debug("rate: %u\n", rate);
for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++)
ratio = sta32x->mclk / rate;
dev_dbg(codec->dev, "rate: %u, ratio: %u\n", rate, ratio);
for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) {
if (interpolation_ratios[i].fs == rate) {
ir = interpolation_ratios[i].ir;
break;
}
if (ir < 0)
}
if (ir < 0) {
dev_err(codec->dev, "Unsupported samplerate: %u\n", rate);
return -EINVAL;
for (i = 0; mclk_ratios[ir][i].ratio; i++)
if (mclk_ratios[ir][i].ratio * rate == sta32x->mclk) {
mcs = mclk_ratios[ir][i].mcs;
}
for (i = 0; i < 6; i++) {
if (mcs_ratio_table[ir][i] == ratio) {
mcs = i;
break;
}
if (mcs < 0)
}
if (mcs < 0) {
dev_err(codec->dev, "Unresolvable ratio: %u\n", ratio);
return -EINVAL;
}
confa = snd_soc_read(codec, STA32X_CONFA);
confa &= ~(STA32X_CONFA_MCS_MASK | STA32X_CONFA_IR_MASK);
confa |= (ir << STA32X_CONFA_IR_SHIFT) | (mcs << STA32X_CONFA_MCS_SHIFT);
confa = (ir << STA32X_CONFA_IR_SHIFT) |
(mcs << STA32X_CONFA_MCS_SHIFT);
confb = 0;
confb = snd_soc_read(codec, STA32X_CONFB);
confb &= ~(STA32X_CONFB_SAI_MASK | STA32X_CONFB_SAIFB);
switch (params_width(params)) {
case 24:
pr_debug("24bit\n");
dev_dbg(codec->dev, "24bit\n");
/* fall through */
case 32:
pr_debug("24bit or 32bit\n");
dev_dbg(codec->dev, "24bit or 32bit\n");
switch (sta32x->format) {
case SND_SOC_DAIFMT_I2S:
confb |= 0x0;
@ -698,7 +718,7 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream,
break;
case 20:
pr_debug("20bit\n");
dev_dbg(codec->dev, "20bit\n");
switch (sta32x->format) {
case SND_SOC_DAIFMT_I2S:
confb |= 0x4;
@ -713,7 +733,7 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream,
break;
case 18:
pr_debug("18bit\n");
dev_dbg(codec->dev, "18bit\n");
switch (sta32x->format) {
case SND_SOC_DAIFMT_I2S:
confb |= 0x8;
@ -728,7 +748,7 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream,
break;
case 16:
pr_debug("16bit\n");
dev_dbg(codec->dev, "16bit\n");
switch (sta32x->format) {
case SND_SOC_DAIFMT_I2S:
confb |= 0x0;
@ -746,8 +766,30 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
snd_soc_write(codec, STA32X_CONFA, confa);
snd_soc_write(codec, STA32X_CONFB, confb);
ret = regmap_update_bits(sta32x->regmap, STA32X_CONFA,
STA32X_CONFA_MCS_MASK | STA32X_CONFA_IR_MASK,
confa);
if (ret < 0)
return ret;
ret = regmap_update_bits(sta32x->regmap, STA32X_CONFB,
STA32X_CONFB_SAI_MASK | STA32X_CONFB_SAIFB,
confb);
if (ret < 0)
return ret;
return 0;
}
static int sta32x_startup_sequence(struct sta32x_priv *sta32x)
{
if (sta32x->gpiod_nreset) {
gpiod_set_value(sta32x->gpiod_nreset, 0);
mdelay(1);
gpiod_set_value(sta32x->gpiod_nreset, 1);
mdelay(1);
}
return 0;
}
@ -766,14 +808,14 @@ static int sta32x_set_bias_level(struct snd_soc_codec *codec,
int ret;
struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
pr_debug("level = %d\n", level);
dev_dbg(codec->dev, "level = %d\n", level);
switch (level) {
case SND_SOC_BIAS_ON:
break;
case SND_SOC_BIAS_PREPARE:
/* Full power on */
snd_soc_update_bits(codec, STA32X_CONFF,
regmap_update_bits(sta32x->regmap, STA32X_CONFF,
STA32X_CONFF_PWDN | STA32X_CONFF_EAPD,
STA32X_CONFF_PWDN | STA32X_CONFF_EAPD);
break;
@ -788,25 +830,28 @@ static int sta32x_set_bias_level(struct snd_soc_codec *codec,
return ret;
}
sta32x_startup_sequence(sta32x);
sta32x_cache_sync(codec);
sta32x_watchdog_start(sta32x);
}
/* Power up to mute */
/* FIXME */
snd_soc_update_bits(codec, STA32X_CONFF,
STA32X_CONFF_PWDN | STA32X_CONFF_EAPD,
STA32X_CONFF_PWDN | STA32X_CONFF_EAPD);
/* Power down */
regmap_update_bits(sta32x->regmap, STA32X_CONFF,
STA32X_CONFF_PWDN | STA32X_CONFF_EAPD,
0);
break;
case SND_SOC_BIAS_OFF:
/* The chip runs through the power down sequence for us. */
snd_soc_update_bits(codec, STA32X_CONFF,
STA32X_CONFF_PWDN | STA32X_CONFF_EAPD,
STA32X_CONFF_PWDN);
regmap_update_bits(sta32x->regmap, STA32X_CONFF,
STA32X_CONFF_PWDN | STA32X_CONFF_EAPD, 0);
msleep(300);
sta32x_watchdog_stop(sta32x);
if (sta32x->gpiod_nreset)
gpiod_set_value(sta32x->gpiod_nreset, 0);
regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies),
sta32x->supplies);
break;
@ -822,7 +867,7 @@ static const struct snd_soc_dai_ops sta32x_dai_ops = {
};
static struct snd_soc_dai_driver sta32x_dai = {
.name = "STA32X",
.name = "sta32x-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
@ -836,11 +881,8 @@ static struct snd_soc_dai_driver sta32x_dai = {
static int sta32x_probe(struct snd_soc_codec *codec)
{
struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
struct sta32x_platform_data *pdata = sta32x->pdata;
int i, ret = 0, thermal = 0;
sta32x->codec = codec;
sta32x->pdata = dev_get_platdata(codec->dev);
ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies),
sta32x->supplies);
if (ret != 0) {
@ -848,50 +890,73 @@ static int sta32x_probe(struct snd_soc_codec *codec)
return ret;
}
/* Chip documentation explicitly requires that the reset values
* of reserved register bits are left untouched.
* Write the register default value to cache for reserved registers,
* so the write to the these registers are suppressed by the cache
* restore code when it skips writes of default registers.
*/
regcache_cache_only(sta32x->regmap, true);
snd_soc_write(codec, STA32X_CONFC, 0xc2);
snd_soc_write(codec, STA32X_CONFE, 0xc2);
snd_soc_write(codec, STA32X_CONFF, 0x5c);
snd_soc_write(codec, STA32X_MMUTE, 0x10);
snd_soc_write(codec, STA32X_AUTO1, 0x60);
snd_soc_write(codec, STA32X_AUTO3, 0x00);
snd_soc_write(codec, STA32X_C3CFG, 0x40);
regcache_cache_only(sta32x->regmap, false);
ret = sta32x_startup_sequence(sta32x);
if (ret < 0) {
dev_err(codec->dev, "Failed to startup device\n");
return ret;
}
/* set thermal warning adjustment and recovery */
if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_ADJUSTMENT_ENABLE))
/* CONFA */
if (!pdata->thermal_warning_recovery)
thermal |= STA32X_CONFA_TWAB;
if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_RECOVERY_ENABLE))
if (!pdata->thermal_warning_adjustment)
thermal |= STA32X_CONFA_TWRB;
snd_soc_update_bits(codec, STA32X_CONFA,
STA32X_CONFA_TWAB | STA32X_CONFA_TWRB,
thermal);
if (!pdata->fault_detect_recovery)
thermal |= STA32X_CONFA_FDRB;
regmap_update_bits(sta32x->regmap, STA32X_CONFA,
STA32X_CONFA_TWAB | STA32X_CONFA_TWRB |
STA32X_CONFA_FDRB,
thermal);
/* CONFC */
regmap_update_bits(sta32x->regmap, STA32X_CONFC,
STA32X_CONFC_CSZ_MASK,
pdata->drop_compensation_ns
<< STA32X_CONFC_CSZ_SHIFT);
/* CONFE */
regmap_update_bits(sta32x->regmap, STA32X_CONFE,
STA32X_CONFE_MPCV,
pdata->max_power_use_mpcc ?
STA32X_CONFE_MPCV : 0);
regmap_update_bits(sta32x->regmap, STA32X_CONFE,
STA32X_CONFE_MPC,
pdata->max_power_correction ?
STA32X_CONFE_MPC : 0);
regmap_update_bits(sta32x->regmap, STA32X_CONFE,
STA32X_CONFE_AME,
pdata->am_reduction_mode ?
STA32X_CONFE_AME : 0);
regmap_update_bits(sta32x->regmap, STA32X_CONFE,
STA32X_CONFE_PWMS,
pdata->odd_pwm_speed_mode ?
STA32X_CONFE_PWMS : 0);
/* CONFF */
regmap_update_bits(sta32x->regmap, STA32X_CONFF,
STA32X_CONFF_IDE,
pdata->invalid_input_detect_mute ?
STA32X_CONFF_IDE : 0);
/* select output configuration */
snd_soc_update_bits(codec, STA32X_CONFF,
STA32X_CONFF_OCFG_MASK,
sta32x->pdata->output_conf
<< STA32X_CONFF_OCFG_SHIFT);
regmap_update_bits(sta32x->regmap, STA32X_CONFF,
STA32X_CONFF_OCFG_MASK,
pdata->output_conf
<< STA32X_CONFF_OCFG_SHIFT);
/* channel to output mapping */
snd_soc_update_bits(codec, STA32X_C1CFG,
STA32X_CxCFG_OM_MASK,
sta32x->pdata->ch1_output_mapping
<< STA32X_CxCFG_OM_SHIFT);
snd_soc_update_bits(codec, STA32X_C2CFG,
STA32X_CxCFG_OM_MASK,
sta32x->pdata->ch2_output_mapping
<< STA32X_CxCFG_OM_SHIFT);
snd_soc_update_bits(codec, STA32X_C3CFG,
STA32X_CxCFG_OM_MASK,
sta32x->pdata->ch3_output_mapping
<< STA32X_CxCFG_OM_SHIFT);
regmap_update_bits(sta32x->regmap, STA32X_C1CFG,
STA32X_CxCFG_OM_MASK,
pdata->ch1_output_mapping
<< STA32X_CxCFG_OM_SHIFT);
regmap_update_bits(sta32x->regmap, STA32X_C2CFG,
STA32X_CxCFG_OM_MASK,
pdata->ch2_output_mapping
<< STA32X_CxCFG_OM_SHIFT);
regmap_update_bits(sta32x->regmap, STA32X_C3CFG,
STA32X_CxCFG_OM_MASK,
pdata->ch3_output_mapping
<< STA32X_CxCFG_OM_SHIFT);
/* initialize coefficient shadow RAM with reset values */
for (i = 4; i <= 49; i += 5)
@ -924,16 +989,6 @@ static int sta32x_remove(struct snd_soc_codec *codec)
return 0;
}
static bool sta32x_reg_is_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
case STA32X_CONFA ... STA32X_L2ATRT:
case STA32X_MPCC1 ... STA32X_FDRC2:
return 0;
}
return 1;
}
static const struct snd_soc_codec_driver sta32x_codec = {
.probe = sta32x_probe,
.remove = sta32x_remove,
@ -954,12 +1009,75 @@ static const struct regmap_config sta32x_regmap = {
.reg_defaults = sta32x_regs,
.num_reg_defaults = ARRAY_SIZE(sta32x_regs),
.cache_type = REGCACHE_RBTREE,
.volatile_reg = sta32x_reg_is_volatile,
.wr_table = &sta32x_write_regs,
.rd_table = &sta32x_read_regs,
.volatile_table = &sta32x_volatile_regs,
};
#ifdef CONFIG_OF
static const struct of_device_id st32x_dt_ids[] = {
{ .compatible = "st,sta32x", },
{ }
};
MODULE_DEVICE_TABLE(of, st32x_dt_ids);
static int sta32x_probe_dt(struct device *dev, struct sta32x_priv *sta32x)
{
struct device_node *np = dev->of_node;
struct sta32x_platform_data *pdata;
u16 tmp;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
of_property_read_u8(np, "st,output-conf",
&pdata->output_conf);
of_property_read_u8(np, "st,ch1-output-mapping",
&pdata->ch1_output_mapping);
of_property_read_u8(np, "st,ch2-output-mapping",
&pdata->ch2_output_mapping);
of_property_read_u8(np, "st,ch3-output-mapping",
&pdata->ch3_output_mapping);
if (of_get_property(np, "st,thermal-warning-recovery", NULL))
pdata->thermal_warning_recovery = 1;
if (of_get_property(np, "st,thermal-warning-adjustment", NULL))
pdata->thermal_warning_adjustment = 1;
if (of_get_property(np, "st,needs_esd_watchdog", NULL))
pdata->needs_esd_watchdog = 1;
tmp = 140;
of_property_read_u16(np, "st,drop-compensation-ns", &tmp);
pdata->drop_compensation_ns = clamp_t(u16, tmp, 0, 300) / 20;
/* CONFE */
if (of_get_property(np, "st,max-power-use-mpcc", NULL))
pdata->max_power_use_mpcc = 1;
if (of_get_property(np, "st,max-power-correction", NULL))
pdata->max_power_correction = 1;
if (of_get_property(np, "st,am-reduction-mode", NULL))
pdata->am_reduction_mode = 1;
if (of_get_property(np, "st,odd-pwm-speed-mode", NULL))
pdata->odd_pwm_speed_mode = 1;
/* CONFF */
if (of_get_property(np, "st,invalid-input-detect-mute", NULL))
pdata->invalid_input_detect_mute = 1;
sta32x->pdata = pdata;
return 0;
}
#endif
static int sta32x_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct device *dev = &i2c->dev;
struct sta32x_priv *sta32x;
int ret, i;
@ -968,6 +1086,29 @@ static int sta32x_i2c_probe(struct i2c_client *i2c,
if (!sta32x)
return -ENOMEM;
mutex_init(&sta32x->coeff_lock);
sta32x->pdata = dev_get_platdata(dev);
#ifdef CONFIG_OF
if (dev->of_node) {
ret = sta32x_probe_dt(dev, sta32x);
if (ret < 0)
return ret;
}
#endif
/* GPIOs */
sta32x->gpiod_nreset = devm_gpiod_get(dev, "reset");
if (IS_ERR(sta32x->gpiod_nreset)) {
ret = PTR_ERR(sta32x->gpiod_nreset);
if (ret != -ENOENT && ret != -ENOSYS)
return ret;
sta32x->gpiod_nreset = NULL;
} else {
gpiod_direction_output(sta32x->gpiod_nreset, 0);
}
/* regulators */
for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++)
sta32x->supplies[i].supply = sta32x_supply_names[i];
@ -982,15 +1123,15 @@ static int sta32x_i2c_probe(struct i2c_client *i2c,
sta32x->regmap = devm_regmap_init_i2c(i2c, &sta32x_regmap);
if (IS_ERR(sta32x->regmap)) {
ret = PTR_ERR(sta32x->regmap);
dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
dev_err(dev, "Failed to init regmap: %d\n", ret);
return ret;
}
i2c_set_clientdata(i2c, sta32x);
ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1);
if (ret != 0)
dev_err(&i2c->dev, "Failed to register codec (%d)\n", ret);
ret = snd_soc_register_codec(dev, &sta32x_codec, &sta32x_dai, 1);
if (ret < 0)
dev_err(dev, "Failed to register codec (%d)\n", ret);
return ret;
}
@ -1013,6 +1154,7 @@ static struct i2c_driver sta32x_i2c_driver = {
.driver = {
.name = "sta32x",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(st32x_dt_ids),
},
.probe = sta32x_i2c_probe,
.remove = sta32x_i2c_remove,

View File

@ -131,7 +131,7 @@
#define STA32X_CONFF_OCFG_MASK 0x03
#define STA32X_CONFF_OCFG_SHIFT 0
#define STA32X_CONFF_IDE 0x04
#define STA32X_CONFF_IDE_SHIFT 3
#define STA32X_CONFF_IDE_SHIFT 2
#define STA32X_CONFF_BCLE 0x08
#define STA32X_CONFF_ECLE 0x20
#define STA32X_CONFF_PWDN 0x40

View File

@ -349,7 +349,8 @@ static int aic31xx_wait_bits(struct aic31xx_priv *aic31xx, unsigned int reg,
static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(w->codec);
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
unsigned int reg = AIC31XX_DACFLAG1;
unsigned int mask;
@ -377,7 +378,7 @@ static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w,
reg = AIC31XX_ADCFLAG;
break;
default:
dev_err(w->codec->dev, "Unknown widget '%s' calling %s\n",
dev_err(codec->dev, "Unknown widget '%s' calling %s\n",
w->name, __func__);
return -EINVAL;
}
@ -388,7 +389,7 @@ static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w,
case SND_SOC_DAPM_POST_PMD:
return aic31xx_wait_bits(aic31xx, reg, mask, 0, 5000, 100);
default:
dev_dbg(w->codec->dev,
dev_dbg(codec->dev,
"Unhandled dapm widget event %d from %s\n",
event, w->name);
}
@ -433,7 +434,7 @@ static const struct snd_kcontrol_new aic31xx_dapm_spr_switch =
static int mic_bias_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec);
switch (event) {

View File

@ -87,6 +87,7 @@ struct aic3x_priv {
#define AIC3X_MODEL_3X 0
#define AIC3X_MODEL_33 1
#define AIC3X_MODEL_3007 2
#define AIC3X_MODEL_3104 3
u16 model;
/* Selects the micbias voltage */
@ -197,7 +198,7 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
static int mic_bias_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -316,52 +317,37 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
* only for swapped L-to-R and R-to-L routes. See below stereo controls
* for direct L-to-L and R-to-R routes.
*/
SOC_SINGLE_TLV("Left Line Mixer Line2R Bypass Volume",
LINE2R_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Left Line Mixer PGAR Bypass Volume",
PGAR_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Left Line Mixer DACR1 Playback Volume",
DACR1_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Right Line Mixer Line2L Bypass Volume",
LINE2L_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Right Line Mixer PGAL Bypass Volume",
PGAL_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Right Line Mixer DACL1 Playback Volume",
DACL1_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Left HP Mixer Line2R Bypass Volume",
LINE2R_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Left HP Mixer PGAR Bypass Volume",
PGAR_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Left HP Mixer DACR1 Playback Volume",
DACR1_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Right HP Mixer Line2L Bypass Volume",
LINE2L_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Right HP Mixer PGAL Bypass Volume",
PGAL_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Right HP Mixer DACL1 Playback Volume",
DACL1_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Left HPCOM Mixer Line2R Bypass Volume",
LINE2R_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Left HPCOM Mixer PGAR Bypass Volume",
PGAR_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Left HPCOM Mixer DACR1 Playback Volume",
DACR1_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Right HPCOM Mixer Line2L Bypass Volume",
LINE2L_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Right HPCOM Mixer PGAL Bypass Volume",
PGAL_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Right HPCOM Mixer DACL1 Playback Volume",
DACL1_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv),
/* Stereo output controls for direct L-to-L and R-to-R routes */
SOC_DOUBLE_R_TLV("Line Line2 Bypass Volume",
LINE2L_2_LLOPM_VOL, LINE2R_2_RLOPM_VOL,
0, 118, 1, output_stage_tlv),
SOC_DOUBLE_R_TLV("Line PGA Bypass Volume",
PGAL_2_LLOPM_VOL, PGAR_2_RLOPM_VOL,
0, 118, 1, output_stage_tlv),
@ -369,9 +355,6 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
DACL1_2_LLOPM_VOL, DACR1_2_RLOPM_VOL,
0, 118, 1, output_stage_tlv),
SOC_DOUBLE_R_TLV("HP Line2 Bypass Volume",
LINE2L_2_HPLOUT_VOL, LINE2R_2_HPROUT_VOL,
0, 118, 1, output_stage_tlv),
SOC_DOUBLE_R_TLV("HP PGA Bypass Volume",
PGAL_2_HPLOUT_VOL, PGAR_2_HPROUT_VOL,
0, 118, 1, output_stage_tlv),
@ -379,9 +362,6 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
DACL1_2_HPLOUT_VOL, DACR1_2_HPROUT_VOL,
0, 118, 1, output_stage_tlv),
SOC_DOUBLE_R_TLV("HPCOM Line2 Bypass Volume",
LINE2L_2_HPLCOM_VOL, LINE2R_2_HPRCOM_VOL,
0, 118, 1, output_stage_tlv),
SOC_DOUBLE_R_TLV("HPCOM PGA Bypass Volume",
PGAL_2_HPLCOM_VOL, PGAR_2_HPRCOM_VOL,
0, 118, 1, output_stage_tlv),
@ -424,6 +404,45 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
SOC_ENUM("Output Driver Ramp-up step", aic3x_rampup_step_enum),
};
/* For other than tlv320aic3104 */
static const struct snd_kcontrol_new aic3x_extra_snd_controls[] = {
/*
* Output controls that map to output mixer switches. Note these are
* only for swapped L-to-R and R-to-L routes. See below stereo controls
* for direct L-to-L and R-to-R routes.
*/
SOC_SINGLE_TLV("Left Line Mixer Line2R Bypass Volume",
LINE2R_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Right Line Mixer Line2L Bypass Volume",
LINE2L_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Left HP Mixer Line2R Bypass Volume",
LINE2R_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Right HP Mixer Line2L Bypass Volume",
LINE2L_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Left HPCOM Mixer Line2R Bypass Volume",
LINE2R_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv),
SOC_SINGLE_TLV("Right HPCOM Mixer Line2L Bypass Volume",
LINE2L_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv),
/* Stereo output controls for direct L-to-L and R-to-R routes */
SOC_DOUBLE_R_TLV("Line Line2 Bypass Volume",
LINE2L_2_LLOPM_VOL, LINE2R_2_RLOPM_VOL,
0, 118, 1, output_stage_tlv),
SOC_DOUBLE_R_TLV("HP Line2 Bypass Volume",
LINE2L_2_HPLOUT_VOL, LINE2R_2_HPROUT_VOL,
0, 118, 1, output_stage_tlv),
SOC_DOUBLE_R_TLV("HPCOM Line2 Bypass Volume",
LINE2L_2_HPLCOM_VOL, LINE2R_2_HPRCOM_VOL,
0, 118, 1, output_stage_tlv),
};
static const struct snd_kcontrol_new aic3x_mono_controls[] = {
SOC_DOUBLE_R_TLV("Mono Line2 Bypass Volume",
LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL,
@ -464,22 +483,24 @@ SOC_DAPM_ENUM("Route", aic3x_right_hpcom_enum);
/* Left Line Mixer */
static const struct snd_kcontrol_new aic3x_left_line_mixer_controls[] = {
SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_LLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_LLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_LLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_LLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_LLOPM_VOL, 7, 1, 0),
/* Not on tlv320aic3104 */
SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_LLOPM_VOL, 7, 1, 0),
};
/* Right Line Mixer */
static const struct snd_kcontrol_new aic3x_right_line_mixer_controls[] = {
SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_RLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_RLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_RLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_RLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_RLOPM_VOL, 7, 1, 0),
/* Not on tlv320aic3104 */
SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_RLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0),
};
/* Mono Mixer */
@ -494,42 +515,46 @@ static const struct snd_kcontrol_new aic3x_mono_mixer_controls[] = {
/* Left HP Mixer */
static const struct snd_kcontrol_new aic3x_left_hp_mixer_controls[] = {
SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPLOUT_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPLOUT_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPLOUT_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPLOUT_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPLOUT_VOL, 7, 1, 0),
/* Not on tlv320aic3104 */
SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPLOUT_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPLOUT_VOL, 7, 1, 0),
};
/* Right HP Mixer */
static const struct snd_kcontrol_new aic3x_right_hp_mixer_controls[] = {
SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPROUT_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPROUT_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPROUT_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPROUT_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPROUT_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPROUT_VOL, 7, 1, 0),
/* Not on tlv320aic3104 */
SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPROUT_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPROUT_VOL, 7, 1, 0),
};
/* Left HPCOM Mixer */
static const struct snd_kcontrol_new aic3x_left_hpcom_mixer_controls[] = {
SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPLCOM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPLCOM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPLCOM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPLCOM_VOL, 7, 1, 0),
/* Not on tlv320aic3104 */
SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPLCOM_VOL, 7, 1, 0),
};
/* Right HPCOM Mixer */
static const struct snd_kcontrol_new aic3x_right_hpcom_mixer_controls[] = {
SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPRCOM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPRCOM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPRCOM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPRCOM_VOL, 7, 1, 0),
/* Not on tlv320aic3104 */
SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPRCOM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0),
};
/* Left PGA Mixer */
@ -550,6 +575,22 @@ static const struct snd_kcontrol_new aic3x_right_pga_mixer_controls[] = {
SOC_DAPM_SINGLE_AIC3X("Mic3R Switch", MIC3LR_2_RADC_CTRL, 0, 1, 1),
};
/* Left PGA Mixer for tlv320aic3104 */
static const struct snd_kcontrol_new aic3104_left_pga_mixer_controls[] = {
SOC_DAPM_SINGLE_AIC3X("Line1L Switch", LINE1L_2_LADC_CTRL, 3, 1, 1),
SOC_DAPM_SINGLE_AIC3X("Line1R Switch", LINE1R_2_LADC_CTRL, 3, 1, 1),
SOC_DAPM_SINGLE_AIC3X("Mic2L Switch", MIC3LR_2_LADC_CTRL, 4, 1, 1),
SOC_DAPM_SINGLE_AIC3X("Mic2R Switch", MIC3LR_2_LADC_CTRL, 0, 1, 1),
};
/* Right PGA Mixer for tlv320aic3104 */
static const struct snd_kcontrol_new aic3104_right_pga_mixer_controls[] = {
SOC_DAPM_SINGLE_AIC3X("Line1R Switch", LINE1R_2_RADC_CTRL, 3, 1, 1),
SOC_DAPM_SINGLE_AIC3X("Line1L Switch", LINE1L_2_RADC_CTRL, 3, 1, 1),
SOC_DAPM_SINGLE_AIC3X("Mic2L Switch", MIC3LR_2_RADC_CTRL, 4, 1, 1),
SOC_DAPM_SINGLE_AIC3X("Mic2R Switch", MIC3LR_2_RADC_CTRL, 0, 1, 1),
};
/* Left Line1 Mux */
static const struct snd_kcontrol_new aic3x_left_line1l_mux_controls =
SOC_DAPM_ENUM("Route", aic3x_line1l_2_l_enum);
@ -593,26 +634,56 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
/* Inputs to Left ADC */
SND_SOC_DAPM_ADC("Left ADC", "Left Capture", LINE1L_2_LADC_CTRL, 2, 0),
SND_SOC_DAPM_MIXER("Left PGA Mixer", SND_SOC_NOPM, 0, 0,
&aic3x_left_pga_mixer_controls[0],
ARRAY_SIZE(aic3x_left_pga_mixer_controls)),
SND_SOC_DAPM_MUX("Left Line1L Mux", SND_SOC_NOPM, 0, 0,
&aic3x_left_line1l_mux_controls),
SND_SOC_DAPM_MUX("Left Line1R Mux", SND_SOC_NOPM, 0, 0,
&aic3x_left_line1r_mux_controls),
SND_SOC_DAPM_MUX("Left Line2L Mux", SND_SOC_NOPM, 0, 0,
&aic3x_left_line2_mux_controls),
/* Inputs to Right ADC */
SND_SOC_DAPM_ADC("Right ADC", "Right Capture",
LINE1R_2_RADC_CTRL, 2, 0),
SND_SOC_DAPM_MIXER("Right PGA Mixer", SND_SOC_NOPM, 0, 0,
&aic3x_right_pga_mixer_controls[0],
ARRAY_SIZE(aic3x_right_pga_mixer_controls)),
SND_SOC_DAPM_MUX("Right Line1L Mux", SND_SOC_NOPM, 0, 0,
&aic3x_right_line1l_mux_controls),
SND_SOC_DAPM_MUX("Right Line1R Mux", SND_SOC_NOPM, 0, 0,
&aic3x_right_line1r_mux_controls),
/* Mic Bias */
SND_SOC_DAPM_SUPPLY("Mic Bias", MICBIAS_CTRL, 6, 0,
mic_bias_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_OUTPUT("LLOUT"),
SND_SOC_DAPM_OUTPUT("RLOUT"),
SND_SOC_DAPM_OUTPUT("HPLOUT"),
SND_SOC_DAPM_OUTPUT("HPROUT"),
SND_SOC_DAPM_OUTPUT("HPLCOM"),
SND_SOC_DAPM_OUTPUT("HPRCOM"),
SND_SOC_DAPM_INPUT("LINE1L"),
SND_SOC_DAPM_INPUT("LINE1R"),
/*
* Virtual output pin to detection block inside codec. This can be
* used to keep codec bias on if gpio or detection features are needed.
* Force pin on or construct a path with an input jack and mic bias
* widgets.
*/
SND_SOC_DAPM_OUTPUT("Detection"),
};
/* For other than tlv320aic3104 */
static const struct snd_soc_dapm_widget aic3x_extra_dapm_widgets[] = {
/* Inputs to Left ADC */
SND_SOC_DAPM_MIXER("Left PGA Mixer", SND_SOC_NOPM, 0, 0,
&aic3x_left_pga_mixer_controls[0],
ARRAY_SIZE(aic3x_left_pga_mixer_controls)),
SND_SOC_DAPM_MUX("Left Line2L Mux", SND_SOC_NOPM, 0, 0,
&aic3x_left_line2_mux_controls),
/* Inputs to Right ADC */
SND_SOC_DAPM_MIXER("Right PGA Mixer", SND_SOC_NOPM, 0, 0,
&aic3x_right_pga_mixer_controls[0],
ARRAY_SIZE(aic3x_right_pga_mixer_controls)),
SND_SOC_DAPM_MUX("Right Line2R Mux", SND_SOC_NOPM, 0, 0,
&aic3x_right_line2_mux_controls),
@ -637,11 +708,6 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "DMic Rate 32",
AIC3X_ASD_INTF_CTRLA, 0, 3, 3, 0),
/* Mic Bias */
SND_SOC_DAPM_SUPPLY("Mic Bias", MICBIAS_CTRL, 6, 0,
mic_bias_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
/* Output mixers */
SND_SOC_DAPM_MIXER("Left Line Mixer", SND_SOC_NOPM, 0, 0,
&aic3x_left_line_mixer_controls[0],
@ -662,27 +728,46 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
&aic3x_right_hpcom_mixer_controls[0],
ARRAY_SIZE(aic3x_right_hpcom_mixer_controls)),
SND_SOC_DAPM_OUTPUT("LLOUT"),
SND_SOC_DAPM_OUTPUT("RLOUT"),
SND_SOC_DAPM_OUTPUT("HPLOUT"),
SND_SOC_DAPM_OUTPUT("HPROUT"),
SND_SOC_DAPM_OUTPUT("HPLCOM"),
SND_SOC_DAPM_OUTPUT("HPRCOM"),
SND_SOC_DAPM_INPUT("MIC3L"),
SND_SOC_DAPM_INPUT("MIC3R"),
SND_SOC_DAPM_INPUT("LINE1L"),
SND_SOC_DAPM_INPUT("LINE1R"),
SND_SOC_DAPM_INPUT("LINE2L"),
SND_SOC_DAPM_INPUT("LINE2R"),
};
/*
* Virtual output pin to detection block inside codec. This can be
* used to keep codec bias on if gpio or detection features are needed.
* Force pin on or construct a path with an input jack and mic bias
* widgets.
*/
SND_SOC_DAPM_OUTPUT("Detection"),
/* For tlv320aic3104 */
static const struct snd_soc_dapm_widget aic3104_extra_dapm_widgets[] = {
/* Inputs to Left ADC */
SND_SOC_DAPM_MIXER("Left PGA Mixer", SND_SOC_NOPM, 0, 0,
&aic3104_left_pga_mixer_controls[0],
ARRAY_SIZE(aic3104_left_pga_mixer_controls)),
/* Inputs to Right ADC */
SND_SOC_DAPM_MIXER("Right PGA Mixer", SND_SOC_NOPM, 0, 0,
&aic3104_right_pga_mixer_controls[0],
ARRAY_SIZE(aic3104_right_pga_mixer_controls)),
/* Output mixers */
SND_SOC_DAPM_MIXER("Left Line Mixer", SND_SOC_NOPM, 0, 0,
&aic3x_left_line_mixer_controls[0],
ARRAY_SIZE(aic3x_left_line_mixer_controls) - 2),
SND_SOC_DAPM_MIXER("Right Line Mixer", SND_SOC_NOPM, 0, 0,
&aic3x_right_line_mixer_controls[0],
ARRAY_SIZE(aic3x_right_line_mixer_controls) - 2),
SND_SOC_DAPM_MIXER("Left HP Mixer", SND_SOC_NOPM, 0, 0,
&aic3x_left_hp_mixer_controls[0],
ARRAY_SIZE(aic3x_left_hp_mixer_controls) - 2),
SND_SOC_DAPM_MIXER("Right HP Mixer", SND_SOC_NOPM, 0, 0,
&aic3x_right_hp_mixer_controls[0],
ARRAY_SIZE(aic3x_right_hp_mixer_controls) - 2),
SND_SOC_DAPM_MIXER("Left HPCOM Mixer", SND_SOC_NOPM, 0, 0,
&aic3x_left_hpcom_mixer_controls[0],
ARRAY_SIZE(aic3x_left_hpcom_mixer_controls) - 2),
SND_SOC_DAPM_MIXER("Right HPCOM Mixer", SND_SOC_NOPM, 0, 0,
&aic3x_right_hpcom_mixer_controls[0],
ARRAY_SIZE(aic3x_right_hpcom_mixer_controls) - 2),
SND_SOC_DAPM_INPUT("MIC2L"),
SND_SOC_DAPM_INPUT("MIC2R"),
};
static const struct snd_soc_dapm_widget aic3x_dapm_mono_widgets[] = {
@ -712,17 +797,10 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Left Line1R Mux", "single-ended", "LINE1R"},
{"Left Line1R Mux", "differential", "LINE1R"},
{"Left Line2L Mux", "single-ended", "LINE2L"},
{"Left Line2L Mux", "differential", "LINE2L"},
{"Left PGA Mixer", "Line1L Switch", "Left Line1L Mux"},
{"Left PGA Mixer", "Line1R Switch", "Left Line1R Mux"},
{"Left PGA Mixer", "Line2L Switch", "Left Line2L Mux"},
{"Left PGA Mixer", "Mic3L Switch", "MIC3L"},
{"Left PGA Mixer", "Mic3R Switch", "MIC3R"},
{"Left ADC", NULL, "Left PGA Mixer"},
{"Left ADC", NULL, "GPIO1 dmic modclk"},
/* Right Input */
{"Right Line1R Mux", "single-ended", "LINE1R"},
@ -730,25 +808,10 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Right Line1L Mux", "single-ended", "LINE1L"},
{"Right Line1L Mux", "differential", "LINE1L"},
{"Right Line2R Mux", "single-ended", "LINE2R"},
{"Right Line2R Mux", "differential", "LINE2R"},
{"Right PGA Mixer", "Line1L Switch", "Right Line1L Mux"},
{"Right PGA Mixer", "Line1R Switch", "Right Line1R Mux"},
{"Right PGA Mixer", "Line2R Switch", "Right Line2R Mux"},
{"Right PGA Mixer", "Mic3L Switch", "MIC3L"},
{"Right PGA Mixer", "Mic3R Switch", "MIC3R"},
{"Right ADC", NULL, "Right PGA Mixer"},
{"Right ADC", NULL, "GPIO1 dmic modclk"},
/*
* Logical path between digital mic enable and GPIO1 modulator clock
* output function
*/
{"GPIO1 dmic modclk", NULL, "DMic Rate 128"},
{"GPIO1 dmic modclk", NULL, "DMic Rate 64"},
{"GPIO1 dmic modclk", NULL, "DMic Rate 32"},
/* Left DAC Output */
{"Left DAC Mux", "DAC_L1", "Left DAC"},
@ -761,10 +824,8 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Right DAC Mux", "DAC_R3", "Right DAC"},
/* Left Line Output */
{"Left Line Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
{"Left Line Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
{"Left Line Mixer", "DACL1 Switch", "Left DAC Mux"},
{"Left Line Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
{"Left Line Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
{"Left Line Mixer", "DACR1 Switch", "Right DAC Mux"},
@ -773,10 +834,8 @@ static const struct snd_soc_dapm_route intercon[] = {
{"LLOUT", NULL, "Left Line Out"},
/* Right Line Output */
{"Right Line Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
{"Right Line Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
{"Right Line Mixer", "DACL1 Switch", "Left DAC Mux"},
{"Right Line Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
{"Right Line Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
{"Right Line Mixer", "DACR1 Switch", "Right DAC Mux"},
@ -785,10 +844,8 @@ static const struct snd_soc_dapm_route intercon[] = {
{"RLOUT", NULL, "Right Line Out"},
/* Left HP Output */
{"Left HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
{"Left HP Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
{"Left HP Mixer", "DACL1 Switch", "Left DAC Mux"},
{"Left HP Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
{"Left HP Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
{"Left HP Mixer", "DACR1 Switch", "Right DAC Mux"},
@ -797,10 +854,8 @@ static const struct snd_soc_dapm_route intercon[] = {
{"HPLOUT", NULL, "Left HP Out"},
/* Right HP Output */
{"Right HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
{"Right HP Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
{"Right HP Mixer", "DACL1 Switch", "Left DAC Mux"},
{"Right HP Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
{"Right HP Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
{"Right HP Mixer", "DACR1 Switch", "Right DAC Mux"},
@ -809,10 +864,8 @@ static const struct snd_soc_dapm_route intercon[] = {
{"HPROUT", NULL, "Right HP Out"},
/* Left HPCOM Output */
{"Left HPCOM Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
{"Left HPCOM Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
{"Left HPCOM Mixer", "DACL1 Switch", "Left DAC Mux"},
{"Left HPCOM Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
{"Left HPCOM Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
{"Left HPCOM Mixer", "DACR1 Switch", "Right DAC Mux"},
@ -823,10 +876,8 @@ static const struct snd_soc_dapm_route intercon[] = {
{"HPLCOM", NULL, "Left HP Com"},
/* Right HPCOM Output */
{"Right HPCOM Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
{"Right HPCOM Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
{"Right HPCOM Mixer", "DACL1 Switch", "Left DAC Mux"},
{"Right HPCOM Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
{"Right HPCOM Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
{"Right HPCOM Mixer", "DACR1 Switch", "Right DAC Mux"},
@ -839,6 +890,72 @@ static const struct snd_soc_dapm_route intercon[] = {
{"HPRCOM", NULL, "Right HP Com"},
};
/* For other than tlv320aic3104 */
static const struct snd_soc_dapm_route intercon_extra[] = {
/* Left Input */
{"Left Line2L Mux", "single-ended", "LINE2L"},
{"Left Line2L Mux", "differential", "LINE2L"},
{"Left PGA Mixer", "Line2L Switch", "Left Line2L Mux"},
{"Left PGA Mixer", "Mic3L Switch", "MIC3L"},
{"Left PGA Mixer", "Mic3R Switch", "MIC3R"},
{"Left ADC", NULL, "GPIO1 dmic modclk"},
/* Right Input */
{"Right Line2R Mux", "single-ended", "LINE2R"},
{"Right Line2R Mux", "differential", "LINE2R"},
{"Right PGA Mixer", "Line2R Switch", "Right Line2R Mux"},
{"Right PGA Mixer", "Mic3L Switch", "MIC3L"},
{"Right PGA Mixer", "Mic3R Switch", "MIC3R"},
{"Right ADC", NULL, "GPIO1 dmic modclk"},
/*
* Logical path between digital mic enable and GPIO1 modulator clock
* output function
*/
{"GPIO1 dmic modclk", NULL, "DMic Rate 128"},
{"GPIO1 dmic modclk", NULL, "DMic Rate 64"},
{"GPIO1 dmic modclk", NULL, "DMic Rate 32"},
/* Left Line Output */
{"Left Line Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
{"Left Line Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
/* Right Line Output */
{"Right Line Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
{"Right Line Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
/* Left HP Output */
{"Left HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
{"Left HP Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
/* Right HP Output */
{"Right HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
{"Right HP Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
/* Left HPCOM Output */
{"Left HPCOM Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
{"Left HPCOM Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
/* Right HPCOM Output */
{"Right HPCOM Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
{"Right HPCOM Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
};
/* For tlv320aic3104 */
static const struct snd_soc_dapm_route intercon_extra_3104[] = {
/* Left Input */
{"Left PGA Mixer", "Mic2L Switch", "MIC2L"},
{"Left PGA Mixer", "Mic2R Switch", "MIC2R"},
/* Right Input */
{"Right PGA Mixer", "Mic2L Switch", "MIC2L"},
{"Right PGA Mixer", "Mic2R Switch", "MIC2R"},
};
static const struct snd_soc_dapm_route intercon_mono[] = {
/* Mono Output */
{"Mono Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
@ -867,17 +984,31 @@ static int aic3x_add_widgets(struct snd_soc_codec *codec)
switch (aic3x->model) {
case AIC3X_MODEL_3X:
case AIC3X_MODEL_33:
snd_soc_dapm_new_controls(dapm, aic3x_extra_dapm_widgets,
ARRAY_SIZE(aic3x_extra_dapm_widgets));
snd_soc_dapm_add_routes(dapm, intercon_extra,
ARRAY_SIZE(intercon_extra));
snd_soc_dapm_new_controls(dapm, aic3x_dapm_mono_widgets,
ARRAY_SIZE(aic3x_dapm_mono_widgets));
snd_soc_dapm_add_routes(dapm, intercon_mono,
ARRAY_SIZE(intercon_mono));
break;
case AIC3X_MODEL_3007:
snd_soc_dapm_new_controls(dapm, aic3x_extra_dapm_widgets,
ARRAY_SIZE(aic3x_extra_dapm_widgets));
snd_soc_dapm_add_routes(dapm, intercon_extra,
ARRAY_SIZE(intercon_extra));
snd_soc_dapm_new_controls(dapm, aic3007_dapm_widgets,
ARRAY_SIZE(aic3007_dapm_widgets));
snd_soc_dapm_add_routes(dapm, intercon_3007,
ARRAY_SIZE(intercon_3007));
break;
case AIC3X_MODEL_3104:
snd_soc_dapm_new_controls(dapm, aic3104_extra_dapm_widgets,
ARRAY_SIZE(aic3104_extra_dapm_widgets));
snd_soc_dapm_add_routes(dapm, intercon_extra_3104,
ARRAY_SIZE(intercon_extra_3104));
break;
}
return 0;
@ -1046,7 +1177,7 @@ static int aic3x_prepare(struct snd_pcm_substream *substream,
delay += aic3x->tdm_delay;
/* Configure data delay */
snd_soc_write(codec, AIC3X_ASD_INTF_CTRLC, aic3x->tdm_delay);
snd_soc_write(codec, AIC3X_ASD_INTF_CTRLC, delay);
return 0;
}
@ -1438,23 +1569,33 @@ static int aic3x_probe(struct snd_soc_codec *codec)
aic3x_init(codec);
if (aic3x->setup) {
/* setup GPIO functions */
snd_soc_write(codec, AIC3X_GPIO1_REG,
(aic3x->setup->gpio_func[0] & 0xf) << 4);
snd_soc_write(codec, AIC3X_GPIO2_REG,
(aic3x->setup->gpio_func[1] & 0xf) << 4);
if (aic3x->model != AIC3X_MODEL_3104) {
/* setup GPIO functions */
snd_soc_write(codec, AIC3X_GPIO1_REG,
(aic3x->setup->gpio_func[0] & 0xf) << 4);
snd_soc_write(codec, AIC3X_GPIO2_REG,
(aic3x->setup->gpio_func[1] & 0xf) << 4);
} else {
dev_warn(codec->dev, "GPIO functionality is not supported on tlv320aic3104\n");
}
}
switch (aic3x->model) {
case AIC3X_MODEL_3X:
case AIC3X_MODEL_33:
snd_soc_add_codec_controls(codec, aic3x_extra_snd_controls,
ARRAY_SIZE(aic3x_extra_snd_controls));
snd_soc_add_codec_controls(codec, aic3x_mono_controls,
ARRAY_SIZE(aic3x_mono_controls));
break;
case AIC3X_MODEL_3007:
snd_soc_add_codec_controls(codec, aic3x_extra_snd_controls,
ARRAY_SIZE(aic3x_extra_snd_controls));
snd_soc_add_codec_controls(codec,
&aic3x_classd_amp_gain_ctrl, 1);
break;
case AIC3X_MODEL_3104:
break;
}
/* set mic bias voltage */
@ -1522,6 +1663,7 @@ static const struct i2c_device_id aic3x_i2c_id[] = {
{ "tlv320aic33", AIC3X_MODEL_33 },
{ "tlv320aic3007", AIC3X_MODEL_3007 },
{ "tlv320aic3106", AIC3X_MODEL_3X },
{ "tlv320aic3104", AIC3X_MODEL_3104 },
{ }
};
MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
@ -1673,6 +1815,7 @@ static const struct of_device_id tlv320aic3x_of_match[] = {
{ .compatible = "ti,tlv320aic33" },
{ .compatible = "ti,tlv320aic3007" },
{ .compatible = "ti,tlv320aic3106" },
{ .compatible = "ti,tlv320aic3104" },
{},
};
MODULE_DEVICE_TABLE(of, tlv320aic3x_of_match);

View File

@ -423,17 +423,18 @@ exit:
static int dac33_playback_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(w->codec);
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
if (likely(dac33->substream)) {
dac33_calculate_times(dac33->substream, w->codec);
dac33_prepare_chip(dac33->substream, w->codec);
dac33_calculate_times(dac33->substream, codec);
dac33_prepare_chip(dac33->substream, codec);
}
break;
case SND_SOC_DAPM_POST_PMD:
dac33_disable_digital(w->codec);
dac33_disable_digital(codec);
break;
}
return 0;

View File

@ -20,6 +20,8 @@
#include <sound/jack.h>
#include <sound/soc.h>
#include "ts3a227e.h"
struct ts3a227e {
struct regmap *regmap;
struct snd_soc_jack *jack;
@ -79,6 +81,10 @@ static const int ts3a227e_buttons[] = {
/* TS3A227E_REG_SETTING_2 0x05 */
#define KP_ENABLE 0x04
/* TS3A227E_REG_SETTING_3 0x06 */
#define MICBIAS_SETTING_SFT (3)
#define MICBIAS_SETTING_MASK (0x7 << MICBIAS_SETTING_SFT)
/* TS3A227E_REG_ACCESSORY_STATUS 0x0b */
#define TYPE_3_POLE 0x01
#define TYPE_4_POLE_OMTP 0x02
@ -221,9 +227,9 @@ int ts3a227e_enable_jack_detect(struct snd_soc_component *component,
struct ts3a227e *ts3a227e = snd_soc_component_get_drvdata(component);
snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_MEDIA);
snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
ts3a227e->jack = jack;
ts3a227e_jack_report(ts3a227e);
@ -248,6 +254,21 @@ static const struct regmap_config ts3a227e_regmap_config = {
.num_reg_defaults = ARRAY_SIZE(ts3a227e_reg_defaults),
};
static int ts3a227e_parse_dt(struct ts3a227e *ts3a227e, struct device_node *np)
{
u32 micbias;
int err;
err = of_property_read_u32(np, "ti,micbias", &micbias);
if (!err) {
regmap_update_bits(ts3a227e->regmap, TS3A227E_REG_SETTING_3,
MICBIAS_SETTING_MASK,
(micbias & 0x07) << MICBIAS_SETTING_SFT);
}
return 0;
}
static int ts3a227e_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@ -266,6 +287,14 @@ static int ts3a227e_i2c_probe(struct i2c_client *i2c,
if (IS_ERR(ts3a227e->regmap))
return PTR_ERR(ts3a227e->regmap);
if (dev->of_node) {
ret = ts3a227e_parse_dt(ts3a227e, dev->of_node);
if (ret) {
dev_err(dev, "Failed to parse device tree: %d\n", ret);
return ret;
}
}
ret = devm_request_threaded_irq(dev, i2c->irq, NULL, ts3a227e_interrupt,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"TS3A227E", ts3a227e);

View File

@ -567,12 +567,13 @@ static const struct snd_kcontrol_new twl4030_dapm_dbypassv_control =
static int pin_name##pga_event(struct snd_soc_dapm_widget *w, \
struct snd_kcontrol *kcontrol, int event) \
{ \
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); \
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); \
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); \
\
switch (event) { \
case SND_SOC_DAPM_POST_PMU: \
twl4030->pin_name##_enabled = 1; \
twl4030_write(w->codec, reg, twl4030_read(w->codec, reg)); \
twl4030_write(codec, reg, twl4030_read(codec, reg)); \
break; \
case SND_SOC_DAPM_POST_PMD: \
twl4030->pin_name##_enabled = 0; \
@ -621,12 +622,14 @@ static void handsfree_ramp(struct snd_soc_codec *codec, int reg, int ramp)
static int handsfreelpga_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
handsfree_ramp(w->codec, TWL4030_REG_HFL_CTL, 1);
handsfree_ramp(codec, TWL4030_REG_HFL_CTL, 1);
break;
case SND_SOC_DAPM_POST_PMD:
handsfree_ramp(w->codec, TWL4030_REG_HFL_CTL, 0);
handsfree_ramp(codec, TWL4030_REG_HFL_CTL, 0);
break;
}
return 0;
@ -635,12 +638,14 @@ static int handsfreelpga_event(struct snd_soc_dapm_widget *w,
static int handsfreerpga_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
handsfree_ramp(w->codec, TWL4030_REG_HFR_CTL, 1);
handsfree_ramp(codec, TWL4030_REG_HFR_CTL, 1);
break;
case SND_SOC_DAPM_POST_PMD:
handsfree_ramp(w->codec, TWL4030_REG_HFR_CTL, 0);
handsfree_ramp(codec, TWL4030_REG_HFR_CTL, 0);
break;
}
return 0;
@ -649,19 +654,23 @@ static int handsfreerpga_event(struct snd_soc_dapm_widget *w,
static int vibramux_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
twl4030_write(w->codec, TWL4030_REG_VIBRA_SET, 0xff);
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
twl4030_write(codec, TWL4030_REG_VIBRA_SET, 0xff);
return 0;
}
static int apll_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
twl4030_apll_enable(w->codec, 1);
twl4030_apll_enable(codec, 1);
break;
case SND_SOC_DAPM_POST_PMD:
twl4030_apll_enable(w->codec, 0);
twl4030_apll_enable(codec, 0);
break;
}
return 0;
@ -670,23 +679,24 @@ static int apll_event(struct snd_soc_dapm_widget *w,
static int aif_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
u8 audio_if;
audio_if = twl4030_read(w->codec, TWL4030_REG_AUDIO_IF);
audio_if = twl4030_read(codec, TWL4030_REG_AUDIO_IF);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
/* Enable AIF */
/* enable the PLL before we use it to clock the DAI */
twl4030_apll_enable(w->codec, 1);
twl4030_apll_enable(codec, 1);
twl4030_write(w->codec, TWL4030_REG_AUDIO_IF,
twl4030_write(codec, TWL4030_REG_AUDIO_IF,
audio_if | TWL4030_AIF_EN);
break;
case SND_SOC_DAPM_POST_PMD:
/* disable the DAI before we stop it's source PLL */
twl4030_write(w->codec, TWL4030_REG_AUDIO_IF,
twl4030_write(codec, TWL4030_REG_AUDIO_IF,
audio_if & ~TWL4030_AIF_EN);
twl4030_apll_enable(w->codec, 0);
twl4030_apll_enable(codec, 0);
break;
}
return 0;
@ -758,20 +768,21 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
static int headsetlpga_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec);
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
/* Do the ramp-up only once */
if (!twl4030->hsr_enabled)
headset_ramp(w->codec, 1);
headset_ramp(codec, 1);
twl4030->hsl_enabled = 1;
break;
case SND_SOC_DAPM_POST_PMD:
/* Do the ramp-down only if both headsetL/R is disabled */
if (!twl4030->hsr_enabled)
headset_ramp(w->codec, 0);
headset_ramp(codec, 0);
twl4030->hsl_enabled = 0;
break;
@ -782,20 +793,21 @@ static int headsetlpga_event(struct snd_soc_dapm_widget *w,
static int headsetrpga_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec);
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
/* Do the ramp-up only once */
if (!twl4030->hsl_enabled)
headset_ramp(w->codec, 1);
headset_ramp(codec, 1);
twl4030->hsr_enabled = 1;
break;
case SND_SOC_DAPM_POST_PMD:
/* Do the ramp-down only if both headsetL/R is disabled */
if (!twl4030->hsl_enabled)
headset_ramp(w->codec, 0);
headset_ramp(codec, 0);
twl4030->hsr_enabled = 0;
break;
@ -806,7 +818,8 @@ static int headsetrpga_event(struct snd_soc_dapm_widget *w,
static int digimic_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec);
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
struct twl4030_codec_data *pdata = twl4030->pdata;
if (pdata && pdata->digimic_delay)

View File

@ -234,7 +234,7 @@ static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
static int twl6040_hs_dac_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
u8 hslctl, hsrctl;
/*
@ -261,7 +261,7 @@ static int twl6040_hs_dac_event(struct snd_soc_dapm_widget *w,
static int twl6040_ep_drv_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
int ret = 0;

View File

@ -683,7 +683,7 @@ static const struct snd_kcontrol_new wm2000_controls[] = {
static int wm2000_anc_power_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
int ret;

View File

@ -775,7 +775,8 @@ static int wm5100_out_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(w->codec);
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
switch (w->reg) {
case WM5100_CHANNEL_ENABLES_1:
@ -839,7 +840,7 @@ static int wm5100_post_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
int ret;

View File

@ -28,6 +28,7 @@
#include <linux/mfd/arizona/core.h>
#include <linux/mfd/arizona/registers.h>
#include <asm/unaligned.h>
#include "arizona.h"
#include "wm5102.h"
@ -580,7 +581,7 @@ static const struct reg_default wm5102_sysclk_revb_patch[] = {
static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
struct regmap *regmap = arizona->regmap;
const struct reg_default *patch = NULL;
@ -617,11 +618,10 @@ static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol,
{
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
uint16_t data;
mutex_lock(&arizona->dac_comp_lock);
data = cpu_to_be16(arizona->dac_comp_coeff);
memcpy(ucontrol->value.bytes.data, &data, sizeof(data));
put_unaligned_be16(arizona->dac_comp_coeff,
ucontrol->value.bytes.data);
mutex_unlock(&arizona->dac_comp_lock);
return 0;
@ -1272,19 +1272,24 @@ SND_SOC_DAPM_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM,
ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM,
ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT2R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),

View File

@ -134,7 +134,7 @@ static const struct reg_default wm5110_sysclk_revd_patch[] = {
static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
struct regmap *regmap = arizona->regmap;
const struct reg_default *patch = NULL;
@ -905,22 +905,28 @@ SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM,
ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM,
ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT2R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT3R", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT3R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),

View File

@ -259,7 +259,7 @@ static void wm8350_pga_work(struct work_struct *work)
static int pga_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec);
struct wm8350_output *out;

View File

@ -324,6 +324,7 @@ SOC_SINGLE("RIN34 Mute Switch", WM8400_RIGHT_LINE_INPUT_3_4_VOLUME,
static int outmixer_event (struct snd_soc_dapm_widget *w,
struct snd_kcontrol * kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
u32 reg_shift = mc->shift;
@ -332,7 +333,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w,
switch (reg_shift) {
case WM8400_SPEAKER_MIXER | (WM8400_LDSPK << 8) :
reg = snd_soc_read(w->codec, WM8400_OUTPUT_MIXER1);
reg = snd_soc_read(codec, WM8400_OUTPUT_MIXER1);
if (reg & WM8400_LDLO) {
printk(KERN_WARNING
"Cannot set as Output Mixer 1 LDLO Set\n");
@ -340,7 +341,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w,
}
break;
case WM8400_SPEAKER_MIXER | (WM8400_RDSPK << 8):
reg = snd_soc_read(w->codec, WM8400_OUTPUT_MIXER2);
reg = snd_soc_read(codec, WM8400_OUTPUT_MIXER2);
if (reg & WM8400_RDRO) {
printk(KERN_WARNING
"Cannot set as Output Mixer 2 RDRO Set\n");
@ -348,7 +349,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w,
}
break;
case WM8400_OUTPUT_MIXER1 | (WM8400_LDLO << 8):
reg = snd_soc_read(w->codec, WM8400_SPEAKER_MIXER);
reg = snd_soc_read(codec, WM8400_SPEAKER_MIXER);
if (reg & WM8400_LDSPK) {
printk(KERN_WARNING
"Cannot set as Speaker Mixer LDSPK Set\n");
@ -356,7 +357,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w,
}
break;
case WM8400_OUTPUT_MIXER2 | (WM8400_RDRO << 8):
reg = snd_soc_read(w->codec, WM8400_SPEAKER_MIXER);
reg = snd_soc_read(codec, WM8400_SPEAKER_MIXER);
if (reg & WM8400_RDSPK) {
printk(KERN_WARNING
"Cannot set as Speaker Mixer RDSPK Set\n");

View File

@ -217,7 +217,8 @@ SND_SOC_DAPM_INPUT("LLINEIN"),
static int wm8731_check_osc(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(source->codec);
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
return wm8731->sysclk_type == WM8731_SYSCLK_XTAL;
}
@ -717,6 +718,8 @@ static int wm8731_i2c_probe(struct i2c_client *i2c,
if (wm8731 == NULL)
return -ENOMEM;
mutex_init(&wm8731->lock);
wm8731->regmap = devm_regmap_init_i2c(i2c, &wm8731_regmap);
if (IS_ERR(wm8731->regmap)) {
ret = PTR_ERR(wm8731->regmap);

View File

@ -308,9 +308,7 @@ static const struct snd_soc_dapm_route wm8770_intercon[] = {
static int vout12supply_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec;
codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
@ -327,9 +325,7 @@ static int vout12supply_event(struct snd_soc_dapm_widget *w,
static int vout34supply_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec;
codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:

View File

@ -648,7 +648,7 @@ static struct snd_soc_dai_driver wm8804_dai = {
.symmetric_rates = 1
};
static struct snd_soc_codec_driver soc_codec_dev_wm8804 = {
static const struct snd_soc_codec_driver soc_codec_dev_wm8804 = {
.probe = wm8804_probe,
.remove = wm8804_remove,
.set_bias_level = wm8804_set_bias_level,
@ -664,7 +664,7 @@ static const struct of_device_id wm8804_of_match[] = {
};
MODULE_DEVICE_TABLE(of, wm8804_of_match);
static struct regmap_config wm8804_regmap_config = {
static const struct regmap_config wm8804_regmap_config = {
.reg_bits = 8,
.val_bits = 8,

View File

@ -224,7 +224,7 @@ static void wm8900_reset(struct snd_soc_codec *codec)
static int wm8900_hp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
u16 hpctl1 = snd_soc_read(codec, WM8900_REG_HPCTL1);
switch (event) {

View File

@ -260,7 +260,7 @@ static int wm8903_cp_event(struct snd_soc_dapm_widget *w,
static int wm8903_dcs_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
switch (event) {

View File

@ -673,7 +673,7 @@ static int cp_event(struct snd_soc_dapm_widget *w,
static int sysclk_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -711,7 +711,7 @@ static int sysclk_event(struct snd_soc_dapm_widget *w,
static int out_pga_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
int reg, val;
int dcs_mask;
@ -2105,6 +2105,24 @@ static const struct regmap_config wm8904_regmap = {
.num_reg_defaults = ARRAY_SIZE(wm8904_reg_defaults),
};
#ifdef CONFIG_OF
static enum wm8904_type wm8904_data = WM8904;
static enum wm8904_type wm8912_data = WM8912;
static const struct of_device_id wm8904_of_match[] = {
{
.compatible = "wlf,wm8904",
.data = &wm8904_data,
}, {
.compatible = "wlf,wm8912",
.data = &wm8912_data,
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(of, wm8904_of_match);
#endif
static int wm8904_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@ -2132,7 +2150,17 @@ static int wm8904_i2c_probe(struct i2c_client *i2c,
return ret;
}
wm8904->devtype = id->driver_data;
if (i2c->dev.of_node) {
const struct of_device_id *match;
match = of_match_node(wm8904_of_match, i2c->dev.of_node);
if (match == NULL)
return -EINVAL;
wm8904->devtype = *((enum wm8904_type *)match->data);
} else {
wm8904->devtype = id->driver_data;
}
i2c_set_clientdata(i2c, wm8904);
wm8904->pdata = i2c->dev.platform_data;
@ -2266,6 +2294,7 @@ static struct i2c_driver wm8904_i2c_driver = {
.driver = {
.name = "wm8904",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(wm8904_of_match),
},
.probe = wm8904_i2c_probe,
.remove = wm8904_i2c_remove,

View File

@ -333,7 +333,7 @@ static int wm8955_configure_clocking(struct snd_soc_codec *codec)
static int wm8955_sysclk(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
int ret = 0;
/* Always disable the clocks - if we're doing reconfiguration this

View File

@ -418,7 +418,7 @@ static void wm8958_dsp_apply(struct snd_soc_codec *codec, int path, int start)
int wm8958_aif_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
int i;
switch (event) {

View File

@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/clk.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <sound/core.h>
@ -117,6 +118,7 @@ static bool wm8960_volatile(struct device *dev, unsigned int reg)
}
struct wm8960_priv {
struct clk *mclk;
struct regmap *regmap;
int (*set_bias_level)(struct snd_soc_codec *,
enum snd_soc_bias_level level);
@ -618,14 +620,38 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
int ret;
switch (level) {
case SND_SOC_BIAS_ON:
break;
case SND_SOC_BIAS_PREPARE:
/* Set VMID to 2x50k */
snd_soc_update_bits(codec, WM8960_POWER1, 0x180, 0x80);
switch (codec->dapm.bias_level) {
case SND_SOC_BIAS_STANDBY:
if (!IS_ERR(wm8960->mclk)) {
ret = clk_prepare_enable(wm8960->mclk);
if (ret) {
dev_err(codec->dev,
"Failed to enable MCLK: %d\n",
ret);
return ret;
}
}
/* Set VMID to 2x50k */
snd_soc_update_bits(codec, WM8960_POWER1, 0x180, 0x80);
break;
case SND_SOC_BIAS_ON:
if (!IS_ERR(wm8960->mclk))
clk_disable_unprepare(wm8960->mclk);
break;
default:
break;
}
break;
case SND_SOC_BIAS_STANDBY:
@ -674,7 +700,7 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
int reg;
int reg, ret;
switch (level) {
case SND_SOC_BIAS_ON:
@ -715,9 +741,22 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec,
WM8960_VREF, WM8960_VREF);
msleep(100);
if (!IS_ERR(wm8960->mclk)) {
ret = clk_prepare_enable(wm8960->mclk);
if (ret) {
dev_err(codec->dev,
"Failed to enable MCLK: %d\n",
ret);
return ret;
}
}
break;
case SND_SOC_BIAS_ON:
if (!IS_ERR(wm8960->mclk))
clk_disable_unprepare(wm8960->mclk);
/* Enable anti-pop mode */
snd_soc_update_bits(codec, WM8960_APOP1,
WM8960_POBCTRL | WM8960_SOFT_ST |
@ -1002,6 +1041,12 @@ static int wm8960_i2c_probe(struct i2c_client *i2c,
if (wm8960 == NULL)
return -ENOMEM;
wm8960->mclk = devm_clk_get(&i2c->dev, "mclk");
if (IS_ERR(wm8960->mclk)) {
if (PTR_ERR(wm8960->mclk) == -EPROBE_DEFER)
return -EPROBE_DEFER;
}
wm8960->regmap = devm_regmap_init_i2c(i2c, &wm8960_regmap);
if (IS_ERR(wm8960->regmap))
return PTR_ERR(wm8960->regmap);

View File

@ -194,7 +194,7 @@ static bool wm8961_readable(struct device *dev, unsigned int reg)
static int wm8961_hp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
u16 hp_reg = snd_soc_read(codec, WM8961_ANALOGUE_HP_0);
u16 cp_reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_1);
u16 pwr_reg = snd_soc_read(codec, WM8961_PWR_MGMT_2);
@ -286,7 +286,7 @@ static int wm8961_hp_event(struct snd_soc_dapm_widget *w,
static int wm8961_spk_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
u16 pwr_reg = snd_soc_read(codec, WM8961_PWR_MGMT_2);
u16 spk_reg = snd_soc_read(codec, WM8961_CLASS_D_CONTROL_1);

View File

@ -1866,7 +1866,7 @@ static int cp_event(struct snd_soc_dapm_widget *w,
static int hp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
int timeout;
int reg;
int expected = (WM8962_DCS_STARTUP_DONE_HP1L |
@ -1960,7 +1960,7 @@ static int hp_event(struct snd_soc_dapm_widget *w,
static int out_pga_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
int reg;
switch (w->shift) {
@ -1993,7 +1993,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
static int dsp2_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
switch (event) {

View File

@ -244,7 +244,7 @@ SOC_DOUBLE_R_TLV("Output 2 Playback Volume", WM8988_LOUT2V, WM8988_ROUT2V,
static int wm8988_lrc_control(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
u16 adctl2 = snd_soc_read(codec, WM8988_ADCTL2);
/* Use the DAC to gate LRC if active, otherwise use ADC */
@ -813,7 +813,7 @@ static int wm8988_probe(struct snd_soc_codec *codec)
return 0;
}
static struct snd_soc_codec_driver soc_codec_dev_wm8988 = {
static const struct snd_soc_codec_driver soc_codec_dev_wm8988 = {
.probe = wm8988_probe,
.set_bias_level = wm8988_set_bias_level,
.suspend_bias_off = true,
@ -826,7 +826,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8988 = {
.num_dapm_routes = ARRAY_SIZE(wm8988_dapm_routes),
};
static struct regmap_config wm8988_regmap = {
static const struct regmap_config wm8988_regmap = {
.reg_bits = 7,
.val_bits = 9,

View File

@ -374,13 +374,14 @@ SOC_SINGLE("RIN34 Mute Switch", WM8990_RIGHT_LINE_INPUT_3_4_VOLUME,
static int outmixer_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
u32 reg_shift = kcontrol->private_value & 0xfff;
int ret = 0;
u16 reg;
switch (reg_shift) {
case WM8990_SPEAKER_MIXER | (WM8990_LDSPK_BIT << 8) :
reg = snd_soc_read(w->codec, WM8990_OUTPUT_MIXER1);
reg = snd_soc_read(codec, WM8990_OUTPUT_MIXER1);
if (reg & WM8990_LDLO) {
printk(KERN_WARNING
"Cannot set as Output Mixer 1 LDLO Set\n");
@ -388,7 +389,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
}
break;
case WM8990_SPEAKER_MIXER | (WM8990_RDSPK_BIT << 8):
reg = snd_soc_read(w->codec, WM8990_OUTPUT_MIXER2);
reg = snd_soc_read(codec, WM8990_OUTPUT_MIXER2);
if (reg & WM8990_RDRO) {
printk(KERN_WARNING
"Cannot set as Output Mixer 2 RDRO Set\n");
@ -396,7 +397,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
}
break;
case WM8990_OUTPUT_MIXER1 | (WM8990_LDLO_BIT << 8):
reg = snd_soc_read(w->codec, WM8990_SPEAKER_MIXER);
reg = snd_soc_read(codec, WM8990_SPEAKER_MIXER);
if (reg & WM8990_LDSPK) {
printk(KERN_WARNING
"Cannot set as Speaker Mixer LDSPK Set\n");
@ -404,7 +405,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
}
break;
case WM8990_OUTPUT_MIXER2 | (WM8990_RDRO_BIT << 8):
reg = snd_soc_read(w->codec, WM8990_SPEAKER_MIXER);
reg = snd_soc_read(codec, WM8990_SPEAKER_MIXER);
if (reg & WM8990_RDSPK) {
printk(KERN_WARNING
"Cannot set as Speaker Mixer RDSPK Set\n");

View File

@ -382,13 +382,14 @@ static const struct snd_kcontrol_new wm8991_snd_controls[] = {
static int outmixer_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
u32 reg_shift = kcontrol->private_value & 0xfff;
int ret = 0;
u16 reg;
switch (reg_shift) {
case WM8991_SPEAKER_MIXER | (WM8991_LDSPK_BIT << 8):
reg = snd_soc_read(w->codec, WM8991_OUTPUT_MIXER1);
reg = snd_soc_read(codec, WM8991_OUTPUT_MIXER1);
if (reg & WM8991_LDLO) {
printk(KERN_WARNING
"Cannot set as Output Mixer 1 LDLO Set\n");
@ -397,7 +398,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
break;
case WM8991_SPEAKER_MIXER | (WM8991_RDSPK_BIT << 8):
reg = snd_soc_read(w->codec, WM8991_OUTPUT_MIXER2);
reg = snd_soc_read(codec, WM8991_OUTPUT_MIXER2);
if (reg & WM8991_RDRO) {
printk(KERN_WARNING
"Cannot set as Output Mixer 2 RDRO Set\n");
@ -406,7 +407,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
break;
case WM8991_OUTPUT_MIXER1 | (WM8991_LDLO_BIT << 8):
reg = snd_soc_read(w->codec, WM8991_SPEAKER_MIXER);
reg = snd_soc_read(codec, WM8991_SPEAKER_MIXER);
if (reg & WM8991_LDSPK) {
printk(KERN_WARNING
"Cannot set as Speaker Mixer LDSPK Set\n");
@ -415,7 +416,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
break;
case WM8991_OUTPUT_MIXER2 | (WM8991_RDRO_BIT << 8):
reg = snd_soc_read(w->codec, WM8991_SPEAKER_MIXER);
reg = snd_soc_read(codec, WM8991_SPEAKER_MIXER);
if (reg & WM8991_RDSPK) {
printk(KERN_WARNING
"Cannot set as Speaker Mixer RDSPK Set\n");

View File

@ -810,7 +810,7 @@ SOC_SINGLE_TLV("EQ5 Volume", WM8993_EQ6, 0, 24, 0, eq_tlv),
static int clk_sys_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:

View File

@ -249,7 +249,8 @@ static int configure_clock(struct snd_soc_codec *codec)
static int check_clk_sys(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
int reg = snd_soc_read(source->codec, WM8994_CLOCKING_1);
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
int reg = snd_soc_read(codec, WM8994_CLOCKING_1);
const char *clk;
/* Check what we're currently using for CLK_SYS */
@ -806,7 +807,7 @@ static void active_dereference(struct snd_soc_codec *codec)
static int clk_sys_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -981,7 +982,7 @@ static void vmid_dereference(struct snd_soc_codec *codec)
static int vmid_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
@ -1037,7 +1038,7 @@ static bool wm8994_check_class_w_digital(struct snd_soc_codec *codec)
static int aif1clk_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994 *control = wm8994->wm8994;
int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA;
@ -1135,7 +1136,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w,
static int aif2clk_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
int i;
int dac;
int adc;
@ -1220,7 +1221,7 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w,
static int aif1clk_late_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -1238,7 +1239,7 @@ static int aif1clk_late_ev(struct snd_soc_dapm_widget *w,
static int aif2clk_late_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -1256,7 +1257,7 @@ static int aif2clk_late_ev(struct snd_soc_dapm_widget *w,
static int late_enable_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -1289,7 +1290,7 @@ static int late_enable_ev(struct snd_soc_dapm_widget *w,
static int late_disable_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -1331,7 +1332,7 @@ static int micbias_ev(struct snd_soc_dapm_widget *w,
static int dac_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
unsigned int mask = 1 << w->shift;
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5,
@ -1372,7 +1373,7 @@ SOC_DAPM_SINGLE("DAC1 Switch", WM8994_SPEAKER_MIXER, 0, 1, 0),
static int post_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
dev_dbg(codec->dev, "SRC status: %x\n",
snd_soc_read(codec,
WM8994_RATE_STATUS));

View File

@ -44,7 +44,7 @@ static const char *wm8995_supply_names[WM8995_NUM_SUPPLIES] = {
"MICVDD"
};
static struct reg_default wm8995_reg_defaults[] = {
static const struct reg_default wm8995_reg_defaults[] = {
{ 0, 0x8995 },
{ 5, 0x0100 },
{ 16, 0x000b },
@ -534,10 +534,11 @@ static void wm8995_update_class_w(struct snd_soc_codec *codec)
static int check_clk_sys(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
unsigned int reg;
const char *clk;
reg = snd_soc_read(source->codec, WM8995_CLOCKING_1);
reg = snd_soc_read(codec, WM8995_CLOCKING_1);
/* Check what we're currently using for CLK_SYS */
if (reg & WM8995_SYSCLK_SRC)
clk = "AIF2CLK";
@ -560,9 +561,7 @@ static int wm8995_put_class_w(struct snd_kcontrol *kcontrol,
static int hp_supply_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec;
codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
@ -611,10 +610,9 @@ static void dc_servo_cmd(struct snd_soc_codec *codec,
static int hp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
unsigned int reg;
codec = w->codec;
reg = snd_soc_read(codec, WM8995_ANALOGUE_HP_1);
switch (event) {
@ -761,9 +759,7 @@ static int configure_clock(struct snd_soc_codec *codec)
static int clk_sys_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec;
codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
@ -2190,7 +2186,7 @@ static struct snd_soc_dai_driver wm8995_dai[] = {
}
};
static struct snd_soc_codec_driver soc_codec_dev_wm8995 = {
static const struct snd_soc_codec_driver soc_codec_dev_wm8995 = {
.probe = wm8995_probe,
.remove = wm8995_remove,
.set_bias_level = wm8995_set_bias_level,
@ -2204,7 +2200,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8995 = {
.num_dapm_routes = ARRAY_SIZE(wm8995_intercon),
};
static struct regmap_config wm8995_regmap = {
static const struct regmap_config wm8995_regmap = {
.reg_bits = 16,
.val_bits = 16,

View File

@ -599,7 +599,7 @@ static void wm8996_bg_disable(struct snd_soc_codec *codec)
static int bg_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
int ret = 0;
switch (event) {
@ -634,7 +634,8 @@ static int cp_event(struct snd_soc_dapm_widget *w,
static int rmv_short_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(w->codec);
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
/* Record which outputs we enabled */
switch (event) {
@ -758,7 +759,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm,
static int dcs_start(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(w->codec);
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
switch (event) {
case SND_SOC_DAPM_POST_PMU:

View File

@ -84,7 +84,7 @@ static const struct reg_default wm8997_sysclk_reva_patch[] = {
static int wm8997_sysclk_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
struct regmap *regmap = arizona->regmap;
const struct reg_default *patch = NULL;
@ -610,13 +610,16 @@ SND_SOC_DAPM_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM,
ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM,
ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),

View File

@ -734,7 +734,7 @@ static int configure_clock(struct snd_soc_codec *codec)
static int clk_sys_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
/* This should be done on init() for bypass paths */

View File

@ -254,7 +254,7 @@ SOC_SINGLE_TLV("MIXOUTR IN2B Volume", WM9090_OUTPUT_MIXER4, 0, 3, 1,
static int hp_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
unsigned int reg = snd_soc_read(codec, WM9090_ANALOGUE_HP_0);
switch (event) {

View File

@ -344,23 +344,27 @@ static int wm9705_soc_probe(struct snd_soc_codec *codec)
struct snd_ac97 *ac97;
int ret = 0;
ac97 = snd_soc_new_ac97_codec(codec);
ac97 = snd_soc_alloc_ac97_codec(codec);
if (IS_ERR(ac97)) {
ret = PTR_ERR(ac97);
dev_err(codec->dev, "Failed to register AC97 codec\n");
return ret;
}
snd_soc_codec_set_drvdata(codec, ac97);
ret = wm9705_reset(codec);
if (ret)
goto reset_err;
goto err_put_device;
ret = device_add(&ac97->dev);
if (ret)
goto err_put_device;
snd_soc_codec_set_drvdata(codec, ac97);
return 0;
reset_err:
snd_soc_free_ac97_codec(ac97);
err_put_device:
put_device(&ac97->dev);
return ret;
}

View File

@ -666,7 +666,7 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec)
struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
wm9712->ac97 = snd_soc_new_ac97_codec(codec);
wm9712->ac97 = snd_soc_alloc_ac97_codec(codec);
if (IS_ERR(wm9712->ac97)) {
ret = PTR_ERR(wm9712->ac97);
dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret);
@ -675,15 +675,19 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec)
ret = wm9712_reset(codec, 0);
if (ret < 0)
goto reset_err;
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;
reset_err:
snd_soc_free_ac97_codec(wm9712->ac97);
err_put_device:
put_device(&wm9712->ac97->dev);
return ret;
}

View File

@ -217,7 +217,7 @@ SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1),
static int wm9713_voice_shutdown(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
u16 status, rate;
if (WARN_ON(event != SND_SOC_DAPM_PRE_PMD))
@ -1225,7 +1225,7 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec)
struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
int ret = 0, reg;
wm9713->ac97 = snd_soc_new_ac97_codec(codec);
wm9713->ac97 = snd_soc_alloc_ac97_codec(codec);
if (IS_ERR(wm9713->ac97))
return PTR_ERR(wm9713->ac97);
@ -1234,7 +1234,11 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec)
wm9713_reset(codec, 0);
ret = wm9713_reset(codec, 1);
if (ret < 0)
goto reset_err;
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;
@ -1242,8 +1246,8 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec)
return 0;
reset_err:
snd_soc_free_ac97_codec(wm9713->ac97);
err_put_device:
put_device(&wm9713->ac97->dev);
return ret;
}

View File

@ -1373,7 +1373,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
struct wm_adsp *dsp = &dsps[w->shift];
struct wm_adsp_alg_region *alg_region;
@ -1605,7 +1605,7 @@ err:
int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
struct wm_adsp *dsp = &dsps[w->shift];
@ -1626,7 +1626,7 @@ EXPORT_SYMBOL_GPL(wm_adsp2_early_event);
int wm_adsp2_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
struct wm_adsp *dsp = &dsps[w->shift];
struct wm_adsp_alg_region *alg_region;

View File

@ -500,7 +500,7 @@ SOC_SINGLE_TLV("LINEOUT2 Volume", WM8993_LINE_OUTPUTS_VOLUME, 0, 1, 1,
static int hp_supply_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
switch (event) {
@ -542,7 +542,7 @@ static int hp_supply_event(struct snd_soc_dapm_widget *w,
static int hp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
unsigned int reg = snd_soc_read(codec, WM8993_ANALOGUE_HP_0);
switch (event) {
@ -594,7 +594,7 @@ static int hp_event(struct snd_soc_dapm_widget *w,
static int earpiece_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *control, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
u16 reg = snd_soc_read(codec, WM8993_ANTIPOP1) & ~WM8993_HPOUT2_IN_ENA;
switch (event) {
@ -619,7 +619,7 @@ static int earpiece_event(struct snd_soc_dapm_widget *w,
static int lineout_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *control, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
bool *flag;
@ -649,7 +649,7 @@ static int lineout_event(struct snd_soc_dapm_widget *w,
static int micbias_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
switch (w->shift) {

View File

@ -58,13 +58,12 @@ choice
depends on MACH_DAVINCI_DM365_EVM
config SND_DM365_AIC3X_CODEC
bool "Audio Codec - AIC3101"
tristate "Audio Codec - AIC3101"
help
Say Y if you want to add support for AIC3101 audio codec
config SND_DM365_VOICE_CODEC
tristate "Voice Codec - CQ93VC"
depends on SND_DAVINCI_SOC
select MFD_DAVINCI_VOICECODEC
select SND_DAVINCI_SOC_VCIF
select SND_SOC_CQ0093VC

View File

@ -14,7 +14,6 @@
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/platform_data/edma.h>
#include <linux/i2c.h>
#include <linux/of_platform.h>
#include <linux/clk.h>
@ -25,11 +24,6 @@
#include <asm/dma.h>
#include <asm/mach-types.h>
#include <linux/edma.h>
#include "davinci-pcm.h"
#include "davinci-i2s.h"
struct snd_soc_card_drvdata_davinci {
struct clk *mclk;
unsigned sysclk;

Some files were not shown because too many files have changed in this diff Show More