Merge remote-tracking branches 'asoc/topic/da7213', 'asoc/topic/da732x', 'asoc/topic/da9055', 'asoc/topic/davinci', 'asoc/topic/fsl', 'asoc/topic/fsl-esai', 'asoc/topic/fsl-sai' and 'asoc/topic/fsl-spdif' into asoc-next

This commit is contained in:
Mark Brown 2014-03-12 23:04:22 +00:00
30 changed files with 973 additions and 534 deletions

View File

@ -0,0 +1,22 @@
* Dialog DA9055 Audio CODEC
DA9055 provides Audio CODEC support (I2C only).
The Audio CODEC device in DA9055 has it's own I2C address which is configurable,
so the device is instantiated separately from the PMIC (MFD) device.
For details on accompanying PMIC I2C device, see the following:
Documentation/devicetree/bindings/mfd/da9055.txt
Required properties:
- compatible: "dlg,da9055-codec"
- reg: Specifies the I2C slave address
Example:
codec: da9055-codec@1a {
compatible = "dlg,da9055-codec";
reg = <0x1a>;
};

View File

@ -5,12 +5,19 @@ Required properties:
- ti,model : The user-visible name of this sound complex.
- ti,audio-codec : The phandle of the TLV320AIC3x audio codec
- ti,mcasp-controller : The phandle of the McASP controller
- ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec
- ti,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 codec's pins, and the jacks on the board:
Optional properties:
- ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec.
- clocks : Reference to the master clock
- clock-names : The clock should be named "mclk"
- Either codec-clock-rate or the codec-clock reference has to be defined. If
the both are defined the driver attempts to set referenced clock to the
defined rate and takes the rate from the clock reference.
Board connectors:
* Headphone Jack

View File

@ -0,0 +1,21 @@
Audio complex for Eukrea boards with tlv320aic23 codec.
Required properties:
- compatible : "eukrea,asoc-tlv320"
- eukrea,model : The user-visible name of this sound complex.
- ssi-controller : The phandle of the SSI controller.
- fsl,mux-int-port : The internal port of the i.MX audio muxer (AUDMUX).
- fsl,mux-ext-port : The external port of the i.MX audio muxer.
Note: The AUDMUX port numbering should start at 1, which is consistent with
hardware manual.
Example:
sound {
compatible = "eukrea,asoc-tlv320";
eukrea,model = "imx51-eukrea-tlv320aic23";
ssi-controller = <&ssi2>;
fsl,mux-int-port = <2>;
fsl,mux-ext-port = <3>;
};

View File

