diff options
Diffstat (limited to 'sound/pci/oxygen/virtuoso.c')
-rw-r--r-- | sound/pci/oxygen/virtuoso.c | 339 |
1 files changed, 270 insertions, 69 deletions
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c index 6c870c12a177..bc5ce11c8b14 100644 --- a/sound/pci/oxygen/virtuoso.c +++ b/sound/pci/oxygen/virtuoso.c | |||
@@ -112,6 +112,34 @@ | |||
112 | * CS4362A: AD0 <- 0 | 112 | * CS4362A: AD0 <- 0 |
113 | */ | 113 | */ |
114 | 114 | ||
115 | /* | ||
116 | * Xonar Essence STX | ||
117 | * ----------------- | ||
118 | * | ||
119 | * CMI8788: | ||
120 | * | ||
121 | * I²C <-> PCM1792A | ||
122 | * | ||
123 | * GPI 0 <- external power present | ||
124 | * | ||
125 | * GPIO 0 -> enable output to speakers | ||
126 | * GPIO 1 -> route HP to front panel (0) or rear jack (1) | ||
127 | * GPIO 2 -> M0 of CS5381 | ||
128 | * GPIO 3 -> M1 of CS5381 | ||
129 | * GPIO 7 -> route output to speaker jacks (0) or HP (1) | ||
130 | * GPIO 8 -> route input jack to line-in (0) or mic-in (1) | ||
131 | * | ||
132 | * PCM1792A: | ||
133 | * | ||
134 | * AD0 <- 0 | ||
135 | * | ||
136 | * H6 daughterboard | ||
137 | * ---------------- | ||
138 | * | ||
139 | * GPIO 4 <- 0 | ||
140 | * GPIO 5 <- 0 | ||
141 | */ | ||
142 | |||
115 | #include <linux/pci.h> | 143 | #include <linux/pci.h> |
116 | #include <linux/delay.h> | 144 | #include <linux/delay.h> |
117 | #include <linux/mutex.h> | 145 | #include <linux/mutex.h> |
@@ -152,6 +180,7 @@ enum { | |||
152 | MODEL_DX, | 180 | MODEL_DX, |
153 | MODEL_HDAV, /* without daughterboard */ | 181 | MODEL_HDAV, /* without daughterboard */ |
154 | MODEL_HDAV_H6, /* with H6 daughterboard */ | 182 | MODEL_HDAV_H6, /* with H6 daughterboard */ |
183 | MODEL_STX, | ||
155 | }; | 184 | }; |
156 | 185 | ||
157 | static struct pci_device_id xonar_ids[] __devinitdata = { | 186 | static struct pci_device_id xonar_ids[] __devinitdata = { |
@@ -160,6 +189,8 @@ static struct pci_device_id xonar_ids[] __devinitdata = { | |||
160 | { OXYGEN_PCI_SUBID(0x1043, 0x82b7), .driver_data = MODEL_D2X }, | 189 | { OXYGEN_PCI_SUBID(0x1043, 0x82b7), .driver_data = MODEL_D2X }, |
161 | { OXYGEN_PCI_SUBID(0x1043, 0x8314), .driver_data = MODEL_HDAV }, | 190 | { OXYGEN_PCI_SUBID(0x1043, 0x8314), .driver_data = MODEL_HDAV }, |
162 | { OXYGEN_PCI_SUBID(0x1043, 0x834f), .driver_data = MODEL_D1 }, | 191 | { OXYGEN_PCI_SUBID(0x1043, 0x834f), .driver_data = MODEL_D1 }, |
192 | { OXYGEN_PCI_SUBID(0x1043, 0x835c), .driver_data = MODEL_STX }, | ||
193 | { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, | ||
163 | { } | 194 | { } |
164 | }; | 195 | }; |
165 | MODULE_DEVICE_TABLE(pci, xonar_ids); | 196 | MODULE_DEVICE_TABLE(pci, xonar_ids); |
@@ -183,12 +214,14 @@ MODULE_DEVICE_TABLE(pci, xonar_ids); | |||
183 | #define GPIO_HDAV_DB_H6 0x0000 | 214 | #define GPIO_HDAV_DB_H6 0x0000 |
184 | #define GPIO_HDAV_DB_XX 0x0020 | 215 | #define GPIO_HDAV_DB_XX 0x0020 |
185 | 216 | ||
217 | #define GPIO_ST_HP_REAR 0x0002 | ||
218 | #define GPIO_ST_HP 0x0080 | ||
219 | |||
186 | #define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ADx=i, /W=0 */ | 220 | #define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ADx=i, /W=0 */ |
187 | #define I2C_DEVICE_CS4398 0x9e /* 10011, AD1=1, AD0=1, /W=0 */ | 221 | #define I2C_DEVICE_CS4398 0x9e /* 10011, AD1=1, AD0=1, /W=0 */ |
188 | #define I2C_DEVICE_CS4362A 0x30 /* 001100, AD0=0, /W=0 */ | 222 | #define I2C_DEVICE_CS4362A 0x30 /* 001100, AD0=0, /W=0 */ |
189 | 223 | ||
190 | struct xonar_data { | 224 | struct xonar_data { |
191 | unsigned int model; | ||
192 | unsigned int anti_pop_delay; | 225 | unsigned int anti_pop_delay; |
193 | unsigned int dacs; | 226 | unsigned int dacs; |
194 | u16 output_enable_bit; | 227 | u16 output_enable_bit; |
@@ -334,15 +367,9 @@ static void xonar_d2_init(struct oxygen *chip) | |||
334 | struct xonar_data *data = chip->model_data; | 367 | struct xonar_data *data = chip->model_data; |
335 | 368 | ||
336 | data->anti_pop_delay = 300; | 369 | data->anti_pop_delay = 300; |
370 | data->dacs = 4; | ||
337 | data->output_enable_bit = GPIO_D2_OUTPUT_ENABLE; | 371 | data->output_enable_bit = GPIO_D2_OUTPUT_ENABLE; |
338 | data->pcm1796_oversampling = PCM1796_OS_64; | 372 | data->pcm1796_oversampling = PCM1796_OS_64; |
339 | if (data->model == MODEL_D2X) { | ||
340 | data->ext_power_reg = OXYGEN_GPIO_DATA; | ||
341 | data->ext_power_int_reg = OXYGEN_GPIO_INTERRUPT_MASK; | ||
342 | data->ext_power_bit = GPIO_D2X_EXT_POWER; | ||
343 | oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, | ||
344 | GPIO_D2X_EXT_POWER); | ||
345 | } | ||
346 | 373 | ||
347 | pcm1796_init(chip); | 374 | pcm1796_init(chip); |
348 | 375 | ||
@@ -355,6 +382,18 @@ static void xonar_d2_init(struct oxygen *chip) | |||
355 | snd_component_add(chip->card, "CS5381"); | 382 | snd_component_add(chip->card, "CS5381"); |
356 | } | 383 | } |
357 | 384 | ||
385 | static void xonar_d2x_init(struct oxygen *chip) | ||
386 | { | ||
387 | struct xonar_data *data = chip->model_data; | ||
388 | |||
389 | data->ext_power_reg = OXYGEN_GPIO_DATA; | ||
390 | data->ext_power_int_reg = OXYGEN_GPIO_INTERRUPT_MASK; | ||
391 | data->ext_power_bit = GPIO_D2X_EXT_POWER; | ||
392 | oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2X_EXT_POWER); | ||
393 | |||
394 | xonar_d2_init(chip); | ||
395 | } | ||
396 | |||
358 | static void update_cs4362a_volumes(struct oxygen *chip) | 397 | static void update_cs4362a_volumes(struct oxygen *chip) |
359 | { | 398 | { |
360 | u8 mute; | 399 | u8 mute; |
@@ -422,11 +461,6 @@ static void xonar_d1_init(struct oxygen *chip) | |||
422 | data->cs4398_fm = CS4398_FM_SINGLE | CS4398_DEM_NONE | CS4398_DIF_LJUST; | 461 | data->cs4398_fm = CS4398_FM_SINGLE | CS4398_DEM_NONE | CS4398_DIF_LJUST; |
423 | data->cs4362a_fm = CS4362A_FM_SINGLE | | 462 | data->cs4362a_fm = CS4362A_FM_SINGLE | |
424 | CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L; | 463 | CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L; |
425 | if (data->model == MODEL_DX) { | ||
426 | data->ext_power_reg = OXYGEN_GPI_DATA; | ||
427 | data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; | ||
428 | data->ext_power_bit = GPI_DX_EXT_POWER; | ||
429 | } | ||
430 | 464 | ||
431 | oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, | 465 | oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, |
432 | OXYGEN_2WIRE_LENGTH_8 | | 466 | OXYGEN_2WIRE_LENGTH_8 | |
@@ -447,6 +481,17 @@ static void xonar_d1_init(struct oxygen *chip) | |||
447 | snd_component_add(chip->card, "CS5361"); | 481 | snd_component_add(chip->card, "CS5361"); |
448 | } | 482 | } |
449 | 483 | ||
484 | static void xonar_dx_init(struct oxygen *chip) | ||
485 | { | ||
486 | struct xonar_data *data = chip->model_data; | ||
487 | |||
488 | data->ext_power_reg = OXYGEN_GPI_DATA; | ||
489 | data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; | ||
490 | data->ext_power_bit = GPI_DX_EXT_POWER; | ||
491 | |||
492 | xonar_d1_init(chip); | ||
493 | } | ||
494 | |||
450 | static void xonar_hdav_init(struct oxygen *chip) | 495 | static void xonar_hdav_init(struct oxygen *chip) |
451 | { | 496 | { |
452 | struct xonar_data *data = chip->model_data; | 497 | struct xonar_data *data = chip->model_data; |
@@ -458,6 +503,7 @@ static void xonar_hdav_init(struct oxygen *chip) | |||
458 | OXYGEN_2WIRE_SPEED_FAST); | 503 | OXYGEN_2WIRE_SPEED_FAST); |
459 | 504 | ||
460 | data->anti_pop_delay = 100; | 505 | data->anti_pop_delay = 100; |
506 | data->dacs = chip->model.private_data == MODEL_HDAV_H6 ? 4 : 1; | ||
461 | data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE; | 507 | data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE; |
462 | data->ext_power_reg = OXYGEN_GPI_DATA; | 508 | data->ext_power_reg = OXYGEN_GPI_DATA; |
463 | data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; | 509 | data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; |
@@ -484,6 +530,36 @@ static void xonar_hdav_init(struct oxygen *chip) | |||
484 | snd_component_add(chip->card, "CS5381"); | 530 | snd_component_add(chip->card, "CS5381"); |
485 | } | 531 | } |
486 | 532 | ||
533 | static void xonar_stx_init(struct oxygen *chip) | ||
534 | { | ||
535 | struct xonar_data *data = chip->model_data; | ||
536 | |||
537 | oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, | ||
538 | OXYGEN_2WIRE_LENGTH_8 | | ||
539 | OXYGEN_2WIRE_INTERRUPT_MASK | | ||
540 | OXYGEN_2WIRE_SPEED_FAST); | ||
541 | |||
542 | data->anti_pop_delay = 100; | ||
543 | data->dacs = 1; | ||
544 | data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE; | ||
545 | data->ext_power_reg = OXYGEN_GPI_DATA; | ||
546 | data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; | ||
547 | data->ext_power_bit = GPI_DX_EXT_POWER; | ||
548 | data->pcm1796_oversampling = PCM1796_OS_64; | ||
549 | |||
550 | pcm1796_init(chip); | ||
551 | |||
552 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, | ||
553 | GPIO_DX_INPUT_ROUTE | GPIO_ST_HP_REAR | GPIO_ST_HP); | ||
554 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, | ||
555 | GPIO_DX_INPUT_ROUTE | GPIO_ST_HP_REAR | GPIO_ST_HP); | ||
556 | |||
557 | xonar_common_init(chip); | ||
558 | |||
559 | snd_component_add(chip->card, "PCM1792A"); | ||
560 | snd_component_add(chip->card, "CS5381"); | ||
561 | } | ||
562 | |||
487 | static void xonar_disable_output(struct oxygen *chip) | 563 | static void xonar_disable_output(struct oxygen *chip) |
488 | { | 564 | { |
489 | struct xonar_data *data = chip->model_data; | 565 | struct xonar_data *data = chip->model_data; |
@@ -511,6 +587,11 @@ static void xonar_hdav_cleanup(struct oxygen *chip) | |||
511 | xonar_disable_output(chip); | 587 | xonar_disable_output(chip); |
512 | } | 588 | } |
513 | 589 | ||
590 | static void xonar_st_cleanup(struct oxygen *chip) | ||
591 | { | ||
592 | xonar_disable_output(chip); | ||
593 | } | ||
594 | |||
514 | static void xonar_d2_suspend(struct oxygen *chip) | 595 | static void xonar_d2_suspend(struct oxygen *chip) |
515 | { | 596 | { |
516 | xonar_d2_cleanup(chip); | 597 | xonar_d2_cleanup(chip); |
@@ -527,6 +608,11 @@ static void xonar_hdav_suspend(struct oxygen *chip) | |||
527 | msleep(2); | 608 | msleep(2); |
528 | } | 609 | } |
529 | 610 | ||
611 | static void xonar_st_suspend(struct oxygen *chip) | ||
612 | { | ||
613 | xonar_st_cleanup(chip); | ||
614 | } | ||
615 | |||
530 | static void xonar_d2_resume(struct oxygen *chip) | 616 | static void xonar_d2_resume(struct oxygen *chip) |
531 | { | 617 | { |
532 | pcm1796_init(chip); | 618 | pcm1796_init(chip); |
@@ -554,6 +640,12 @@ static void xonar_hdav_resume(struct oxygen *chip) | |||
554 | xonar_enable_output(chip); | 640 | xonar_enable_output(chip); |
555 | } | 641 | } |
556 | 642 | ||
643 | static void xonar_st_resume(struct oxygen *chip) | ||
644 | { | ||
645 | pcm1796_init(chip); | ||
646 | xonar_enable_output(chip); | ||
647 | } | ||
648 | |||
557 | static void xonar_hdav_pcm_hardware_filter(unsigned int channel, | 649 | static void xonar_hdav_pcm_hardware_filter(unsigned int channel, |
558 | struct snd_pcm_hardware *hardware) | 650 | struct snd_pcm_hardware *hardware) |
559 | { | 651 | { |
@@ -733,6 +825,72 @@ static const struct snd_kcontrol_new front_panel_switch = { | |||
733 | .private_value = GPIO_DX_FRONT_PANEL, | 825 | .private_value = GPIO_DX_FRONT_PANEL, |
734 | }; | 826 | }; |
735 | 827 | ||
828 | static int st_output_switch_info(struct snd_kcontrol *ctl, | ||
829 | struct snd_ctl_elem_info *info) | ||
830 | { | ||
831 | static const char *const names[3] = { | ||
832 | "Speakers", "Headphones", "FP Headphones" | ||
833 | }; | ||
834 | |||
835 | info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
836 | info->count = 1; | ||
837 | info->value.enumerated.items = 3; | ||
838 | if (info->value.enumerated.item >= 3) | ||
839 | info->value.enumerated.item = 2; | ||
840 | strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); | ||
841 | return 0; | ||
842 | } | ||
843 | |||
844 | static int st_output_switch_get(struct snd_kcontrol *ctl, | ||
845 | struct snd_ctl_elem_value *value) | ||
846 | { | ||
847 | struct oxygen *chip = ctl->private_data; | ||
848 | u16 gpio; | ||
849 | |||
850 | gpio = oxygen_read16(chip, OXYGEN_GPIO_DATA); | ||
851 | if (!(gpio & GPIO_ST_HP)) | ||
852 | value->value.enumerated.item[0] = 0; | ||
853 | else if (gpio & GPIO_ST_HP_REAR) | ||
854 | value->value.enumerated.item[0] = 1; | ||
855 | else | ||
856 | value->value.enumerated.item[0] = 2; | ||
857 | return 0; | ||
858 | } | ||
859 | |||
860 | |||
861 | static int st_output_switch_put(struct snd_kcontrol *ctl, | ||
862 | struct snd_ctl_elem_value *value) | ||
863 | { | ||
864 | struct oxygen *chip = ctl->private_data; | ||
865 | u16 gpio_old, gpio; | ||
866 | |||
867 | mutex_lock(&chip->mutex); | ||
868 | gpio_old = oxygen_read16(chip, OXYGEN_GPIO_DATA); | ||
869 | gpio = gpio_old; | ||
870 | switch (value->value.enumerated.item[0]) { | ||
871 | case 0: | ||
872 | gpio &= ~(GPIO_ST_HP | GPIO_ST_HP_REAR); | ||
873 | break; | ||
874 | case 1: | ||
875 | gpio |= GPIO_ST_HP | GPIO_ST_HP_REAR; | ||
876 | break; | ||
877 | case 2: | ||
878 | gpio = (gpio | GPIO_ST_HP) & ~GPIO_ST_HP_REAR; | ||
879 | break; | ||
880 | } | ||
881 | oxygen_write16(chip, OXYGEN_GPIO_DATA, gpio); | ||
882 | mutex_unlock(&chip->mutex); | ||
883 | return gpio != gpio_old; | ||
884 | } | ||
885 | |||
886 | static const struct snd_kcontrol_new st_output_switch = { | ||
887 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
888 | .name = "Analog Output", | ||
889 | .info = st_output_switch_info, | ||
890 | .get = st_output_switch_get, | ||
891 | .put = st_output_switch_put, | ||
892 | }; | ||
893 | |||
736 | static void xonar_line_mic_ac97_switch(struct oxygen *chip, | 894 | static void xonar_line_mic_ac97_switch(struct oxygen *chip, |
737 | unsigned int reg, unsigned int mute) | 895 | unsigned int reg, unsigned int mute) |
738 | { | 896 | { |
@@ -745,8 +903,8 @@ static void xonar_line_mic_ac97_switch(struct oxygen *chip, | |||
745 | } | 903 | } |
746 | } | 904 | } |
747 | 905 | ||
748 | static const DECLARE_TLV_DB_SCALE(pcm1796_db_scale, -12000, 50, 0); | 906 | static const DECLARE_TLV_DB_SCALE(pcm1796_db_scale, -6000, 50, 0); |
749 | static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -12700, 100, 0); | 907 | static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -6000, 100, 0); |
750 | 908 | ||
751 | static int xonar_d2_control_filter(struct snd_kcontrol_new *template) | 909 | static int xonar_d2_control_filter(struct snd_kcontrol_new *template) |
752 | { | 910 | { |
@@ -763,6 +921,15 @@ static int xonar_d1_control_filter(struct snd_kcontrol_new *template) | |||
763 | return 0; | 921 | return 0; |
764 | } | 922 | } |
765 | 923 | ||
924 | static int xonar_st_control_filter(struct snd_kcontrol_new *template) | ||
925 | { | ||
926 | if (!strncmp(template->name, "CD Capture ", 11)) | ||
927 | return 1; /* no CD input */ | ||
928 | if (!strcmp(template->name, "Stereo Upmixing")) | ||
929 | return 1; /* stereo only - we don't need upmixing */ | ||
930 | return 0; | ||
931 | } | ||
932 | |||
766 | static int xonar_d2_mixer_init(struct oxygen *chip) | 933 | static int xonar_d2_mixer_init(struct oxygen *chip) |
767 | { | 934 | { |
768 | return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip)); | 935 | return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip)); |
@@ -773,51 +940,14 @@ static int xonar_d1_mixer_init(struct oxygen *chip) | |||
773 | return snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip)); | 940 | return snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip)); |
774 | } | 941 | } |
775 | 942 | ||
776 | static int xonar_model_probe(struct oxygen *chip, unsigned long driver_data) | 943 | static int xonar_st_mixer_init(struct oxygen *chip) |
777 | { | 944 | { |
778 | static const char *const names[] = { | 945 | return snd_ctl_add(chip->card, snd_ctl_new1(&st_output_switch, chip)); |
779 | [MODEL_D1] = "Xonar D1", | ||
780 | [MODEL_DX] = "Xonar DX", | ||
781 | [MODEL_D2] = "Xonar D2", | ||
782 | [MODEL_D2X] = "Xonar D2X", | ||
783 | [MODEL_HDAV] = "Xonar HDAV1.3", | ||
784 | [MODEL_HDAV_H6] = "Xonar HDAV1.3+H6", | ||
785 | }; | ||
786 | static const u8 dacs[] = { | ||
787 | [MODEL_D1] = 2, | ||
788 | [MODEL_DX] = 2, | ||
789 | [MODEL_D2] = 4, | ||
790 | [MODEL_D2X] = 4, | ||
791 | [MODEL_HDAV] = 1, | ||
792 | [MODEL_HDAV_H6] = 4, | ||
793 | }; | ||
794 | struct xonar_data *data = chip->model_data; | ||
795 | |||
796 | data->model = driver_data; | ||
797 | if (data->model == MODEL_HDAV) { | ||
798 | oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, | ||
799 | GPIO_HDAV_DB_MASK); | ||
800 | switch (oxygen_read16(chip, OXYGEN_GPIO_DATA) & | ||
801 | GPIO_HDAV_DB_MASK) { | ||
802 | case GPIO_HDAV_DB_H6: | ||
803 | data->model = MODEL_HDAV_H6; | ||
804 | break; | ||
805 | case GPIO_HDAV_DB_XX: | ||
806 | snd_printk(KERN_ERR "unknown daughterboard\n"); | ||
807 | return -ENODEV; | ||
808 | } | ||
809 | } | ||
810 | |||
811 | data->dacs = dacs[data->model]; | ||
812 | chip->model.shortname = names[data->model]; | ||
813 | return 0; | ||
814 | } | 946 | } |
815 | 947 | ||
816 | static const struct oxygen_model model_xonar_d2 = { | 948 | static const struct oxygen_model model_xonar_d2 = { |
817 | .longname = "Asus Virtuoso 200", | 949 | .longname = "Asus Virtuoso 200", |
818 | .chip = "AV200", | 950 | .chip = "AV200", |
819 | .owner = THIS_MODULE, | ||
820 | .probe = xonar_model_probe, | ||
821 | .init = xonar_d2_init, | 951 | .init = xonar_d2_init, |
822 | .control_filter = xonar_d2_control_filter, | 952 | .control_filter = xonar_d2_control_filter, |
823 | .mixer_init = xonar_d2_mixer_init, | 953 | .mixer_init = xonar_d2_mixer_init, |
@@ -837,8 +967,8 @@ static const struct oxygen_model model_xonar_d2 = { | |||
837 | MIDI_OUTPUT | | 967 | MIDI_OUTPUT | |
838 | MIDI_INPUT, | 968 | MIDI_INPUT, |
839 | .dac_channels = 8, | 969 | .dac_channels = 8, |
840 | .dac_volume_min = 0x0f, | 970 | .dac_volume_min = 255 - 2*60, |
841 | .dac_volume_max = 0xff, | 971 | .dac_volume_max = 255, |
842 | .misc_flags = OXYGEN_MISC_MIDI, | 972 | .misc_flags = OXYGEN_MISC_MIDI, |
843 | .function_flags = OXYGEN_FUNCTION_SPI | | 973 | .function_flags = OXYGEN_FUNCTION_SPI | |
844 | OXYGEN_FUNCTION_ENABLE_SPI_4_5, | 974 | OXYGEN_FUNCTION_ENABLE_SPI_4_5, |
@@ -849,8 +979,6 @@ static const struct oxygen_model model_xonar_d2 = { | |||
849 | static const struct oxygen_model model_xonar_d1 = { | 979 | static const struct oxygen_model model_xonar_d1 = { |
850 | .longname = "Asus Virtuoso 100", | 980 | .longname = "Asus Virtuoso 100", |
851 | .chip = "AV200", | 981 | .chip = "AV200", |
852 | .owner = THIS_MODULE, | ||
853 | .probe = xonar_model_probe, | ||
854 | .init = xonar_d1_init, | 982 | .init = xonar_d1_init, |
855 | .control_filter = xonar_d1_control_filter, | 983 | .control_filter = xonar_d1_control_filter, |
856 | .mixer_init = xonar_d1_mixer_init, | 984 | .mixer_init = xonar_d1_mixer_init, |
@@ -868,7 +996,7 @@ static const struct oxygen_model model_xonar_d1 = { | |||
868 | PLAYBACK_1_TO_SPDIF | | 996 | PLAYBACK_1_TO_SPDIF | |
869 | CAPTURE_0_FROM_I2S_2, | 997 | CAPTURE_0_FROM_I2S_2, |
870 | .dac_channels = 8, | 998 | .dac_channels = 8, |
871 | .dac_volume_min = 0, | 999 | .dac_volume_min = 127 - 60, |
872 | .dac_volume_max = 127, | 1000 | .dac_volume_max = 127, |
873 | .function_flags = OXYGEN_FUNCTION_2WIRE, | 1001 | .function_flags = OXYGEN_FUNCTION_2WIRE, |
874 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 1002 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
@@ -878,8 +1006,6 @@ static const struct oxygen_model model_xonar_d1 = { | |||
878 | static const struct oxygen_model model_xonar_hdav = { | 1006 | static const struct oxygen_model model_xonar_hdav = { |
879 | .longname = "Asus Virtuoso 200", | 1007 | .longname = "Asus Virtuoso 200", |
880 | .chip = "AV200", | 1008 | .chip = "AV200", |
881 | .owner = THIS_MODULE, | ||
882 | .probe = xonar_model_probe, | ||
883 | .init = xonar_hdav_init, | 1009 | .init = xonar_hdav_init, |
884 | .cleanup = xonar_hdav_cleanup, | 1010 | .cleanup = xonar_hdav_cleanup, |
885 | .suspend = xonar_hdav_suspend, | 1011 | .suspend = xonar_hdav_suspend, |
@@ -897,16 +1023,43 @@ static const struct oxygen_model model_xonar_hdav = { | |||
897 | PLAYBACK_1_TO_SPDIF | | 1023 | PLAYBACK_1_TO_SPDIF | |
898 | CAPTURE_0_FROM_I2S_2, | 1024 | CAPTURE_0_FROM_I2S_2, |
899 | .dac_channels = 8, | 1025 | .dac_channels = 8, |
900 | .dac_volume_min = 0x0f, | 1026 | .dac_volume_min = 255 - 2*60, |
901 | .dac_volume_max = 0xff, | 1027 | .dac_volume_max = 255, |
902 | .misc_flags = OXYGEN_MISC_MIDI, | 1028 | .misc_flags = OXYGEN_MISC_MIDI, |
903 | .function_flags = OXYGEN_FUNCTION_2WIRE, | 1029 | .function_flags = OXYGEN_FUNCTION_2WIRE, |
904 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 1030 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
905 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 1031 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
906 | }; | 1032 | }; |
907 | 1033 | ||
908 | static int __devinit xonar_probe(struct pci_dev *pci, | 1034 | static const struct oxygen_model model_xonar_st = { |
909 | const struct pci_device_id *pci_id) | 1035 | .longname = "Asus Virtuoso 100", |
1036 | .chip = "AV200", | ||
1037 | .init = xonar_stx_init, | ||
1038 | .control_filter = xonar_st_control_filter, | ||
1039 | .mixer_init = xonar_st_mixer_init, | ||
1040 | .cleanup = xonar_st_cleanup, | ||
1041 | .suspend = xonar_st_suspend, | ||
1042 | .resume = xonar_st_resume, | ||
1043 | .set_dac_params = set_pcm1796_params, | ||
1044 | .set_adc_params = set_cs53x1_params, | ||
1045 | .update_dac_volume = update_pcm1796_volume, | ||
1046 | .update_dac_mute = update_pcm1796_mute, | ||
1047 | .ac97_switch = xonar_line_mic_ac97_switch, | ||
1048 | .dac_tlv = pcm1796_db_scale, | ||
1049 | .model_data_size = sizeof(struct xonar_data), | ||
1050 | .device_config = PLAYBACK_0_TO_I2S | | ||
1051 | PLAYBACK_1_TO_SPDIF | | ||
1052 | CAPTURE_0_FROM_I2S_2, | ||
1053 | .dac_channels = 2, | ||
1054 | .dac_volume_min = 255 - 2*60, | ||
1055 | .dac_volume_max = 255, | ||
1056 | .function_flags = OXYGEN_FUNCTION_2WIRE, | ||
1057 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | ||
1058 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | ||
1059 | }; | ||
1060 | |||
1061 | static int __devinit get_xonar_model(struct oxygen *chip, | ||
1062 | const struct pci_device_id *id) | ||
910 | { | 1063 | { |
911 | static const struct oxygen_model *const models[] = { | 1064 | static const struct oxygen_model *const models[] = { |
912 | [MODEL_D1] = &model_xonar_d1, | 1065 | [MODEL_D1] = &model_xonar_d1, |
@@ -914,7 +1067,57 @@ static int __devinit xonar_probe(struct pci_dev *pci, | |||
914 | [MODEL_D2] = &model_xonar_d2, | 1067 | [MODEL_D2] = &model_xonar_d2, |
915 | [MODEL_D2X] = &model_xonar_d2, | 1068 | [MODEL_D2X] = &model_xonar_d2, |
916 | [MODEL_HDAV] = &model_xonar_hdav, | 1069 | [MODEL_HDAV] = &model_xonar_hdav, |
1070 | [MODEL_STX] = &model_xonar_st, | ||
917 | }; | 1071 | }; |
1072 | static const char *const names[] = { | ||
1073 | [MODEL_D1] = "Xonar D1", | ||
1074 | [MODEL_DX] = "Xonar DX", | ||
1075 | [MODEL_D2] = "Xonar D2", | ||
1076 | [MODEL_D2X] = "Xonar D2X", | ||
1077 | [MODEL_HDAV] = "Xonar HDAV1.3", | ||
1078 | [MODEL_HDAV_H6] = "Xonar HDAV1.3+H6", | ||
1079 | [MODEL_STX] = "Xonar Essence STX", | ||
1080 | }; | ||
1081 | unsigned int model = id->driver_data; | ||
1082 | |||
1083 | if (model >= ARRAY_SIZE(models) || !models[model]) | ||
1084 | return -EINVAL; | ||
1085 | chip->model = *models[model]; | ||
1086 | |||
1087 | switch (model) { | ||
1088 | case MODEL_D2X: | ||
1089 | chip->model.init = xonar_d2x_init; | ||
1090 | break; | ||
1091 | case MODEL_DX: | ||
1092 | chip->model.init = xonar_dx_init; | ||
1093 | break; | ||
1094 | case MODEL_HDAV: | ||
1095 | oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, | ||
1096 | GPIO_HDAV_DB_MASK); | ||
1097 | switch (oxygen_read16(chip, OXYGEN_GPIO_DATA) & | ||
1098 | GPIO_HDAV_DB_MASK) { | ||
1099 | case GPIO_HDAV_DB_H6: | ||
1100 | model = MODEL_HDAV_H6; | ||
1101 | break; | ||
1102 | case GPIO_HDAV_DB_XX: | ||
1103 | snd_printk(KERN_ERR "unknown daughterboard\n"); | ||
1104 | return -ENODEV; | ||
1105 | } | ||
1106 | break; | ||
1107 | case MODEL_STX: | ||
1108 | oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, | ||
1109 | GPIO_HDAV_DB_MASK); | ||
1110 | break; | ||
1111 | } | ||
1112 | |||
1113 | chip->model.shortname = names[model]; | ||
1114 | chip->model.private_data = model; | ||
1115 | return 0; | ||
1116 | } | ||
1117 | |||
1118 | static int __devinit xonar_probe(struct pci_dev *pci, | ||
1119 | const struct pci_device_id *pci_id) | ||
1120 | { | ||
918 | static int dev; | 1121 | static int dev; |
919 | int err; | 1122 | int err; |
920 | 1123 | ||
@@ -924,10 +1127,8 @@ static int __devinit xonar_probe(struct pci_dev *pci, | |||
924 | ++dev; | 1127 | ++dev; |
925 | return -ENOENT; | 1128 | return -ENOENT; |
926 | } | 1129 | } |
927 | BUG_ON(pci_id->driver_data >= ARRAY_SIZE(models)); | 1130 | err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, |
928 | err = oxygen_pci_probe(pci, index[dev], id[dev], | 1131 | xonar_ids, get_xonar_model); |
929 | models[pci_id->driver_data], | ||
930 | pci_id->driver_data); | ||
931 | if (err >= 0) | 1132 | if (err >= 0) |
932 | ++dev; | 1133 | ++dev; |
933 | return err; | 1134 | return err; |