diff options
| -rw-r--r-- | Documentation/sound/alsa/ALSA-Configuration.txt | 2 | ||||
| -rw-r--r-- | sound/pci/Kconfig | 3 | ||||
| -rw-r--r-- | sound/pci/oxygen/hifier.c | 12 | ||||
| -rw-r--r-- | sound/pci/oxygen/oxygen.c | 114 | ||||
| -rw-r--r-- | sound/pci/oxygen/oxygen.h | 22 | ||||
| -rw-r--r-- | sound/pci/oxygen/oxygen_io.c | 31 | ||||
| -rw-r--r-- | sound/pci/oxygen/oxygen_lib.c | 100 | ||||
| -rw-r--r-- | sound/pci/oxygen/virtuoso.c | 339 |
8 files changed, 507 insertions, 116 deletions
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index c911c203d1f5..012858d2b119 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt | |||
| @@ -1859,7 +1859,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
| 1859 | ------------------- | 1859 | ------------------- |
| 1860 | 1860 | ||
| 1861 | Module for sound cards based on the Asus AV100/AV200 chips, | 1861 | Module for sound cards based on the Asus AV100/AV200 chips, |
| 1862 | i.e., Xonar D1, DX, D2, D2X and HDAV1.3 (Deluxe). | 1862 | i.e., Xonar D1, DX, D2, D2X, HDAV1.3 (Deluxe), and Essence STX. |
| 1863 | 1863 | ||
| 1864 | This module supports autoprobe and multiple cards. | 1864 | This module supports autoprobe and multiple cards. |
| 1865 | 1865 | ||
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 9387ab00a41b..ca25e6179d76 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
| @@ -764,7 +764,8 @@ config SND_VIRTUOSO | |||
| 764 | select SND_OXYGEN_LIB | 764 | select SND_OXYGEN_LIB |
| 765 | help | 765 | help |
| 766 | Say Y here to include support for sound cards based on the | 766 | Say Y here to include support for sound cards based on the |
| 767 | Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2 and D2X. | 767 | Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, and |
| 768 | Essence STX. | ||
| 768 | Support for the HDAV1.3 (Deluxe) is very experimental. | 769 | Support for the HDAV1.3 (Deluxe) is very experimental. |
| 769 | 770 | ||
| 770 | To compile this driver as a module, choose M here: the module | 771 | To compile this driver as a module, choose M here: the module |
diff --git a/sound/pci/oxygen/hifier.c b/sound/pci/oxygen/hifier.c index 1ab833f843eb..84ef13183419 100644 --- a/sound/pci/oxygen/hifier.c +++ b/sound/pci/oxygen/hifier.c | |||
| @@ -45,6 +45,7 @@ MODULE_PARM_DESC(enable, "enable card"); | |||
| 45 | static struct pci_device_id hifier_ids[] __devinitdata = { | 45 | static struct pci_device_id hifier_ids[] __devinitdata = { |
| 46 | { OXYGEN_PCI_SUBID(0x14c3, 0x1710) }, | 46 | { OXYGEN_PCI_SUBID(0x14c3, 0x1710) }, |
| 47 | { OXYGEN_PCI_SUBID(0x14c3, 0x1711) }, | 47 | { OXYGEN_PCI_SUBID(0x14c3, 0x1711) }, |
| 48 | { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, | ||
| 48 | { } | 49 | { } |
| 49 | }; | 50 | }; |
| 50 | MODULE_DEVICE_TABLE(pci, hifier_ids); | 51 | MODULE_DEVICE_TABLE(pci, hifier_ids); |
| @@ -151,7 +152,6 @@ static const struct oxygen_model model_hifier = { | |||
| 151 | .shortname = "C-Media CMI8787", | 152 | .shortname = "C-Media CMI8787", |
| 152 | .longname = "C-Media Oxygen HD Audio", | 153 | .longname = "C-Media Oxygen HD Audio", |
| 153 | .chip = "CMI8788", | 154 | .chip = "CMI8788", |
| 154 | .owner = THIS_MODULE, | ||
| 155 | .init = hifier_init, | 155 | .init = hifier_init, |
| 156 | .control_filter = hifier_control_filter, | 156 | .control_filter = hifier_control_filter, |
| 157 | .cleanup = hifier_cleanup, | 157 | .cleanup = hifier_cleanup, |
| @@ -173,6 +173,13 @@ static const struct oxygen_model model_hifier = { | |||
| 173 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 173 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
| 174 | }; | 174 | }; |
| 175 | 175 | ||
| 176 | static int __devinit get_hifier_model(struct oxygen *chip, | ||
| 177 | const struct pci_device_id *id) | ||
| 178 | { | ||
| 179 | chip->model = model_hifier; | ||
| 180 | return 0; | ||
| 181 | } | ||
| 182 | |||
| 176 | static int __devinit hifier_probe(struct pci_dev *pci, | 183 | static int __devinit hifier_probe(struct pci_dev *pci, |
| 177 | const struct pci_device_id *pci_id) | 184 | const struct pci_device_id *pci_id) |
| 178 | { | 185 | { |
| @@ -185,7 +192,8 @@ static int __devinit hifier_probe(struct pci_dev *pci, | |||
| 185 | ++dev; | 192 | ++dev; |
| 186 | return -ENOENT; | 193 | return -ENOENT; |
| 187 | } | 194 | } |
| 188 | err = oxygen_pci_probe(pci, index[dev], id[dev], &model_hifier, 0); | 195 | err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, |
| 196 | hifier_ids, get_hifier_model); | ||
| 189 | if (err >= 0) | 197 | if (err >= 0) |
| 190 | ++dev; | 198 | ++dev; |
| 191 | return err; | 199 | return err; |
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c index de999c6d6dd3..72db4c39007f 100644 --- a/sound/pci/oxygen/oxygen.c +++ b/sound/pci/oxygen/oxygen.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * C-Media CMI8788 driver for C-Media's reference design and for the X-Meridian | 2 | * C-Media CMI8788 driver for C-Media's reference design and similar models |
| 3 | * | 3 | * |
| 4 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> | 4 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> |
| 5 | * | 5 | * |
| @@ -26,6 +26,7 @@ | |||
| 26 | * | 26 | * |
| 27 | * GPIO 0 -> DFS0 of AK5385 | 27 | * GPIO 0 -> DFS0 of AK5385 |
| 28 | * GPIO 1 -> DFS1 of AK5385 | 28 | * GPIO 1 -> DFS1 of AK5385 |
| 29 | * GPIO 8 -> enable headphone amplifier on HT-Omega models | ||
| 29 | */ | 30 | */ |
| 30 | 31 | ||
| 31 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
| @@ -61,7 +62,8 @@ MODULE_PARM_DESC(enable, "enable card"); | |||
| 61 | enum { | 62 | enum { |
| 62 | MODEL_CMEDIA_REF, /* C-Media's reference design */ | 63 | MODEL_CMEDIA_REF, /* C-Media's reference design */ |
| 63 | MODEL_MERIDIAN, /* AuzenTech X-Meridian */ | 64 | MODEL_MERIDIAN, /* AuzenTech X-Meridian */ |
| 64 | MODEL_HALO, /* HT-Omega Claro halo */ | 65 | MODEL_CLARO, /* HT-Omega Claro */ |
| 66 | MODEL_CLARO_HALO, /* HT-Omega Claro halo */ | ||
| 65 | }; | 67 | }; |
| 66 | 68 | ||
| 67 | static struct pci_device_id oxygen_ids[] __devinitdata = { | 69 | static struct pci_device_id oxygen_ids[] __devinitdata = { |
| @@ -74,8 +76,8 @@ static struct pci_device_id oxygen_ids[] __devinitdata = { | |||
| 74 | { OXYGEN_PCI_SUBID(0x147a, 0xa017), .driver_data = MODEL_CMEDIA_REF }, | 76 | { OXYGEN_PCI_SUBID(0x147a, 0xa017), .driver_data = MODEL_CMEDIA_REF }, |
| 75 | { OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF }, | 77 | { OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF }, |
| 76 | { OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN }, | 78 | { OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN }, |
| 77 | { OXYGEN_PCI_SUBID(0x7284, 0x9761), .driver_data = MODEL_CMEDIA_REF }, | 79 | { OXYGEN_PCI_SUBID(0x7284, 0x9761), .driver_data = MODEL_CLARO }, |
| 78 | { OXYGEN_PCI_SUBID(0x7284, 0x9781), .driver_data = MODEL_HALO }, | 80 | { OXYGEN_PCI_SUBID(0x7284, 0x9781), .driver_data = MODEL_CLARO_HALO }, |
| 79 | { } | 81 | { } |
| 80 | }; | 82 | }; |
| 81 | MODULE_DEVICE_TABLE(pci, oxygen_ids); | 83 | MODULE_DEVICE_TABLE(pci, oxygen_ids); |
| @@ -86,6 +88,8 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids); | |||
| 86 | #define GPIO_AK5385_DFS_DOUBLE 0x0001 | 88 | #define GPIO_AK5385_DFS_DOUBLE 0x0001 |
| 87 | #define GPIO_AK5385_DFS_QUAD 0x0002 | 89 | #define GPIO_AK5385_DFS_QUAD 0x0002 |
| 88 | 90 | ||
| 91 | #define GPIO_CLARO_HP 0x0100 | ||
| 92 | |||
| 89 | struct generic_data { | 93 | struct generic_data { |
| 90 | u8 ak4396_ctl2; | 94 | u8 ak4396_ctl2; |
| 91 | u16 saved_wm8785_registers[2]; | 95 | u16 saved_wm8785_registers[2]; |
| @@ -196,10 +200,46 @@ static void meridian_init(struct oxygen *chip) | |||
| 196 | ak5385_init(chip); | 200 | ak5385_init(chip); |
| 197 | } | 201 | } |
| 198 | 202 | ||
| 203 | static void claro_enable_hp(struct oxygen *chip) | ||
| 204 | { | ||
| 205 | msleep(300); | ||
| 206 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CLARO_HP); | ||
| 207 | oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_HP); | ||
| 208 | } | ||
| 209 | |||
| 210 | static void claro_init(struct oxygen *chip) | ||
| 211 | { | ||
| 212 | ak4396_init(chip); | ||
| 213 | wm8785_init(chip); | ||
| 214 | claro_enable_hp(chip); | ||
| 215 | } | ||
| 216 | |||
| 217 | static void claro_halo_init(struct oxygen *chip) | ||
| 218 | { | ||
| 219 | ak4396_init(chip); | ||
| 220 | ak5385_init(chip); | ||
| 221 | claro_enable_hp(chip); | ||
| 222 | } | ||
| 223 | |||
| 199 | static void generic_cleanup(struct oxygen *chip) | 224 | static void generic_cleanup(struct oxygen *chip) |
| 200 | { | 225 | { |
| 201 | } | 226 | } |
| 202 | 227 | ||
| 228 | static void claro_disable_hp(struct oxygen *chip) | ||
| 229 | { | ||
| 230 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_HP); | ||
| 231 | } | ||
| 232 | |||
| 233 | static void claro_cleanup(struct oxygen *chip) | ||
| 234 | { | ||
| 235 | claro_disable_hp(chip); | ||
| 236 | } | ||
| 237 | |||
| 238 | static void claro_suspend(struct oxygen *chip) | ||
| 239 | { | ||
| 240 | claro_disable_hp(chip); | ||
| 241 | } | ||
| 242 | |||
| 203 | static void generic_resume(struct oxygen *chip) | 243 | static void generic_resume(struct oxygen *chip) |
| 204 | { | 244 | { |
| 205 | ak4396_registers_init(chip); | 245 | ak4396_registers_init(chip); |
| @@ -211,6 +251,12 @@ static void meridian_resume(struct oxygen *chip) | |||
| 211 | ak4396_registers_init(chip); | 251 | ak4396_registers_init(chip); |
| 212 | } | 252 | } |
| 213 | 253 | ||
| 254 | static void claro_resume(struct oxygen *chip) | ||
| 255 | { | ||
| 256 | ak4396_registers_init(chip); | ||
| 257 | claro_enable_hp(chip); | ||
| 258 | } | ||
| 259 | |||
| 214 | static void set_ak4396_params(struct oxygen *chip, | 260 | static void set_ak4396_params(struct oxygen *chip, |
| 215 | struct snd_pcm_hw_params *params) | 261 | struct snd_pcm_hw_params *params) |
| 216 | { | 262 | { |
| @@ -293,30 +339,10 @@ static void set_ak5385_params(struct oxygen *chip, | |||
| 293 | 339 | ||
| 294 | static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); | 340 | static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); |
| 295 | 341 | ||
| 296 | static int generic_probe(struct oxygen *chip, unsigned long driver_data) | ||
| 297 | { | ||
| 298 | if (driver_data == MODEL_MERIDIAN) { | ||
| 299 | chip->model.init = meridian_init; | ||
| 300 | chip->model.resume = meridian_resume; | ||
| 301 | chip->model.set_adc_params = set_ak5385_params; | ||
| 302 | chip->model.device_config = PLAYBACK_0_TO_I2S | | ||
| 303 | PLAYBACK_1_TO_SPDIF | | ||
| 304 | CAPTURE_0_FROM_I2S_2 | | ||
| 305 | CAPTURE_1_FROM_SPDIF; | ||
| 306 | } | ||
| 307 | if (driver_data == MODEL_MERIDIAN || driver_data == MODEL_HALO) { | ||
| 308 | chip->model.misc_flags = OXYGEN_MISC_MIDI; | ||
| 309 | chip->model.device_config |= MIDI_OUTPUT | MIDI_INPUT; | ||
| 310 | } | ||
| 311 | return 0; | ||
| 312 | } | ||
| 313 | |||
| 314 | static const struct oxygen_model model_generic = { | 342 | static const struct oxygen_model model_generic = { |
| 315 | .shortname = "C-Media CMI8788", | 343 | .shortname = "C-Media CMI8788", |
| 316 | .longname = "C-Media Oxygen HD Audio", | 344 | .longname = "C-Media Oxygen HD Audio", |
| 317 | .chip = "CMI8788", | 345 | .chip = "CMI8788", |
| 318 | .owner = THIS_MODULE, | ||
| 319 | .probe = generic_probe, | ||
| 320 | .init = generic_init, | 346 | .init = generic_init, |
| 321 | .cleanup = generic_cleanup, | 347 | .cleanup = generic_cleanup, |
| 322 | .resume = generic_resume, | 348 | .resume = generic_resume, |
| @@ -341,6 +367,42 @@ static const struct oxygen_model model_generic = { | |||
| 341 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 367 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
| 342 | }; | 368 | }; |
| 343 | 369 | ||
| 370 | static int __devinit get_oxygen_model(struct oxygen *chip, | ||
| 371 | const struct pci_device_id *id) | ||
| 372 | { | ||
| 373 | chip->model = model_generic; | ||
| 374 | switch (id->driver_data) { | ||
| 375 | case MODEL_MERIDIAN: | ||
| 376 | chip->model.init = meridian_init; | ||
| 377 | chip->model.resume = meridian_resume; | ||
| 378 | chip->model.set_adc_params = set_ak5385_params; | ||
| 379 | chip->model.device_config = PLAYBACK_0_TO_I2S | | ||
| 380 | PLAYBACK_1_TO_SPDIF | | ||
| 381 | CAPTURE_0_FROM_I2S_2 | | ||
| 382 | CAPTURE_1_FROM_SPDIF; | ||
| 383 | break; | ||
| 384 | case MODEL_CLARO: | ||
| 385 | chip->model.init = claro_init; | ||
| 386 | chip->model.cleanup = claro_cleanup; | ||
| 387 | chip->model.suspend = claro_suspend; | ||
| 388 | chip->model.resume = claro_resume; | ||
| 389 | break; | ||
| 390 | case MODEL_CLARO_HALO: | ||
| 391 | chip->model.init = claro_halo_init; | ||
| 392 | chip->model.cleanup = claro_cleanup; | ||
| 393 | chip->model.suspend = claro_suspend; | ||
| 394 | chip->model.resume = claro_resume; | ||
| 395 | chip->model.set_adc_params = set_ak5385_params; | ||
| 396 | break; | ||
| 397 | } | ||
| 398 | if (id->driver_data == MODEL_MERIDIAN || | ||
| 399 | id->driver_data == MODEL_CLARO_HALO) { | ||
| 400 | chip->model.misc_flags = OXYGEN_MISC_MIDI; | ||
| 401 | chip->model.device_config |= MIDI_OUTPUT | MIDI_INPUT; | ||
| 402 | } | ||
| 403 | return 0; | ||
| 404 | } | ||
| 405 | |||
| 344 | static int __devinit generic_oxygen_probe(struct pci_dev *pci, | 406 | static int __devinit generic_oxygen_probe(struct pci_dev *pci, |
| 345 | const struct pci_device_id *pci_id) | 407 | const struct pci_device_id *pci_id) |
| 346 | { | 408 | { |
| @@ -353,8 +415,8 @@ static int __devinit generic_oxygen_probe(struct pci_dev *pci, | |||
| 353 | ++dev; | 415 | ++dev; |
| 354 | return -ENOENT; | 416 | return -ENOENT; |
| 355 | } | 417 | } |
| 356 | err = oxygen_pci_probe(pci, index[dev], id[dev], | 418 | err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, |
| 357 | &model_generic, pci_id->driver_data); | 419 | oxygen_ids, get_oxygen_model); |
| 358 | if (err >= 0) | 420 | if (err >= 0) |
| 359 | ++dev; | 421 | ++dev; |
| 360 | return err; | 422 | return err; |
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h index 19107c6307e5..bd615dbffadb 100644 --- a/sound/pci/oxygen/oxygen.h +++ b/sound/pci/oxygen/oxygen.h | |||
| @@ -18,6 +18,8 @@ | |||
| 18 | 18 | ||
| 19 | #define OXYGEN_IO_SIZE 0x100 | 19 | #define OXYGEN_IO_SIZE 0x100 |
| 20 | 20 | ||
| 21 | #define OXYGEN_EEPROM_ID 0x434d /* "CM" */ | ||
| 22 | |||
| 21 | /* model-specific configuration of outputs/inputs */ | 23 | /* model-specific configuration of outputs/inputs */ |
| 22 | #define PLAYBACK_0_TO_I2S 0x0001 | 24 | #define PLAYBACK_0_TO_I2S 0x0001 |
| 23 | /* PLAYBACK_0_TO_AC97_0 not implemented */ | 25 | /* PLAYBACK_0_TO_AC97_0 not implemented */ |
| @@ -49,7 +51,13 @@ enum { | |||
| 49 | .subvendor = sv, \ | 51 | .subvendor = sv, \ |
| 50 | .subdevice = sd | 52 | .subdevice = sd |
| 51 | 53 | ||
| 54 | #define BROKEN_EEPROM_DRIVER_DATA ((unsigned long)-1) | ||
| 55 | #define OXYGEN_PCI_SUBID_BROKEN_EEPROM \ | ||
| 56 | OXYGEN_PCI_SUBID(PCI_VENDOR_ID_CMEDIA, 0x8788), \ | ||
| 57 | .driver_data = BROKEN_EEPROM_DRIVER_DATA | ||
| 58 | |||
| 52 | struct pci_dev; | 59 | struct pci_dev; |
| 60 | struct pci_device_id; | ||
| 53 | struct snd_card; | 61 | struct snd_card; |
| 54 | struct snd_pcm_substream; | 62 | struct snd_pcm_substream; |
| 55 | struct snd_pcm_hardware; | 63 | struct snd_pcm_hardware; |
| @@ -62,8 +70,6 @@ struct oxygen_model { | |||
| 62 | const char *shortname; | 70 | const char *shortname; |
| 63 | const char *longname; | 71 | const char *longname; |
| 64 | const char *chip; | 72 | const char *chip; |
| 65 | struct module *owner; | ||
| 66 | int (*probe)(struct oxygen *chip, unsigned long driver_data); | ||
| 67 | void (*init)(struct oxygen *chip); | 73 | void (*init)(struct oxygen *chip); |
| 68 | int (*control_filter)(struct snd_kcontrol_new *template); | 74 | int (*control_filter)(struct snd_kcontrol_new *template); |
| 69 | int (*mixer_init)(struct oxygen *chip); | 75 | int (*mixer_init)(struct oxygen *chip); |
| @@ -83,6 +89,7 @@ struct oxygen_model { | |||
| 83 | void (*ac97_switch)(struct oxygen *chip, | 89 | void (*ac97_switch)(struct oxygen *chip, |
| 84 | unsigned int reg, unsigned int mute); | 90 | unsigned int reg, unsigned int mute); |
| 85 | const unsigned int *dac_tlv; | 91 | const unsigned int *dac_tlv; |
| 92 | unsigned long private_data; | ||
| 86 | size_t model_data_size; | 93 | size_t model_data_size; |
| 87 | unsigned int device_config; | 94 | unsigned int device_config; |
| 88 | u8 dac_channels; | 95 | u8 dac_channels; |
| @@ -134,8 +141,12 @@ struct oxygen { | |||
| 134 | /* oxygen_lib.c */ | 141 | /* oxygen_lib.c */ |
| 135 | 142 | ||
| 136 | int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | 143 | int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, |
| 137 | const struct oxygen_model *model, | 144 | struct module *owner, |
| 138 | unsigned long driver_data); | 145 | const struct pci_device_id *ids, |
| 146 | int (*get_model)(struct oxygen *chip, | ||
| 147 | const struct pci_device_id *id | ||
| 148 | ) | ||
| 149 | ); | ||
| 139 | void oxygen_pci_remove(struct pci_dev *pci); | 150 | void oxygen_pci_remove(struct pci_dev *pci); |
| 140 | #ifdef CONFIG_PM | 151 | #ifdef CONFIG_PM |
| 141 | int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state); | 152 | int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state); |
| @@ -180,6 +191,9 @@ void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data); | |||
| 180 | void oxygen_reset_uart(struct oxygen *chip); | 191 | void oxygen_reset_uart(struct oxygen *chip); |
| 181 | void oxygen_write_uart(struct oxygen *chip, u8 data); | 192 | void oxygen_write_uart(struct oxygen *chip, u8 data); |
| 182 | 193 | ||
| 194 | u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index); | ||
| 195 | void oxygen_write_eeprom(struct oxygen *chip, unsigned int index, u16 value); | ||
| 196 | |||
| 183 | static inline void oxygen_set_bits8(struct oxygen *chip, | 197 | static inline void oxygen_set_bits8(struct oxygen *chip, |
| 184 | unsigned int reg, u8 value) | 198 | unsigned int reg, u8 value) |
| 185 | { | 199 | { |
diff --git a/sound/pci/oxygen/oxygen_io.c b/sound/pci/oxygen/oxygen_io.c index 3126c4b403dd..c1eb923f2ac9 100644 --- a/sound/pci/oxygen/oxygen_io.c +++ b/sound/pci/oxygen/oxygen_io.c | |||
| @@ -254,3 +254,34 @@ void oxygen_write_uart(struct oxygen *chip, u8 data) | |||
| 254 | _write_uart(chip, 0, data); | 254 | _write_uart(chip, 0, data); |
| 255 | } | 255 | } |
| 256 | EXPORT_SYMBOL(oxygen_write_uart); | 256 | EXPORT_SYMBOL(oxygen_write_uart); |
| 257 | |||
| 258 | u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index) | ||
| 259 | { | ||
| 260 | unsigned int timeout; | ||
| 261 | |||
| 262 | oxygen_write8(chip, OXYGEN_EEPROM_CONTROL, | ||
| 263 | index | OXYGEN_EEPROM_DIR_READ); | ||
| 264 | for (timeout = 0; timeout < 100; ++timeout) { | ||
| 265 | udelay(1); | ||
| 266 | if (!(oxygen_read8(chip, OXYGEN_EEPROM_STATUS) | ||
| 267 | & OXYGEN_EEPROM_BUSY)) | ||
| 268 | break; | ||
| 269 | } | ||
| 270 | return oxygen_read16(chip, OXYGEN_EEPROM_DATA); | ||
| 271 | } | ||
| 272 | |||
| 273 | void oxygen_write_eeprom(struct oxygen *chip, unsigned int index, u16 value) | ||
| 274 | { | ||
| 275 | unsigned int timeout; | ||
| 276 | |||
| 277 | oxygen_write16(chip, OXYGEN_EEPROM_DATA, value); | ||
| 278 | oxygen_write8(chip, OXYGEN_EEPROM_CONTROL, | ||
| 279 | index | OXYGEN_EEPROM_DIR_WRITE); | ||
| 280 | for (timeout = 0; timeout < 10; ++timeout) { | ||
| 281 | msleep(1); | ||
| 282 | if (!(oxygen_read8(chip, OXYGEN_EEPROM_STATUS) | ||
| 283 | & OXYGEN_EEPROM_BUSY)) | ||
| 284 | return; | ||
| 285 | } | ||
| 286 | snd_printk(KERN_ERR "EEPROM write timeout\n"); | ||
| 287 | } | ||
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index 9c81e0b05113..312251d39696 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c | |||
| @@ -34,6 +34,7 @@ MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); | |||
| 34 | MODULE_DESCRIPTION("C-Media CMI8788 helper library"); | 34 | MODULE_DESCRIPTION("C-Media CMI8788 helper library"); |
| 35 | MODULE_LICENSE("GPL v2"); | 35 | MODULE_LICENSE("GPL v2"); |
| 36 | 36 | ||
| 37 | #define DRIVER "oxygen" | ||
| 37 | 38 | ||
| 38 | static inline int oxygen_uart_input_ready(struct oxygen *chip) | 39 | static inline int oxygen_uart_input_ready(struct oxygen *chip) |
| 39 | { | 40 | { |
| @@ -243,6 +244,62 @@ static void oxygen_proc_init(struct oxygen *chip) | |||
| 243 | #define oxygen_proc_init(chip) | 244 | #define oxygen_proc_init(chip) |
| 244 | #endif | 245 | #endif |
| 245 | 246 | ||
| 247 | static const struct pci_device_id * | ||
| 248 | oxygen_search_pci_id(struct oxygen *chip, const struct pci_device_id ids[]) | ||
| 249 | { | ||
| 250 | u16 subdevice; | ||
| 251 | |||
| 252 | /* | ||
| 253 | * Make sure the EEPROM pins are available, i.e., not used for SPI. | ||
| 254 | * (This function is called before we initialize or use SPI.) | ||
| 255 | */ | ||
| 256 | oxygen_clear_bits8(chip, OXYGEN_FUNCTION, | ||
| 257 | OXYGEN_FUNCTION_ENABLE_SPI_4_5); | ||
| 258 | /* | ||
| 259 | * Read the subsystem device ID directly from the EEPROM, because the | ||
| 260 | * chip didn't if the first EEPROM word was overwritten. | ||
| 261 | */ | ||
| 262 | subdevice = oxygen_read_eeprom(chip, 2); | ||
| 263 | /* | ||
| 264 | * We use only the subsystem device ID for searching because it is | ||
| 265 | * unique even without the subsystem vendor ID, which may have been | ||
| 266 | * overwritten in the EEPROM. | ||
| 267 | */ | ||
| 268 | for (; ids->vendor; ++ids) | ||
| 269 | if (ids->subdevice == subdevice && | ||
| 270 | ids->driver_data != BROKEN_EEPROM_DRIVER_DATA) | ||
| 271 | return ids; | ||
| 272 | return NULL; | ||
| 273 | } | ||
| 274 | |||
| 275 | static void oxygen_restore_eeprom(struct oxygen *chip, | ||
| 276 | const struct pci_device_id *id) | ||
| 277 | { | ||
| 278 | if (oxygen_read_eeprom(chip, 0) != OXYGEN_EEPROM_ID) { | ||
| 279 | /* | ||
| 280 | * This function gets called only when a known card model has | ||
| 281 | * been detected, i.e., we know there is a valid subsystem | ||
| 282 | * product ID at index 2 in the EEPROM. Therefore, we have | ||
| 283 | * been able to deduce the correct subsystem vendor ID, and | ||
| 284 | * this is enough information to restore the original EEPROM | ||
| 285 | * contents. | ||
| 286 | */ | ||
| 287 | oxygen_write_eeprom(chip, 1, id->subvendor); | ||
| 288 | oxygen_write_eeprom(chip, 0, OXYGEN_EEPROM_ID); | ||
| 289 | |||
| 290 | oxygen_set_bits8(chip, OXYGEN_MISC, | ||
| 291 | OXYGEN_MISC_WRITE_PCI_SUBID); | ||
| 292 | pci_write_config_word(chip->pci, PCI_SUBSYSTEM_VENDOR_ID, | ||
| 293 | id->subvendor); | ||
| 294 | pci_write_config_word(chip->pci, PCI_SUBSYSTEM_ID, | ||
| 295 | id->subdevice); | ||
| 296 | oxygen_clear_bits8(chip, OXYGEN_MISC, | ||
| 297 | OXYGEN_MISC_WRITE_PCI_SUBID); | ||
| 298 | |||
| 299 | snd_printk(KERN_INFO "EEPROM ID restored\n"); | ||
| 300 | } | ||
| 301 | } | ||
| 302 | |||
| 246 | static void oxygen_init(struct oxygen *chip) | 303 | static void oxygen_init(struct oxygen *chip) |
| 247 | { | 304 | { |
| 248 | unsigned int i; | 305 | unsigned int i; |
| @@ -446,21 +503,26 @@ static void oxygen_card_free(struct snd_card *card) | |||
| 446 | free_irq(chip->irq, chip); | 503 | free_irq(chip->irq, chip); |
| 447 | flush_scheduled_work(); | 504 | flush_scheduled_work(); |
| 448 | chip->model.cleanup(chip); | 505 | chip->model.cleanup(chip); |
| 506 | kfree(chip->model_data); | ||
| 449 | mutex_destroy(&chip->mutex); | 507 | mutex_destroy(&chip->mutex); |
| 450 | pci_release_regions(chip->pci); | 508 | pci_release_regions(chip->pci); |
| 451 | pci_disable_device(chip->pci); | 509 | pci_disable_device(chip->pci); |
| 452 | } | 510 | } |
| 453 | 511 | ||
| 454 | int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | 512 | int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, |
| 455 | const struct oxygen_model *model, | 513 | struct module *owner, |
| 456 | unsigned long driver_data) | 514 | const struct pci_device_id *ids, |
| 515 | int (*get_model)(struct oxygen *chip, | ||
| 516 | const struct pci_device_id *id | ||
| 517 | ) | ||
| 518 | ) | ||
| 457 | { | 519 | { |
| 458 | struct snd_card *card; | 520 | struct snd_card *card; |
| 459 | struct oxygen *chip; | 521 | struct oxygen *chip; |
| 522 | const struct pci_device_id *pci_id; | ||
| 460 | int err; | 523 | int err; |
| 461 | 524 | ||
| 462 | err = snd_card_create(index, id, model->owner, | 525 | err = snd_card_create(index, id, owner, sizeof(*chip), &card); |
| 463 | sizeof(*chip) + model->model_data_size, &card); | ||
| 464 | if (err < 0) | 526 | if (err < 0) |
| 465 | return err; | 527 | return err; |
| 466 | 528 | ||
| @@ -468,8 +530,6 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
| 468 | chip->card = card; | 530 | chip->card = card; |
| 469 | chip->pci = pci; | 531 | chip->pci = pci; |
| 470 | chip->irq = -1; | 532 | chip->irq = -1; |
| 471 | chip->model = *model; | ||
| 472 | chip->model_data = chip + 1; | ||
| 473 | spin_lock_init(&chip->reg_lock); | 533 | spin_lock_init(&chip->reg_lock); |
| 474 | mutex_init(&chip->mutex); | 534 | mutex_init(&chip->mutex); |
| 475 | INIT_WORK(&chip->spdif_input_bits_work, | 535 | INIT_WORK(&chip->spdif_input_bits_work, |
| @@ -481,7 +541,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
| 481 | if (err < 0) | 541 | if (err < 0) |
| 482 | goto err_card; | 542 | goto err_card; |
| 483 | 543 | ||
| 484 | err = pci_request_regions(pci, model->chip); | 544 | err = pci_request_regions(pci, DRIVER); |
| 485 | if (err < 0) { | 545 | if (err < 0) { |
| 486 | snd_printk(KERN_ERR "cannot reserve PCI resources\n"); | 546 | snd_printk(KERN_ERR "cannot reserve PCI resources\n"); |
| 487 | goto err_pci_enable; | 547 | goto err_pci_enable; |
| @@ -495,20 +555,34 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
| 495 | } | 555 | } |
| 496 | chip->addr = pci_resource_start(pci, 0); | 556 | chip->addr = pci_resource_start(pci, 0); |
| 497 | 557 | ||
| 558 | pci_id = oxygen_search_pci_id(chip, ids); | ||
| 559 | if (!pci_id) { | ||
| 560 | err = -ENODEV; | ||
| 561 | goto err_pci_regions; | ||
| 562 | } | ||
| 563 | oxygen_restore_eeprom(chip, pci_id); | ||
| 564 | err = get_model(chip, pci_id); | ||
| 565 | if (err < 0) | ||
| 566 | goto err_pci_regions; | ||
| 567 | |||
| 568 | if (chip->model.model_data_size) { | ||
| 569 | chip->model_data = kzalloc(chip->model.model_data_size, | ||
| 570 | GFP_KERNEL); | ||
| 571 | if (!chip->model_data) { | ||
| 572 | err = -ENOMEM; | ||
| 573 | goto err_pci_regions; | ||
| 574 | } | ||
| 575 | } | ||
| 576 | |||
| 498 | pci_set_master(pci); | 577 | pci_set_master(pci); |
| 499 | snd_card_set_dev(card, &pci->dev); | 578 | snd_card_set_dev(card, &pci->dev); |
| 500 | card->private_free = oxygen_card_free; | 579 | card->private_free = oxygen_card_free; |
| 501 | 580 | ||
| 502 | if (chip->model.probe) { | ||
| 503 | err = chip->model.probe(chip, driver_data); | ||
| 504 | if (err < 0) | ||
| 505 | goto err_card; | ||
| 506 | } | ||
| 507 | oxygen_init(chip); | 581 | oxygen_init(chip); |
| 508 | chip->model.init(chip); | 582 | chip->model.init(chip); |
| 509 | 583 | ||
| 510 | err = request_irq(pci->irq, oxygen_interrupt, IRQF_SHARED, | 584 | err = request_irq(pci->irq, oxygen_interrupt, IRQF_SHARED, |
| 511 | chip->model.chip, chip); | 585 | DRIVER, chip); |
| 512 | if (err < 0) { | 586 | if (err < 0) { |
| 513 | snd_printk(KERN_ERR "cannot grab interrupt %d\n", pci->irq); | 587 | snd_printk(KERN_ERR "cannot grab interrupt %d\n", pci->irq); |
| 514 | goto err_card; | 588 | goto err_card; |
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; |
