diff options
Diffstat (limited to 'sound/soc/codecs/sirf-audio-codec.c')
-rw-r--r-- | sound/soc/codecs/sirf-audio-codec.c | 82 |
1 files changed, 69 insertions, 13 deletions
diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c index 58e7c1f23771..d90cb0fafcb2 100644 --- a/sound/soc/codecs/sirf-audio-codec.c +++ b/sound/soc/codecs/sirf-audio-codec.c | |||
@@ -109,7 +109,7 @@ static void enable_and_reset_codec(struct regmap *regmap, | |||
109 | { | 109 | { |
110 | regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1, | 110 | regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1, |
111 | codec_enable_bits | codec_reset_bits, | 111 | codec_enable_bits | codec_reset_bits, |
112 | codec_enable_bits | ~codec_reset_bits); | 112 | codec_enable_bits); |
113 | msleep(20); | 113 | msleep(20); |
114 | regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1, | 114 | regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1, |
115 | codec_reset_bits, codec_reset_bits); | 115 | codec_reset_bits, codec_reset_bits); |
@@ -128,8 +128,7 @@ static int atlas6_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w, | |||
128 | break; | 128 | break; |
129 | case SND_SOC_DAPM_POST_PMD: | 129 | case SND_SOC_DAPM_POST_PMD: |
130 | regmap_update_bits(sirf_audio_codec->regmap, | 130 | regmap_update_bits(sirf_audio_codec->regmap, |
131 | AUDIO_IC_CODEC_CTRL1, ATLAS6_CODEC_ENABLE_BITS, | 131 | AUDIO_IC_CODEC_CTRL1, ATLAS6_CODEC_ENABLE_BITS, 0); |
132 | ~ATLAS6_CODEC_ENABLE_BITS); | ||
133 | break; | 132 | break; |
134 | default: | 133 | default: |
135 | break; | 134 | break; |
@@ -151,8 +150,7 @@ static int prima2_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w, | |||
151 | break; | 150 | break; |
152 | case SND_SOC_DAPM_POST_PMD: | 151 | case SND_SOC_DAPM_POST_PMD: |
153 | regmap_update_bits(sirf_audio_codec->regmap, | 152 | regmap_update_bits(sirf_audio_codec->regmap, |
154 | AUDIO_IC_CODEC_CTRL1, PRIMA2_CODEC_ENABLE_BITS, | 153 | AUDIO_IC_CODEC_CTRL1, PRIMA2_CODEC_ENABLE_BITS, 0); |
155 | ~PRIMA2_CODEC_ENABLE_BITS); | ||
156 | break; | 154 | break; |
157 | default: | 155 | default: |
158 | break; | 156 | break; |
@@ -279,13 +277,63 @@ static const struct snd_soc_dapm_route sirf_audio_codec_map[] = { | |||
279 | {"Mic input mode mux", "Differential", "MICIN1"}, | 277 | {"Mic input mode mux", "Differential", "MICIN1"}, |
280 | }; | 278 | }; |
281 | 279 | ||
280 | static void sirf_audio_codec_tx_enable(struct sirf_audio_codec *sirf_audio_codec) | ||
281 | { | ||
282 | regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, | ||
283 | AUDIO_FIFO_RESET, AUDIO_FIFO_RESET); | ||
284 | regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, | ||
285 | AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET); | ||
286 | regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_INT_MSK, 0); | ||
287 | regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0); | ||
288 | regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, | ||
289 | AUDIO_FIFO_START, AUDIO_FIFO_START); | ||
290 | regmap_update_bits(sirf_audio_codec->regmap, | ||
291 | AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, IC_TX_ENABLE); | ||
292 | } | ||
293 | |||
294 | static void sirf_audio_codec_tx_disable(struct sirf_audio_codec *sirf_audio_codec) | ||
295 | { | ||
296 | regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0); | ||
297 | regmap_update_bits(sirf_audio_codec->regmap, | ||
298 | AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, ~IC_TX_ENABLE); | ||
299 | } | ||
300 | |||
301 | static void sirf_audio_codec_rx_enable(struct sirf_audio_codec *sirf_audio_codec, | ||
302 | int channels) | ||
303 | { | ||
304 | regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, | ||
305 | AUDIO_FIFO_RESET, AUDIO_FIFO_RESET); | ||
306 | regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, | ||
307 | AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET); | ||
308 | regmap_write(sirf_audio_codec->regmap, | ||
309 | AUDIO_PORT_IC_RXFIFO_INT_MSK, 0); | ||
310 | regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, 0); | ||
311 | regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, | ||
312 | AUDIO_FIFO_START, AUDIO_FIFO_START); | ||
313 | if (channels == 1) | ||
314 | regmap_update_bits(sirf_audio_codec->regmap, | ||
315 | AUDIO_PORT_IC_CODEC_RX_CTRL, | ||
316 | IC_RX_ENABLE_MONO, IC_RX_ENABLE_MONO); | ||
317 | else | ||
318 | regmap_update_bits(sirf_audio_codec->regmap, | ||
319 | AUDIO_PORT_IC_CODEC_RX_CTRL, | ||
320 | IC_RX_ENABLE_STEREO, IC_RX_ENABLE_STEREO); | ||
321 | } | ||
322 | |||
323 | static void sirf_audio_codec_rx_disable(struct sirf_audio_codec *sirf_audio_codec) | ||
324 | { | ||
325 | regmap_update_bits(sirf_audio_codec->regmap, | ||
326 | AUDIO_PORT_IC_CODEC_RX_CTRL, | ||
327 | IC_RX_ENABLE_STEREO, ~IC_RX_ENABLE_STEREO); | ||
328 | } | ||
329 | |||
282 | static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream, | 330 | static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream, |
283 | int cmd, | 331 | int cmd, |
284 | struct snd_soc_dai *dai) | 332 | struct snd_soc_dai *dai) |
285 | { | 333 | { |
286 | int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
287 | struct snd_soc_codec *codec = dai->codec; | 334 | struct snd_soc_codec *codec = dai->codec; |
288 | u32 val = 0; | 335 | struct sirf_audio_codec *sirf_audio_codec = snd_soc_codec_get_drvdata(codec); |
336 | int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
289 | 337 | ||
290 | /* | 338 | /* |
291 | * This is a workaround, When stop playback, | 339 | * This is a workaround, When stop playback, |
@@ -295,20 +343,28 @@ static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream, | |||
295 | case SNDRV_PCM_TRIGGER_STOP: | 343 | case SNDRV_PCM_TRIGGER_STOP: |
296 | case SNDRV_PCM_TRIGGER_SUSPEND: | 344 | case SNDRV_PCM_TRIGGER_SUSPEND: |
297 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 345 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
346 | if (playback) { | ||
347 | snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0, | ||
348 | IC_HSLEN | IC_HSREN, 0); | ||
349 | sirf_audio_codec_tx_disable(sirf_audio_codec); | ||
350 | } else | ||
351 | sirf_audio_codec_rx_disable(sirf_audio_codec); | ||
298 | break; | 352 | break; |
299 | case SNDRV_PCM_TRIGGER_START: | 353 | case SNDRV_PCM_TRIGGER_START: |
300 | case SNDRV_PCM_TRIGGER_RESUME: | 354 | case SNDRV_PCM_TRIGGER_RESUME: |
301 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 355 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
302 | if (playback) | 356 | if (playback) { |
303 | val = IC_HSLEN | IC_HSREN; | 357 | sirf_audio_codec_tx_enable(sirf_audio_codec); |
358 | snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0, | ||
359 | IC_HSLEN | IC_HSREN, IC_HSLEN | IC_HSREN); | ||
360 | } else | ||
361 | sirf_audio_codec_rx_enable(sirf_audio_codec, | ||
362 | substream->runtime->channels); | ||
304 | break; | 363 | break; |
305 | default: | 364 | default: |
306 | return -EINVAL; | 365 | return -EINVAL; |
307 | } | 366 | } |
308 | 367 | ||
309 | if (playback) | ||
310 | snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0, | ||
311 | IC_HSLEN | IC_HSREN, val); | ||
312 | return 0; | 368 | return 0; |
313 | } | 369 | } |
314 | 370 | ||
@@ -392,7 +448,7 @@ static const struct regmap_config sirf_audio_codec_regmap_config = { | |||
392 | .reg_bits = 32, | 448 | .reg_bits = 32, |
393 | .reg_stride = 4, | 449 | .reg_stride = 4, |
394 | .val_bits = 32, | 450 | .val_bits = 32, |
395 | .max_register = AUDIO_IC_CODEC_CTRL3, | 451 | .max_register = AUDIO_PORT_IC_RXFIFO_INT_MSK, |
396 | .cache_type = REGCACHE_NONE, | 452 | .cache_type = REGCACHE_NONE, |
397 | }; | 453 | }; |
398 | 454 | ||