aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/oxygen/virtuoso.c
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2009-02-19 02:42:44 -0500
committerTakashi Iwai <tiwai@suse.de>2009-02-19 04:22:25 -0500
commit30459d7b1843cbdea56ca120c8cac10dc5613e90 (patch)
tree47341d43931193917c28dab16eaf7e1a12b2b6d6 /sound/pci/oxygen/virtuoso.c
parenta69bb3c3fe0881d986ec78e253cb8a6bb9c28230 (diff)
sound: oxygen: handle cards with broken EEPROM
Under as yet unknown circumstances, the first word of the sound card's EEPROM gets overwritten. When this has happened, we cannot rely on the subsystem IDs that the kernel reads from the PCI configuration registers. Instead, we read the IDs directly from the EEPROM and do the ID matching manually. Because the model-specific driver cannot determine the model before calling oxygen_pci_probe(), that function now gets a get_model() callback as parameter. The customizing of the model structure, which was formerly done by the probe() callback, also has moved into get_model(). Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/oxygen/virtuoso.c')
-rw-r--r--sound/pci/oxygen/virtuoso.c134
1 files changed, 73 insertions, 61 deletions
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index c05f7e7bdb34..4ac49772da8c 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -160,6 +160,7 @@ static struct pci_device_id xonar_ids[] __devinitdata = {
160 { OXYGEN_PCI_SUBID(0x1043, 0x82b7), .driver_data = MODEL_D2X }, 160 { OXYGEN_PCI_SUBID(0x1043, 0x82b7), .driver_data = MODEL_D2X },
161 { OXYGEN_PCI_SUBID(0x1043, 0x8314), .driver_data = MODEL_HDAV }, 161 { OXYGEN_PCI_SUBID(0x1043, 0x8314), .driver_data = MODEL_HDAV },
162 { OXYGEN_PCI_SUBID(0x1043, 0x834f), .driver_data = MODEL_D1 }, 162 { OXYGEN_PCI_SUBID(0x1043, 0x834f), .driver_data = MODEL_D1 },
163 { OXYGEN_PCI_SUBID_BROKEN_EEPROM },
163 { } 164 { }
164}; 165};
165MODULE_DEVICE_TABLE(pci, xonar_ids); 166MODULE_DEVICE_TABLE(pci, xonar_ids);
@@ -188,7 +189,6 @@ MODULE_DEVICE_TABLE(pci, xonar_ids);
188#define I2C_DEVICE_CS4362A 0x30 /* 001100, AD0=0, /W=0 */ 189#define I2C_DEVICE_CS4362A 0x30 /* 001100, AD0=0, /W=0 */
189 190
190struct xonar_data { 191struct xonar_data {
191 unsigned int model;
192 unsigned int anti_pop_delay; 192 unsigned int anti_pop_delay;
193 unsigned int dacs; 193 unsigned int dacs;
194 u16 output_enable_bit; 194 u16 output_enable_bit;
@@ -334,15 +334,9 @@ static void xonar_d2_init(struct oxygen *chip)
334 struct xonar_data *data = chip->model_data; 334 struct xonar_data *data = chip->model_data;
335 335
336 data->anti_pop_delay = 300; 336 data->anti_pop_delay = 300;
337 data->dacs = 4;
337 data->output_enable_bit = GPIO_D2_OUTPUT_ENABLE; 338 data->output_enable_bit = GPIO_D2_OUTPUT_ENABLE;
338 data->pcm1796_oversampling = PCM1796_OS_64; 339 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 340
347 pcm1796_init(chip); 341 pcm1796_init(chip);
348 342
@@ -355,6 +349,18 @@ static void xonar_d2_init(struct oxygen *chip)
355 snd_component_add(chip->card, "CS5381"); 349 snd_component_add(chip->card, "CS5381");
356} 350}
357 351
352static void xonar_d2x_init(struct oxygen *chip)
353{
354 struct xonar_data *data = chip->model_data;
355
356 data->ext_power_reg = OXYGEN_GPIO_DATA;
357 data->ext_power_int_reg = OXYGEN_GPIO_INTERRUPT_MASK;
358 data->ext_power_bit = GPIO_D2X_EXT_POWER;
359 oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2X_EXT_POWER);
360
361 xonar_d2_init(chip);
362}
363
358static void update_cs4362a_volumes(struct oxygen *chip) 364static void update_cs4362a_volumes(struct oxygen *chip)
359{ 365{
360 u8 mute; 366 u8 mute;
@@ -422,11 +428,6 @@ static void xonar_d1_init(struct oxygen *chip)
422 data->cs4398_fm = CS4398_FM_SINGLE | CS4398_DEM_NONE | CS4398_DIF_LJUST; 428 data->cs4398_fm = CS4398_FM_SINGLE | CS4398_DEM_NONE | CS4398_DIF_LJUST;
423 data->cs4362a_fm = CS4362A_FM_SINGLE | 429 data->cs4362a_fm = CS4362A_FM_SINGLE |
424 CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L; 430 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 431
431 oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, 432 oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
432 OXYGEN_2WIRE_LENGTH_8 | 433 OXYGEN_2WIRE_LENGTH_8 |
@@ -447,6 +448,17 @@ static void xonar_d1_init(struct oxygen *chip)
447 snd_component_add(chip->card, "CS5361"); 448 snd_component_add(chip->card, "CS5361");
448} 449}
449 450
451static void xonar_dx_init(struct oxygen *chip)
452{
453 struct xonar_data *data = chip->model_data;
454
455 data->ext_power_reg = OXYGEN_GPI_DATA;
456 data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
457 data->ext_power_bit = GPI_DX_EXT_POWER;
458
459 xonar_d1_init(chip);
460}
461
450static void xonar_hdav_init(struct oxygen *chip) 462static void xonar_hdav_init(struct oxygen *chip)
451{ 463{
452 struct xonar_data *data = chip->model_data; 464 struct xonar_data *data = chip->model_data;
@@ -458,6 +470,7 @@ static void xonar_hdav_init(struct oxygen *chip)
458 OXYGEN_2WIRE_SPEED_FAST); 470 OXYGEN_2WIRE_SPEED_FAST);
459 471
460 data->anti_pop_delay = 100; 472 data->anti_pop_delay = 100;
473 data->dacs = chip->model.private_data == MODEL_HDAV_H6 ? 4 : 1;
461 data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE; 474 data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE;
462 data->ext_power_reg = OXYGEN_GPI_DATA; 475 data->ext_power_reg = OXYGEN_GPI_DATA;
463 data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; 476 data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
@@ -773,50 +786,9 @@ static int xonar_d1_mixer_init(struct oxygen *chip)
773 return snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip)); 786 return snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip));
774} 787}
775 788
776static int xonar_model_probe(struct oxygen *chip, unsigned long driver_data)
777{
778 static const char *const names[] = {
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}
815
816static const struct oxygen_model model_xonar_d2 = { 789static const struct oxygen_model model_xonar_d2 = {
817 .longname = "Asus Virtuoso 200", 790 .longname = "Asus Virtuoso 200",
818 .chip = "AV200", 791 .chip = "AV200",
819 .probe = xonar_model_probe,
820 .init = xonar_d2_init, 792 .init = xonar_d2_init,
821 .control_filter = xonar_d2_control_filter, 793 .control_filter = xonar_d2_control_filter,
822 .mixer_init = xonar_d2_mixer_init, 794 .mixer_init = xonar_d2_mixer_init,
@@ -848,7 +820,6 @@ static const struct oxygen_model model_xonar_d2 = {
848static const struct oxygen_model model_xonar_d1 = { 820static const struct oxygen_model model_xonar_d1 = {
849 .longname = "Asus Virtuoso 100", 821 .longname = "Asus Virtuoso 100",
850 .chip = "AV200", 822 .chip = "AV200",
851 .probe = xonar_model_probe,
852 .init = xonar_d1_init, 823 .init = xonar_d1_init,
853 .control_filter = xonar_d1_control_filter, 824 .control_filter = xonar_d1_control_filter,
854 .mixer_init = xonar_d1_mixer_init, 825 .mixer_init = xonar_d1_mixer_init,
@@ -876,7 +847,6 @@ static const struct oxygen_model model_xonar_d1 = {
876static const struct oxygen_model model_xonar_hdav = { 847static const struct oxygen_model model_xonar_hdav = {
877 .longname = "Asus Virtuoso 200", 848 .longname = "Asus Virtuoso 200",
878 .chip = "AV200", 849 .chip = "AV200",
879 .probe = xonar_model_probe,
880 .init = xonar_hdav_init, 850 .init = xonar_hdav_init,
881 .cleanup = xonar_hdav_cleanup, 851 .cleanup = xonar_hdav_cleanup,
882 .suspend = xonar_hdav_suspend, 852 .suspend = xonar_hdav_suspend,
@@ -902,8 +872,8 @@ static const struct oxygen_model model_xonar_hdav = {
902 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, 872 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
903}; 873};
904 874
905static int __devinit xonar_probe(struct pci_dev *pci, 875static int __devinit get_xonar_model(struct oxygen *chip,
906 const struct pci_device_id *pci_id) 876 const struct pci_device_id *id)
907{ 877{
908 static const struct oxygen_model *const models[] = { 878 static const struct oxygen_model *const models[] = {
909 [MODEL_D1] = &model_xonar_d1, 879 [MODEL_D1] = &model_xonar_d1,
@@ -912,6 +882,50 @@ static int __devinit xonar_probe(struct pci_dev *pci,
912 [MODEL_D2X] = &model_xonar_d2, 882 [MODEL_D2X] = &model_xonar_d2,
913 [MODEL_HDAV] = &model_xonar_hdav, 883 [MODEL_HDAV] = &model_xonar_hdav,
914 }; 884 };
885 static const char *const names[] = {
886 [MODEL_D1] = "Xonar D1",
887 [MODEL_DX] = "Xonar DX",
888 [MODEL_D2] = "Xonar D2",
889 [MODEL_D2X] = "Xonar D2X",
890 [MODEL_HDAV] = "Xonar HDAV1.3",
891 [MODEL_HDAV_H6] = "Xonar HDAV1.3+H6",
892 };
893 unsigned int model = id->driver_data;
894
895 if (model >= ARRAY_SIZE(models) || !models[model])
896 return -EINVAL;
897 chip->model = *models[model];
898
899 switch (model) {
900 case MODEL_D2X:
901 chip->model.init = xonar_d2x_init;
902 break;
903 case MODEL_DX:
904 chip->model.init = xonar_dx_init;
905 break;
906 case MODEL_HDAV:
907 oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
908 GPIO_HDAV_DB_MASK);
909 switch (oxygen_read16(chip, OXYGEN_GPIO_DATA) &
910 GPIO_HDAV_DB_MASK) {
911 case GPIO_HDAV_DB_H6:
912 model = MODEL_HDAV_H6;
913 break;
914 case GPIO_HDAV_DB_XX:
915 snd_printk(KERN_ERR "unknown daughterboard\n");
916 return -ENODEV;
917 }
918 break;
919 }
920
921 chip->model.shortname = names[model];
922 chip->model.private_data = model;
923 return 0;
924}
925
926static int __devinit xonar_probe(struct pci_dev *pci,
927 const struct pci_device_id *pci_id)
928{
915 static int dev; 929 static int dev;
916 int err; 930 int err;
917 931
@@ -921,10 +935,8 @@ static int __devinit xonar_probe(struct pci_dev *pci,
921 ++dev; 935 ++dev;
922 return -ENOENT; 936 return -ENOENT;
923 } 937 }
924 BUG_ON(pci_id->driver_data >= ARRAY_SIZE(models));
925 err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, 938 err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE,
926 models[pci_id->driver_data], 939 xonar_ids, get_xonar_model);
927 pci_id->driver_data);
928 if (err >= 0) 940 if (err >= 0)
929 ++dev; 941 ++dev;
930 return err; 942 return err;