aboutsummaryrefslogtreecommitdiffstats
path: root/sound
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
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')
-rw-r--r--sound/pci/oxygen/hifier.c11
-rw-r--r--sound/pci/oxygen/oxygen.c44
-rw-r--r--sound/pci/oxygen/oxygen.h17
-rw-r--r--sound/pci/oxygen/oxygen_io.c15
-rw-r--r--sound/pci/oxygen/oxygen_lib.c51
-rw-r--r--sound/pci/oxygen/virtuoso.c134
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");
45static struct pci_device_id hifier_ids[] __devinitdata = { 45static 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};
50MODULE_DEVICE_TABLE(pci, hifier_ids); 51MODULE_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
176static 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
175static int __devinit hifier_probe(struct pci_dev *pci, 183static 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
294static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); 294static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
295 295
296static 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
314static const struct oxygen_model model_generic = { 296static 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
324static 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
343static int __devinit generic_oxygen_probe(struct pci_dev *pci, 347static 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
52struct pci_dev; 57struct pci_dev;
58struct pci_device_id;
53struct snd_card; 59struct snd_card;
54struct snd_pcm_substream; 60struct snd_pcm_substream;
55struct snd_pcm_hardware; 61struct 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
135int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, 141int 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 );
139void oxygen_pci_remove(struct pci_dev *pci); 148void oxygen_pci_remove(struct pci_dev *pci);
140#ifdef CONFIG_PM 149#ifdef CONFIG_PM
141int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state); 150int 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);
180void oxygen_reset_uart(struct oxygen *chip); 189void oxygen_reset_uart(struct oxygen *chip);
181void oxygen_write_uart(struct oxygen *chip, u8 data); 190void oxygen_write_uart(struct oxygen *chip, u8 data);
182 191
192u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index);
193
183static inline void oxygen_set_bits8(struct oxygen *chip, 194static 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}
256EXPORT_SYMBOL(oxygen_write_uart); 256EXPORT_SYMBOL(oxygen_write_uart);
257
258u16 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
247static const struct pci_device_id *
248oxygen_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
247static void oxygen_init(struct oxygen *chip) 275static 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
456int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, 484int 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};
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;