@ -34,6 +34,10 @@ Required properties:
that ESAI would work in the synchronous mode, which means all the settings
for Receiving would be duplicated from Transmition related registers.
- big-endian : If this property is absent, the native endian mode will
be in use as default, or the big endian mode will be in use for all the
device registers.
Example:
esai: esai@02024000 {
@ -46,5 +50,6 @@ esai: esai@02024000 {
dma-names = "rx", "tx";
fsl,fifo-depth = <128>;
fsl,esai-synchronous;
big-endian;
status = "disabled";
};

View File

@ -29,6 +29,10 @@ Required properties:
can also be referred to TxClk_Source
bit of register SPDIF_STC.
- big-endian : If this property is absent, the native endian mode will
be in use as default, or the big endian mode will be in use for all the
device registers.
Example:
spdif: spdif@02004000 {
@ -50,5 +54,6 @@ spdif: spdif@02004000 {
"rxtx5", "rxtx6",
"rxtx7";
big-endian;
status = "okay";
};

View File

@ -18,7 +18,7 @@
#include <linux/genalloc.h>
struct snd_platform_data {
struct davinci_mcasp_pdata {
u32 tx_dma_offset;
u32 rx_dma_offset;
int asp_chan_q; /* event queue number for ASP channel */
@ -87,6 +87,8 @@ struct snd_platform_data {
int tx_dma_channel;
int rx_dma_channel;
};
/* TODO: Fix arch/arm/mach-davinci/ users and remove this define */
#define snd_platform_data davinci_mcasp_pdata
enum {
MCASP_VERSION_1 = 0, /* DM646x */

View File

@ -58,6 +58,6 @@ config SND_AT91_SOC_AFEB9260
depends on ARCH_AT91 && ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC
select SND_ATMEL_SOC_PDC
select SND_ATMEL_SOC_SSC
select SND_SOC_TLV320AIC23
select SND_SOC_TLV320AIC23_I2C
help
Say Y here to support sound on AFEB9260 board.

View File

@ -18,7 +18,7 @@ config SND_EP93XX_SOC_SNAPPERCL15
tristate "SoC Audio support for Bluewater Systems Snapper CL15 module"
depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15
select SND_EP93XX_SOC_I2S
select SND_SOC_TLV320AIC23
select SND_SOC_TLV320AIC23_I2C
help
Say Y or M here if you want to add support for I2S audio on the
Bluewater Systems Snapper CL15 module.

View File

@ -80,7 +80,8 @@ config SND_SOC_ALL_CODECS
select SND_SOC_STA529 if I2C
select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
select SND_SOC_TAS5086 if I2C
select SND_SOC_TLV320AIC23 if I2C
select SND_SOC_TLV320AIC23_I2C if I2C
select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
select SND_SOC_TLV320AIC26 if SPI_MASTER
select SND_SOC_TLV320AIC32X4 if I2C
select SND_SOC_TLV320AIC3X if I2C
@ -422,6 +423,14 @@ config SND_SOC_TAS5086
config SND_SOC_TLV320AIC23
tristate
config SND_SOC_TLV320AIC23_I2C
tristate
select SND_SOC_TLV320AIC23
config SND_SOC_TLV320AIC23_SPI
tristate
select SND_SOC_TLV320AIC23
config SND_SOC_TLV320AIC26
tristate
depends on SPI

View File

@ -73,6 +73,8 @@ snd-soc-sta529-objs := sta529.o
snd-soc-stac9766-objs := stac9766.o
snd-soc-tas5086-objs := tas5086.o
snd-soc-tlv320aic23-objs := tlv320aic23.o
snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o
snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o
snd-soc-tlv320aic26-objs := tlv320aic26.o
snd-soc-tlv320aic3x-objs := tlv320aic3x.o
snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o
@ -213,6 +215,8 @@ obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o
obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o
obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o
obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o
obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o

View File

@ -63,30 +63,30 @@ static const char * const da7213_voice_hpf_corner_txt[] = {
"2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz"
};
static const struct soc_enum da7213_dac_voice_hpf_corner =
SOC_ENUM_SINGLE(DA7213_DAC_FILTERS1, DA7213_VOICE_HPF_CORNER_SHIFT,
DA7213_VOICE_HPF_CORNER_MAX,
da7213_voice_hpf_corner_txt);
static SOC_ENUM_SINGLE_DECL(da7213_dac_voice_hpf_corner,
DA7213_DAC_FILTERS1,
DA7213_VOICE_HPF_CORNER_SHIFT,
da7213_voice_hpf_corner_txt);
static const struct soc_enum da7213_adc_voice_hpf_corner =
SOC_ENUM_SINGLE(DA7213_ADC_FILTERS1, DA7213_VOICE_HPF_CORNER_SHIFT,
DA7213_VOICE_HPF_CORNER_MAX,
da7213_voice_hpf_corner_txt);
static SOC_ENUM_SINGLE_DECL(da7213_adc_voice_hpf_corner,
DA7213_ADC_FILTERS1,
DA7213_VOICE_HPF_CORNER_SHIFT,
da7213_voice_hpf_corner_txt);
/* ADC and DAC high pass filter cutoff value */
static const char * const da7213_audio_hpf_corner_txt[] = {
"Fs/24000", "Fs/12000", "Fs/6000", "Fs/3000"
};
static const struct soc_enum da7213_dac_audio_hpf_corner =
SOC_ENUM_SINGLE(DA7213_DAC_FILTERS1, DA7213_AUDIO_HPF_CORNER_SHIFT,
DA7213_AUDIO_HPF_CORNER_MAX,
da7213_audio_hpf_corner_txt);
static SOC_ENUM_SINGLE_DECL(da7213_dac_audio_hpf_corner,
DA7213_DAC_FILTERS1
, DA7213_AUDIO_HPF_CORNER_SHIFT,
da7213_audio_hpf_corner_txt);
static const struct soc_enum da7213_adc_audio_hpf_corner =
SOC_ENUM_SINGLE(DA7213_ADC_FILTERS1, DA7213_AUDIO_HPF_CORNER_SHIFT,
DA7213_AUDIO_HPF_CORNER_MAX,
da7213_audio_hpf_corner_txt);
static SOC_ENUM_SINGLE_DECL(da7213_adc_audio_hpf_corner,
DA7213_ADC_FILTERS1,
DA7213_AUDIO_HPF_CORNER_SHIFT,
da7213_audio_hpf_corner_txt);
/* Gain ramping rate value */
static const char * const da7213_gain_ramp_rate_txt[] = {
@ -94,52 +94,50 @@ static const char * const da7213_gain_ramp_rate_txt[] = {
"nominal rate / 32"
};
static const struct soc_enum da7213_gain_ramp_rate =
SOC_ENUM_SINGLE(DA7213_GAIN_RAMP_CTRL, DA7213_GAIN_RAMP_RATE_SHIFT,
DA7213_GAIN_RAMP_RATE_MAX, da7213_gain_ramp_rate_txt);
static SOC_ENUM_SINGLE_DECL(da7213_gain_ramp_rate,
DA7213_GAIN_RAMP_CTRL,
DA7213_GAIN_RAMP_RATE_SHIFT,
da7213_gain_ramp_rate_txt);
/* DAC noise gate setup time value */
static const char * const da7213_dac_ng_setup_time_txt[] = {
"256 samples", "512 samples", "1024 samples", "2048 samples"
};
static const struct soc_enum da7213_dac_ng_setup_time =
SOC_ENUM_SINGLE(DA7213_DAC_NG_SETUP_TIME,
DA7213_DAC_NG_SETUP_TIME_SHIFT,
DA7213_DAC_NG_SETUP_TIME_MAX,
da7213_dac_ng_setup_time_txt);
static SOC_ENUM_SINGLE_DECL(da7213_dac_ng_setup_time,
DA7213_DAC_NG_SETUP_TIME,
DA7213_DAC_NG_SETUP_TIME_SHIFT,
da7213_dac_ng_setup_time_txt);
/* DAC noise gate rampup rate value */
static const char * const da7213_dac_ng_rampup_txt[] = {
"0.02 ms/dB", "0.16 ms/dB"
};
static const struct soc_enum da7213_dac_ng_rampup_rate =
SOC_ENUM_SINGLE(DA7213_DAC_NG_SETUP_TIME,
DA7213_DAC_NG_RAMPUP_RATE_SHIFT,
DA7213_DAC_NG_RAMP_RATE_MAX,
da7213_dac_ng_rampup_txt);
static SOC_ENUM_SINGLE_DECL(da7213_dac_ng_rampup_rate,
DA7213_DAC_NG_SETUP_TIME,
DA7213_DAC_NG_RAMPUP_RATE_SHIFT,
da7213_dac_ng_rampup_txt);
/* DAC noise gate rampdown rate value */
static const char * const da7213_dac_ng_rampdown_txt[] = {
"0.64 ms/dB", "20.48 ms/dB"
};
static const struct soc_enum da7213_dac_ng_rampdown_rate =
SOC_ENUM_SINGLE(DA7213_DAC_NG_SETUP_TIME,
DA7213_DAC_NG_RAMPDN_RATE_SHIFT,
DA7213_DAC_NG_RAMP_RATE_MAX,
da7213_dac_ng_rampdown_txt);
static SOC_ENUM_SINGLE_DECL(da7213_dac_ng_rampdown_rate,
DA7213_DAC_NG_SETUP_TIME,
DA7213_DAC_NG_RAMPDN_RATE_SHIFT,
da7213_dac_ng_rampdown_txt);
/* DAC soft mute rate value */
static const char * const da7213_dac_soft_mute_rate_txt[] = {
"1", "2", "4", "8", "16", "32", "64"
};
static const struct soc_enum da7213_dac_soft_mute_rate =
SOC_ENUM_SINGLE(DA7213_DAC_FILTERS5, DA7213_DAC_SOFTMUTE_RATE_SHIFT,
DA7213_DAC_SOFTMUTE_RATE_MAX,
da7213_dac_soft_mute_rate_txt);
static SOC_ENUM_SINGLE_DECL(da7213_dac_soft_mute_rate,
DA7213_DAC_FILTERS5,
DA7213_DAC_SOFTMUTE_RATE_SHIFT,
da7213_dac_soft_mute_rate_txt);
/* ALC Attack Rate select */
static const char * const da7213_alc_attack_rate_txt[] = {
@ -147,9 +145,10 @@ static const char * const da7213_alc_attack_rate_txt[] = {
"5632/fs", "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs"
};
static const struct soc_enum da7213_alc_attack_rate =
SOC_ENUM_SINGLE(DA7213_ALC_CTRL2, DA7213_ALC_ATTACK_SHIFT,
DA7213_ALC_ATTACK_MAX, da7213_alc_attack_rate_txt);
static SOC_ENUM_SINGLE_DECL(da7213_alc_attack_rate,
DA7213_ALC_CTRL2,
DA7213_ALC_ATTACK_SHIFT,
da7213_alc_attack_rate_txt);
/* ALC Release Rate select */
static const char * const da7213_alc_release_rate_txt[] = {
@ -157,9 +156,10 @@ static const char * const da7213_alc_release_rate_txt[] = {
"11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs"
};
static const struct soc_enum da7213_alc_release_rate =
SOC_ENUM_SINGLE(DA7213_ALC_CTRL2, DA7213_ALC_RELEASE_SHIFT,
DA7213_ALC_RELEASE_MAX, da7213_alc_release_rate_txt);
static SOC_ENUM_SINGLE_DECL(da7213_alc_release_rate,
DA7213_ALC_CTRL2,
DA7213_ALC_RELEASE_SHIFT,
da7213_alc_release_rate_txt);
/* ALC Hold Time select */
static const char * const da7213_alc_hold_time_txt[] = {
@ -168,22 +168,25 @@ static const char * const da7213_alc_hold_time_txt[] = {
"253952/fs", "507904/fs", "1015808/fs", "2031616/fs"
};
static const struct soc_enum da7213_alc_hold_time =
SOC_ENUM_SINGLE(DA7213_ALC_CTRL3, DA7213_ALC_HOLD_SHIFT,
DA7213_ALC_HOLD_MAX, da7213_alc_hold_time_txt);
static SOC_ENUM_SINGLE_DECL(da7213_alc_hold_time,
DA7213_ALC_CTRL3,
DA7213_ALC_HOLD_SHIFT,
da7213_alc_hold_time_txt);
/* ALC Input Signal Tracking rate select */
static const char * const da7213_alc_integ_rate_txt[] = {
"1/4", "1/16", "1/256", "1/65536"
};
static const struct soc_enum da7213_alc_integ_attack_rate =
SOC_ENUM_SINGLE(DA7213_ALC_CTRL3, DA7213_ALC_INTEG_ATTACK_SHIFT,
DA7213_ALC_INTEG_MAX, da7213_alc_integ_rate_txt);
static SOC_ENUM_SINGLE_DECL(da7213_alc_integ_attack_rate,
DA7213_ALC_CTRL3,
DA7213_ALC_INTEG_ATTACK_SHIFT,
da7213_alc_integ_rate_txt);
static const struct soc_enum da7213_alc_integ_release_rate =
SOC_ENUM_SINGLE(DA7213_ALC_CTRL3, DA7213_ALC_INTEG_RELEASE_SHIFT,
DA7213_ALC_INTEG_MAX, da7213_alc_integ_rate_txt);
static SOC_ENUM_SINGLE_DECL(da7213_alc_integ_release_rate,
DA7213_ALC_CTRL3,
DA7213_ALC_INTEG_RELEASE_SHIFT,
da7213_alc_integ_rate_txt);
/*
@ -584,15 +587,17 @@ static const char * const da7213_mic_amp_in_sel_txt[] = {
"Differential", "MIC_P", "MIC_N"
};
static const struct soc_enum da7213_mic_1_amp_in_sel =
SOC_ENUM_SINGLE(DA7213_MIC_1_CTRL, DA7213_MIC_AMP_IN_SEL_SHIFT,
DA7213_MIC_AMP_IN_SEL_MAX, da7213_mic_amp_in_sel_txt);
static SOC_ENUM_SINGLE_DECL(da7213_mic_1_amp_in_sel,
DA7213_MIC_1_CTRL,
DA7213_MIC_AMP_IN_SEL_SHIFT,
da7213_mic_amp_in_sel_txt);
static const struct snd_kcontrol_new da7213_mic_1_amp_in_sel_mux =
SOC_DAPM_ENUM("Mic 1 Amp Source MUX", da7213_mic_1_amp_in_sel);
static const struct soc_enum da7213_mic_2_amp_in_sel =
SOC_ENUM_SINGLE(DA7213_MIC_2_CTRL, DA7213_MIC_AMP_IN_SEL_SHIFT,
DA7213_MIC_AMP_IN_SEL_MAX, da7213_mic_amp_in_sel_txt);
static SOC_ENUM_SINGLE_DECL(da7213_mic_2_amp_in_sel,
DA7213_MIC_2_CTRL,
DA7213_MIC_AMP_IN_SEL_SHIFT,
da7213_mic_amp_in_sel_txt);
static const struct snd_kcontrol_new da7213_mic_2_amp_in_sel_mux =
SOC_DAPM_ENUM("Mic 2 Amp Source MUX", da7213_mic_2_amp_in_sel);
@ -601,15 +606,17 @@ static const char * const da7213_dai_src_txt[] = {
"ADC Left", "ADC Right", "DAI Input Left", "DAI Input Right"
};
static const struct soc_enum da7213_dai_l_src =
SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAI, DA7213_DAI_L_SRC_SHIFT,
DA7213_DAI_SRC_MAX, da7213_dai_src_txt);
static SOC_ENUM_SINGLE_DECL(da7213_dai_l_src,
DA7213_DIG_ROUTING_DAI,
DA7213_DAI_L_SRC_SHIFT,
da7213_dai_src_txt);
static const struct snd_kcontrol_new da7213_dai_l_src_mux =
SOC_DAPM_ENUM("DAI Left Source MUX", da7213_dai_l_src);
static const struct soc_enum da7213_dai_r_src =
SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAI, DA7213_DAI_R_SRC_SHIFT,
DA7213_DAI_SRC_MAX, da7213_dai_src_txt);
static SOC_ENUM_SINGLE_DECL(da7213_dai_r_src,
DA7213_DIG_ROUTING_DAI,
DA7213_DAI_R_SRC_SHIFT,
da7213_dai_src_txt);
static const struct snd_kcontrol_new da7213_dai_r_src_mux =
SOC_DAPM_ENUM("DAI Right Source MUX", da7213_dai_r_src);
@ -619,15 +626,17 @@ static const char * const da7213_dac_src_txt[] = {
"DAI Input Right"
};
static const struct soc_enum da7213_dac_l_src =
SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAC, DA7213_DAC_L_SRC_SHIFT,
DA7213_DAC_SRC_MAX, da7213_dac_src_txt);
static SOC_ENUM_SINGLE_DECL(da7213_dac_l_src,
DA7213_DIG_ROUTING_DAC,
DA7213_DAC_L_SRC_SHIFT,
da7213_dac_src_txt);
static const struct snd_kcontrol_new da7213_dac_l_src_mux =
SOC_DAPM_ENUM("DAC Left Source MUX", da7213_dac_l_src);
static const struct soc_enum da7213_dac_r_src =
SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAC, DA7213_DAC_R_SRC_SHIFT,
DA7213_DAC_SRC_MAX, da7213_dac_src_txt);
static SOC_ENUM_SINGLE_DECL(da7213_dac_r_src,
DA7213_DIG_ROUTING_DAC,
DA7213_DAC_R_SRC_SHIFT,
da7213_dac_src_txt);
static const struct snd_kcontrol_new da7213_dac_r_src_mux =
SOC_DAPM_ENUM("DAC Right Source MUX", da7213_dac_r_src);

View File

@ -269,81 +269,65 @@ static const char *da732x_hpf_voice[] = {
"150Hz", "200Hz", "300Hz", "400Hz"
};
static const struct soc_enum da732x_dac1_hpf_mode_enum[] = {
SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MODE_SHIFT,
DA732X_HPF_MODE_MAX, da732x_hpf_mode)
};
static SOC_ENUM_SINGLE_DECL(da732x_dac1_hpf_mode_enum,
DA732X_REG_DAC1_HPF, DA732X_HPF_MODE_SHIFT,
da732x_hpf_mode);
static const struct soc_enum da732x_dac2_hpf_mode_enum[] = {
SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MODE_SHIFT,
DA732X_HPF_MODE_MAX, da732x_hpf_mode)
};
static SOC_ENUM_SINGLE_DECL(da732x_dac2_hpf_mode_enum,
DA732X_REG_DAC2_HPF, DA732X_HPF_MODE_SHIFT,
da732x_hpf_mode);
static const struct soc_enum da732x_dac3_hpf_mode_enum[] = {
SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MODE_SHIFT,
DA732X_HPF_MODE_MAX, da732x_hpf_mode)
};
static SOC_ENUM_SINGLE_DECL(da732x_dac3_hpf_mode_enum,
DA732X_REG_DAC3_HPF, DA732X_HPF_MODE_SHIFT,
da732x_hpf_mode);
static const struct soc_enum da732x_adc1_hpf_mode_enum[] = {
SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MODE_SHIFT,
DA732X_HPF_MODE_MAX, da732x_hpf_mode)
};
static SOC_ENUM_SINGLE_DECL(da732x_adc1_hpf_mode_enum,
DA732X_REG_ADC1_HPF, DA732X_HPF_MODE_SHIFT,
da732x_hpf_mode);
static const struct soc_enum da732x_adc2_hpf_mode_enum[] = {
SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MODE_SHIFT,
DA732X_HPF_MODE_MAX, da732x_hpf_mode)
};
static SOC_ENUM_SINGLE_DECL(da732x_adc2_hpf_mode_enum,
DA732X_REG_ADC2_HPF, DA732X_HPF_MODE_SHIFT,
da732x_hpf_mode);
static const struct soc_enum da732x_dac1_hp_filter_enum[] = {
SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MUSIC_SHIFT,
DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
};
static SOC_ENUM_SINGLE_DECL(da732x_dac1_hp_filter_enum,
DA732X_REG_DAC1_HPF, DA732X_HPF_MUSIC_SHIFT,
da732x_hpf_music);
static const struct soc_enum da732x_dac2_hp_filter_enum[] = {
SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MUSIC_SHIFT,
DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
};
static SOC_ENUM_SINGLE_DECL(da732x_dac2_hp_filter_enum,
DA732X_REG_DAC2_HPF, DA732X_HPF_MUSIC_SHIFT,
da732x_hpf_music);
static const struct soc_enum da732x_dac3_hp_filter_enum[] = {
SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MUSIC_SHIFT,
DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
};
static SOC_ENUM_SINGLE_DECL(da732x_dac3_hp_filter_enum,
DA732X_REG_DAC3_HPF, DA732X_HPF_MUSIC_SHIFT,
da732x_hpf_music);
static const struct soc_enum da732x_adc1_hp_filter_enum[] = {
SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MUSIC_SHIFT,
DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
};
static SOC_ENUM_SINGLE_DECL(da732x_adc1_hp_filter_enum,
DA732X_REG_ADC1_HPF, DA732X_HPF_MUSIC_SHIFT,
da732x_hpf_music);
static const struct soc_enum da732x_adc2_hp_filter_enum[] = {
SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MUSIC_SHIFT,
DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
};
static SOC_ENUM_SINGLE_DECL(da732x_adc2_hp_filter_enum,
DA732X_REG_ADC2_HPF, DA732X_HPF_MUSIC_SHIFT,
da732x_hpf_music);
static const struct soc_enum da732x_dac1_voice_filter_enum[] = {
SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_VOICE_SHIFT,
DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
};
static SOC_ENUM_SINGLE_DECL(da732x_dac1_voice_filter_enum,
DA732X_REG_DAC1_HPF, DA732X_HPF_VOICE_SHIFT,
da732x_hpf_voice);
static const struct soc_enum da732x_dac2_voice_filter_enum[] = {
SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_VOICE_SHIFT,
DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
};
static SOC_ENUM_SINGLE_DECL(da732x_dac2_voice_filter_enum,
DA732X_REG_DAC2_HPF, DA732X_HPF_VOICE_SHIFT,
da732x_hpf_voice);
static const struct soc_enum da732x_dac3_voice_filter_enum[] = {
SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_VOICE_SHIFT,
DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
};
static SOC_ENUM_SINGLE_DECL(da732x_dac3_voice_filter_enum,
DA732X_REG_DAC3_HPF, DA732X_HPF_VOICE_SHIFT,
da732x_hpf_voice);
static const struct soc_enum da732x_adc1_voice_filter_enum[] = {
SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_VOICE_SHIFT,
DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
};
static const struct soc_enum da732x_adc2_voice_filter_enum[] = {
SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_VOICE_SHIFT,
DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
};
static SOC_ENUM_SINGLE_DECL(da732x_adc1_voice_filter_enum,
DA732X_REG_ADC1_HPF, DA732X_HPF_VOICE_SHIFT,
da732x_hpf_voice);
static SOC_ENUM_SINGLE_DECL(da732x_adc2_voice_filter_enum,
DA732X_REG_ADC2_HPF, DA732X_HPF_VOICE_SHIFT,
da732x_hpf_voice);
static int da732x_hpf_set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@ -714,65 +698,65 @@ static const char *enable_text[] = {
};
/* ADC1LMUX */
static const struct soc_enum adc1l_enum =
SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1L_MUX_SEL_SHIFT,
DA732X_ADCL_MUX_MAX, adcl_text);
static SOC_ENUM_SINGLE_DECL(adc1l_enum,
DA732X_REG_INP_MUX, DA732X_ADC1L_MUX_SEL_SHIFT,
adcl_text);
static const struct snd_kcontrol_new adc1l_mux =
SOC_DAPM_ENUM("ADC Route", adc1l_enum);
/* ADC1RMUX */
static const struct soc_enum adc1r_enum =
SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1R_MUX_SEL_SHIFT,
DA732X_ADCR_MUX_MAX, adcr_text);
static SOC_ENUM_SINGLE_DECL(adc1r_enum,
DA732X_REG_INP_MUX, DA732X_ADC1R_MUX_SEL_SHIFT,
adcr_text);
static const struct snd_kcontrol_new adc1r_mux =
SOC_DAPM_ENUM("ADC Route", adc1r_enum);
/* ADC2LMUX */
static const struct soc_enum adc2l_enum =
SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2L_MUX_SEL_SHIFT,
DA732X_ADCL_MUX_MAX, adcl_text);
static SOC_ENUM_SINGLE_DECL(adc2l_enum,
DA732X_REG_INP_MUX, DA732X_ADC2L_MUX_SEL_SHIFT,
adcl_text);
static const struct snd_kcontrol_new adc2l_mux =
SOC_DAPM_ENUM("ADC Route", adc2l_enum);
/* ADC2RMUX */
static const struct soc_enum adc2r_enum =
SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2R_MUX_SEL_SHIFT,
DA732X_ADCR_MUX_MAX, adcr_text);
static SOC_ENUM_SINGLE_DECL(adc2r_enum,
DA732X_REG_INP_MUX, DA732X_ADC2R_MUX_SEL_SHIFT,
adcr_text);
static const struct snd_kcontrol_new adc2r_mux =
SOC_DAPM_ENUM("ADC Route", adc2r_enum);
static const struct soc_enum da732x_hp_left_output =
SOC_ENUM_SINGLE(DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN_SHIFT,
DA732X_DAC_EN_MAX, enable_text);
static SOC_ENUM_SINGLE_DECL(da732x_hp_left_output,
DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN_SHIFT,
enable_text);
static const struct snd_kcontrol_new hpl_mux =
SOC_DAPM_ENUM("HPL Switch", da732x_hp_left_output);
static const struct soc_enum da732x_hp_right_output =
SOC_ENUM_SINGLE(DA732X_REG_HPR, DA732X_HP_OUT_DAC_EN_SHIFT,
DA732X_DAC_EN_MAX, enable_text);
static SOC_ENUM_SINGLE_DECL(da732x_hp_right_output,
DA732X_REG_HPR, DA732X_HP_OUT_DAC_EN_SHIFT,
enable_text);
static const struct snd_kcontrol_new hpr_mux =
SOC_DAPM_ENUM("HPR Switch", da732x_hp_right_output);
static const struct soc_enum da732x_speaker_output =
SOC_ENUM_SINGLE(DA732X_REG_LIN3, DA732X_LOUT_DAC_EN_SHIFT,
DA732X_DAC_EN_MAX, enable_text);
static SOC_ENUM_SINGLE_DECL(da732x_speaker_output,
DA732X_REG_LIN3, DA732X_LOUT_DAC_EN_SHIFT,
enable_text);
static const struct snd_kcontrol_new spk_mux =
SOC_DAPM_ENUM("SPK Switch", da732x_speaker_output);
static const struct soc_enum da732x_lout4_output =
SOC_ENUM_SINGLE(DA732X_REG_LIN4, DA732X_LOUT_DAC_EN_SHIFT,
DA732X_DAC_EN_MAX, enable_text);
static SOC_ENUM_SINGLE_DECL(da732x_lout4_output,
DA732X_REG_LIN4, DA732X_LOUT_DAC_EN_SHIFT,
enable_text);
static const struct snd_kcontrol_new lout4_mux =
SOC_DAPM_ENUM("LOUT4 Switch", da732x_lout4_output);
static const struct soc_enum da732x_lout2_output =
SOC_ENUM_SINGLE(DA732X_REG_LIN2, DA732X_LOUT_DAC_EN_SHIFT,
DA732X_DAC_EN_MAX, enable_text);
static SOC_ENUM_SINGLE_DECL(da732x_lout2_output,
DA732X_REG_LIN2, DA732X_LOUT_DAC_EN_SHIFT,
enable_text);
static const struct snd_kcontrol_new lout2_mux =
SOC_DAPM_ENUM("LOUT2 Switch", da732x_lout2_output);
@ -1499,8 +1483,8 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec,
da732x_hp_dc_offset_cancellation(codec);
regcache_cache_only(codec->control_data, false);
regcache_sync(codec->control_data);
regcache_cache_only(da732x->regmap, false);
regcache_sync(da732x->regmap);
} else {
snd_soc_update_bits(codec, DA732X_REG_BIAS_EN,
DA732X_BIAS_BOOST_MASK,
@ -1511,7 +1495,7 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec,
}
break;
case SND_SOC_BIAS_OFF:
regcache_cache_only(codec->control_data, true);
regcache_cache_only(da732x->regmap, true);
da732x_set_charge_pump(codec, DA732X_DISABLE_CP);
snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, DA732X_BIAS_EN,
DA732X_BIAS_DIS);
@ -1566,7 +1550,6 @@ static struct snd_soc_codec_driver soc_codec_dev_da732x = {
.dapm_routes = da732x_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(da732x_dapm_routes),
.set_pll = da732x_set_dai_pll,
.reg_cache_size = ARRAY_SIZE(da732x_reg_cache),
};
static int da732x_i2c_probe(struct i2c_client *i2c,

View File

@ -18,6 +18,8 @@
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
@ -321,22 +323,22 @@ static const char * const da9055_hpf_cutoff_txt[] = {
"Fs/24000", "Fs/12000", "Fs/6000", "Fs/3000"
};
static const struct soc_enum da9055_dac_hpf_cutoff =
SOC_ENUM_SINGLE(DA9055_DAC_FILTERS1, 4, 4, da9055_hpf_cutoff_txt);
static SOC_ENUM_SINGLE_DECL(da9055_dac_hpf_cutoff,
DA9055_DAC_FILTERS1, 4, da9055_hpf_cutoff_txt);
static const struct soc_enum da9055_adc_hpf_cutoff =
SOC_ENUM_SINGLE(DA9055_ADC_FILTERS1, 4, 4, da9055_hpf_cutoff_txt);
static SOC_ENUM_SINGLE_DECL(da9055_adc_hpf_cutoff,
DA9055_ADC_FILTERS1, 4, da9055_hpf_cutoff_txt);
/* ADC and DAC voice mode (8kHz) high pass cutoff value */
static const char * const da9055_vf_cutoff_txt[] = {
"2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz"
};
static const struct soc_enum da9055_dac_vf_cutoff =
SOC_ENUM_SINGLE(DA9055_DAC_FILTERS1, 0, 8, da9055_vf_cutoff_txt);
static SOC_ENUM_SINGLE_DECL(da9055_dac_vf_cutoff,
DA9055_DAC_FILTERS1, 0, da9055_vf_cutoff_txt);
static const struct soc_enum da9055_adc_vf_cutoff =
SOC_ENUM_SINGLE(DA9055_ADC_FILTERS1, 0, 8, da9055_vf_cutoff_txt);
static SOC_ENUM_SINGLE_DECL(da9055_adc_vf_cutoff,
DA9055_ADC_FILTERS1, 0, da9055_vf_cutoff_txt);
/* Gain ramping rate value */
static const char * const da9055_gain_ramping_txt[] = {
@ -344,44 +346,44 @@ static const char * const da9055_gain_ramping_txt[] = {
"nominal rate / 8"
};
static const struct soc_enum da9055_gain_ramping_rate =
SOC_ENUM_SINGLE(DA9055_GAIN_RAMP_CTRL, 0, 4, da9055_gain_ramping_txt);
static SOC_ENUM_SINGLE_DECL(da9055_gain_ramping_rate,
DA9055_GAIN_RAMP_CTRL, 0, da9055_gain_ramping_txt);
/* DAC noise gate setup time value */
static const char * const da9055_dac_ng_setup_time_txt[] = {
"256 samples", "512 samples", "1024 samples", "2048 samples"
};
static const struct soc_enum da9055_dac_ng_setup_time =
SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 0, 4,
da9055_dac_ng_setup_time_txt);
static SOC_ENUM_SINGLE_DECL(da9055_dac_ng_setup_time,
DA9055_DAC_NG_SETUP_TIME, 0,
da9055_dac_ng_setup_time_txt);
/* DAC noise gate rampup rate value */
static const char * const da9055_dac_ng_rampup_txt[] = {
"0.02 ms/dB", "0.16 ms/dB"
};
static const struct soc_enum da9055_dac_ng_rampup_rate =
SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 2, 2,
da9055_dac_ng_rampup_txt);
static SOC_ENUM_SINGLE_DECL(da9055_dac_ng_rampup_rate,
DA9055_DAC_NG_SETUP_TIME, 2,
da9055_dac_ng_rampup_txt);
/* DAC noise gate rampdown rate value */
static const char * const da9055_dac_ng_rampdown_txt[] = {
"0.64 ms/dB", "20.48 ms/dB"
};
static const struct soc_enum da9055_dac_ng_rampdown_rate =
SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 3, 2,
da9055_dac_ng_rampdown_txt);
static SOC_ENUM_SINGLE_DECL(da9055_dac_ng_rampdown_rate,
DA9055_DAC_NG_SETUP_TIME, 3,
da9055_dac_ng_rampdown_txt);
/* DAC soft mute rate value */
static const char * const da9055_dac_soft_mute_rate_txt[] = {
"1", "2", "4", "8", "16", "32", "64"
};
static const struct soc_enum da9055_dac_soft_mute_rate =
SOC_ENUM_SINGLE(DA9055_DAC_FILTERS5, 4, 7,
da9055_dac_soft_mute_rate_txt);
static SOC_ENUM_SINGLE_DECL(da9055_dac_soft_mute_rate,
DA9055_DAC_FILTERS5, 4,
da9055_dac_soft_mute_rate_txt);
/* DAC routing select */
static const char * const da9055_dac_src_txt[] = {
@ -389,40 +391,40 @@ static const char * const da9055_dac_src_txt[] = {
"AIF input right"
};
static const struct soc_enum da9055_dac_l_src =
SOC_ENUM_SINGLE(DA9055_DIG_ROUTING_DAC, 0, 4, da9055_dac_src_txt);
static SOC_ENUM_SINGLE_DECL(da9055_dac_l_src,
DA9055_DIG_ROUTING_DAC, 0, da9055_dac_src_txt);
static const struct soc_enum da9055_dac_r_src =
SOC_ENUM_SINGLE(DA9055_DIG_ROUTING_DAC, 4, 4, da9055_dac_src_txt);
static SOC_ENUM_SINGLE_DECL(da9055_dac_r_src,
DA9055_DIG_ROUTING_DAC, 4, da9055_dac_src_txt);
/* MIC PGA Left source select */
static const char * const da9055_mic_l_src_txt[] = {
"MIC1_P_N", "MIC1_P", "MIC1_N", "MIC2_L"
};
static const struct soc_enum da9055_mic_l_src =
SOC_ENUM_SINGLE(DA9055_MIXIN_L_SELECT, 4, 4, da9055_mic_l_src_txt);
static SOC_ENUM_SINGLE_DECL(da9055_mic_l_src,
DA9055_MIXIN_L_SELECT, 4, da9055_mic_l_src_txt);
/* MIC PGA Right source select */
static const char * const da9055_mic_r_src_txt[] = {
"MIC2_R_L", "MIC2_R", "MIC2_L"
};
static const struct soc_enum da9055_mic_r_src =
SOC_ENUM_SINGLE(DA9055_MIXIN_R_SELECT, 4, 3, da9055_mic_r_src_txt);
static SOC_ENUM_SINGLE_DECL(da9055_mic_r_src,
DA9055_MIXIN_R_SELECT, 4, da9055_mic_r_src_txt);
/* ALC Input Signal Tracking rate select */
static const char * const da9055_signal_tracking_rate_txt[] = {
"1/4", "1/16", "1/256", "1/65536"
};
static const struct soc_enum da9055_integ_attack_rate =
SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 4, 4,
da9055_signal_tracking_rate_txt);
static SOC_ENUM_SINGLE_DECL(da9055_integ_attack_rate,
DA9055_ALC_CTRL3, 4,
da9055_signal_tracking_rate_txt);
static const struct soc_enum da9055_integ_release_rate =
SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 6, 4,
da9055_signal_tracking_rate_txt);
static SOC_ENUM_SINGLE_DECL(da9055_integ_release_rate,
DA9055_ALC_CTRL3, 6,
da9055_signal_tracking_rate_txt);
/* ALC Attack Rate select */
static const char * const da9055_attack_rate_txt[] = {
@ -430,8 +432,8 @@ static const char * const da9055_attack_rate_txt[] = {
"5632/fs", "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs"
};
static const struct soc_enum da9055_attack_rate =
SOC_ENUM_SINGLE(DA9055_ALC_CTRL2, 0, 13, da9055_attack_rate_txt);
static SOC_ENUM_SINGLE_DECL(da9055_attack_rate,
DA9055_ALC_CTRL2, 0, da9055_attack_rate_txt);
/* ALC Release Rate select */
static const char * const da9055_release_rate_txt[] = {
@ -439,8 +441,8 @@ static const char * const da9055_release_rate_txt[] = {
"11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs"
};
static const struct soc_enum da9055_release_rate =
SOC_ENUM_SINGLE(DA9055_ALC_CTRL2, 4, 11, da9055_release_rate_txt);
static SOC_ENUM_SINGLE_DECL(da9055_release_rate,
DA9055_ALC_CTRL2, 4, da9055_release_rate_txt);
/* ALC Hold Time select */
static const char * const da9055_hold_time_txt[] = {
@ -449,8 +451,8 @@ static const char * const da9055_hold_time_txt[] = {
"253952/fs", "507904/fs", "1015808/fs", "2031616/fs"
};
static const struct soc_enum da9055_hold_time =
SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 0, 16, da9055_hold_time_txt);
static SOC_ENUM_SINGLE_DECL(da9055_hold_time,
DA9055_ALC_CTRL3, 0, da9055_hold_time_txt);
static int da9055_get_alc_data(struct snd_soc_codec *codec, u8 reg_val)
{
@ -1536,11 +1538,17 @@ static const struct i2c_device_id da9055_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, da9055_i2c_id);
static const struct of_device_id da9055_of_match[] = {
{ .compatible = "dlg,da9055-codec", },
{ }
};
/* I2C codec control layer */
static struct i2c_driver da9055_i2c_driver = {
.driver = {
.name = "da9055-codec",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(da9055_of_match),
},
.probe = da9055_i2c_probe,
.remove = da9055_remove,

View File

@ -0,0 +1,59 @@
/*
* ALSA SoC TLV320AIC23 codec driver I2C interface
*
* Author: Arun KS, <arunks@mistralsolutions.com>
* Copyright: (C) 2008 Mistral Solutions Pvt Ltd.,
*
* Based on sound/soc/codecs/wm8731.c by Richard Purdie
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <sound/soc.h>
#include "tlv320aic23.h"
static int tlv320aic23_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *i2c_id)
{
struct regmap *regmap;
if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -EINVAL;
regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap);
return tlv320aic23_probe(&i2c->dev, regmap);
}
static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c)
{
snd_soc_unregister_codec(&i2c->dev);
return 0;
}
static const struct i2c_device_id tlv320aic23_id[] = {
{"tlv320aic23", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, tlv320aic23_id);
static struct i2c_driver tlv320aic23_i2c_driver = {
.driver = {
.name = "tlv320aic23-codec",
},
.probe = tlv320aic23_i2c_probe,
.remove = __exit_p(tlv320aic23_i2c_remove),
.id_table = tlv320aic23_id,
};
module_i2c_driver(tlv320aic23_i2c_driver);
MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver I2C");
MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,57 @@
/*
* ALSA SoC TLV320AIC23 codec driver SPI interface
*
* Author: Arun KS, <arunks@mistralsolutions.com>
* Copyright: (C) 2008 Mistral Solutions Pvt Ltd.,
*
* Based on sound/soc/codecs/wm8731.c by Richard Purdie
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <sound/soc.h>
#include "tlv320aic23.h"
static int aic23_spi_probe(struct spi_device *spi)
{
int ret;
struct regmap *regmap;
dev_dbg(&spi->dev, "probing tlv320aic23 spi device\n");
spi->bits_per_word = 16;
spi->mode = SPI_MODE_0;
ret = spi_setup(spi);
if (ret < 0)
return ret;
regmap = devm_regmap_init_spi(spi, &tlv320aic23_regmap);
return tlv320aic23_probe(&spi->dev, regmap);
}
static int aic23_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
}
static struct spi_driver aic23_spi = {
.driver = {
.name = "tlv320aic23",
.owner = THIS_MODULE,
},
.probe = aic23_spi_probe,
.remove = aic23_spi_remove,
};
module_spi_driver(aic23_spi);
MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver SPI");
MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
MODULE_LICENSE("GPL");

View File

@ -23,7 +23,6 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/core.h>
@ -51,7 +50,7 @@ static const struct reg_default tlv320aic23_reg[] = {
{ 9, 0x0000 },
};
static const struct regmap_config tlv320aic23_regmap = {
const struct regmap_config tlv320aic23_regmap = {
.reg_bits = 7,
.val_bits = 9,
@ -64,16 +63,16 @@ static const struct regmap_config tlv320aic23_regmap = {
static const char *rec_src_text[] = { "Line", "Mic" };
static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"};
static const struct soc_enum rec_src_enum =
SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text);
static SOC_ENUM_SINGLE_DECL(rec_src_enum,
TLV320AIC23_ANLG, 2, rec_src_text);
static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls =
SOC_DAPM_ENUM("Input Select", rec_src_enum);
static const struct soc_enum tlv320aic23_rec_src =
SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text);
static const struct soc_enum tlv320aic23_deemph =
SOC_ENUM_SINGLE(TLV320AIC23_DIGT, 1, 4, deemph_text);
static SOC_ENUM_SINGLE_DECL(tlv320aic23_rec_src,
TLV320AIC23_ANLG, 2, rec_src_text);
static SOC_ENUM_SINGLE_DECL(tlv320aic23_deemph,
TLV320AIC23_DIGT, 1, deemph_text);
static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -12100, 100, 0);
static const DECLARE_TLV_DB_SCALE(input_gain_tlv, -1725, 75, 0);
@ -557,7 +556,7 @@ static int tlv320aic23_resume(struct snd_soc_codec *codec)
return 0;
}
static int tlv320aic23_probe(struct snd_soc_codec *codec)
static int tlv320aic23_codec_probe(struct snd_soc_codec *codec)
{
int ret;
@ -604,7 +603,7 @@ static int tlv320aic23_remove(struct snd_soc_codec *codec)
}
static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = {
.probe = tlv320aic23_probe,
.probe = tlv320aic23_codec_probe,
.remove = tlv320aic23_remove,
.suspend = tlv320aic23_suspend,
.resume = tlv320aic23_resume,
@ -617,56 +616,24 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = {
.num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon),
};
/*
* If the i2c layer weren't so broken, we could pass this kind of data
* around
*/
static int tlv320aic23_codec_probe(struct i2c_client *i2c,
const struct i2c_device_id *i2c_id)
int tlv320aic23_probe(struct device *dev, struct regmap *regmap)
{
struct aic23 *aic23;
int ret;
if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -EINVAL;
if (IS_ERR(regmap))
return PTR_ERR(regmap);
aic23 = devm_kzalloc(&i2c->dev, sizeof(struct aic23), GFP_KERNEL);
aic23 = devm_kzalloc(dev, sizeof(struct aic23), GFP_KERNEL);
if (aic23 == NULL)
return -ENOMEM;
aic23->regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap);
if (IS_ERR(aic23->regmap))
return PTR_ERR(aic23->regmap);
aic23->regmap = regmap;
i2c_set_clientdata(i2c, aic23);
dev_set_drvdata(dev, aic23);
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1);
return ret;
return snd_soc_register_codec(dev, &soc_codec_dev_tlv320aic23,
&tlv320aic23_dai, 1);
}
static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c)
{
snd_soc_unregister_codec(&i2c->dev);
return 0;
}
static const struct i2c_device_id tlv320aic23_id[] = {
{"tlv320aic23", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, tlv320aic23_id);
static struct i2c_driver tlv320aic23_i2c_driver = {
.driver = {
.name = "tlv320aic23-codec",
},
.probe = tlv320aic23_codec_probe,
.remove = __exit_p(tlv320aic23_i2c_remove),
.id_table = tlv320aic23_id,
};
module_i2c_driver(tlv320aic23_i2c_driver);
MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver");
MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");

View File

@ -12,6 +12,12 @@
#ifndef _TLV320AIC23_H
#define _TLV320AIC23_H
struct device;
struct regmap_config;
extern const struct regmap_config tlv320aic23_regmap;
int tlv320aic23_probe(struct device *dev, struct regmap *regmap);
/* Codec TLV320AIC23 */
#define TLV320AIC23_LINVOL 0x00
#define TLV320AIC23_RINVOL 0x01

View File

@ -17,6 +17,7 @@
#include <linux/platform_data/edma.h>
#include <linux/i2c.h>
#include <linux/of_platform.h>
#include <linux/clk.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
@ -30,9 +31,34 @@
#include "davinci-i2s.h"
struct snd_soc_card_drvdata_davinci {
struct clk *mclk;
unsigned sysclk;
};
static int evm_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *soc_card = rtd->codec->card;
struct snd_soc_card_drvdata_davinci *drvdata =
snd_soc_card_get_drvdata(soc_card);
if (drvdata->mclk)
return clk_prepare_enable(drvdata->mclk);
return 0;
}
static void evm_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *soc_card = rtd->codec->card;
struct snd_soc_card_drvdata_davinci *drvdata =
snd_soc_card_get_drvdata(soc_card);
if (drvdata->mclk)
clk_disable_unprepare(drvdata->mclk);
}
static int evm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
@ -59,6 +85,8 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
}
static struct snd_soc_ops evm_ops = {
.startup = evm_startup,
.shutdown = evm_shutdown,
.hw_params = evm_hw_params,
};
@ -348,6 +376,7 @@ static int davinci_evm_probe(struct platform_device *pdev)
of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev);
struct snd_soc_dai_link *dai = (struct snd_soc_dai_link *) match->data;
struct snd_soc_card_drvdata_davinci *drvdata = NULL;
struct clk *mclk;
int ret = 0;
evm_soc_card.dai_link = dai;
@ -367,13 +396,38 @@ static int davinci_evm_probe(struct platform_device *pdev)
if (ret)
return ret;
mclk = devm_clk_get(&pdev->dev, "mclk");
if (PTR_ERR(mclk) == -EPROBE_DEFER) {
return -EPROBE_DEFER;
} else if (IS_ERR(mclk)) {
dev_dbg(&pdev->dev, "mclk not found.\n");
mclk = NULL;
}
drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
drvdata->mclk = mclk;
ret = of_property_read_u32(np, "ti,codec-clock-rate", &drvdata->sysclk);
if (ret < 0)
return -EINVAL;
if (ret < 0) {
if (!drvdata->mclk) {
dev_err(&pdev->dev,
"No clock or clock rate defined.\n");
return -EINVAL;
}
drvdata->sysclk = clk_get_rate(drvdata->mclk);
} else if (drvdata->mclk) {
unsigned int requestd_rate = drvdata->sysclk;
clk_set_rate(drvdata->mclk, drvdata->sysclk);
drvdata->sysclk = clk_get_rate(drvdata->mclk);
if (drvdata->sysclk != requestd_rate)
dev_warn(&pdev->dev,
"Could not get requested rate %u using %u.\n",
requestd_rate, drvdata->sysclk);
}
snd_soc_card_set_drvdata(&evm_soc_card, drvdata);
ret = devm_snd_soc_register_card(&pdev->dev, &evm_soc_card);

