aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/oxygen/xonar_pcm179x.c
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2009-09-28 05:20:47 -0400
committerTakashi Iwai <tiwai@suse.de>2009-09-28 05:54:52 -0400
commit973dca93a3d46cca7e4743300f8a510b779906af (patch)
tree35ecad5f3d2f5453aff442471d5b1b88e1b0aa98 /sound/pci/oxygen/xonar_pcm179x.c
parent76ffe1e3fb2f65e98d7ed001c5a2b6f334655364 (diff)
sound: virtuoso: add PCM1796 oversampling control
Add a control to increase the oversampling factor to 128x on cards with PCM1796 or PCM1792A DACs. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/oxygen/xonar_pcm179x.c')
-rw-r--r--sound/pci/oxygen/xonar_pcm179x.c182
1 files changed, 157 insertions, 25 deletions
diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c
index 35b3fb4071fb..7f153fb1848d 100644
--- a/sound/pci/oxygen/xonar_pcm179x.c
+++ b/sound/pci/oxygen/xonar_pcm179x.c
@@ -173,8 +173,11 @@ struct xonar_pcm179x {
173 struct xonar_generic generic; 173 struct xonar_generic generic;
174 unsigned int dacs; 174 unsigned int dacs;
175 u8 pcm1796_regs[4][5]; 175 u8 pcm1796_regs[4][5];
176 unsigned int current_rate;
177 bool os_128;
176 bool hp_active; 178 bool hp_active;
177 s8 hp_gain_offset; 179 s8 hp_gain_offset;
180 bool has_cs2000;
178 u8 cs2000_fun_cfg_1; 181 u8 cs2000_fun_cfg_1;
179}; 182};
180 183
@@ -277,6 +280,7 @@ static void pcm1796_init(struct oxygen *chip)
277 PCM1796_DMF_DISABLED | PCM1796_FMT_24_LJUST | PCM1796_ATLD; 280 PCM1796_DMF_DISABLED | PCM1796_FMT_24_LJUST | PCM1796_ATLD;
278 data->pcm1796_regs[0][20 - PCM1796_REG_BASE] = PCM1796_OS_64; 281 data->pcm1796_regs[0][20 - PCM1796_REG_BASE] = PCM1796_OS_64;
279 pcm1796_registers_init(chip); 282 pcm1796_registers_init(chip);
283 data->current_rate = 48000;
280} 284}
281 285
282static void xonar_d2_init(struct oxygen *chip) 286static void xonar_d2_init(struct oxygen *chip)
@@ -401,6 +405,7 @@ static void xonar_st_init(struct oxygen *chip)
401{ 405{
402 struct xonar_pcm179x *data = chip->model_data; 406 struct xonar_pcm179x *data = chip->model_data;
403 407
408 data->has_cs2000 = 1;
404 data->cs2000_fun_cfg_1 = CS2000_REF_CLK_DIV_1; 409 data->cs2000_fun_cfg_1 = CS2000_REF_CLK_DIV_1;
405 410
406 oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, 411 oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
@@ -486,18 +491,57 @@ static void xonar_st_resume(struct oxygen *chip)
486 xonar_stx_resume(chip); 491 xonar_stx_resume(chip);
487} 492}
488 493
489static void set_pcm1796_params(struct oxygen *chip, 494static unsigned int mclk_from_rate(struct oxygen *chip, unsigned int rate)
490 struct snd_pcm_hw_params *params) 495{
496 struct xonar_pcm179x *data = chip->model_data;
497
498 if (rate <= 32000)
499 return OXYGEN_I2S_MCLK_512;
500 else if (rate <= 48000 && data->os_128)
501 return OXYGEN_I2S_MCLK_512;
502 else if (rate <= 96000)
503 return OXYGEN_I2S_MCLK_256;
504 else
505 return OXYGEN_I2S_MCLK_128;
506}
507
508static unsigned int get_pcm1796_i2s_mclk(struct oxygen *chip,
509 unsigned int channel,
510 struct snd_pcm_hw_params *params)
511{
512 if (channel == PCM_MULTICH)
513 return mclk_from_rate(chip, params_rate(params));
514 else
515 return oxygen_default_i2s_mclk(chip, channel, params);
516}
517
518static void update_pcm1796_oversampling(struct oxygen *chip)
491{ 519{
492 struct xonar_pcm179x *data = chip->model_data; 520 struct xonar_pcm179x *data = chip->model_data;
493 unsigned int i; 521 unsigned int i;
494 u8 reg; 522 u8 reg;
495 523
496 reg = params_rate(params) >= 96000 ? PCM1796_OS_32 : PCM1796_OS_64; 524 if (data->current_rate <= 32000)
525 reg = PCM1796_OS_128;
526 else if (data->current_rate <= 48000 && data->os_128)
527 reg = PCM1796_OS_128;
528 else if (data->current_rate <= 96000 || data->os_128)
529 reg = PCM1796_OS_64;
530 else
531 reg = PCM1796_OS_32;
497 for (i = 0; i < data->dacs; ++i) 532 for (i = 0; i < data->dacs; ++i)
498 pcm1796_write_cached(chip, i, 20, reg); 533 pcm1796_write_cached(chip, i, 20, reg);
499} 534}
500 535
536static void set_pcm1796_params(struct oxygen *chip,
537 struct snd_pcm_hw_params *params)
538{
539 struct xonar_pcm179x *data = chip->model_data;
540
541 data->current_rate = params_rate(params);
542 update_pcm1796_oversampling(chip);
543}
544
501static void update_pcm1796_volume(struct oxygen *chip) 545static void update_pcm1796_volume(struct oxygen *chip)
502{ 546{
503 struct xonar_pcm179x *data = chip->model_data; 547 struct xonar_pcm179x *data = chip->model_data;
@@ -526,26 +570,44 @@ static void update_pcm1796_mute(struct oxygen *chip)
526 pcm1796_write_cached(chip, i, 18, value); 570 pcm1796_write_cached(chip, i, 18, value);
527} 571}
528 572
529static void set_cs2000_params(struct oxygen *chip, 573static void update_cs2000_rate(struct oxygen *chip, unsigned int rate)
530 struct snd_pcm_hw_params *params)
531{ 574{
532 /* XXX Why is the I2S A MCLK half the actual I2S multich MCLK? */ 575 struct xonar_pcm179x *data = chip->model_data;
533 static const u8 rate_mclks[] = {
534 [OXYGEN_RATE_32000] = OXYGEN_RATE_32000 | OXYGEN_I2S_MCLK_128,
535 [OXYGEN_RATE_44100] = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_128,
536 [OXYGEN_RATE_48000] = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_128,
537 [OXYGEN_RATE_64000] = OXYGEN_RATE_32000 | OXYGEN_I2S_MCLK_256,
538 [OXYGEN_RATE_88200] = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256,
539 [OXYGEN_RATE_96000] = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256,
540 [OXYGEN_RATE_176400] = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256,
541 [OXYGEN_RATE_192000] = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256,
542 };
543 unsigned int rate_index;
544 u8 rate_mclk, reg; 576 u8 rate_mclk, reg;
545 577
546 rate_index = oxygen_read16(chip, OXYGEN_I2S_MULTICH_FORMAT) 578 switch (rate) {
547 & OXYGEN_I2S_RATE_MASK; 579 /* XXX Why is the I2S A MCLK half the actual I2S MCLK? */
548 rate_mclk = rate_mclks[rate_index]; 580 case 32000:
581 rate_mclk = OXYGEN_RATE_32000 | OXYGEN_I2S_MCLK_256;
582 break;
583 case 44100:
584 if (data->os_128)
585 rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256;
586 else
587 rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_128;
588 break;
589 default: /* 48000 */
590 if (data->os_128)
591 rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256;
592 else
593 rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_128;
594 break;
595 case 64000:
596 rate_mclk = OXYGEN_RATE_32000 | OXYGEN_I2S_MCLK_256;
597 break;
598 case 88200:
599 rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256;
600 break;
601 case 96000:
602 rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256;
603 break;
604 case 176400:
605 rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256;
606 break;
607 case 192000:
608 rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256;
609 break;
610 }
549 oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, rate_mclk, 611 oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, rate_mclk,
550 OXYGEN_I2S_RATE_MASK | OXYGEN_I2S_MCLK_MASK); 612 OXYGEN_I2S_RATE_MASK | OXYGEN_I2S_MCLK_MASK);
551 if ((rate_mclk & OXYGEN_I2S_MCLK_MASK) <= OXYGEN_I2S_MCLK_128) 613 if ((rate_mclk & OXYGEN_I2S_MCLK_MASK) <= OXYGEN_I2S_MCLK_128)
@@ -558,7 +620,7 @@ static void set_cs2000_params(struct oxygen *chip,
558static void set_st_params(struct oxygen *chip, 620static void set_st_params(struct oxygen *chip,
559 struct snd_pcm_hw_params *params) 621 struct snd_pcm_hw_params *params)
560{ 622{
561 set_cs2000_params(chip, params); 623 update_cs2000_rate(chip, params_rate(params));
562 set_pcm1796_params(chip, params); 624 set_pcm1796_params(chip, params);
563} 625}
564 626
@@ -580,6 +642,59 @@ static const struct snd_kcontrol_new alt_switch = {
580 .private_value = GPIO_D2_ALT, 642 .private_value = GPIO_D2_ALT,
581}; 643};
582 644
645static int os_128_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
646{
647 static const char *const names[2] = { "64x", "128x" };
648
649 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
650 info->count = 1;
651 info->value.enumerated.items = 2;
652 if (info->value.enumerated.item >= 2)
653 info->value.enumerated.item = 1;
654 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
655 return 0;
656}
657
658static int os_128_get(struct snd_kcontrol *ctl,
659 struct snd_ctl_elem_value *value)
660{
661 struct oxygen *chip = ctl->private_data;
662 struct xonar_pcm179x *data = chip->model_data;
663
664 value->value.enumerated.item[0] = data->os_128;
665 return 0;
666}
667
668static int os_128_put(struct snd_kcontrol *ctl,
669 struct snd_ctl_elem_value *value)
670{
671 struct oxygen *chip = ctl->private_data;
672 struct xonar_pcm179x *data = chip->model_data;
673 int changed;
674
675 mutex_lock(&chip->mutex);
676 changed = value->value.enumerated.item[0] != data->os_128;
677 if (changed) {
678 data->os_128 = value->value.enumerated.item[0];
679 if (data->has_cs2000)
680 update_cs2000_rate(chip, data->current_rate);
681 oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT,
682 mclk_from_rate(chip, data->current_rate),
683 OXYGEN_I2S_MCLK_MASK);
684 update_pcm1796_oversampling(chip);
685 }
686 mutex_unlock(&chip->mutex);
687 return changed;
688}
689
690static const struct snd_kcontrol_new os_128_control = {
691 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
692 .name = "DAC Oversampling Playback Enum",
693 .info = os_128_info,
694 .get = os_128_get,
695 .put = os_128_put,
696};
697
583static int st_output_switch_info(struct snd_kcontrol *ctl, 698static int st_output_switch_info(struct snd_kcontrol *ctl,
584 struct snd_ctl_elem_info *info) 699 struct snd_ctl_elem_info *info)
585{ 700{
@@ -745,7 +860,20 @@ static int xonar_st_control_filter(struct snd_kcontrol_new *template)
745 860
746static int xonar_d2_mixer_init(struct oxygen *chip) 861static int xonar_d2_mixer_init(struct oxygen *chip)
747{ 862{
748 return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip)); 863 int err;
864
865 err = snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip));
866 if (err < 0)
867 return err;
868 err = snd_ctl_add(chip->card, snd_ctl_new1(&os_128_control, chip));
869 if (err < 0)
870 return err;
871 return 0;
872}
873
874static int xonar_hdav_mixer_init(struct oxygen *chip)
875{
876 return snd_ctl_add(chip->card, snd_ctl_new1(&os_128_control, chip));
749} 877}
750 878
751static int xonar_st_mixer_init(struct oxygen *chip) 879static int xonar_st_mixer_init(struct oxygen *chip)
@@ -759,6 +887,9 @@ static int xonar_st_mixer_init(struct oxygen *chip)
759 if (err < 0) 887 if (err < 0)
760 return err; 888 return err;
761 } 889 }
890 err = snd_ctl_add(chip->card, snd_ctl_new1(&os_128_control, chip));
891 if (err < 0)
892 return err;
762 return 0; 893 return 0;
763} 894}
764 895
@@ -771,7 +902,7 @@ static const struct oxygen_model model_xonar_d2 = {
771 .cleanup = xonar_d2_cleanup, 902 .cleanup = xonar_d2_cleanup,
772 .suspend = xonar_d2_suspend, 903 .suspend = xonar_d2_suspend,
773 .resume = xonar_d2_resume, 904 .resume = xonar_d2_resume,
774 .get_i2s_mclk = oxygen_default_i2s_mclk, 905 .get_i2s_mclk = get_pcm1796_i2s_mclk,
775 .set_dac_params = set_pcm1796_params, 906 .set_dac_params = set_pcm1796_params,
776 .set_adc_params = xonar_set_cs53x1_params, 907 .set_adc_params = xonar_set_cs53x1_params,
777 .update_dac_volume = update_pcm1796_volume, 908 .update_dac_volume = update_pcm1796_volume,
@@ -798,11 +929,12 @@ static const struct oxygen_model model_xonar_hdav = {
798 .longname = "Asus Virtuoso 200", 929 .longname = "Asus Virtuoso 200",
799 .chip = "AV200", 930 .chip = "AV200",
800 .init = xonar_hdav_init, 931 .init = xonar_hdav_init,
932 .mixer_init = xonar_hdav_mixer_init,
801 .cleanup = xonar_hdav_cleanup, 933 .cleanup = xonar_hdav_cleanup,
802 .suspend = xonar_hdav_suspend, 934 .suspend = xonar_hdav_suspend,
803 .resume = xonar_hdav_resume, 935 .resume = xonar_hdav_resume,
804 .pcm_hardware_filter = xonar_hdmi_pcm_hardware_filter, 936 .pcm_hardware_filter = xonar_hdmi_pcm_hardware_filter,
805 .get_i2s_mclk = oxygen_default_i2s_mclk, 937 .get_i2s_mclk = get_pcm1796_i2s_mclk,
806 .set_dac_params = set_hdav_params, 938 .set_dac_params = set_hdav_params,
807 .set_adc_params = xonar_set_cs53x1_params, 939 .set_adc_params = xonar_set_cs53x1_params,
808 .update_dac_volume = update_pcm1796_volume, 940 .update_dac_volume = update_pcm1796_volume,
@@ -833,7 +965,7 @@ static const struct oxygen_model model_xonar_st = {
833 .cleanup = xonar_st_cleanup, 965 .cleanup = xonar_st_cleanup,
834 .suspend = xonar_st_suspend, 966 .suspend = xonar_st_suspend,
835 .resume = xonar_st_resume, 967 .resume = xonar_st_resume,
836 .get_i2s_mclk = oxygen_default_i2s_mclk, 968 .get_i2s_mclk = get_pcm1796_i2s_mclk,
837 .set_dac_params = set_st_params, 969 .set_dac_params = set_st_params,
838 .set_adc_params = xonar_set_cs53x1_params, 970 .set_adc_params = xonar_set_cs53x1_params,
839 .update_dac_volume = update_pcm1796_volume, 971 .update_dac_volume = update_pcm1796_volume,