aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew F. Davis2013-10-25 08:29:39 -0500
committerAndrew F. Davis2018-04-21 19:27:07 -0500
commitbb503f36fef8523ccd03b6d00c022a6d3a62111c (patch)
tree5abf8bdb38cd7b1016c52e02fc0474e931c98b81
parente5bb2a46a4129192110f5fa8f6d77724a52c4537 (diff)
downloadafd-analog-tlv320aic325x.tar.gz
afd-analog-tlv320aic325x.tar.xz
afd-analog-tlv320aic325x.zip
ASoC: Add TLV320AIC3254 MiniDSP supporttlv320aic325x
Signed-off-by: Andrew F. Davis <afd@ti.com>
-rw-r--r--sound/soc/codecs/tlv320aic325x.c475
1 files changed, 471 insertions, 4 deletions
diff --git a/sound/soc/codecs/tlv320aic325x.c b/sound/soc/codecs/tlv320aic325x.c
index 07e238bb6055..e2aed8f12a51 100644
--- a/sound/soc/codecs/tlv320aic325x.c
+++ b/sound/soc/codecs/tlv320aic325x.c
@@ -33,6 +33,9 @@
33#include <sound/tlv.h> 33#include <sound/tlv.h>
34#include <sound/jack.h> 34#include <sound/jack.h>
35 35
36#include "ti-minidsp/aic3xxx_cfw.h"
37#include "ti-minidsp/aic3xxx_cfw_ops.h"
38
36#include "tlv320aic325x.h" 39#include "tlv320aic325x.h"
37 40
38struct aic325x_priv { 41struct aic325x_priv {
@@ -40,6 +43,11 @@ struct aic325x_priv {
40 bool master; 43 bool master;
41 struct snd_soc_codec *codec; 44 struct snd_soc_codec *codec;
42 45
46 struct cfw_state cfw_ps;
47 struct firmware *cur_fw;
48
49 int dsp_runstate;
50
43 struct regmap *regmap; 51 struct regmap *regmap;
44}; 52};
45 53
@@ -201,6 +209,25 @@ static const struct snd_kcontrol_new adcl_mux =
201static const struct snd_kcontrol_new adcr_mux = 209static const struct snd_kcontrol_new adcr_mux =
202 SOC_DAPM_ENUM("Right ADC Route", adcr_enum); 210 SOC_DAPM_ENUM("Right ADC Route", adcr_enum);
203 211
212static int aic3xxx_wait_bits(struct snd_soc_codec *codec, unsigned int reg,
213 unsigned char mask, unsigned char val)
214{
215 unsigned int status;
216 unsigned int counter;
217 int timeout = AIC325x_TIME_DELAY * AIC325x_DELAY_COUNTER;
218
219 for (counter = 0; counter < AIC325x_DELAY_COUNTER; counter++) {
220 status = snd_soc_read(codec, reg);
221 if ((status & mask) == val)
222 return 0;
223 usleep_range(AIC325x_TIME_DELAY, AIC325x_TIME_DELAY + 100);
224 }
225
226 dev_err(codec->dev, "wait_bits timedout (%d microsecs). page %d reg %d lastval 0x%x\n", timeout, reg / 128, reg % 128, status);
227
228 return -1;
229}
230
204static int pll_power_on_event(struct snd_soc_dapm_widget *w, 231static int pll_power_on_event(struct snd_soc_dapm_widget *w,
205 struct snd_kcontrol *kcontrol, int event) 232 struct snd_kcontrol *kcontrol, int event)
206{ 233{
@@ -209,6 +236,229 @@ static int pll_power_on_event(struct snd_soc_dapm_widget *w,
209 return 0; 236 return 0;
210} 237}
211 238
239static int aic3256_get_runstate(struct snd_soc_codec *codec)
240{
241 unsigned int dac, adc;
242 u8 state = 0;
243
244 dac = snd_soc_read(codec, AIC325x_DACFLAG1);
245
246 if (dac & BIT(7))
247 state |= AIC3XXX_COPS_MDSP_D_L;
248
249 if (dac & BIT(3))
250 state |= AIC3XXX_COPS_MDSP_D_R;
251
252 adc = snd_soc_read(codec, AIC325x_ADCFLAG);
253
254 if (adc & BIT(6))
255 state |= AIC3XXX_COPS_MDSP_A_L;
256
257 if (adc & BIT(2))
258 state |= AIC3XXX_COPS_MDSP_A_R;
259
260 return state;
261}
262
263static int aic3256_dsp_pwrdwn_status(struct snd_soc_codec *codec)
264{
265 snd_soc_update_bits(codec, AIC325x_ADCSETUP, 0xc0, 0);
266 snd_soc_update_bits(codec, AIC325x_DACSETUP, 0xc0, 0);
267
268 if (aic3xxx_wait_bits(codec, AIC325x_ADCFLAG, AIC325x_ADC_POWER_MASK, 0))
269 goto err;
270
271 if (aic3xxx_wait_bits(codec, AIC325x_DACFLAG1, AIC325x_DAC_POWER_MASK, 0))
272 goto err;
273
274 return 0;
275
276err:
277 dev_err(codec->dev, "DAC/ADC Power down timedout\n");
278
279 return -EINVAL;
280}
281
282static int aic3256_dsp_pwrup(struct snd_soc_codec *codec, int state)
283{
284 int adc_reg_mask = 0;
285 int adc_power = 0;
286 int dac_reg_mask = 0;
287 int dac_power = 0;
288 int ret_wbits;
289
290 if (state & AIC3XXX_COPS_MDSP_A_L) {
291 adc_reg_mask |= 0x80;
292 adc_power |= AIC325x_LADC_POWER;
293 }
294
295 if (state & AIC3XXX_COPS_MDSP_A_R) {
296 adc_reg_mask |= 0x40;
297 adc_power |= AIC325x_RADC_POWER;
298 }
299
300 if (state & AIC3XXX_COPS_MDSP_A)
301 snd_soc_update_bits(codec, AIC325x_ADCSETUP, 0xc0, adc_reg_mask);
302
303 if (state & AIC3XXX_COPS_MDSP_D_L) {
304 dac_reg_mask |= 0x80;
305 dac_power |= AIC325x_LDAC_POWER;
306 }
307
308 if (state & AIC3XXX_COPS_MDSP_D_R) {
309 dac_reg_mask |= 0x40;
310 dac_power |= AIC325x_RDAC_POWER;
311 }
312
313 if (state & AIC3XXX_COPS_MDSP_D)
314 snd_soc_update_bits(codec, AIC325x_DACSETUP, 0xc0, dac_reg_mask);
315
316 if (state & AIC3XXX_COPS_MDSP_A) {
317 ret_wbits = aic3xxx_wait_bits(codec, AIC325x_ADCFLAG, AIC325x_ADC_POWER_MASK, adc_power);
318 if (ret_wbits)
319 dev_err(codec->dev, "ADC Power down timedout\n");
320 }
321
322 if (state & AIC3XXX_COPS_MDSP_D) {
323 ret_wbits = aic3xxx_wait_bits(codec, AIC325x_DACFLAG1, AIC325x_DAC_POWER_MASK, dac_power);
324 if (ret_wbits)
325 dev_err(codec->dev, "ADC Power down timedout\n");
326 }
327
328 return 0;
329}
330
331static int aic3256_restart_dsps_sync(struct snd_soc_codec *codec, int run_state)
332{
333 aic3256_dsp_pwrdwn_status(codec);
334 aic3256_dsp_pwrup(codec, run_state);
335 return 0;
336}
337
338/**
339 *aic325x_dac_event: Headset popup reduction and powering up dsps together
340 * when they are in sync mode
341 * @w: pointer variable to dapm_widget
342 * @kcontrol: pointer to sound control
343 * @event: event element information
344 *
345 * Returns 0 for success.
346 */
347static int aic325x_dac_event(struct snd_soc_dapm_widget *w,
348 struct snd_kcontrol *kcontrol, int event)
349{
350 int reg_mask = 0;
351 int ret_wbits = 0;
352 int run_state_mask;
353 int sync_needed = 0, non_sync_state = 0;
354 int other_dsp = 0, run_state = 0;
355 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
356 struct aic325x_priv *aic325x = snd_soc_codec_get_drvdata(codec);
357
358 printk("dac event *******\n");
359
360 if (w->shift == 7) {
361 reg_mask = AIC325x_LDAC_POWER;
362 run_state_mask = AIC3XXX_COPS_MDSP_D_L;
363 }
364 if (w->shift == 6) {
365 reg_mask = AIC325x_RDAC_POWER;
366 run_state_mask = AIC3XXX_COPS_MDSP_D_R;
367 }
368
369 switch (event) {
370 case SND_SOC_DAPM_POST_PMU:
371 ret_wbits = aic3xxx_wait_bits(codec, AIC325x_DACFLAG1, reg_mask, reg_mask);
372 sync_needed = snd_soc_read(codec, AIC325x_DAC_PRB);
373 non_sync_state = !(aic325x->dsp_runstate & AIC3XXX_COPS_MDSP_ALL);
374 other_dsp = aic325x->dsp_runstate & AIC3XXX_COPS_MDSP_A;
375 if (sync_needed && non_sync_state && other_dsp) {
376 run_state = aic3256_get_runstate(aic325x->codec);
377 aic3256_dsp_pwrdwn_status(aic325x->codec);
378 aic3256_dsp_pwrup(aic325x->codec, run_state);
379 }
380 aic325x->dsp_runstate |= run_state_mask;
381 if (ret_wbits) {
382 dev_err(codec->dev, "DAC_post_pmu timed out\n");
383 return -1;
384 }
385 break;
386 case SND_SOC_DAPM_POST_PMD:
387 ret_wbits = aic3xxx_wait_bits(codec, AIC325x_DACFLAG1, reg_mask, 0);
388 aic325x->dsp_runstate = (aic325x->dsp_runstate & ~run_state_mask);
389 if (ret_wbits) {
390 dev_err(codec->dev, "DAC_post_pmd timed out\n");
391 return -1;
392 }
393 break;
394 default:
395 BUG();
396 return -EINVAL;
397 }
398 return 0;
399}
400
401/**
402 * aic325x_adc_event: To get DSP run state to perform synchronization
403 * @w: pointer variable to dapm_widget
404 * @kcontrol: pointer to sound control
405 * @event: event element information
406 *
407 * Returns 0 for success.
408 */
409static int aic325x_adc_event(struct snd_soc_dapm_widget *w,
410 struct snd_kcontrol *kcontrol, int event)
411{
412 int run_state = 0;
413 int non_sync_state = 0, sync_needed = 0;
414 int other_dsp = 0;
415 int run_state_mask = 0;
416 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
417 struct aic325x_priv *aic3256 = snd_soc_codec_get_drvdata(codec);
418 int reg_mask = 0;
419 int ret_wbits = 0;
420
421 if (w->shift == 7) {
422 reg_mask = AIC325x_LADC_POWER;
423 run_state_mask = AIC3XXX_COPS_MDSP_A_L;
424 }
425 if (w->shift == 6) {
426 reg_mask = AIC325x_RADC_POWER;
427 run_state_mask = AIC3XXX_COPS_MDSP_A_R;
428 }
429
430 switch (event) {
431 case SND_SOC_DAPM_POST_PMU:
432 ret_wbits = aic3xxx_wait_bits(codec, AIC325x_ADCFLAG , reg_mask, reg_mask);
433 sync_needed = snd_soc_read(codec, AIC325x_DAC_PRB);
434 non_sync_state = !(aic3256->dsp_runstate & AIC3XXX_COPS_MDSP_ALL);
435 other_dsp = aic3256->dsp_runstate & AIC3XXX_COPS_MDSP_D;
436 if (sync_needed && non_sync_state && other_dsp) {
437 run_state = aic3256_get_runstate(aic3256->codec);
438 aic3256_dsp_pwrdwn_status(aic3256->codec);
439 aic3256_dsp_pwrup(aic3256->codec, run_state);
440 }
441 aic3256->dsp_runstate |= run_state_mask;
442 if (ret_wbits) {
443 dev_err(codec->dev, "ADC POST_PMU timedout\n");
444 return -1;
445 }
446 break;
447 case SND_SOC_DAPM_POST_PMD:
448 ret_wbits = aic3xxx_wait_bits(codec, AIC325x_ADCFLAG, reg_mask, 0);
449 aic3256->dsp_runstate = (aic3256->dsp_runstate & ~run_state_mask);
450 if (ret_wbits) {
451 dev_err(codec->dev, "ADC POST_PMD timedout\n");
452 return -1;
453 }
454 break;
455 default:
456 BUG();
457 return -EINVAL;
458 }
459 return 0;
460}
461
212static const struct snd_soc_dapm_widget aic325x_dapm_widgets[] = { 462static const struct snd_soc_dapm_widget aic325x_dapm_widgets[] = {
213 SND_SOC_DAPM_AIF_IN("ASIIN", "ASI Playback", 0, SND_SOC_NOPM, 0, 0), 463 SND_SOC_DAPM_AIF_IN("ASIIN", "ASI Playback", 0, SND_SOC_NOPM, 0, 0),
214 SND_SOC_DAPM_PGA("ASILIN", SND_SOC_NOPM, 0, 0, NULL, 0), 464 SND_SOC_DAPM_PGA("ASILIN", SND_SOC_NOPM, 0, 0, NULL, 0),
@@ -217,8 +467,8 @@ static const struct snd_soc_dapm_widget aic325x_dapm_widgets[] = {
217 SND_SOC_DAPM_MUX("ASIIn Left Route", SND_SOC_NOPM, 0, 0, &asilin_control), 467 SND_SOC_DAPM_MUX("ASIIn Left Route", SND_SOC_NOPM, 0, 0, &asilin_control),
218 SND_SOC_DAPM_MUX("ASIIn Right Route", SND_SOC_NOPM, 0, 0, &asirin_control), 468 SND_SOC_DAPM_MUX("ASIIn Right Route", SND_SOC_NOPM, 0, 0, &asirin_control),
219 SND_SOC_DAPM_PGA("ASI IN Port", SND_SOC_NOPM, 0, 0, NULL, 0), 469 SND_SOC_DAPM_PGA("ASI IN Port", SND_SOC_NOPM, 0, 0, NULL, 0),
220 SND_SOC_DAPM_DAC("Left DAC", NULL, AIC325x_DACSETUP, 7, 0), 470 SND_SOC_DAPM_DAC_E("Left DAC", NULL, AIC325x_DACSETUP, 7, 0, aic325x_dac_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
221 SND_SOC_DAPM_DAC("Right DAC", NULL, AIC325x_DACSETUP, 6, 0), 471 SND_SOC_DAPM_DAC_E("Right DAC", NULL, AIC325x_DACSETUP, 6, 0, aic325x_dac_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
222 472
223 SND_SOC_DAPM_MIXER("HPL Output Mixer", SND_SOC_NOPM, 0, 0, hpl_output_mixer_controls, ARRAY_SIZE(hpl_output_mixer_controls)), 473 SND_SOC_DAPM_MIXER("HPL Output Mixer", SND_SOC_NOPM, 0, 0, hpl_output_mixer_controls, ARRAY_SIZE(hpl_output_mixer_controls)),
224 SND_SOC_DAPM_MIXER("HPR Output Mixer", SND_SOC_NOPM, 0, 0, hpr_output_mixer_controls, ARRAY_SIZE(hpr_output_mixer_controls)), 474 SND_SOC_DAPM_MIXER("HPR Output Mixer", SND_SOC_NOPM, 0, 0, hpr_output_mixer_controls, ARRAY_SIZE(hpr_output_mixer_controls)),
@@ -271,8 +521,8 @@ static const struct snd_soc_dapm_widget aic325x_dapm_widgets[] = {
271 SND_SOC_DAPM_MUX("Left ADC Route", SND_SOC_NOPM, 0, 0, &adcl_mux), 521 SND_SOC_DAPM_MUX("Left ADC Route", SND_SOC_NOPM, 0, 0, &adcl_mux),
272 SND_SOC_DAPM_MUX("Right ADC Route", SND_SOC_NOPM, 0, 0, &adcr_mux), 522 SND_SOC_DAPM_MUX("Right ADC Route", SND_SOC_NOPM, 0, 0, &adcr_mux),
273 523
274 SND_SOC_DAPM_ADC("Left ADC", "Left Capture", AIC325x_ADCSETUP, 7, 0), 524 SND_SOC_DAPM_ADC_E("Left ADC", "Left Capture", AIC325x_ADCSETUP, 7, 0, aic325x_adc_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
275 SND_SOC_DAPM_ADC("Right ADC", "Right Capture", AIC325x_ADCSETUP, 6, 0), 525 SND_SOC_DAPM_ADC_E("Right ADC", "Right Capture", AIC325x_ADCSETUP, 6, 0, aic325x_adc_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
276 526
277 SND_SOC_DAPM_MICBIAS("Mic Bias", AIC325x_MICBIAS_CTRL, 6, 0), 527 SND_SOC_DAPM_MICBIAS("Mic Bias", AIC325x_MICBIAS_CTRL, 6, 0),
278 528
@@ -405,6 +655,160 @@ static const struct snd_soc_dapm_route aic325x_dapm_routes[] = {
405 {"Right ADC", NULL, "MADC_DIV"}, 655 {"Right ADC", NULL, "MADC_DIV"},
406}; 656};
407 657
658/**
659 * Methods for CFW Operations
660 *
661 * Due to incompatibilities between structures used by regmap and CFW
662 * we need to transform the register format before linking to
663 * CFW operations.
664 */
665static unsigned int aic3256_ops_cfw2reg(unsigned int reg)
666{
667 union cfw_register *c = (union cfw_register *)&reg;
668
669 if (c->book)
670 pr_warn("Book not 0\n");
671
672 return AIC325x_REG(c->page, c->offset);
673}
674
675static int aic3256_ops_reg_read(struct snd_soc_codec *codec, unsigned int reg)
676{
677 unsigned int val = snd_soc_read(codec, aic3256_ops_cfw2reg(reg));
678
679 printk(" ** read page %d, reg %d: 0x%08x\n", aic3256_ops_cfw2reg(reg) / 128, aic3256_ops_cfw2reg(reg) % 128, val);
680
681 return snd_soc_read(codec, aic3256_ops_cfw2reg(reg));
682}
683
684static int aic3256_ops_reg_write(struct snd_soc_codec *codec, unsigned int reg,
685 unsigned char val)
686{
687 printk(" ** write page %d, reg %d: 0x%08x\n", aic3256_ops_cfw2reg(reg) / 128, aic3256_ops_cfw2reg(reg) % 128, val);
688
689 return snd_soc_write(codec, aic3256_ops_cfw2reg(reg), val);
690}
691
692static int aic3256_ops_set_bits(struct snd_soc_codec *codec, unsigned int reg,
693 unsigned char mask, unsigned char val)
694{
695 printk(" ** setbits page %d, reg %d: 0x%08x 0x%08x\n", aic3256_ops_cfw2reg(reg) / 128, aic3256_ops_cfw2reg(reg) % 128, mask, val);
696
697 return snd_soc_update_bits(codec, aic3256_ops_cfw2reg(reg), mask, val);
698}
699
700static int aic3256_ops_bulk_read(struct snd_soc_codec *codec, unsigned int reg,
701 int count, u8 *buf)
702{
703 struct aic325x_priv *aic325x = snd_soc_codec_get_drvdata(codec);
704
705 printk(" ** bulk read page %d, reg %d: %d count\n", aic3256_ops_cfw2reg(reg) / 128, aic3256_ops_cfw2reg(reg) % 128, count);
706
707 return regmap_bulk_read(aic325x->regmap, aic3256_ops_cfw2reg(reg), buf, count);
708}
709
710static int aic3256_ops_bulk_write(struct snd_soc_codec *codec, unsigned int reg,
711 int count, const u8 *buf)
712{
713 struct aic325x_priv *aic325x = snd_soc_codec_get_drvdata(codec);
714
715 printk(" ** bulk write page %d, reg %d: %d count\n", aic3256_ops_cfw2reg(reg) / 128, aic3256_ops_cfw2reg(reg) % 128, count);
716
717 return regmap_bulk_write(aic325x->regmap, aic3256_ops_cfw2reg(reg), buf, count);
718}
719
720int aic3256_ops_lock(struct snd_soc_codec *codec)
721{
722// mutex_lock(&codec->mutex);
723 /* Reading the run state of adc and dac */
724 return aic3256_get_runstate(codec);
725}
726
727int aic3256_ops_unlock(struct snd_soc_codec *codec)
728{
729 /*Releasing the lock of mutex */
730// mutex_unlock(&codec->mutex);
731 return 0;
732}
733
734int aic3256_ops_stop(struct snd_soc_codec *codec, int mask)
735{
736 int run_state = 0;
737
738 run_state = aic3256_get_runstate(codec);
739
740 if (mask & AIC3XXX_COPS_MDSP_A) /* power-down ADCs */
741 snd_soc_update_bits(codec, AIC325x_ADCSETUP, 0xc0, 0);
742
743 if (mask & AIC3XXX_COPS_MDSP_D) /* power-down DACs */
744 snd_soc_update_bits(codec, AIC325x_DACSETUP, 0xc0, 0);
745
746 if ((mask & AIC3XXX_COPS_MDSP_A) && aic3xxx_wait_bits(codec, AIC325x_ADCFLAG, AIC325x_ADC_POWER_MASK, 0))
747 goto err;
748
749 if ((mask & AIC3XXX_COPS_MDSP_D) && aic3xxx_wait_bits(codec, AIC325x_DACFLAG1, AIC325x_DAC_POWER_MASK, 0))
750 goto err;
751
752 return run_state;
753
754err:
755 dev_err(codec->dev, "Unable to turn off ADCs or DACs\n");
756 return -EINVAL;
757}
758
759static int aic3256_ops_restore(struct snd_soc_codec *codec, int run_state)
760{
761 int sync_state;
762
763 /* This is for read the sync mode register state */
764 sync_state = snd_soc_read(codec, AIC325x_DAC_PRB);
765 /* checking whether the sync mode has been set or not and checking the current state */
766 if ((run_state & AIC3XXX_COPS_MDSP_ALL) && (sync_state & 0x80))
767 aic3256_restart_dsps_sync(codec, run_state);
768 else
769 aic3256_dsp_pwrup(codec, run_state);
770
771 return 0;
772}
773
774static const int sbuf[][2] = {
775 { AIC3XXX_ABUF_MDSP_A, AIC325x_ADC_ADAPTIVE_CRAM_REG },
776 { AIC3XXX_ABUF_MDSP_D1, AIC325x_DAC_ADAPTIVE_CRAM_REG },
777 /* { AIC3XXX_ABUF_MDSP_D2, AIC325x_DAC_ADAPTIVE_BANK2_REG }, */
778};
779
780int aic3256_ops_adaptivebuffer_swap(struct snd_soc_codec *codec, int mask)
781{
782 int i;
783
784 for (i = 0; i < ARRAY_SIZE(sbuf); i++) {
785 if (!(mask & sbuf[i][0]))
786 continue;
787 snd_soc_update_bits(codec, sbuf[i][1], 0x1, 0x1);
788 if (aic3xxx_wait_bits(codec, sbuf[i][1], 0x1, 0))
789 goto err;
790 }
791
792 return 0;
793
794err:
795 dev_err(codec->dev, "miniDSP buffer swap failure\n");
796 return -EINVAL;
797}
798
799static const struct aic3xxx_codec_ops aic3256_cfw_codec_ops = {
800 .reg_read = aic3256_ops_reg_read,
801 .reg_write = aic3256_ops_reg_write,
802 .set_bits = aic3256_ops_set_bits,
803 .bulk_read = aic3256_ops_bulk_read,
804 .bulk_write = aic3256_ops_bulk_write,
805 .lock = aic3256_ops_lock,
806 .unlock = aic3256_ops_unlock,
807 .stop = aic3256_ops_stop,
808 .restore = aic3256_ops_restore,
809 .bswap = aic3256_ops_adaptivebuffer_swap,
810};
811
408struct AIC325x_rate_divs { 812struct AIC325x_rate_divs {
409 u32 mclk; 813 u32 mclk;
410 u32 rate; 814 u32 rate;
@@ -653,6 +1057,15 @@ static int aic325x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
653 return 0; 1057 return 0;
654} 1058}
655 1059
1060static int aic325x_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
1061 unsigned int freq_in, unsigned int freq_out)
1062{
1063 struct snd_soc_codec *codec = dai->codec;
1064 struct aic325x_priv *aic325x = snd_soc_codec_get_drvdata(codec);
1065
1066 return aic3xxx_cfw_set_pll(&aic325x->cfw_ps, dai->id);
1067}
1068
656static int aic325x_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) 1069static int aic325x_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level)
657{ 1070{
658// struct aic325x_priv *aic325x = snd_soc_codec_get_drvdata(codec); 1071// struct aic325x_priv *aic325x = snd_soc_codec_get_drvdata(codec);
@@ -680,6 +1093,7 @@ struct snd_soc_dai_ops aic325x_dai_ops = {
680 .hw_params = aic325x_hw_params, 1093 .hw_params = aic325x_hw_params,
681 .set_sysclk = aic325x_set_dai_sysclk, 1094 .set_sysclk = aic325x_set_dai_sysclk,
682 .set_fmt = aic325x_set_dai_fmt, 1095 .set_fmt = aic325x_set_dai_fmt,
1096 .set_pll = aic325x_dai_set_pll,
683}; 1097};
684 1098
685static struct snd_soc_dai_driver tlv320aic325x_dai_driver[] = { 1099static struct snd_soc_dai_driver tlv320aic325x_dai_driver[] = {
@@ -703,6 +1117,41 @@ static struct snd_soc_dai_driver tlv320aic325x_dai_driver[] = {
703 }, 1117 },
704}; 1118};
705 1119
1120static void aic3256_firmware_load(const struct firmware *fw, void *context)
1121{
1122 struct snd_soc_codec *codec = context;
1123 struct aic325x_priv *aic325x = snd_soc_codec_get_drvdata(codec);
1124 int ret = 0;
1125
1126 if (aic325x->cur_fw) {
1127 release_firmware(aic325x->cur_fw);
1128 aic325x->cur_fw = NULL;
1129 }
1130
1131 if (!fw) {
1132 dev_err(codec->dev, "Codec Firmware failed\n");
1133 return;
1134 }
1135
1136 dev_dbg(codec->dev, "Firmware binary load\n");
1137 aic325x->cur_fw = (void *)fw;
1138 ret = aic3xxx_cfw_load(&aic325x->cfw_ps, (void *)fw->data, fw->size);
1139 if (ret < 0) {
1140 dev_err(codec->dev, "Firmware binary load failed\n");
1141 release_firmware(aic325x->cur_fw);
1142 aic325x->cur_fw = NULL;
1143 fw = NULL;
1144 }
1145
1146 if (ret >= 0) {
1147 /* init function for transition */
1148 aic3xxx_cfw_transition(&aic325x->cfw_ps, "INIT");
1149 aic3xxx_cfw_add_modes(codec, &aic325x->cfw_ps);
1150 aic3xxx_cfw_add_controls(codec, &aic325x->cfw_ps);
1151 aic3xxx_cfw_setmode_cfg(&aic325x->cfw_ps, 0, 0);
1152 }
1153}
1154
706static int aic325x_codec_probe(struct snd_soc_codec *codec) 1155static int aic325x_codec_probe(struct snd_soc_codec *codec)
707{ 1156{
708 struct aic325x_priv *aic325x = snd_soc_codec_get_drvdata(codec); 1157 struct aic325x_priv *aic325x = snd_soc_codec_get_drvdata(codec);
@@ -711,10 +1160,24 @@ static int aic325x_codec_probe(struct snd_soc_codec *codec)
711 1160
712 aic325x->codec = codec; 1161 aic325x->codec = codec;
713 1162
1163 aic325x->cur_fw = NULL;
1164 aic3xxx_cfw_init(aic325x->codec, &aic325x->cfw_ps, &aic3256_cfw_codec_ops);
1165 aic325x->dsp_runstate = 0;
1166
714 aic325x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1167 aic325x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
715 1168
716 snd_soc_write(codec, AIC325x_LDO_CTRL, 0x01); /* FIXME: make conditional on regulator */ 1169 snd_soc_write(codec, AIC325x_LDO_CTRL, 0x01); /* FIXME: make conditional on regulator */
717 1170
1171 /* firmware load */
1172 ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
1173 "tlv320aic3254_fw_v1.bin",
1174 codec->dev, GFP_KERNEL, codec,
1175 aic3256_firmware_load);
1176 if (ret < 0) {
1177 dev_err(codec->dev, "Firmware request failed\n");
1178 return ret;
1179 }
1180
718 return 0; 1181 return 0;
719} 1182}
720 1183
@@ -725,6 +1188,10 @@ static int aic325x_codec_remove(struct snd_soc_codec *codec)
725 1188
726 aic325x_set_bias_level(codec, SND_SOC_BIAS_OFF); 1189 aic325x_set_bias_level(codec, SND_SOC_BIAS_OFF);
727 1190
1191 /* Release firmware if any */
1192 if (aic325x->cur_fw)
1193 release_firmware(aic325x->cur_fw);
1194
728 return 0; 1195 return 0;
729} 1196}
730 1197