View File

@ -37,6 +37,16 @@
#include "davinci-pcm.h"
#include "davinci-mcasp.h"
struct davinci_mcasp_context {
u32 txfmtctl;
u32 rxfmtctl;
u32 txfmt;
u32 rxfmt;
u32 aclkxctl;
u32 aclkrctl;
u32 pdir;
};
struct davinci_mcasp {
struct davinci_pcm_dma_params dma_params[2];
struct snd_dmaengine_dai_dma_data dma_data[2];
@ -53,6 +63,9 @@ struct davinci_mcasp {
u16 bclk_lrclk_ratio;
int streams;
int sysclk_freq;
bool bclk_master;
/* McASP FIFO related */
u8 txnumevt;
u8 rxnumevt;
@ -60,15 +73,7 @@ struct davinci_mcasp {
bool dat_port;
#ifdef CONFIG_PM_SLEEP
struct {
u32 txfmtctl;
u32 rxfmtctl;
u32 txfmt;
u32 rxfmt;
u32 aclkxctl;
u32 aclkrctl;
u32 pdir;
} context;
struct davinci_mcasp_context context;
#endif
};
@ -294,6 +299,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR);
mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR);
mcasp->bclk_master = 1;
break;
case SND_SOC_DAIFMT_CBM_CFS:
/* codec is clock master and frame slave */
@ -305,6 +311,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR);
mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR);
mcasp->bclk_master = 0;
break;
case SND_SOC_DAIFMT_CBM_CFM:
/* codec is clock and frame master */
@ -316,6 +323,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG,
ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR);
mcasp->bclk_master = 0;
break;
default:
@ -410,6 +418,8 @@ static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id,
mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AHCLKX);
}
mcasp->sysclk_freq = freq;
return 0;
}
@ -603,20 +613,23 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
u8 fifo_level;
u8 slots = mcasp->tdm_slots;
u8 active_serializers;
int channels;
int channels = params_channels(params);
int ret;
struct snd_interval *pcm_channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS);
channels = pcm_channels->min;
active_serializers = (channels + slots - 1) / slots;
/* If mcasp is BCLK master we need to set BCLK divider */
if (mcasp->bclk_master) {
unsigned int bclk_freq = snd_soc_params_to_bclk(params);
if (mcasp->sysclk_freq % bclk_freq != 0) {
dev_err(mcasp->dev, "Can't produce requred BCLK\n");
return -EINVAL;
}
davinci_mcasp_set_clkdiv(
cpu_dai, 1, mcasp->sysclk_freq / bclk_freq);
}
if (mcasp_common_hw_param(mcasp, substream->stream, channels) == -EINVAL)
return -EINVAL;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
fifo_level = mcasp->txnumevt * active_serializers;
else
fifo_level = mcasp->rxnumevt * active_serializers;
ret = mcasp_common_hw_param(mcasp, substream->stream, channels);
if (ret)
return ret;
if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
ret = mcasp_dit_hw_param(mcasp);
@ -658,6 +671,13 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
/* Calculate FIFO level */
active_serializers = (channels + slots - 1) / slots;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
fifo_level = mcasp->txnumevt * active_serializers;
else
fifo_level = mcasp->rxnumevt * active_serializers;
if (mcasp->version == MCASP_VERSION_2 && !fifo_level)
dma_params->acnt = 4;
else
@ -719,6 +739,43 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
.set_sysclk = davinci_mcasp_set_sysclk,
};
#ifdef CONFIG_PM_SLEEP
static int davinci_mcasp_suspend(struct snd_soc_dai *dai)
{
struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
struct davinci_mcasp_context *context = &mcasp->context;
context->txfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG);
context->rxfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG);
context->txfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMT_REG);
context->rxfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMT_REG);
context->aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG);
context->aclkrctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG);
context->pdir = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG);
return 0;
}
static int davinci_mcasp_resume(struct snd_soc_dai *dai)
{
struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
struct davinci_mcasp_context *context = &mcasp->context;
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, context->txfmtctl);
mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG, context->rxfmtctl);
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMT_REG, context->txfmt);
mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMT_REG, context->rxfmt);
mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, context->aclkxctl);
mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, context->aclkrctl);
mcasp_set_reg(mcasp, DAVINCI_MCASP_PDIR_REG, context->pdir);
return 0;
}
#else
#define davinci_mcasp_suspend NULL
#define davinci_mcasp_resume NULL
#endif
#define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_192000
#define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \
@ -735,6 +792,8 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
{
.name = "davinci-mcasp.0",
.suspend = davinci_mcasp_suspend,
.resume = davinci_mcasp_resume,
.playback = {
.channels_min = 2,
.channels_max = 32 * 16,
@ -768,28 +827,28 @@ static const struct snd_soc_component_driver davinci_mcasp_component = {
};
/* Some HW specific values and defaults. The rest is filled in from DT. */
static struct snd_platform_data dm646x_mcasp_pdata = {
static struct davinci_mcasp_pdata dm646x_mcasp_pdata = {
.tx_dma_offset = 0x400,
.rx_dma_offset = 0x400,
.asp_chan_q = EVENTQ_0,
.version = MCASP_VERSION_1,
};
static struct snd_platform_data da830_mcasp_pdata = {
static struct davinci_mcasp_pdata da830_mcasp_pdata = {
.tx_dma_offset = 0x2000,
.rx_dma_offset = 0x2000,
.asp_chan_q = EVENTQ_0,
.version = MCASP_VERSION_2,
};
static struct snd_platform_data am33xx_mcasp_pdata = {
static struct davinci_mcasp_pdata am33xx_mcasp_pdata = {
.tx_dma_offset = 0,
.rx_dma_offset = 0,
.asp_chan_q = EVENTQ_0,
.version = MCASP_VERSION_3,
};
static struct snd_platform_data dra7_mcasp_pdata = {
static struct davinci_mcasp_pdata dra7_mcasp_pdata = {
.tx_dma_offset = 0x200,
.rx_dma_offset = 0x284,
.asp_chan_q = EVENTQ_0,
@ -857,11 +916,11 @@ err1:
return ret;
}
static struct snd_platform_data *davinci_mcasp_set_pdata_from_of(
static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of(
struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct snd_platform_data *pdata = NULL;
struct davinci_mcasp_pdata *pdata = NULL;
const struct of_device_id *match =
of_match_device(mcasp_dt_ids, &pdev->dev);
struct of_phandle_args dma_spec;
@ -874,7 +933,7 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of(
pdata = pdev->dev.platform_data;
return pdata;
} else if (match) {
pdata = (struct snd_platform_data *) match->data;
pdata = (struct davinci_mcasp_pdata*) match->data;
} else {
/* control shouldn't reach here. something is wrong */
ret = -EINVAL;
@ -966,9 +1025,9 @@ nodata:
static int davinci_mcasp_probe(struct platform_device *pdev)
{
struct davinci_pcm_dma_params *dma_data;
struct davinci_pcm_dma_params *dma_params;
struct resource *mem, *ioarea, *res, *dat;
struct snd_platform_data *pdata;
struct davinci_mcasp_pdata *pdata;
struct davinci_mcasp *mcasp;
int ret;
@ -1035,41 +1094,41 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
if (dat)
mcasp->dat_port = true;
dma_data = &mcasp->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
dma_data->asp_chan_q = pdata->asp_chan_q;
dma_data->ram_chan_q = pdata->ram_chan_q;
dma_data->sram_pool = pdata->sram_pool;
dma_data->sram_size = pdata->sram_size_playback;
dma_params = &mcasp->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
dma_params->asp_chan_q = pdata->asp_chan_q;
dma_params->ram_chan_q = pdata->ram_chan_q;
dma_params->sram_pool = pdata->sram_pool;
dma_params->sram_size = pdata->sram_size_playback;
if (dat)
dma_data->dma_addr = dat->start;
dma_params->dma_addr = dat->start;
else
dma_data->dma_addr = mem->start + pdata->tx_dma_offset;
dma_params->dma_addr = mem->start + pdata->tx_dma_offset;
/* Unconditional dmaengine stuff */
mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = dma_data->dma_addr;
mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = dma_params->dma_addr;
res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
if (res)
dma_data->channel = res->start;
dma_params->channel = res->start;
else
dma_data->channel = pdata->tx_dma_channel;
dma_params->channel = pdata->tx_dma_channel;
dma_data = &mcasp->dma_params[SNDRV_PCM_STREAM_CAPTURE];
dma_data->asp_chan_q = pdata->asp_chan_q;
dma_data->ram_chan_q = pdata->ram_chan_q;
dma_data->sram_pool = pdata->sram_pool;
dma_data->sram_size = pdata->sram_size_capture;
dma_params = &mcasp->dma_params[SNDRV_PCM_STREAM_CAPTURE];
dma_params->asp_chan_q = pdata->asp_chan_q;
dma_params->ram_chan_q = pdata->ram_chan_q;
dma_params->sram_pool = pdata->sram_pool;
dma_params->sram_size = pdata->sram_size_capture;
if (dat)
dma_data->dma_addr = dat->start;
dma_params->dma_addr = dat->start;
else
dma_data->dma_addr = mem->start + pdata->rx_dma_offset;
dma_params->dma_addr = mem->start + pdata->rx_dma_offset;
/* Unconditional dmaengine stuff */
mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = dma_data->dma_addr;
mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = dma_params->dma_addr;
if (mcasp->version < MCASP_VERSION_3) {
mcasp->fifo_base = DAVINCI_MCASP_V2_AFIFO_BASE;
/* dma_data->dma_addr is pointing to the data port address */
/* dma_params->dma_addr is pointing to the data port address */
mcasp->dat_port = true;
} else {
mcasp->fifo_base = DAVINCI_MCASP_V3_AFIFO_BASE;
@ -1077,9 +1136,9 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
if (res)
dma_data->channel = res->start;
dma_params->channel = res->start;
else
dma_data->channel = pdata->rx_dma_channel;
dma_params->channel = pdata->rx_dma_channel;
/* Unconditional dmaengine stuff */
mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].filter_data = "tx";
@ -1127,49 +1186,12 @@ static int davinci_mcasp_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int davinci_mcasp_suspend(struct device *dev)
{
struct davinci_mcasp *mcasp = dev_get_drvdata(dev);
mcasp->context.txfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG);
mcasp->context.rxfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG);
mcasp->context.txfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMT_REG);
mcasp->context.rxfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMT_REG);
mcasp->context.aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG);
mcasp->context.aclkrctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG);
mcasp->context.pdir = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG);
return 0;
}
static int davinci_mcasp_resume(struct device *dev)
{
struct davinci_mcasp *mcasp = dev_get_drvdata(dev);
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, mcasp->context.txfmtctl);
mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG, mcasp->context.rxfmtctl);
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMT_REG, mcasp->context.txfmt);
mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMT_REG, mcasp->context.rxfmt);
mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, mcasp->context.aclkxctl);
mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, mcasp->context.aclkrctl);
mcasp_set_reg(mcasp, DAVINCI_MCASP_PDIR_REG, mcasp->context.pdir);
return 0;
}
#endif
SIMPLE_DEV_PM_OPS(davinci_mcasp_pm_ops,
davinci_mcasp_suspend,
davinci_mcasp_resume);
static struct platform_driver davinci_mcasp_driver = {
.probe = davinci_mcasp_probe,
.remove = davinci_mcasp_remove,
.driver = {
.name = "davinci-mcasp",
.owner = THIS_MODULE,
.pm = &davinci_mcasp_pm_ops,
.of_match_table = mcasp_dt_ids,
},
};

