diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/twl4030.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index b07d8d68a939..4199498a8918 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -122,6 +122,9 @@ struct twl4030_priv { | |||
122 | unsigned int bypass_state; | 122 | unsigned int bypass_state; |
123 | unsigned int codec_powered; | 123 | unsigned int codec_powered; |
124 | unsigned int codec_muted; | 124 | unsigned int codec_muted; |
125 | |||
126 | struct snd_pcm_substream *master_substream; | ||
127 | struct snd_pcm_substream *slave_substream; | ||
125 | }; | 128 | }; |
126 | 129 | ||
127 | /* | 130 | /* |
@@ -1217,6 +1220,50 @@ static int twl4030_set_bias_level(struct snd_soc_codec *codec, | |||
1217 | return 0; | 1220 | return 0; |
1218 | } | 1221 | } |
1219 | 1222 | ||
1223 | static int twl4030_startup(struct snd_pcm_substream *substream) | ||
1224 | { | ||
1225 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
1226 | struct snd_soc_device *socdev = rtd->socdev; | ||
1227 | struct snd_soc_codec *codec = socdev->codec; | ||
1228 | struct twl4030_priv *twl4030 = codec->private_data; | ||
1229 | |||
1230 | /* If we already have a playback or capture going then constrain | ||
1231 | * this substream to match it. | ||
1232 | */ | ||
1233 | if (twl4030->master_substream) { | ||
1234 | struct snd_pcm_runtime *master_runtime; | ||
1235 | master_runtime = twl4030->master_substream->runtime; | ||
1236 | |||
1237 | snd_pcm_hw_constraint_minmax(substream->runtime, | ||
1238 | SNDRV_PCM_HW_PARAM_RATE, | ||
1239 | master_runtime->rate, | ||
1240 | master_runtime->rate); | ||
1241 | |||
1242 | snd_pcm_hw_constraint_minmax(substream->runtime, | ||
1243 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, | ||
1244 | master_runtime->sample_bits, | ||
1245 | master_runtime->sample_bits); | ||
1246 | |||
1247 | twl4030->slave_substream = substream; | ||
1248 | } else | ||
1249 | twl4030->master_substream = substream; | ||
1250 | |||
1251 | return 0; | ||
1252 | } | ||
1253 | |||
1254 | static void twl4030_shutdown(struct snd_pcm_substream *substream) | ||
1255 | { | ||
1256 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
1257 | struct snd_soc_device *socdev = rtd->socdev; | ||
1258 | struct snd_soc_codec *codec = socdev->codec; | ||
1259 | struct twl4030_priv *twl4030 = codec->private_data; | ||
1260 | |||
1261 | if (twl4030->master_substream == substream) | ||
1262 | twl4030->master_substream = twl4030->slave_substream; | ||
1263 | |||
1264 | twl4030->slave_substream = NULL; | ||
1265 | } | ||
1266 | |||
1220 | static int twl4030_hw_params(struct snd_pcm_substream *substream, | 1267 | static int twl4030_hw_params(struct snd_pcm_substream *substream, |
1221 | struct snd_pcm_hw_params *params, | 1268 | struct snd_pcm_hw_params *params, |
1222 | struct snd_soc_dai *dai) | 1269 | struct snd_soc_dai *dai) |
@@ -1224,8 +1271,13 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, | |||
1224 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1271 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1225 | struct snd_soc_device *socdev = rtd->socdev; | 1272 | struct snd_soc_device *socdev = rtd->socdev; |
1226 | struct snd_soc_codec *codec = socdev->card->codec; | 1273 | struct snd_soc_codec *codec = socdev->card->codec; |
1274 | struct twl4030_priv *twl4030 = codec->private_data; | ||
1227 | u8 mode, old_mode, format, old_format; | 1275 | u8 mode, old_mode, format, old_format; |
1228 | 1276 | ||
1277 | if (substream == twl4030->slave_substream) | ||
1278 | /* Ignoring hw_params for slave substream */ | ||
1279 | return 0; | ||
1280 | |||
1229 | /* bit rate */ | 1281 | /* bit rate */ |
1230 | old_mode = twl4030_read_reg_cache(codec, | 1282 | old_mode = twl4030_read_reg_cache(codec, |
1231 | TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ; | 1283 | TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ; |
@@ -1384,6 +1436,8 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
1384 | #define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) | 1436 | #define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) |
1385 | 1437 | ||
1386 | static struct snd_soc_dai_ops twl4030_dai_ops = { | 1438 | static struct snd_soc_dai_ops twl4030_dai_ops = { |
1439 | .startup = twl4030_startup, | ||
1440 | .shutdown = twl4030_shutdown, | ||
1387 | .hw_params = twl4030_hw_params, | 1441 | .hw_params = twl4030_hw_params, |
1388 | .set_sysclk = twl4030_set_dai_sysclk, | 1442 | .set_sysclk = twl4030_set_dai_sysclk, |
1389 | .set_fmt = twl4030_set_dai_fmt, | 1443 | .set_fmt = twl4030_set_dai_fmt, |