diff options
author | Karl Beldan <karl.beldan@gmail.com> | 2008-11-20 09:39:27 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2008-11-21 09:02:07 -0500 |
commit | faab5a32f4d0784d6bde57963267be0453be3546 (patch) | |
tree | c5857519e2897a6ba9597054472e898f582a835d /sound/soc/codecs/ssm2602.c | |
parent | bd903bde7e0ad017cb87a228f451e05011e6d302 (diff) |
ASoC: ssm2602: Fix priv substreams refs
Clean up our record of the active streams in shutdown(), fixing
subsequent failures of snd_pcm_hw_constraints_complete after closure of
a stream.
NOTE:
- The ssm2602 allows pairs of non-matching PB/REC rates.
- This is a fix for less evil:
The logic is flawed (e.g. the slave might startup before the
master's rate and sample_bits are set).
Signed-off-by: Karl Beldan <karl.beldan@gmail.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/ssm2602.c')
-rw-r--r-- | sound/soc/codecs/ssm2602.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 44ef0dacd564..0e522e718dfc 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c | |||
@@ -292,9 +292,15 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream, | |||
292 | struct snd_soc_device *socdev = rtd->socdev; | 292 | struct snd_soc_device *socdev = rtd->socdev; |
293 | struct snd_soc_codec *codec = socdev->codec; | 293 | struct snd_soc_codec *codec = socdev->codec; |
294 | struct ssm2602_priv *ssm2602 = codec->private_data; | 294 | struct ssm2602_priv *ssm2602 = codec->private_data; |
295 | struct i2c_client *i2c = codec->control_data; | ||
295 | u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3; | 296 | u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3; |
296 | int i = get_coeff(ssm2602->sysclk, params_rate(params)); | 297 | int i = get_coeff(ssm2602->sysclk, params_rate(params)); |
297 | 298 | ||
299 | if (substream == ssm2602->slave_substream) { | ||
300 | dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n"); | ||
301 | return 0; | ||
302 | } | ||
303 | |||
298 | /*no match is found*/ | 304 | /*no match is found*/ |
299 | if (i == ARRAY_SIZE(coeff_div)) | 305 | if (i == ARRAY_SIZE(coeff_div)) |
300 | return -EINVAL; | 306 | return -EINVAL; |
@@ -330,13 +336,19 @@ static int ssm2602_startup(struct snd_pcm_substream *substream) | |||
330 | struct snd_soc_device *socdev = rtd->socdev; | 336 | struct snd_soc_device *socdev = rtd->socdev; |
331 | struct snd_soc_codec *codec = socdev->codec; | 337 | struct snd_soc_codec *codec = socdev->codec; |
332 | struct ssm2602_priv *ssm2602 = codec->private_data; | 338 | struct ssm2602_priv *ssm2602 = codec->private_data; |
339 | struct i2c_client *i2c = codec->control_data; | ||
333 | struct snd_pcm_runtime *master_runtime; | 340 | struct snd_pcm_runtime *master_runtime; |
334 | 341 | ||
335 | /* The DAI has shared clocks so if we already have a playback or | 342 | /* The DAI has shared clocks so if we already have a playback or |
336 | * capture going then constrain this substream to match it. | 343 | * capture going then constrain this substream to match it. |
344 | * TODO: the ssm2602 allows pairs of non-matching PB/REC rates | ||
337 | */ | 345 | */ |
338 | if (ssm2602->master_substream) { | 346 | if (ssm2602->master_substream) { |
339 | master_runtime = ssm2602->master_substream->runtime; | 347 | master_runtime = ssm2602->master_substream->runtime; |
348 | dev_dbg(&i2c->dev, "Constraining to %d bits at %dHz\n", | ||
349 | master_runtime->sample_bits, | ||
350 | master_runtime->rate); | ||
351 | |||
340 | snd_pcm_hw_constraint_minmax(substream->runtime, | 352 | snd_pcm_hw_constraint_minmax(substream->runtime, |
341 | SNDRV_PCM_HW_PARAM_RATE, | 353 | SNDRV_PCM_HW_PARAM_RATE, |
342 | master_runtime->rate, | 354 | master_runtime->rate, |
@@ -370,9 +382,15 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream) | |||
370 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 382 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
371 | struct snd_soc_device *socdev = rtd->socdev; | 383 | struct snd_soc_device *socdev = rtd->socdev; |
372 | struct snd_soc_codec *codec = socdev->codec; | 384 | struct snd_soc_codec *codec = socdev->codec; |
385 | struct ssm2602_priv *ssm2602 = codec->private_data; | ||
373 | /* deactivate */ | 386 | /* deactivate */ |
374 | if (!codec->active) | 387 | if (!codec->active) |
375 | ssm2602_write(codec, SSM2602_ACTIVE, 0); | 388 | ssm2602_write(codec, SSM2602_ACTIVE, 0); |
389 | |||
390 | if (ssm2602->master_substream == substream) | ||
391 | ssm2602->master_substream = ssm2602->slave_substream; | ||
392 | |||
393 | ssm2602->slave_substream = NULL; | ||
376 | } | 394 | } |
377 | 395 | ||
378 | static int ssm2602_mute(struct snd_soc_dai *dai, int mute) | 396 | static int ssm2602_mute(struct snd_soc_dai *dai, int mute) |