View File

@ -1,5 +1,6 @@
config SND_SOC_FSL_SAI
tristate
select REGMAP_MMIO
select SND_SOC_GENERIC_DMAENGINE_PCM
config SND_SOC_FSL_SSI
@ -7,9 +8,11 @@ config SND_SOC_FSL_SSI
config SND_SOC_FSL_SPDIF
tristate
select REGMAP_MMIO
config SND_SOC_FSL_ESAI
tristate
select REGMAP_MMIO
config SND_SOC_FSL_UTILS
tristate
@ -168,12 +171,14 @@ config SND_SOC_EUKREA_TLV320
depends on MACH_EUKREA_MBIMX27_BASEBOARD \
|| MACH_EUKREA_MBIMXSD25_BASEBOARD \
|| MACH_EUKREA_MBIMXSD35_BASEBOARD \
|| MACH_EUKREA_MBIMXSD51_BASEBOARD
|| MACH_EUKREA_MBIMXSD51_BASEBOARD \
|| (OF && ARM)
depends on I2C
select SND_SOC_TLV320AIC23
select SND_SOC_IMX_PCM_FIQ
select SND_SOC_TLV320AIC23_I2C
select SND_SOC_IMX_AUDMUX
select SND_SOC_IMX_SSI
select SND_SOC_FSL_SSI
select SND_SOC_IMX_PCM_DMA
help
Enable I2S based access to the TLV320AIC23B codec attached
to the SSI interface
@ -204,7 +209,6 @@ config SND_SOC_IMX_SPDIF
tristate "SoC Audio support for i.MX boards with S/PDIF"
select SND_SOC_IMX_PCM_DMA
select SND_SOC_FSL_SPDIF
select REGMAP_MMIO
help
SoC Audio support for i.MX boards with S/PDIF
Say Y if you want to add support for SoC audio on an i.MX board with

