diff options
-rw-r--r-- | sound/pci/oxygen/hifier.c | 11 | ||||
-rw-r--r-- | sound/pci/oxygen/oxygen.c | 44 | ||||
-rw-r--r-- | sound/pci/oxygen/oxygen.h | 17 | ||||
-rw-r--r-- | sound/pci/oxygen/oxygen_io.c | 15 | ||||
-rw-r--r-- | sound/pci/oxygen/oxygen_lib.c | 51 | ||||
-rw-r--r-- | sound/pci/oxygen/virtuoso.c | 134 |
6 files changed, 179 insertions, 93 deletions
diff --git a/sound/pci/oxygen/hifier.c b/sound/pci/oxygen/hifier.c index cc98bad9916a..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); |
@@ -172,6 +173,13 @@ static const struct oxygen_model model_hifier = { | |||
172 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 173 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
173 | }; | 174 | }; |
174 | 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 | |||
175 | static int __devinit hifier_probe(struct pci_dev *pci, | 183 | static int __devinit hifier_probe(struct pci_dev *pci, |
176 | const struct pci_device_id *pci_id) | 184 | const struct pci_device_id *pci_id) |
177 | { | 185 | { |
@@ -184,7 +192,8 @@ static int __devinit hifier_probe(struct pci_dev *pci, | |||
184 | ++dev; | 192 | ++dev; |
185 | return -ENOENT; | 193 | return -ENOENT; |
186 | } | 194 | } |
187 | err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, &model_hifier, 0); | 195 | err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, |
196 | hifier_ids, get_hifier_model); | ||
188 | if (err >= 0) | 197 | if (err >= 0) |
189 | ++dev; | 198 | ++dev; |
190 | return err; | 199 | return err; |
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c index 12b6c2137d50..f2c37f379d39 100644 --- a/sound/pci/oxygen/oxygen.c +++ b/sound/pci/oxygen/oxygen.c | |||
@@ -293,29 +293,10 @@ static void set_ak5385_params(struct oxygen *chip, | |||
293 | 293 | ||
294 | static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); | 294 | static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); |
295 | 295 | ||
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 = { | 296 | static const struct oxygen_model model_generic = { |
315 | .shortname = "C-Media CMI8788", | 297 | .shortname = "C-Media CMI8788", |
316 | .longname = "C-Media Oxygen HD Audio", | 298 | .longname = "C-Media Oxygen HD Audio", |
317 | .chip = "CMI8788", | 299 | .chip = "CMI8788", |
318 | .probe = generic_probe, | ||
319 | .init = generic_init, | 300 | .init = generic_init, |
320 | .cleanup = generic_cleanup, | 301 | .cleanup = generic_cleanup, |
321 | .resume = generic_resume, | 302 | .resume = generic_resume, |
@@ -340,6 +321,29 @@ static const struct oxygen_model model_generic = { | |||
340 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 321 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
341 | }; | 322 | }; |
342 | 323 | ||
324 | static int __devinit get_oxygen_model(struct oxygen *chip, | ||
325 | const struct pci_device_id *id) | ||
326 | { | ||
327 | chip->model = model_generic; | ||
328 | switch (id->driver_data) { | ||
329 | case MODEL_MERIDIAN: | ||
330 | chip->model.init = meridian_init; | ||
331 | chip->model.resume = meridian_resume; | ||
332 | chip->model.set_adc_params = set_ak5385_params; | ||
333 | chip->model.device_config = PLAYBACK_0_TO_I2S | | ||
334 | PLAYBACK_1_TO_SPDIF | | ||
335 | CAPTURE_0_FROM_I2S_2 | | ||
336 | CAPTURE_1_FROM_SPDIF; | ||
337 | break; | ||
338 | } | ||
339 | if (id->driver_data == MODEL_MERIDIAN || | ||
340 | id->driver_data == MODEL_HALO) { | ||
341 | chip->model.misc_flags = OXYGEN_MISC_MIDI; | ||
342 | chip->model.device_config |= MIDI_OUTPUT | MIDI_INPUT; | ||
343 | } | ||
344 | return 0; | ||
345 | } | ||
346 | |||
343 | static int __devinit generic_oxygen_probe(struct pci_dev *pci, | 347 | static int __devinit generic_oxygen_probe(struct pci_dev *pci, |
344 | const struct pci_device_id *pci_id) | 348 | const struct pci_device_id *pci_id) |
345 | { | 349 | { |
@@ -353,7 +357,7 @@ static int __devinit generic_oxygen_probe(struct pci_dev *pci, | |||
353 | return -ENOENT; | 357 | return -ENOENT; |
354 | } | 358 | } |
355 | err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, | 359 | err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, |
356 | &model_generic, pci_id->driver_data); | 360 | oxygen_ids, get_oxygen_model); |
357 | if (err >= 0) | 361 | if (err >= 0) |
358 | ++dev; | 362 | ++dev; |
359 | return err; | 363 | return err; |
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h index 268bff4f29d2..c500d48ea349 100644 --- a/sound/pci/oxygen/oxygen.h +++ b/sound/pci/oxygen/oxygen.h | |||
@@ -49,7 +49,13 @@ enum { | |||
49 | .subvendor = sv, \ | 49 | .subvendor = sv, \ |
50 | .subdevice = sd | 50 | .subdevice = sd |
51 | 51 | ||
52 | #define BROKEN_EEPROM_DRIVER_DATA ((unsigned long)-1) | ||
53 | #define OXYGEN_PCI_SUBID_BROKEN_EEPROM \ | ||
54 | OXYGEN_PCI_SUBID(PCI_VENDOR_ID_CMEDIA, 0x8788), \ | ||
55 | .driver_data = BROKEN_EEPROM_DRIVER_DATA | ||
56 | |||
52 | struct pci_dev; | 57 | struct pci_dev; |
58 | struct pci_device_id; | ||
53 | struct snd_card; | 59 | struct snd_card; |
54 | struct snd_pcm_substream; | 60 | struct snd_pcm_substream; |
55 | struct snd_pcm_hardware; | 61 | struct snd_pcm_hardware; |
@@ -62,7 +68,6 @@ struct oxygen_model { | |||
62 | const char *shortname; | 68 | const char *shortname; |
63 | const char *longname; | 69 | const char *longname; |
64 | const char *chip; | 70 | const char *chip; |
65 | int (*probe)(struct oxygen *chip, unsigned long driver_data); | ||
66 | void (*init)(struct oxygen *chip); | 71 | void (*init)(struct oxygen *chip); |
67 | int (*control_filter)(struct snd_kcontrol_new *template); | 72 | int (*control_filter)(struct snd_kcontrol_new *template); |
68 | int (*mixer_init)(struct oxygen *chip); | 73 | int (*mixer_init)(struct oxygen *chip); |
@@ -82,6 +87,7 @@ struct oxygen_model { | |||
82 | void (*ac97_switch)(struct oxygen *chip, | 87 | void (*ac97_switch)(struct oxygen *chip, |
83 | unsigned int reg, unsigned int mute); | 88 | unsigned int reg, unsigned int mute); |
84 | const unsigned int *dac_tlv; | 89 | const unsigned int *dac_tlv; |
90 | unsigned long private_data; | ||
85 | size_t model_data_size; | 91 | size_t model_data_size; |
86 | unsigned int device_config; | 92 | unsigned int device_config; |
87 | u8 dac_channels; | 93 | u8 dac_channels; |
@@ -134,8 +140,11 @@ struct oxygen { | |||
134 | 140 | ||
135 | int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | 141 | int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, |
136 | struct module *owner, | 142 | struct module *owner, |
137 | const struct oxygen_model *model, | 143 | const struct pci_device_id *ids, |
138 | unsigned long driver_data); | 144 | int (*get_model)(struct oxygen *chip, |
145 | const struct pci_device_id *id | ||
146 | ) | ||
147 | ); | ||
139 | void oxygen_pci_remove(struct pci_dev *pci); | 148 | void oxygen_pci_remove(struct pci_dev *pci); |
140 | #ifdef CONFIG_PM | 149 | #ifdef CONFIG_PM |
141 | int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state); | 150 | int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state); |
@@ -180,6 +189,8 @@ void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data); | |||
180 | void oxygen_reset_uart(struct oxygen *chip); | 189 | void oxygen_reset_uart(struct oxygen *chip); |
181 | void oxygen_write_uart(struct oxygen *chip, u8 data); | 190 | void oxygen_write_uart(struct oxygen *chip, u8 data); |
182 | 191 | ||
192 | u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index); | ||
193 | |||
183 | static inline void oxygen_set_bits8(struct oxygen *chip, | 194 | static inline void oxygen_set_bits8(struct oxygen *chip, |
184 | unsigned int reg, u8 value) | 195 | unsigned int reg, u8 value) |
185 | { | 196 | { |
diff --git a/sound/pci/oxygen/oxygen_io.c b/sound/pci/oxygen/oxygen_io.c index 3126c4b403dd..05f48ef1a442 100644 --- a/sound/pci/oxygen/oxygen_io.c +++ b/sound/pci/oxygen/oxygen_io.c | |||
@@ -254,3 +254,18 @@ 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 | } | ||
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index 516d94ad2bbb..d83c3a957323 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c | |||
@@ -244,6 +244,34 @@ static void oxygen_proc_init(struct oxygen *chip) | |||
244 | #define oxygen_proc_init(chip) | 244 | #define oxygen_proc_init(chip) |
245 | #endif | 245 | #endif |
246 | 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 | |||
247 | static void oxygen_init(struct oxygen *chip) | 275 | static void oxygen_init(struct oxygen *chip) |
248 | { | 276 | { |
249 | unsigned int i; | 277 | unsigned int i; |
@@ -455,11 +483,15 @@ static void oxygen_card_free(struct snd_card *card) | |||
455 | 483 | ||
456 | int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | 484 | int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, |
457 | struct module *owner, | 485 | struct module *owner, |
458 | const struct oxygen_model *model, | 486 | const struct pci_device_id *ids, |
459 | unsigned long driver_data) | 487 | int (*get_model)(struct oxygen *chip, |
488 | const struct pci_device_id *id | ||
489 | ) | ||
490 | ) | ||
460 | { | 491 | { |
461 | struct snd_card *card; | 492 | struct snd_card *card; |
462 | struct oxygen *chip; | 493 | struct oxygen *chip; |
494 | const struct pci_device_id *pci_id; | ||
463 | int err; | 495 | int err; |
464 | 496 | ||
465 | err = snd_card_create(index, id, owner, sizeof(*chip), &card); | 497 | err = snd_card_create(index, id, owner, sizeof(*chip), &card); |
@@ -470,7 +502,6 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
470 | chip->card = card; | 502 | chip->card = card; |
471 | chip->pci = pci; | 503 | chip->pci = pci; |
472 | chip->irq = -1; | 504 | chip->irq = -1; |
473 | chip->model = *model; | ||
474 | spin_lock_init(&chip->reg_lock); | 505 | spin_lock_init(&chip->reg_lock); |
475 | mutex_init(&chip->mutex); | 506 | mutex_init(&chip->mutex); |
476 | INIT_WORK(&chip->spdif_input_bits_work, | 507 | INIT_WORK(&chip->spdif_input_bits_work, |
@@ -496,6 +527,15 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
496 | } | 527 | } |
497 | chip->addr = pci_resource_start(pci, 0); | 528 | chip->addr = pci_resource_start(pci, 0); |
498 | 529 | ||
530 | pci_id = oxygen_search_pci_id(chip, ids); | ||
531 | if (!pci_id) { | ||
532 | err = -ENODEV; | ||
533 | goto err_pci_regions; | ||
534 | } | ||
535 | err = get_model(chip, pci_id); | ||
536 | if (err < 0) | ||
537 | goto err_pci_regions; | ||
538 | |||
499 | if (chip->model.model_data_size) { | 539 | if (chip->model.model_data_size) { |
500 | chip->model_data = kmalloc(chip->model.model_data_size, | 540 | chip->model_data = kmalloc(chip->model.model_data_size, |
501 | GFP_KERNEL); | 541 | GFP_KERNEL); |
@@ -509,11 +549,6 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
509 | snd_card_set_dev(card, &pci->dev); | 549 | snd_card_set_dev(card, &pci->dev); |
510 | card->private_free = oxygen_card_free; | 550 | card->private_free = oxygen_card_free; |
511 | 551 | ||
512 | if (chip->model.probe) { | ||
513 | err = chip->model.probe(chip, driver_data); | ||
514 | if (err < 0) | ||
515 | goto err_card; | ||
516 | } | ||
517 | oxygen_init(chip); | 552 | oxygen_init(chip); |
518 | chip->model.init(chip); | 553 | chip->model.init(chip); |
519 | 554 | ||
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 | }; |
165 | MODULE_DEVICE_TABLE(pci, xonar_ids); | 166 | MODULE_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 | ||
190 | struct xonar_data { | 191 | struct 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 | ||
352 | static 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 | |||
358 | static void update_cs4362a_volumes(struct oxygen *chip) | 364 | static 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 | ||
451 | static 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 | |||
450 | static void xonar_hdav_init(struct oxygen *chip) | 462 | static 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 | ||
776 | static 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 | |||
816 | static const struct oxygen_model model_xonar_d2 = { | 789 | static 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 = { | |||
848 | static const struct oxygen_model model_xonar_d1 = { | 820 | static 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 = { | |||
876 | static const struct oxygen_model model_xonar_hdav = { | 847 | static 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 | ||
905 | static int __devinit xonar_probe(struct pci_dev *pci, | 875 | static 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 | |||
926 | static 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; |