aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/oxygen
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2008-09-22 03:00:30 -0400
committerClemens Ladisch <clemens@ladisch.de>2008-09-22 03:00:30 -0400
commitfe10662c3c7e1a77cac7949a4b269622da663c2e (patch)
treec866cee6729fd5db6239a11cd8b54ad896f68eae /sound/pci/oxygen
parent4bd0c3a690594b4037c3edc49e6475f1df13c59d (diff)
ALSA: virtuoso: handle D2X/DX dynamically
The Xonar D2X and DX are very similar to the D2 and D1, respectively, so we can handle the differences dynamically instead of using a separate model structure for each one. Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Diffstat (limited to 'sound/pci/oxygen')
-rw-r--r--sound/pci/oxygen/virtuoso.c241
1 files changed, 99 insertions, 142 deletions
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 4aa2857a1b05..c4ac91f80235 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -128,6 +128,7 @@ MODULE_DEVICE_TABLE(pci, xonar_ids);
128#define I2C_DEVICE_CS4362A 0x30 /* 001100, AD0=0, /W=0 */ 128#define I2C_DEVICE_CS4362A 0x30 /* 001100, AD0=0, /W=0 */
129 129
130struct xonar_data { 130struct xonar_data {
131 unsigned int model;
131 unsigned int anti_pop_delay; 132 unsigned int anti_pop_delay;
132 u16 output_enable_bit; 133 u16 output_enable_bit;
133 u8 ext_power_reg; 134 u8 ext_power_reg;
@@ -139,6 +140,8 @@ struct xonar_data {
139 u8 cs4362a_fm; 140 u8 cs4362a_fm;
140}; 141};
141 142
143static void xonar_gpio_changed(struct oxygen *chip);
144
142static void pcm1796_write(struct oxygen *chip, unsigned int codec, 145static void pcm1796_write(struct oxygen *chip, unsigned int codec,
143 u8 reg, u8 value) 146 u8 reg, u8 value)
144{ 147{
@@ -180,6 +183,7 @@ static void xonar_common_init(struct oxygen *chip)
180 oxygen_set_bits8(chip, data->ext_power_int_reg, 183 oxygen_set_bits8(chip, data->ext_power_int_reg,
181 data->ext_power_bit); 184 data->ext_power_bit);
182 chip->interrupt_mask |= OXYGEN_INT_GPIO; 185 chip->interrupt_mask |= OXYGEN_INT_GPIO;
186 chip->model.gpio_changed = xonar_gpio_changed;
183 data->has_power = !!(oxygen_read8(chip, data->ext_power_reg) 187 data->has_power = !!(oxygen_read8(chip, data->ext_power_reg)
184 & data->ext_power_bit); 188 & data->ext_power_bit);
185 } 189 }
@@ -234,6 +238,13 @@ static void xonar_d2_init(struct oxygen *chip)
234 data->anti_pop_delay = 300; 238 data->anti_pop_delay = 300;
235 data->output_enable_bit = GPIO_D2_OUTPUT_ENABLE; 239 data->output_enable_bit = GPIO_D2_OUTPUT_ENABLE;
236 data->pcm1796_oversampling = PCM1796_OS_64; 240 data->pcm1796_oversampling = PCM1796_OS_64;
241 if (data->model == MODEL_D2X) {
242 data->ext_power_reg = OXYGEN_GPIO_DATA;
243 data->ext_power_int_reg = OXYGEN_GPIO_INTERRUPT_MASK;
244 data->ext_power_bit = GPIO_D2X_EXT_POWER;
245 oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
246 GPIO_D2X_EXT_POWER);
247 }
237 248
238 pcm1796_init(chip); 249 pcm1796_init(chip);
239 250
@@ -246,17 +257,6 @@ static void xonar_d2_init(struct oxygen *chip)
246 snd_component_add(chip->card, "CS5381"); 257 snd_component_add(chip->card, "CS5381");
247} 258}
248 259
249static void xonar_d2x_init(struct oxygen *chip)
250{
251 struct xonar_data *data = chip->model_data;
252
253 data->ext_power_reg = OXYGEN_GPIO_DATA;
254 data->ext_power_int_reg = OXYGEN_GPIO_INTERRUPT_MASK;
255 data->ext_power_bit = GPIO_D2X_EXT_POWER;
256 oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2X_EXT_POWER);
257 xonar_d2_init(chip);
258}
259
260static void update_cs4362a_volumes(struct oxygen *chip) 260static void update_cs4362a_volumes(struct oxygen *chip)
261{ 261{
262 u8 mute; 262 u8 mute;
@@ -324,6 +324,11 @@ static void xonar_d1_init(struct oxygen *chip)
324 data->cs4398_fm = CS4398_FM_SINGLE | CS4398_DEM_NONE | CS4398_DIF_LJUST; 324 data->cs4398_fm = CS4398_FM_SINGLE | CS4398_DEM_NONE | CS4398_DIF_LJUST;
325 data->cs4362a_fm = CS4362A_FM_SINGLE | 325 data->cs4362a_fm = CS4362A_FM_SINGLE |
326 CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L; 326 CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L;
327 if (data->model == MODEL_DX) {
328 data->ext_power_reg = OXYGEN_GPI_DATA;
329 data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
330 data->ext_power_bit = GPI_DX_EXT_POWER;
331 }
327 332
328 oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, 333 oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
329 OXYGEN_2WIRE_LENGTH_8 | 334 OXYGEN_2WIRE_LENGTH_8 |
@@ -344,16 +349,6 @@ static void xonar_d1_init(struct oxygen *chip)
344 snd_component_add(chip->card, "CS5361"); 349 snd_component_add(chip->card, "CS5361");
345} 350}
346 351
347static void xonar_dx_init(struct oxygen *chip)
348{
349 struct xonar_data *data = chip->model_data;
350
351 data->ext_power_reg = OXYGEN_GPI_DATA;
352 data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
353 data->ext_power_bit = GPI_DX_EXT_POWER;
354 xonar_d1_init(chip);
355}
356
357static void xonar_cleanup(struct oxygen *chip) 352static void xonar_cleanup(struct oxygen *chip)
358{ 353{
359 struct xonar_data *data = chip->model_data; 354 struct xonar_data *data = chip->model_data;
@@ -552,7 +547,7 @@ static int xonar_d1_control_filter(struct snd_kcontrol_new *template)
552 return 0; 547 return 0;
553} 548}
554 549
555static int xonar_mixer_init(struct oxygen *chip) 550static int xonar_d2_mixer_init(struct oxygen *chip)
556{ 551{
557 return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip)); 552 return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip));
558} 553}
@@ -562,130 +557,90 @@ static int xonar_d1_mixer_init(struct oxygen *chip)
562 return snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip)); 557 return snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip));
563} 558}
564 559
565static const struct oxygen_model xonar_models[] = { 560static int xonar_model_probe(struct oxygen *chip, unsigned long driver_data)
566 [MODEL_D2] = { 561{
567 .shortname = "Xonar D2", 562 static const char *const names[] = {
568 .longname = "Asus Virtuoso 200", 563 [MODEL_D1] = "Xonar D1",
569 .chip = "AV200", 564 [MODEL_DX] = "Xonar DX",
570 .owner = THIS_MODULE, 565 [MODEL_D2] = "Xonar D2",
571 .init = xonar_d2_init, 566 [MODEL_D2X] = "Xonar D2X",
572 .control_filter = xonar_d2_control_filter, 567 };
573 .mixer_init = xonar_mixer_init, 568 struct xonar_data *data = chip->model_data;
574 .cleanup = xonar_cleanup, 569
575 .suspend = xonar_cleanup, 570 data->model = driver_data;
576 .resume = xonar_d2_resume, 571 chip->model.shortname = names[data->model];
577 .set_dac_params = set_pcm1796_params, 572 return 0;
578 .set_adc_params = set_cs53x1_params, 573}
579 .update_dac_volume = update_pcm1796_volume, 574
580 .update_dac_mute = update_pcm1796_mute, 575static const struct oxygen_model model_xonar_d2 = {
581 .dac_tlv = pcm1796_db_scale, 576 .longname = "Asus Virtuoso 200",
582 .model_data_size = sizeof(struct xonar_data), 577 .chip = "AV200",
583 .pcm_dev_cfg = PLAYBACK_0_TO_I2S | 578 .owner = THIS_MODULE,
584 PLAYBACK_1_TO_SPDIF | 579 .probe = xonar_model_probe,
585 CAPTURE_0_FROM_I2S_2 | 580 .init = xonar_d2_init,
586 CAPTURE_1_FROM_SPDIF, 581 .control_filter = xonar_d2_control_filter,
587 .dac_channels = 8, 582 .mixer_init = xonar_d2_mixer_init,
588 .dac_volume_min = 0x0f, 583 .cleanup = xonar_cleanup,
589 .dac_volume_max = 0xff, 584 .suspend = xonar_cleanup,
590 .misc_flags = OXYGEN_MISC_MIDI, 585 .resume = xonar_d2_resume,
591 .function_flags = OXYGEN_FUNCTION_SPI | 586 .set_dac_params = set_pcm1796_params,
592 OXYGEN_FUNCTION_ENABLE_SPI_4_5, 587 .set_adc_params = set_cs53x1_params,
593 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, 588 .update_dac_volume = update_pcm1796_volume,
594 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, 589 .update_dac_mute = update_pcm1796_mute,
595 }, 590 .dac_tlv = pcm1796_db_scale,
596 [MODEL_D2X] = { 591 .model_data_size = sizeof(struct xonar_data),
597 .shortname = "Xonar D2X", 592 .pcm_dev_cfg = PLAYBACK_0_TO_I2S |
598 .longname = "Asus Virtuoso 200", 593 PLAYBACK_1_TO_SPDIF |
599 .chip = "AV200", 594 CAPTURE_0_FROM_I2S_2 |
600 .owner = THIS_MODULE, 595 CAPTURE_1_FROM_SPDIF,
601 .init = xonar_d2x_init, 596 .dac_channels = 8,
602 .control_filter = xonar_d2_control_filter, 597 .dac_volume_min = 0x0f,
603 .mixer_init = xonar_mixer_init, 598 .dac_volume_max = 0xff,
604 .cleanup = xonar_cleanup, 599 .misc_flags = OXYGEN_MISC_MIDI,
605 .suspend = xonar_cleanup, 600 .function_flags = OXYGEN_FUNCTION_SPI |
606 .resume = xonar_d2_resume, 601 OXYGEN_FUNCTION_ENABLE_SPI_4_5,
607 .set_dac_params = set_pcm1796_params, 602 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
608 .set_adc_params = set_cs53x1_params, 603 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
609 .update_dac_volume = update_pcm1796_volume, 604};
610 .update_dac_mute = update_pcm1796_mute, 605
611 .gpio_changed = xonar_gpio_changed, 606static const struct oxygen_model model_xonar_d1 = {
612 .dac_tlv = pcm1796_db_scale, 607 .longname = "Asus Virtuoso 100",
613 .model_data_size = sizeof(struct xonar_data), 608 .chip = "AV200",
614 .pcm_dev_cfg = PLAYBACK_0_TO_I2S | 609 .owner = THIS_MODULE,
615 PLAYBACK_1_TO_SPDIF | 610 .probe = xonar_model_probe,
616 CAPTURE_0_FROM_I2S_2 | 611 .init = xonar_d1_init,
617 CAPTURE_1_FROM_SPDIF, 612 .control_filter = xonar_d1_control_filter,
618 .dac_channels = 8, 613 .mixer_init = xonar_d1_mixer_init,
619 .dac_volume_min = 0x0f, 614 .cleanup = xonar_d1_cleanup,
620 .dac_volume_max = 0xff, 615 .suspend = xonar_d1_cleanup,
621 .misc_flags = OXYGEN_MISC_MIDI, 616 .resume = xonar_d1_resume,
622 .function_flags = OXYGEN_FUNCTION_SPI | 617 .set_dac_params = set_cs43xx_params,
623 OXYGEN_FUNCTION_ENABLE_SPI_4_5, 618 .set_adc_params = set_cs53x1_params,
624 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, 619 .update_dac_volume = update_cs43xx_volume,
625 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, 620 .update_dac_mute = update_cs43xx_mute,
626 }, 621 .ac97_switch = xonar_d1_ac97_switch,
627 [MODEL_D1] = { 622 .dac_tlv = cs4362a_db_scale,
628 .shortname = "Xonar D1", 623 .model_data_size = sizeof(struct xonar_data),
629 .longname = "Asus Virtuoso 100", 624 .pcm_dev_cfg = PLAYBACK_0_TO_I2S |
630 .chip = "AV200", 625 PLAYBACK_1_TO_SPDIF |
631 .owner = THIS_MODULE, 626 CAPTURE_0_FROM_I2S_2,
632 .init = xonar_d1_init, 627 .dac_channels = 8,
633 .control_filter = xonar_d1_control_filter, 628 .dac_volume_min = 0,
634 .mixer_init = xonar_d1_mixer_init, 629 .dac_volume_max = 127,
635 .cleanup = xonar_d1_cleanup, 630 .function_flags = OXYGEN_FUNCTION_2WIRE,
636 .suspend = xonar_d1_cleanup, 631 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
637 .resume = xonar_d1_resume, 632 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
638 .set_dac_params = set_cs43xx_params,
639 .set_adc_params = set_cs53x1_params,
640 .update_dac_volume = update_cs43xx_volume,
641 .update_dac_mute = update_cs43xx_mute,
642 .ac97_switch = xonar_d1_ac97_switch,
643 .dac_tlv = cs4362a_db_scale,
644 .model_data_size = sizeof(struct xonar_data),
645 .pcm_dev_cfg = PLAYBACK_0_TO_I2S |
646 PLAYBACK_1_TO_SPDIF |
647 CAPTURE_0_FROM_I2S_2,
648 .dac_channels = 8,
649 .dac_volume_min = 0,
650 .dac_volume_max = 127,
651 .function_flags = OXYGEN_FUNCTION_2WIRE,
652 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
653 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
654 },
655 [MODEL_DX] = {
656 .shortname = "Xonar DX",
657 .longname = "Asus Virtuoso 100",
658 .chip = "AV200",
659 .owner = THIS_MODULE,
660 .init = xonar_dx_init,
661 .control_filter = xonar_d1_control_filter,
662 .mixer_init = xonar_d1_mixer_init,
663 .cleanup = xonar_d1_cleanup,
664 .suspend = xonar_d1_cleanup,
665 .resume = xonar_d1_resume,
666 .set_dac_params = set_cs43xx_params,
667 .set_adc_params = set_cs53x1_params,
668 .update_dac_volume = update_cs43xx_volume,
669 .update_dac_mute = update_cs43xx_mute,
670 .gpio_changed = xonar_gpio_changed,
671 .ac97_switch = xonar_d1_ac97_switch,
672 .dac_tlv = cs4362a_db_scale,
673 .model_data_size = sizeof(struct xonar_data),
674 .pcm_dev_cfg = PLAYBACK_0_TO_I2S |
675 PLAYBACK_1_TO_SPDIF |
676 CAPTURE_0_FROM_I2S_2,
677 .dac_channels = 8,
678 .dac_volume_min = 0,
679 .dac_volume_max = 127,
680 .function_flags = OXYGEN_FUNCTION_2WIRE,
681 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
682 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
683 },
684}; 633};
685 634
686static int __devinit xonar_probe(struct pci_dev *pci, 635static int __devinit xonar_probe(struct pci_dev *pci,
687 const struct pci_device_id *pci_id) 636 const struct pci_device_id *pci_id)
688{ 637{
638 static const struct oxygen_model *const models[] = {
639 [MODEL_D1] = &model_xonar_d1,
640 [MODEL_DX] = &model_xonar_d1,
641 [MODEL_D2] = &model_xonar_d2,
642 [MODEL_D2X] = &model_xonar_d2,
643 };
689 static int dev; 644 static int dev;
690 int err; 645 int err;
691 646
@@ -695,8 +650,10 @@ static int __devinit xonar_probe(struct pci_dev *pci,
695 ++dev; 650 ++dev;
696 return -ENOENT; 651 return -ENOENT;
697 } 652 }
653 BUG_ON(pci_id->driver_data >= ARRAY_SIZE(models));
698 err = oxygen_pci_probe(pci, index[dev], id[dev], 654 err = oxygen_pci_probe(pci, index[dev], id[dev],
699 &xonar_models[pci_id->driver_data], 0); 655 models[pci_id->driver_data],
656 pci_id->driver_data);
700 if (err >= 0) 657 if (err >= 0)
701 ++dev; 658 ++dev;
702 return err; 659 return err;