View File

@ -15,8 +15,11 @@
*
*/
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/device.h>
#include <linux/i2c.h>
#include <sound/core.h>
@ -26,6 +29,7 @@
#include "../codecs/tlv320aic23.h"
#include "imx-ssi.h"
#include "fsl_ssi.h"
#include "imx-audmux.h"
#define CODEC_CLOCK 12000000
@ -41,7 +45,8 @@ static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream,
ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM);
if (ret) {
/* fsl_ssi lacks the set_fmt ops. */
if (ret && ret != -ENOTSUPP) {
dev_err(cpu_dai->dev,
"Failed to set the cpu dai format.\n");
return ret;
@ -63,11 +68,13 @@ static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream,
"Failed to set the codec sysclk.\n");
return ret;
}
snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffc, 0xffffffc, 2, 0);
ret = snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0,
SND_SOC_CLOCK_IN);
if (ret) {
/* fsl_ssi lacks the set_sysclk ops */
if (ret && ret != -EINVAL) {
dev_err(cpu_dai->dev,
"Can't set the IMX_SSP_SYS_CLK CPU system clock.\n");
return ret;
@ -84,14 +91,10 @@ static struct snd_soc_dai_link eukrea_tlv320_dai = {
.name = "tlv320aic23",
.stream_name = "TLV320AIC23",
.codec_dai_name = "tlv320aic23-hifi",
.platform_name = "imx-ssi.0",
.codec_name = "tlv320aic23-codec.0-001a",
.cpu_dai_name = "imx-ssi.0",
.ops = &eukrea_tlv320_snd_ops,
};
static struct snd_soc_card eukrea_tlv320 = {
.name = "cpuimx-audio",
.owner = THIS_MODULE,
.dai_link = &eukrea_tlv320_dai,
.num_links = 1,
@ -101,8 +104,65 @@ static int eukrea_tlv320_probe(struct platform_device *pdev)
{
int ret;
int int_port = 0, ext_port;
struct device_node *np = pdev->dev.of_node;
struct device_node *ssi_np, *codec_np;
if (machine_is_eukrea_cpuimx27()) {
eukrea_tlv320.dev = &pdev->dev;
if (np) {
ret = snd_soc_of_parse_card_name(&eukrea_tlv320,
"eukrea,model");
if (ret) {
dev_err(&pdev->dev,
"eukrea,model node missing or invalid.\n");
goto err;
}
ssi_np = of_parse_phandle(pdev->dev.of_node,
"ssi-controller", 0);
if (!ssi_np) {
dev_err(&pdev->dev,
"ssi-controller missing or invalid.\n");
ret = -ENODEV;
goto err;
}
codec_np = of_parse_phandle(ssi_np, "codec-handle", 0);
if (codec_np)
eukrea_tlv320_dai.codec_of_node = codec_np;
else
dev_err(&pdev->dev, "codec-handle node missing or invalid.\n");
ret = of_property_read_u32(np, "fsl,mux-int-port", &int_port);
if (ret) {
dev_err(&pdev->dev,
"fsl,mux-int-port node missing or invalid.\n");
return ret;
}
ret = of_property_read_u32(np, "fsl,mux-ext-port", &ext_port);
if (ret) {
dev_err(&pdev->dev,
"fsl,mux-ext-port node missing or invalid.\n");
return ret;
}
/*
* The port numbering in the hardware manual starts at 1, while
* the audmux API expects it starts at 0.
*/
int_port--;
ext_port--;
eukrea_tlv320_dai.cpu_of_node = ssi_np;
eukrea_tlv320_dai.platform_of_node = ssi_np;
} else {
eukrea_tlv320_dai.cpu_dai_name = "imx-ssi.0";
eukrea_tlv320_dai.platform_name = "imx-ssi.0";
eukrea_tlv320_dai.codec_name = "tlv320aic23-codec.0-001a";
eukrea_tlv320.name = "cpuimx-audio";
}
if (machine_is_eukrea_cpuimx27() ||
of_find_compatible_node(NULL, NULL, "fsl,imx21-audmux")) {
imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
IMX_AUDMUX_V1_PCR_SYN |
IMX_AUDMUX_V1_PCR_TFSDIR |
@ -119,8 +179,12 @@ static int eukrea_tlv320_probe(struct platform_device *pdev)
);
} else if (machine_is_eukrea_cpuimx25sd() ||
machine_is_eukrea_cpuimx35sd() ||
machine_is_eukrea_cpuimx51sd()) {
ext_port = machine_is_eukrea_cpuimx25sd() ? 4 : 3;
machine_is_eukrea_cpuimx51sd() ||
of_find_compatible_node(NULL, NULL, "fsl,imx31-audmux")) {
if (!np)
ext_port = machine_is_eukrea_cpuimx25sd() ?
4 : 3;
imx_audmux_v2_configure_port(int_port,
IMX_AUDMUX_V2_PTCR_SYN |
IMX_AUDMUX_V2_PTCR_TFSDIR |
@ -134,14 +198,27 @@ static int eukrea_tlv320_probe(struct platform_device *pdev)
IMX_AUDMUX_V2_PDCR_RXDSEL(int_port)
);
} else {
/* return happy. We might run on a totally different machine */
return 0;
if (np) {
/* The eukrea,asoc-tlv320 driver was explicitely
* requested (through the device tree).
*/
dev_err(&pdev->dev,
"Missing or invalid audmux DT node.\n");
return -ENODEV;
} else {
/* Return happy.
* We might run on a totally different machine.
*/
return 0;
}
}
eukrea_tlv320.dev = &pdev->dev;
ret = snd_soc_register_card(&eukrea_tlv320);
err:
if (ret)
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
if (np)
of_node_put(ssi_np);
return ret;
}
@ -153,10 +230,17 @@ static int eukrea_tlv320_remove(struct platform_device *pdev)
return 0;
}
static const struct of_device_id imx_tlv320_dt_ids[] = {
{ .compatible = "eukrea,asoc-tlv320"},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, imx_tlv320_dt_ids);
static struct platform_driver eukrea_tlv320_driver = {
.driver = {
.name = "eukrea_tlv320",
.owner = THIS_MODULE,
.of_match_table = imx_tlv320_dt_ids,
},
.probe = eukrea_tlv320_probe,
.remove = eukrea_tlv320_remove,

View File

@ -431,17 +431,26 @@ static int fsl_esai_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
static int fsl_esai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
int ret;
struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
/*
* Some platforms might use the same bit to gate all three or two of
* clocks, so keep all clocks open/close at the same time for safety
*/
clk_prepare_enable(esai_priv->coreclk);
if (!IS_ERR(esai_priv->extalclk))
clk_prepare_enable(esai_priv->extalclk);
if (!IS_ERR(esai_priv->fsysclk))
clk_prepare_enable(esai_priv->fsysclk);
ret = clk_prepare_enable(esai_priv->coreclk);
if (ret)
return ret;
if (!IS_ERR(esai_priv->extalclk)) {
ret = clk_prepare_enable(esai_priv->extalclk);
if (ret)
goto err_extalck;
}
if (!IS_ERR(esai_priv->fsysclk)) {
ret = clk_prepare_enable(esai_priv->fsysclk);
if (ret)
goto err_fsysclk;
}
if (!dai->active) {
/* Reset Port C */
@ -463,6 +472,14 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream,
}
return 0;
err_fsysclk:
if (!IS_ERR(esai_priv->extalclk))
clk_disable_unprepare(esai_priv->extalclk);
err_extalck:
clk_disable_unprepare(esai_priv->coreclk);
return ret;
}
static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
@ -661,7 +678,7 @@ static bool fsl_esai_writeable_reg(struct device *dev, unsigned int reg)
}
}
static const struct regmap_config fsl_esai_regmap_config = {
static struct regmap_config fsl_esai_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
@ -687,6 +704,9 @@ static int fsl_esai_probe(struct platform_device *pdev)
esai_priv->pdev = pdev;
strcpy(esai_priv->name, np->name);
if (of_property_read_bool(np, "big-endian"))
fsl_esai_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG;
/* Get the addresses and IRQ */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
regs = devm_ioremap_resource(&pdev->dev, res);

View File

@ -15,6 +15,7 @@
#include <linux/dmaengine.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/dmaengine_pcm.h>
@ -22,34 +23,6 @@
#include "fsl_sai.h"
static inline u32 sai_readl(struct fsl_sai *sai,
const void __iomem *addr)
{
u32 val;
val = __raw_readl(addr);
if (likely(sai->big_endian_regs))
val = be32_to_cpu(val);
else
val = le32_to_cpu(val);
rmb();
return val;
}
static inline void sai_writel(struct fsl_sai *sai,
u32 val, void __iomem *addr)
{
wmb();
if (likely(sai->big_endian_regs))
val = cpu_to_be32(val);
else
val = cpu_to_le32(val);
__raw_writel(val, addr);
}
static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
int clk_id, unsigned int freq, int fsl_dir)
{
@ -61,7 +34,8 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
else
reg_cr2 = FSL_SAI_RCR2;
val_cr2 = sai_readl(sai, sai->base + reg_cr2);
regmap_read(sai->regmap, reg_cr2, &val_cr2);
val_cr2 &= ~FSL_SAI_CR2_MSEL_MASK;
switch (clk_id) {
@ -81,7 +55,7 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
return -EINVAL;
}
sai_writel(sai, val_cr2, sai->base + reg_cr2);
regmap_write(sai->regmap, reg_cr2, val_cr2);
return 0;
}
@ -89,32 +63,22 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
static int fsl_sai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
int clk_id, unsigned int freq, int dir)
{
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
int ret;
if (dir == SND_SOC_CLOCK_IN)
return 0;
ret = clk_prepare_enable(sai->clk);
if (ret)
return ret;
ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq,
FSL_FMT_TRANSMITTER);
if (ret) {
dev_err(cpu_dai->dev, "Cannot set tx sysclk: %d\n", ret);
goto err_clk;
return ret;
}
ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq,
FSL_FMT_RECEIVER);
if (ret) {
if (ret)
dev_err(cpu_dai->dev, "Cannot set rx sysclk: %d\n", ret);
goto err_clk;
}
err_clk:
clk_disable_unprepare(sai->clk);
return ret;
}
@ -133,43 +97,84 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
reg_cr4 = FSL_SAI_RCR4;
}
val_cr2 = sai_readl(sai, sai->base + reg_cr2);
val_cr4 = sai_readl(sai, sai->base + reg_cr4);
regmap_read(sai->regmap, reg_cr2, &val_cr2);
regmap_read(sai->regmap, reg_cr4, &val_cr4);
if (sai->big_endian_data)
val_cr4 &= ~FSL_SAI_CR4_MF;
else
val_cr4 |= FSL_SAI_CR4_MF;
/* DAI mode */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
val_cr4 |= FSL_SAI_CR4_FSE;
/*
* Frame low, 1clk before data, one word length for frame sync,
* frame sync starts one serial clock cycle earlier,
* that is, together with the last bit of the previous
* data word.
*/
val_cr2 &= ~FSL_SAI_CR2_BCP;
val_cr4 |= FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP;
break;
case SND_SOC_DAIFMT_LEFT_J:
/*
* Frame high, one word length for frame sync,
* frame sync asserts with the first bit of the frame.
*/
val_cr2 &= ~FSL_SAI_CR2_BCP;
val_cr4 &= ~(FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP);
break;
case SND_SOC_DAIFMT_DSP_A:
/*
* Frame high, 1clk before data, one bit for frame sync,
* frame sync starts one serial clock cycle earlier,
* that is, together with the last bit of the previous
* data word.
*/
val_cr2 &= ~FSL_SAI_CR2_BCP;
val_cr4 &= ~FSL_SAI_CR4_FSP;
val_cr4 |= FSL_SAI_CR4_FSE;
sai->is_dsp_mode = true;
break;
case SND_SOC_DAIFMT_DSP_B:
/*
* Frame high, one bit for frame sync,
* frame sync asserts with the first bit of the frame.
*/
val_cr2 &= ~FSL_SAI_CR2_BCP;
val_cr4 &= ~(FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP);
sai->is_dsp_mode = true;
break;
case SND_SOC_DAIFMT_RIGHT_J:
/* To be done */
default:
return -EINVAL;
}
/* DAI clock inversion */
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_IB_IF:
val_cr4 |= FSL_SAI_CR4_FSP;
val_cr2 &= ~FSL_SAI_CR2_BCP;
/* Invert both clocks */
val_cr2 ^= FSL_SAI_CR2_BCP;
val_cr4 ^= FSL_SAI_CR4_FSP;
break;
case SND_SOC_DAIFMT_IB_NF:
val_cr4 &= ~FSL_SAI_CR4_FSP;
val_cr2 &= ~FSL_SAI_CR2_BCP;
/* Invert bit clock */
val_cr2 ^= FSL_SAI_CR2_BCP;
break;
case SND_SOC_DAIFMT_NB_IF:
val_cr4 |= FSL_SAI_CR4_FSP;
val_cr2 |= FSL_SAI_CR2_BCP;
/* Invert frame clock */
val_cr4 ^= FSL_SAI_CR4_FSP;
break;
case SND_SOC_DAIFMT_NB_NF:
val_cr4 &= ~FSL_SAI_CR4_FSP;
val_cr2 |= FSL_SAI_CR2_BCP;
/* Nothing to do for both normal cases */
break;
default:
return -EINVAL;
}
/* DAI clock master masks */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
val_cr2 |= FSL_SAI_CR2_BCD_MSTR;
@ -179,39 +184,37 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR;
val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR;
break;
case SND_SOC_DAIFMT_CBS_CFM:
val_cr2 |= FSL_SAI_CR2_BCD_MSTR;
val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR;
break;
case SND_SOC_DAIFMT_CBM_CFS:
val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR;
val_cr4 |= FSL_SAI_CR4_FSD_MSTR;
break;
default:
return -EINVAL;
}
sai_writel(sai, val_cr2, sai->base + reg_cr2);
sai_writel(sai, val_cr4, sai->base + reg_cr4);
regmap_write(sai->regmap, reg_cr2, val_cr2);
regmap_write(sai->regmap, reg_cr4, val_cr4);
return 0;
}
static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
{
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
int ret;
ret = clk_prepare_enable(sai->clk);
if (ret)
return ret;
ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_TRANSMITTER);
if (ret) {
dev_err(cpu_dai->dev, "Cannot set tx format: %d\n", ret);
goto err_clk;
return ret;
}
ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_RECEIVER);
if (ret) {
if (ret)
dev_err(cpu_dai->dev, "Cannot set rx format: %d\n", ret);
goto err_clk;
}
err_clk:
clk_disable_unprepare(sai->clk);
return ret;
}
@ -235,16 +238,19 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
reg_mr = FSL_SAI_RMR;
}
val_cr4 = sai_readl(sai, sai->base + reg_cr4);
regmap_read(sai->regmap, reg_cr4, &val_cr4);
regmap_read(sai->regmap, reg_cr4, &val_cr5);
val_cr4 &= ~FSL_SAI_CR4_SYWD_MASK;
val_cr4 &= ~FSL_SAI_CR4_FRSZ_MASK;
val_cr5 = sai_readl(sai, sai->base + reg_cr5);
val_cr5 &= ~FSL_SAI_CR5_WNW_MASK;
val_cr5 &= ~FSL_SAI_CR5_W0W_MASK;
val_cr5 &= ~FSL_SAI_CR5_FBT_MASK;
val_cr4 |= FSL_SAI_CR4_SYWD(word_width);
if (!sai->is_dsp_mode)
val_cr4 |= FSL_SAI_CR4_SYWD(word_width);
val_cr5 |= FSL_SAI_CR5_WNW(word_width);
val_cr5 |= FSL_SAI_CR5_W0W(word_width);
@ -257,9 +263,9 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
val_cr4 |= FSL_SAI_CR4_FRSZ(channels);
val_mr = ~0UL - ((1 << channels) - 1);
sai_writel(sai, val_cr4, sai->base + reg_cr4);
sai_writel(sai, val_cr5, sai->base + reg_cr5);
sai_writel(sai, val_mr, sai->base + reg_mr);
regmap_write(sai->regmap, reg_cr4, val_cr4);
regmap_write(sai->regmap, reg_cr5, val_cr5);
regmap_write(sai->regmap, reg_mr, val_mr);
return 0;
}
@ -268,44 +274,42 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *cpu_dai)
{
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
u32 tcsr, rcsr, val_cr2, val_cr3, reg_cr3;
u32 tcsr, rcsr;
val_cr2 = sai_readl(sai, sai->base + FSL_SAI_TCR2);
val_cr2 &= ~FSL_SAI_CR2_SYNC;
sai_writel(sai, val_cr2, sai->base + FSL_SAI_TCR2);
/*
* The transmitter bit clock and frame sync are to be
* used by both the transmitter and receiver.
*/
regmap_update_bits(sai->regmap, FSL_SAI_TCR2, FSL_SAI_CR2_SYNC,
~FSL_SAI_CR2_SYNC);
regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC,
FSL_SAI_CR2_SYNC);
val_cr2 = sai_readl(sai, sai->base + FSL_SAI_RCR2);
val_cr2 |= FSL_SAI_CR2_SYNC;
sai_writel(sai, val_cr2, sai->base + FSL_SAI_RCR2);
tcsr = sai_readl(sai, sai->base + FSL_SAI_TCSR);
rcsr = sai_readl(sai, sai->base + FSL_SAI_RCSR);
regmap_read(sai->regmap, FSL_SAI_TCSR, &tcsr);
regmap_read(sai->regmap, FSL_SAI_RCSR, &rcsr);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
tcsr |= FSL_SAI_CSR_FRDE;
rcsr &= ~FSL_SAI_CSR_FRDE;
reg_cr3 = FSL_SAI_TCR3;
} else {
rcsr |= FSL_SAI_CSR_FRDE;
tcsr &= ~FSL_SAI_CSR_FRDE;
reg_cr3 = FSL_SAI_RCR3;
}
val_cr3 = sai_readl(sai, sai->base + reg_cr3);
/*
* It is recommended that the transmitter is the last enabled
* and the first disabled.
*/
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
tcsr |= FSL_SAI_CSR_TERE;
rcsr |= FSL_SAI_CSR_TERE;
val_cr3 |= FSL_SAI_CR3_TRCE;
sai_writel(sai, val_cr3, sai->base + reg_cr3);
sai_writel(sai, rcsr, sai->base + FSL_SAI_RCSR);
sai_writel(sai, tcsr, sai->base + FSL_SAI_TCSR);
regmap_write(sai->regmap, FSL_SAI_RCSR, rcsr);
regmap_write(sai->regmap, FSL_SAI_TCSR, tcsr);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@ -314,11 +318,8 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
rcsr &= ~FSL_SAI_CSR_TERE;
}
val_cr3 &= ~FSL_SAI_CR3_TRCE;
sai_writel(sai, tcsr, sai->base + FSL_SAI_TCSR);
sai_writel(sai, rcsr, sai->base + FSL_SAI_RCSR);
sai_writel(sai, val_cr3, sai->base + reg_cr3);
regmap_write(sai->regmap, FSL_SAI_TCSR, tcsr);
regmap_write(sai->regmap, FSL_SAI_RCSR, rcsr);
break;
default:
return -EINVAL;
@ -331,16 +332,32 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
u32 reg;
return clk_prepare_enable(sai->clk);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
reg = FSL_SAI_TCR3;
else
reg = FSL_SAI_RCR3;
regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE,
FSL_SAI_CR3_TRCE);
return 0;
}
static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
u32 reg;
clk_disable_unprepare(sai->clk);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
reg = FSL_SAI_TCR3;
else
reg = FSL_SAI_RCR3;
regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE,
~FSL_SAI_CR3_TRCE);
}
static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
@ -355,18 +372,13 @@ static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
{
struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
int ret;
ret = clk_prepare_enable(sai->clk);
if (ret)
return ret;
sai_writel(sai, 0x0, sai->base + FSL_SAI_RCSR);
sai_writel(sai, 0x0, sai->base + FSL_SAI_TCSR);
sai_writel(sai, FSL_SAI_MAXBURST_TX * 2, sai->base + FSL_SAI_TCR1);
sai_writel(sai, FSL_SAI_MAXBURST_RX - 1, sai->base + FSL_SAI_RCR1);
clk_disable_unprepare(sai->clk);
regmap_update_bits(sai->regmap, FSL_SAI_TCSR, 0xffffffff, 0x0);
regmap_update_bits(sai->regmap, FSL_SAI_RCSR, 0xffffffff, 0x0);
regmap_update_bits(sai->regmap, FSL_SAI_TCR1, FSL_SAI_CR1_RFW_MASK,
FSL_SAI_MAXBURST_TX * 2);
regmap_update_bits(sai->regmap, FSL_SAI_RCR1, FSL_SAI_CR1_RFW_MASK,
FSL_SAI_MAXBURST_RX - 1);
snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx,
&sai->dma_params_rx);
@ -397,26 +409,109 @@ static const struct snd_soc_component_driver fsl_component = {
.name = "fsl-sai",
};
static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case FSL_SAI_TCSR:
case FSL_SAI_TCR1:
case FSL_SAI_TCR2:
case FSL_SAI_TCR3:
case FSL_SAI_TCR4:
case FSL_SAI_TCR5:
case FSL_SAI_TFR:
case FSL_SAI_TMR:
case FSL_SAI_RCSR:
case FSL_SAI_RCR1:
case FSL_SAI_RCR2:
case FSL_SAI_RCR3:
case FSL_SAI_RCR4:
case FSL_SAI_RCR5:
case FSL_SAI_RDR:
case FSL_SAI_RFR:
case FSL_SAI_RMR:
return true;
default:
return false;
}
}
static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case FSL_SAI_TFR:
case FSL_SAI_RFR:
case FSL_SAI_TDR:
case FSL_SAI_RDR:
return true;
default:
return false;
}
}
static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case FSL_SAI_TCSR:
case FSL_SAI_TCR1:
case FSL_SAI_TCR2:
case FSL_SAI_TCR3:
case FSL_SAI_TCR4:
case FSL_SAI_TCR5:
case FSL_SAI_TDR:
case FSL_SAI_TMR:
case FSL_SAI_RCSR:
case FSL_SAI_RCR1:
case FSL_SAI_RCR2:
case FSL_SAI_RCR3:
case FSL_SAI_RCR4:
case FSL_SAI_RCR5:
case FSL_SAI_RMR:
return true;
default:
return false;
}
}
static struct regmap_config fsl_sai_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = FSL_SAI_RMR,
.readable_reg = fsl_sai_readable_reg,
.volatile_reg = fsl_sai_volatile_reg,
.writeable_reg = fsl_sai_writeable_reg,
};
static int fsl_sai_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct fsl_sai *sai;
struct resource *res;
void __iomem *base;
int ret;
sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
if (!sai)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
sai->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(sai->base))
return PTR_ERR(sai->base);
sai->big_endian_regs = of_property_read_bool(np, "big-endian-regs");
if (sai->big_endian_regs)
fsl_sai_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG;
sai->clk = devm_clk_get(&pdev->dev, "sai");
if (IS_ERR(sai->clk)) {
dev_err(&pdev->dev, "Cannot get SAI's clock\n");
return PTR_ERR(sai->clk);
sai->big_endian_data = of_property_read_bool(np, "big-endian-data");
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
"sai", base, &fsl_sai_regmap_config);
if (IS_ERR(sai->regmap)) {
dev_err(&pdev->dev, "regmap init failed\n");
return PTR_ERR(sai->regmap);
}
sai->dma_params_rx.addr = res->start + FSL_SAI_RDR;
@ -424,9 +519,6 @@ static int fsl_sai_probe(struct platform_device *pdev)
sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX;
sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX;
sai->big_endian_regs = of_property_read_bool(np, "big-endian-regs");
sai->big_endian_data = of_property_read_bool(np, "big-endian-data");
platform_set_drvdata(pdev, sai);
ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component,

