Commit 6681bc0d authored by Takashi Iwai's avatar Takashi Iwai

Merge tag 'asoc-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus

Last minute ASoC updates for 3.4

There's a couple of small features here that were added late on but have
been in -next in my tree and some bug fixes.  The wm_hubs stuff is
actually bug fixes - the stuff that's currently in 3.4 is a half way
house between the two solutions that the latest change allows the
machine to select between.
parents ca3e9297 22f8d055
...@@ -777,13 +777,15 @@ static void vmid_reference(struct snd_soc_codec *codec) ...@@ -777,13 +777,15 @@ static void vmid_reference(struct snd_soc_codec *codec)
if (wm8994->vmid_refcount == 1) { if (wm8994->vmid_refcount == 1) {
snd_soc_update_bits(codec, WM8994_ANTIPOP_1, snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
WM8994_LINEOUT_VMID_BUF_ENA |
WM8994_LINEOUT1_DISCH | WM8994_LINEOUT1_DISCH |
WM8994_LINEOUT2_DISCH, WM8994_LINEOUT2_DISCH, 0);
WM8994_LINEOUT_VMID_BUF_ENA);
wm_hubs_vmid_ena(codec); wm_hubs_vmid_ena(codec);
switch (wm8994->vmid_mode) {
default:
WARN_ON(0 == "Invalid VMID mode");
case WM8994_VMID_NORMAL:
/* Startup bias, VMID ramp & buffer */ /* Startup bias, VMID ramp & buffer */
snd_soc_update_bits(codec, WM8994_ANTIPOP_2, snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
WM8994_BIAS_SRC | WM8994_BIAS_SRC |
...@@ -794,7 +796,7 @@ static void vmid_reference(struct snd_soc_codec *codec) ...@@ -794,7 +796,7 @@ static void vmid_reference(struct snd_soc_codec *codec)
WM8994_BIAS_SRC | WM8994_BIAS_SRC |
WM8994_STARTUP_BIAS_ENA | WM8994_STARTUP_BIAS_ENA |
WM8994_VMID_BUF_ENA | WM8994_VMID_BUF_ENA |
(0x2 << WM8994_VMID_RAMP_SHIFT)); (0x3 << WM8994_VMID_RAMP_SHIFT));
/* Main bias enable, VMID=2x40k */ /* Main bias enable, VMID=2x40k */
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
...@@ -805,8 +807,38 @@ static void vmid_reference(struct snd_soc_codec *codec) ...@@ -805,8 +807,38 @@ static void vmid_reference(struct snd_soc_codec *codec)
msleep(50); msleep(50);
snd_soc_update_bits(codec, WM8994_ANTIPOP_2, snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
WM8994_VMID_RAMP_MASK | WM8994_BIAS_SRC, WM8994_VMID_RAMP_MASK |
WM8994_BIAS_SRC,
0); 0);
break;
case WM8994_VMID_FORCE:
/* Startup bias, slow VMID ramp & buffer */
snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
WM8994_BIAS_SRC |
WM8994_VMID_DISCH |
WM8994_STARTUP_BIAS_ENA |
WM8994_VMID_BUF_ENA |
WM8994_VMID_RAMP_MASK,
WM8994_BIAS_SRC |
WM8994_STARTUP_BIAS_ENA |
WM8994_VMID_BUF_ENA |
(0x2 << WM8994_VMID_RAMP_SHIFT));
/* Main bias enable, VMID=2x40k */
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
WM8994_BIAS_ENA |
WM8994_VMID_SEL_MASK,
WM8994_BIAS_ENA | 0x2);
msleep(400);
snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
WM8994_VMID_RAMP_MASK |
WM8994_BIAS_SRC,
0);
break;
}
} }
} }
...@@ -820,34 +852,55 @@ static void vmid_dereference(struct snd_soc_codec *codec) ...@@ -820,34 +852,55 @@ static void vmid_dereference(struct snd_soc_codec *codec)
wm8994->vmid_refcount); wm8994->vmid_refcount);
if (wm8994->vmid_refcount == 0) { if (wm8994->vmid_refcount == 0) {
/* Switch over to startup biases */ if (wm8994->hubs.lineout1_se)
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3,
WM8994_LINEOUT1N_ENA |
WM8994_LINEOUT1P_ENA,
WM8994_LINEOUT1N_ENA |
WM8994_LINEOUT1P_ENA);
if (wm8994->hubs.lineout2_se)
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3,
WM8994_LINEOUT2N_ENA |
WM8994_LINEOUT2P_ENA,
WM8994_LINEOUT2N_ENA |
WM8994_LINEOUT2P_ENA);
/* Start discharging VMID */
snd_soc_update_bits(codec, WM8994_ANTIPOP_2, snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
WM8994_BIAS_SRC | WM8994_BIAS_SRC |
WM8994_STARTUP_BIAS_ENA | WM8994_VMID_DISCH,
WM8994_VMID_BUF_ENA |
WM8994_VMID_RAMP_MASK,
WM8994_BIAS_SRC | WM8994_BIAS_SRC |
WM8994_STARTUP_BIAS_ENA | WM8994_VMID_DISCH);
WM8994_VMID_BUF_ENA |
(1 << WM8994_VMID_RAMP_SHIFT));
/* Disable main biases */ switch (wm8994->vmid_mode) {
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, case WM8994_VMID_FORCE:
WM8994_BIAS_ENA | msleep(350);
WM8994_VMID_SEL_MASK, 0); break;
default:
break;
}
/* Discharge VMID */ snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL,
snd_soc_update_bits(codec, WM8994_ANTIPOP_2, WM8994_VROI, WM8994_VROI);
WM8994_VMID_DISCH, WM8994_VMID_DISCH);
/* Discharge line */ /* Active discharge */
snd_soc_update_bits(codec, WM8994_ANTIPOP_1, snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
WM8994_LINEOUT1_DISCH | WM8994_LINEOUT1_DISCH |
WM8994_LINEOUT2_DISCH, WM8994_LINEOUT2_DISCH,
WM8994_LINEOUT1_DISCH | WM8994_LINEOUT1_DISCH |
WM8994_LINEOUT2_DISCH); WM8994_LINEOUT2_DISCH);
msleep(5); msleep(150);
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3,
WM8994_LINEOUT1N_ENA |
WM8994_LINEOUT1P_ENA |
WM8994_LINEOUT2N_ENA |
WM8994_LINEOUT2P_ENA, 0);
snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL,
WM8994_VROI, 0);
/* Switch off startup biases */ /* Switch off startup biases */
snd_soc_update_bits(codec, WM8994_ANTIPOP_2, snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
...@@ -855,6 +908,12 @@ static void vmid_dereference(struct snd_soc_codec *codec) ...@@ -855,6 +908,12 @@ static void vmid_dereference(struct snd_soc_codec *codec)
WM8994_STARTUP_BIAS_ENA | WM8994_STARTUP_BIAS_ENA |
WM8994_VMID_BUF_ENA | WM8994_VMID_BUF_ENA |
WM8994_VMID_RAMP_MASK, 0); WM8994_VMID_RAMP_MASK, 0);
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
WM8994_BIAS_ENA | WM8994_VMID_SEL_MASK, 0);
snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
WM8994_VMID_RAMP_MASK, 0);
} }
pm_runtime_put(codec->dev); pm_runtime_put(codec->dev);
...@@ -2197,6 +2256,55 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, ...@@ -2197,6 +2256,55 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
return 0; return 0;
} }
int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
switch (mode) {
case WM8994_VMID_NORMAL:
if (wm8994->hubs.lineout1_se) {
snd_soc_dapm_disable_pin(&codec->dapm,
"LINEOUT1N Driver");
snd_soc_dapm_disable_pin(&codec->dapm,
"LINEOUT1P Driver");
}
if (wm8994->hubs.lineout2_se) {
snd_soc_dapm_disable_pin(&codec->dapm,
"LINEOUT2N Driver");
snd_soc_dapm_disable_pin(&codec->dapm,
"LINEOUT2P Driver");
}
/* Do the sync with the old mode to allow it to clean up */
snd_soc_dapm_sync(&codec->dapm);
wm8994->vmid_mode = mode;
break;
case WM8994_VMID_FORCE:
if (wm8994->hubs.lineout1_se) {
snd_soc_dapm_force_enable_pin(&codec->dapm,
"LINEOUT1N Driver");
snd_soc_dapm_force_enable_pin(&codec->dapm,
"LINEOUT1P Driver");
}
if (wm8994->hubs.lineout2_se) {
snd_soc_dapm_force_enable_pin(&codec->dapm,
"LINEOUT2N Driver");
snd_soc_dapm_force_enable_pin(&codec->dapm,
"LINEOUT2P Driver");
}
wm8994->vmid_mode = mode;
snd_soc_dapm_sync(&codec->dapm);
break;
default:
return -EINVAL;
}
return 0;
}
static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{ {
struct snd_soc_codec *codec = dai->codec; struct snd_soc_codec *codec = dai->codec;
...@@ -2819,6 +2927,7 @@ static int wm8994_codec_resume(struct snd_soc_codec *codec) ...@@ -2819,6 +2927,7 @@ static int wm8994_codec_resume(struct snd_soc_codec *codec)
WM1811_JACKDET_MODE_JACK); WM1811_JACKDET_MODE_JACK);
break; break;
} }
break;
case WM8958: case WM8958:
if (wm8994->jack_cb) if (wm8994->jack_cb)
snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
......
...@@ -32,6 +32,11 @@ ...@@ -32,6 +32,11 @@
#define WM8994_FLL_SRC_LRCLK 3 #define WM8994_FLL_SRC_LRCLK 3
#define WM8994_FLL_SRC_BCLK 4 #define WM8994_FLL_SRC_BCLK 4
enum wm8994_vmid_mode {
WM8994_VMID_NORMAL,
WM8994_VMID_FORCE,
};
typedef void (*wm8958_micdet_cb)(u16 status, void *data); typedef void (*wm8958_micdet_cb)(u16 status, void *data);
int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
...@@ -39,6 +44,8 @@ int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, ...@@ -39,6 +44,8 @@ int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
wm8958_micdet_cb cb, void *cb_data); wm8958_micdet_cb cb, void *cb_data);
int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode);
int wm8958_aif_ev(struct snd_soc_dapm_widget *w, int wm8958_aif_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event); struct snd_kcontrol *kcontrol, int event);
...@@ -75,6 +82,7 @@ struct wm8994_priv { ...@@ -75,6 +82,7 @@ struct wm8994_priv {
int vmid_refcount; int vmid_refcount;
int active_refcount; int active_refcount;
enum wm8994_vmid_mode vmid_mode;
int dac_rates[2]; int dac_rates[2];
int lrclk_shared[2]; int lrclk_shared[2];
......
...@@ -1914,7 +1914,7 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream, ...@@ -1914,7 +1914,7 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream,
{ {
struct snd_soc_codec *codec = dai->codec; struct snd_soc_codec *codec = dai->codec;
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
int bits, i, bclk_rate; int bits, i, bclk_rate, best;
int aifdata = 0; int aifdata = 0;
int lrclk = 0; int lrclk = 0;
int dsp = 0; int dsp = 0;
...@@ -1963,14 +1963,11 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream, ...@@ -1963,14 +1963,11 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream,
return bits; return bits;
aifdata |= (bits << WM8996_AIF1TX_WL_SHIFT) | bits; aifdata |= (bits << WM8996_AIF1TX_WL_SHIFT) | bits;
best = 0;
for (i = 0; i < ARRAY_SIZE(dsp_divs); i++) { for (i = 0; i < ARRAY_SIZE(dsp_divs); i++) {
if (dsp_divs[i] == params_rate(params)) if (abs(dsp_divs[i] - params_rate(params)) <
break; abs(dsp_divs[best] - params_rate(params)))
} best = i;
if (i == ARRAY_SIZE(dsp_divs)) {
dev_err(codec->dev, "Unsupported sample rate %dHz\n",
params_rate(params));
return -EINVAL;
} }
dsp |= i << dsp_shift; dsp |= i << dsp_shift;
...@@ -2030,13 +2027,16 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai, ...@@ -2030,13 +2027,16 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai,
} }
switch (wm8996->sysclk) { switch (wm8996->sysclk) {
case 5644800:
case 6144000: case 6144000:
snd_soc_update_bits(codec, WM8996_AIF_RATE, snd_soc_update_bits(codec, WM8996_AIF_RATE,
WM8996_SYSCLK_RATE, 0); WM8996_SYSCLK_RATE, 0);
break; break;
case 22579200:
case 24576000: case 24576000:
ratediv = WM8996_SYSCLK_DIV; ratediv = WM8996_SYSCLK_DIV;
wm8996->sysclk /= 2; wm8996->sysclk /= 2;
case 11289600:
case 12288000: case 12288000:
snd_soc_update_bits(codec, WM8996_AIF_RATE, snd_soc_update_bits(codec, WM8996_AIF_RATE,
WM8996_SYSCLK_RATE, WM8996_SYSCLK_RATE); WM8996_SYSCLK_RATE, WM8996_SYSCLK_RATE);
...@@ -3060,7 +3060,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8996 = { ...@@ -3060,7 +3060,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8996 = {
}; };
#define WM8996_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ #define WM8996_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000) SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
SNDRV_PCM_RATE_48000)
#define WM8996_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ #define WM8996_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |\ SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |\
SNDRV_PCM_FMTBIT_S32_LE) SNDRV_PCM_FMTBIT_S32_LE)
......
...@@ -643,8 +643,6 @@ SND_SOC_DAPM_INPUT("IN2RP:VXRP"), ...@@ -643,8 +643,6 @@ SND_SOC_DAPM_INPUT("IN2RP:VXRP"),
SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("LINEOUT_VMID_BUF", WM8993_ANTIPOP1, 7, 0, NULL, 0),
SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0, SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0,
in1l_pga, ARRAY_SIZE(in1l_pga)), in1l_pga, ARRAY_SIZE(in1l_pga)),
SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0, SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0,
...@@ -869,11 +867,9 @@ static const struct snd_soc_dapm_route lineout1_diff_routes[] = { ...@@ -869,11 +867,9 @@ static const struct snd_soc_dapm_route lineout1_diff_routes[] = {
}; };
static const struct snd_soc_dapm_route lineout1_se_routes[] = { static const struct snd_soc_dapm_route lineout1_se_routes[] = {
{ "LINEOUT1N Mixer", NULL, "LINEOUT_VMID_BUF" },
{ "LINEOUT1N Mixer", "Left Output Switch", "Left Output PGA" }, { "LINEOUT1N Mixer", "Left Output Switch", "Left Output PGA" },
{ "LINEOUT1N Mixer", "Right Output Switch", "Right Output PGA" }, { "LINEOUT1N Mixer", "Right Output Switch", "Right Output PGA" },
{ "LINEOUT1P Mixer", NULL, "LINEOUT_VMID_BUF" },
{ "LINEOUT1P Mixer", "Left Output Switch", "Left Output PGA" }, { "LINEOUT1P Mixer", "Left Output Switch", "Left Output PGA" },
{ "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" }, { "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" },
...@@ -890,11 +886,9 @@ static const struct snd_soc_dapm_route lineout2_diff_routes[] = { ...@@ -890,11 +886,9 @@ static const struct snd_soc_dapm_route lineout2_diff_routes[] = {
}; };
static const struct snd_soc_dapm_route lineout2_se_routes[] = { static const struct snd_soc_dapm_route lineout2_se_routes[] = {
{ "LINEOUT2N Mixer", NULL, "LINEOUT_VMID_BUF" },
{ "LINEOUT2N Mixer", "Left Output Switch", "Left Output PGA" }, { "LINEOUT2N Mixer", "Left Output Switch", "Left Output PGA" },
{ "LINEOUT2N Mixer", "Right Output Switch", "Right Output PGA" }, { "LINEOUT2N Mixer", "Right Output Switch", "Right Output PGA" },
{ "LINEOUT2P Mixer", NULL, "LINEOUT_VMID_BUF" },
{ "LINEOUT2P Mixer", "Right Output Switch", "Right Output PGA" }, { "LINEOUT2P Mixer", "Right Output Switch", "Right Output PGA" },
{ "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" }, { "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" },
...@@ -996,6 +990,11 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec, ...@@ -996,6 +990,11 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec,
WM8993_LINEOUT2_MODE, WM8993_LINEOUT2_MODE,
WM8993_LINEOUT2_MODE); WM8993_LINEOUT2_MODE);
if (!lineout1_diff && !lineout2_diff)
snd_soc_update_bits(codec, WM8993_ANTIPOP1,
WM8993_LINEOUT_VMID_BUF_ENA,
WM8993_LINEOUT_VMID_BUF_ENA);
if (lineout1fb) if (lineout1fb)
snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL, snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB); WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB);
...@@ -1068,11 +1067,6 @@ void wm_hubs_set_bias_level(struct snd_soc_codec *codec, ...@@ -1068,11 +1067,6 @@ void wm_hubs_set_bias_level(struct snd_soc_codec *codec,
WM8993_LINEOUT2P_ENA, WM8993_LINEOUT2P_ENA,
val); val);
if (!hubs->lineout1n_ena && !hubs->lineout1p_ena &&
!hubs->lineout2n_ena && !hubs->lineout2p_ena)
snd_soc_update_bits(codec, WM8993_ANTIPOP1,
WM8993_LINEOUT_VMID_BUF_ENA, 0);
/* Remove the input clamps */ /* Remove the input clamps */
snd_soc_update_bits(codec, WM8993_INPUTS_CLAMP_REG, snd_soc_update_bits(codec, WM8993_INPUTS_CLAMP_REG,
WM8993_INPUTS_CLAMP, 0); WM8993_INPUTS_CLAMP, 0);
......
...@@ -395,7 +395,8 @@ static int p1022_ds_probe(struct platform_device *pdev) ...@@ -395,7 +395,8 @@ static int p1022_ds_probe(struct platform_device *pdev)
} }
if (strcasecmp(sprop, "i2s-slave") == 0) { if (strcasecmp(sprop, "i2s-slave") == 0) {
mdata->dai_format = SND_SOC_DAIFMT_I2S; mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM;
mdata->codec_clk_direction = SND_SOC_CLOCK_OUT; mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
mdata->cpu_clk_direction = SND_SOC_CLOCK_IN; mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
...@@ -412,31 +413,38 @@ static int p1022_ds_probe(struct platform_device *pdev) ...@@ -412,31 +413,38 @@ static int p1022_ds_probe(struct platform_device *pdev)
} }
mdata->clk_frequency = be32_to_cpup(iprop); mdata->clk_frequency = be32_to_cpup(iprop);
} else if (strcasecmp(sprop, "i2s-master") == 0) { } else if (strcasecmp(sprop, "i2s-master") == 0) {
mdata->dai_format = SND_SOC_DAIFMT_I2S; mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS;
mdata->codec_clk_direction = SND_SOC_CLOCK_IN; mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT; mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
} else if (strcasecmp(sprop, "lj-slave") == 0) { } else if (strcasecmp(sprop, "lj-slave") == 0) {
mdata->dai_format = SND_SOC_DAIFMT_LEFT_J; mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM;
mdata->codec_clk_direction = SND_SOC_CLOCK_OUT; mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
mdata->cpu_clk_direction = SND_SOC_CLOCK_IN; mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
} else if (strcasecmp(sprop, "lj-master") == 0) { } else if (strcasecmp(sprop, "lj-master") == 0) {
mdata->dai_format = SND_SOC_DAIFMT_LEFT_J; mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBS_CFS;
mdata->codec_clk_direction = SND_SOC_CLOCK_IN; mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT; mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
} else if (strcasecmp(sprop, "rj-slave") == 0) { } else if (strcasecmp(sprop, "rj-slave") == 0) {
mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J; mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBM_CFM;
mdata->codec_clk_direction = SND_SOC_CLOCK_OUT; mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
mdata->cpu_clk_direction = SND_SOC_CLOCK_IN; mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
} else if (strcasecmp(sprop, "rj-master") == 0) { } else if (strcasecmp(sprop, "rj-master") == 0) {
mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J; mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBS_CFS;
mdata->codec_clk_direction = SND_SOC_CLOCK_IN; mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT; mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
} else if (strcasecmp(sprop, "ac97-slave") == 0) { } else if (strcasecmp(sprop, "ac97-slave") == 0) {
mdata->dai_format = SND_SOC_DAIFMT_AC97; mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBM_CFM;
mdata->codec_clk_direction = SND_SOC_CLOCK_OUT; mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
mdata->cpu_clk_direction = SND_SOC_CLOCK_IN; mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
} else if (strcasecmp(sprop, "ac97-master") == 0) { } else if (strcasecmp(sprop, "ac97-master") == 0) {
mdata->dai_format = SND_SOC_DAIFMT_AC97; mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBS_CFS;
mdata->codec_clk_direction = SND_SOC_CLOCK_IN; mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT; mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
} else { } else {
......
...@@ -668,6 +668,38 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, ...@@ -668,6 +668,38 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
return 0; return 0;
} }
static void pxa_ssp_set_running_bit(struct snd_pcm_substream *substream,
struct ssp_device *ssp, int value)
{
uint32_t sscr0 = pxa_ssp_read_reg(ssp, SSCR0);
uint32_t sscr1 = pxa_ssp_read_reg(ssp, SSCR1);
uint32_t sspsp = pxa_ssp_read_reg(ssp, SSPSP);
uint32_t sssr = pxa_ssp_read_reg(ssp, SSSR);
if (value && (sscr0 & SSCR0_SSE))
pxa_ssp_write_reg(ssp, SSCR0, sscr0 & ~SSCR0_SSE);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (value)
sscr1 |= SSCR1_TSRE;
else
sscr1 &= ~SSCR1_TSRE;
} else {
if (value)
sscr1 |= SSCR1_RSRE;
else
sscr1 &= ~SSCR1_RSRE;
}
pxa_ssp_write_reg(ssp, SSCR1, sscr1);
if (value) {
pxa_ssp_write_reg(ssp, SSSR, sssr);
pxa_ssp_write_reg(ssp, SSPSP, sspsp);
pxa_ssp_write_reg(ssp, SSCR0, sscr0 | SSCR0_SSE);
}
}
static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *cpu_dai) struct snd_soc_dai *cpu_dai)
{ {
...@@ -681,42 +713,21 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -681,42 +713,21 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
pxa_ssp_enable(ssp); pxa_ssp_enable(ssp);
break; break;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
val = pxa_ssp_read_reg(ssp, SSCR1); pxa_ssp_set_running_bit(substream, ssp, 1);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
val |= SSCR1_TSRE;
else
val |= SSCR1_RSRE;
pxa_ssp_write_reg(ssp, SSCR1, val);
val = pxa_ssp_read_reg(ssp, SSSR); val = pxa_ssp_read_reg(ssp, SSSR);
pxa_ssp_write_reg(ssp, SSSR, val); pxa_ssp_write_reg(ssp, SSSR, val);
break; break;
case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_START:
val = pxa_ssp_read_reg(ssp, SSCR1); pxa_ssp_set_running_bit(substream, ssp, 1);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
val |= SSCR1_TSRE;
else
val |= SSCR1_RSRE;
pxa_ssp_write_reg(ssp, SSCR1, val);
pxa_ssp_enable(ssp);
break; break;
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
val = pxa_ssp_read_reg(ssp, SSCR1); pxa_ssp_set_running_bit(substream, ssp, 0);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
val &= ~SSCR1_TSRE;
else
val &= ~SSCR1_RSRE;
pxa_ssp_write_reg(ssp, SSCR1, val);
break; break;
case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_SUSPEND:
pxa_ssp_disable(ssp); pxa_ssp_disable(ssp);
break; break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
val = pxa_ssp_read_reg(ssp, SSCR1); pxa_ssp_set_running_bit(substream, ssp, 0);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
val &= ~SSCR1_TSRE;
else
val &= ~SSCR1_RSRE;
pxa_ssp_write_reg(ssp, SSCR1, val);
break; break;
default: default:
......
...@@ -559,6 +559,17 @@ static int i2s_hw_params(struct snd_pcm_substream *substream, ...@@ -559,6 +559,17 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
mod |= MOD_DC1_EN; mod |= MOD_DC1_EN;
break; break;
case 2: case 2:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
i2s->dma_playback.dma_size = 4;
else
i2s->dma_capture.dma_size = 4;
break;
case 1:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
i2s->dma_playback.dma_size = 2;
else
i2s->dma_capture.dma_size = 2;
break; break;
default: default:
dev_err(&i2s->pdev->dev, "%d channels not supported\n", dev_err(&i2s->pdev->dev, "%d channels not supported\n",
...@@ -963,7 +974,7 @@ struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec) ...@@ -963,7 +974,7 @@ struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
i2s->i2s_dai_drv.playback.formats = SAMSUNG_I2S_FMTS; i2s->i2s_dai_drv.playback.formats = SAMSUNG_I2S_FMTS;
if (!sec) { if (!sec) {
i2s->i2s_dai_drv.capture.channels_min = 2; i2s->i2s_dai_drv.capture.channels_min = 1;
i2s->i2s_dai_drv.capture.channels_max = 2; i2s->i2s_dai_drv.capture.channels_max = 2;
i2s->i2s_dai_drv.capture.rates = SAMSUNG_I2S_RATES; i2s->i2s_dai_drv.capture.rates = SAMSUNG_I2S_RATES;
i2s->i2s_dai_drv.capture.formats = SAMSUNG_I2S_FMTS; i2s->i2s_dai_drv.capture.formats = SAMSUNG_I2S_FMTS;
......
...@@ -1686,7 +1686,6 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card) ...@@ -1686,7 +1686,6 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card)
snd_soc_dapm_free(&card->dapm); snd_soc_dapm_free(&card->dapm);
kfree(card->rtd);
snd_card_free(card->snd_card); snd_card_free(card->snd_card);
return 0; return 0;
...@@ -3112,7 +3111,8 @@ int snd_soc_register_card(struct snd_soc_card *card) ...@@ -3112,7 +3111,8 @@ int snd_soc_register_card(struct snd_soc_card *card)
soc_init_card_debugfs(card); soc_init_card_debugfs(card);
card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) * card->rtd = devm_kzalloc(card->dev,
sizeof(struct snd_soc_pcm_runtime) *
(card->num_links + card->num_aux_devs), (card->num_links + card->num_aux_devs),
GFP_KERNEL); GFP_KERNEL);
if (card->rtd == NULL) if (card->rtd == NULL)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment