aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/twl4030.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/twl4030.c')
-rw-r--r--sound/soc/codecs/twl4030.c59
1 files changed, 58 insertions, 1 deletions
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 97738e2ece04..bfda7a88e825 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
1223static 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
1254static 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
1220static int twl4030_hw_params(struct snd_pcm_substream *substream, 1267static 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;
@@ -1259,6 +1311,9 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
1259 case 48000: 1311 case 48000:
1260 mode |= TWL4030_APLL_RATE_48000; 1312 mode |= TWL4030_APLL_RATE_48000;
1261 break; 1313 break;
1314 case 96000:
1315 mode |= TWL4030_APLL_RATE_96000;
1316 break;
1262 default: 1317 default:
1263 printk(KERN_ERR "TWL4030 hw params: unknown rate %d\n", 1318 printk(KERN_ERR "TWL4030 hw params: unknown rate %d\n",
1264 params_rate(params)); 1319 params_rate(params));
@@ -1384,6 +1439,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) 1439#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)
1385 1440
1386static struct snd_soc_dai_ops twl4030_dai_ops = { 1441static struct snd_soc_dai_ops twl4030_dai_ops = {
1442 .startup = twl4030_startup,
1443 .shutdown = twl4030_shutdown,
1387 .hw_params = twl4030_hw_params, 1444 .hw_params = twl4030_hw_params,
1388 .set_sysclk = twl4030_set_dai_sysclk, 1445 .set_sysclk = twl4030_set_dai_sysclk,
1389 .set_fmt = twl4030_set_dai_fmt, 1446 .set_fmt = twl4030_set_dai_fmt,
@@ -1395,7 +1452,7 @@ struct snd_soc_dai twl4030_dai = {
1395 .stream_name = "Playback", 1452 .stream_name = "Playback",
1396 .channels_min = 2, 1453 .channels_min = 2,
1397 .channels_max = 2, 1454 .channels_max = 2,
1398 .rates = TWL4030_RATES, 1455 .rates = TWL4030_RATES | SNDRV_PCM_RATE_96000,
1399 .formats = TWL4030_FORMATS,}, 1456 .formats = TWL4030_FORMATS,},
1400 .capture = { 1457 .capture = {
1401 .stream_name = "Capture", 1458 .stream_name = "Capture",