View File

@ -15,31 +15,36 @@
SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE)
/* SAI Register Map Register */
#define FSL_SAI_TCSR 0x00 /* SAI Transmit Control */
#define FSL_SAI_TCR1 0x04 /* SAI Transmit Configuration 1 */
#define FSL_SAI_TCR2 0x08 /* SAI Transmit Configuration 2 */
#define FSL_SAI_TCR3 0x0c /* SAI Transmit Configuration 3 */
#define FSL_SAI_TCR4 0x10 /* SAI Transmit Configuration 4 */
#define FSL_SAI_TCR5 0x14 /* SAI Transmit Configuration 5 */
#define FSL_SAI_TDR 0x20 /* SAI Transmit Data */
#define FSL_SAI_TFR 0x40 /* SAI Transmit FIFO */
#define FSL_SAI_TMR 0x60 /* SAI Transmit Mask */
#define FSL_SAI_RCSR 0x80 /* SAI Receive Control */
#define FSL_SAI_RCR1 0x84 /* SAI Receive Configuration 1 */
#define FSL_SAI_RCR2 0x88 /* SAI Receive Configuration 2 */
#define FSL_SAI_RCR3 0x8c /* SAI Receive Configuration 3 */
#define FSL_SAI_RCR4 0x90 /* SAI Receive Configuration 4 */
#define FSL_SAI_RCR5 0x94 /* SAI Receive Configuration 5 */
#define FSL_SAI_RDR 0xa0 /* SAI Receive Data */
#define FSL_SAI_RFR 0xc0 /* SAI Receive FIFO */
#define FSL_SAI_RMR 0xe0 /* SAI Receive Mask */
/* SAI Transmit/Recieve Control Register */
#define FSL_SAI_TCSR 0x00
#define FSL_SAI_RCSR 0x80
#define FSL_SAI_CSR_TERE BIT(31)
#define FSL_SAI_CSR_FWF BIT(17)
#define FSL_SAI_CSR_FRIE BIT(8)
#define FSL_SAI_CSR_FRDE BIT(0)
/* SAI Transmit Data/FIFO/MASK Register */
#define FSL_SAI_TDR 0x20
#define FSL_SAI_TFR 0x40
#define FSL_SAI_TMR 0x60
/* SAI Recieve Data/FIFO/MASK Register */
#define FSL_SAI_RDR 0xa0
#define FSL_SAI_RFR 0xc0
#define FSL_SAI_RMR 0xe0
/* SAI Transmit and Recieve Configuration 1 Register */
#define FSL_SAI_TCR1 0x04
#define FSL_SAI_RCR1 0x84
#define FSL_SAI_CR1_RFW_MASK 0x1f
/* SAI Transmit and Recieve Configuration 2 Register */
#define FSL_SAI_TCR2 0x08
#define FSL_SAI_RCR2 0x88
#define FSL_SAI_CR2_SYNC BIT(30)
#define FSL_SAI_CR2_MSEL_MASK (0xff << 26)
#define FSL_SAI_CR2_MSEL_BUS 0
@ -50,15 +55,11 @@
#define FSL_SAI_CR2_BCD_MSTR BIT(24)
/* SAI Transmit and Recieve Configuration 3 Register */
#define FSL_SAI_TCR3 0x0c
#define FSL_SAI_RCR3 0x8c
#define FSL_SAI_CR3_TRCE BIT(16)
#define FSL_SAI_CR3_WDFL(x) (x)
#define FSL_SAI_CR3_WDFL_MASK 0x1f
/* SAI Transmit and Recieve Configuration 4 Register */
#define FSL_SAI_TCR4 0x10
#define FSL_SAI_RCR4 0x90
#define FSL_SAI_CR4_FRSZ(x) (((x) - 1) << 16)
#define FSL_SAI_CR4_FRSZ_MASK (0x1f << 16)
#define FSL_SAI_CR4_SYWD(x) (((x) - 1) << 8)
@ -69,8 +70,6 @@
#define FSL_SAI_CR4_FSD_MSTR BIT(0)
/* SAI Transmit and Recieve Configuration 5 Register */
#define FSL_SAI_TCR5 0x14
#define FSL_SAI_RCR5 0x94
#define FSL_SAI_CR5_WNW(x) (((x) - 1) << 24)
#define FSL_SAI_CR5_WNW_MASK (0x1f << 24)
#define FSL_SAI_CR5_W0W(x) (((x) - 1) << 16)
@ -100,12 +99,11 @@
#define FSL_SAI_MAXBURST_RX 6
struct fsl_sai {
struct clk *clk;
void __iomem *base;
struct regmap *regmap;
bool big_endian_regs;
bool big_endian_data;
bool is_dsp_mode;
struct snd_dmaengine_dai_dma_data dma_params_rx;
struct snd_dmaengine_dai_dma_data dma_params_tx;

View File

@ -911,8 +911,8 @@ static int fsl_spdif_dai_probe(struct snd_soc_dai *dai)
{
struct fsl_spdif_priv *spdif_private = snd_soc_dai_get_drvdata(dai);
dai->playback_dma_data = &spdif_private->dma_params_tx;
dai->capture_dma_data = &spdif_private->dma_params_rx;
snd_soc_dai_init_dma_data(dai, &spdif_private->dma_params_tx,
&spdif_private->dma_params_rx);
snd_soc_add_dai_controls(dai, fsl_spdif_ctrls, ARRAY_SIZE(fsl_spdif_ctrls));
@ -985,7 +985,7 @@ static bool fsl_spdif_writeable_reg(struct device *dev, unsigned int reg)
}
}
static const struct regmap_config fsl_spdif_regmap_config = {
static struct regmap_config fsl_spdif_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
@ -1105,6 +1105,9 @@ static int fsl_spdif_probe(struct platform_device *pdev)
memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai));
spdif_priv->cpu_dai_drv.name = spdif_priv->name;
if (of_property_read_bool(np, "big-endian"))
fsl_spdif_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG;
/* Get the addresses and IRQ */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
regs = devm_ioremap_resource(&pdev->dev, res);

View File

@ -270,18 +270,17 @@ static int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
ret = imx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
goto out;
return ret;
}
if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = imx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
if (ret)
goto out;
return ret;
}
out:
return ret;
return 0;
}
static int ssi_irq = 0;

View File

@ -214,12 +214,6 @@ static int wm1133_ev1_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
snd_soc_dapm_new_controls(dapm, wm1133_ev1_widgets,
ARRAY_SIZE(wm1133_ev1_widgets));
snd_soc_dapm_add_routes(dapm, wm1133_ev1_map,
ARRAY_SIZE(wm1133_ev1_map));
/* Headphone jack detection */
snd_soc_jack_new(codec, "Headphone", SND_JACK_HEADPHONE, &hp_jack);
snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins),
@ -257,6 +251,11 @@ static struct snd_soc_card wm1133_ev1 = {
.owner = THIS_MODULE,
.dai_link = &wm1133_ev1_dai,
.num_links = 1,
.dapm_widgets = wm1133_ev1_widgets,
.num_dapm_widgets = ARRAY_SIZE(wm1133_ev1_widgets),
.dapm_routes = wm1133_ev1_map,
.num_dapm_routes = ARRAY_SIZE(wm1133_ev1_map),
};
static struct platform_device *wm1133_ev1_snd_device;

View File

@ -58,7 +58,7 @@ config SND_OMAP_SOC_OSK5912
tristate "SoC Audio support for omap osk5912"
depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C
select SND_OMAP_SOC_MCBSP
select SND_SOC_TLV320AIC23
select SND_SOC_TLV320AIC23_I2C
help
Say Y if you want to add support for SoC audio on osk5912.
@ -66,7 +66,7 @@ config SND_OMAP_SOC_AM3517EVM
tristate "SoC Audio support for OMAP3517 / AM3517 EVM"
depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C
select SND_OMAP_SOC_MCBSP
select SND_SOC_TLV320AIC23
select SND_SOC_TLV320AIC23_I2C
help
Say Y if you want to add support for SoC audio on the OMAP3517 / AM3517
EVM.

View File

@ -117,7 +117,7 @@ config SND_SOC_SAMSUNG_SIMTEC_TLV320AIC23
tristate "SoC I2S Audio support for TLV320AIC23 on Simtec boards"
depends on SND_SOC_SAMSUNG && ARCH_S3C24XX
select SND_S3C24XX_I2S
select SND_SOC_TLV320AIC23
select SND_SOC_TLV320AIC23_I2C
select SND_SOC_SAMSUNG_SIMTEC
config SND_SOC_SAMSUNG_SIMTEC_HERMES

View File

@ -105,7 +105,7 @@ config SND_SOC_TEGRA_TRIMSLICE
tristate "SoC Audio support for TrimSlice board"
depends on SND_SOC_TEGRA && I2C
select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
select SND_SOC_TLV320AIC23
select SND_SOC_TLV320AIC23_I2C
help
Say Y or M here if you want to add support for SoC audio on the
TrimSlice platform.