Loading Documentation/sound/alsa/ALSA-Configuration.txt +1 −1 Original line number Diff line number Diff line Loading @@ -1859,7 +1859,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ------------------- Module for sound cards based on the Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X and HDAV1.3 (Deluxe). i.e., Xonar D1, DX, D2, D2X, HDAV1.3 (Deluxe), and Essence STX. This module supports autoprobe and multiple cards. Loading sound/pci/Kconfig +2 −1 Original line number Diff line number Diff line Loading @@ -764,7 +764,8 @@ config SND_VIRTUOSO select SND_OXYGEN_LIB help Say Y here to include support for sound cards based on the Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2 and D2X. Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, and Essence STX. Support for the HDAV1.3 (Deluxe) is very experimental. To compile this driver as a module, choose M here: the module Loading sound/pci/oxygen/hifier.c +10 −2 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ MODULE_PARM_DESC(enable, "enable card"); static struct pci_device_id hifier_ids[] __devinitdata = { { OXYGEN_PCI_SUBID(0x14c3, 0x1710) }, { OXYGEN_PCI_SUBID(0x14c3, 0x1711) }, { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, { } }; MODULE_DEVICE_TABLE(pci, hifier_ids); Loading Loading @@ -151,7 +152,6 @@ static const struct oxygen_model model_hifier = { .shortname = "C-Media CMI8787", .longname = "C-Media Oxygen HD Audio", .chip = "CMI8788", .owner = THIS_MODULE, .init = hifier_init, .control_filter = hifier_control_filter, .cleanup = hifier_cleanup, Loading @@ -173,6 +173,13 @@ static const struct oxygen_model model_hifier = { .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, }; static int __devinit get_hifier_model(struct oxygen *chip, const struct pci_device_id *id) { chip->model = model_hifier; return 0; } static int __devinit hifier_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { Loading @@ -185,7 +192,8 @@ static int __devinit hifier_probe(struct pci_dev *pci, ++dev; return -ENOENT; } err = oxygen_pci_probe(pci, index[dev], id[dev], &model_hifier, 0); err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, hifier_ids, get_hifier_model); if (err >= 0) ++dev; return err; Loading sound/pci/oxygen/oxygen.c +88 −26 Original line number Diff line number Diff line /* * C-Media CMI8788 driver for C-Media's reference design and for the X-Meridian * C-Media CMI8788 driver for C-Media's reference design and similar models * * Copyright (c) Clemens Ladisch <clemens@ladisch.de> * Loading @@ -26,6 +26,7 @@ * * GPIO 0 -> DFS0 of AK5385 * GPIO 1 -> DFS1 of AK5385 * GPIO 8 -> enable headphone amplifier on HT-Omega models */ #include <linux/delay.h> Loading Loading @@ -61,7 +62,8 @@ MODULE_PARM_DESC(enable, "enable card"); enum { MODEL_CMEDIA_REF, /* C-Media's reference design */ MODEL_MERIDIAN, /* AuzenTech X-Meridian */ MODEL_HALO, /* HT-Omega Claro halo */ MODEL_CLARO, /* HT-Omega Claro */ MODEL_CLARO_HALO, /* HT-Omega Claro halo */ }; static struct pci_device_id oxygen_ids[] __devinitdata = { Loading @@ -74,8 +76,8 @@ static struct pci_device_id oxygen_ids[] __devinitdata = { { OXYGEN_PCI_SUBID(0x147a, 0xa017), .driver_data = MODEL_CMEDIA_REF }, { OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF }, { OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN }, { OXYGEN_PCI_SUBID(0x7284, 0x9761), .driver_data = MODEL_CMEDIA_REF }, { OXYGEN_PCI_SUBID(0x7284, 0x9781), .driver_data = MODEL_HALO }, { OXYGEN_PCI_SUBID(0x7284, 0x9761), .driver_data = MODEL_CLARO }, { OXYGEN_PCI_SUBID(0x7284, 0x9781), .driver_data = MODEL_CLARO_HALO }, { } }; MODULE_DEVICE_TABLE(pci, oxygen_ids); Loading @@ -86,6 +88,8 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids); #define GPIO_AK5385_DFS_DOUBLE 0x0001 #define GPIO_AK5385_DFS_QUAD 0x0002 #define GPIO_CLARO_HP 0x0100 struct generic_data { u8 ak4396_ctl2; u16 saved_wm8785_registers[2]; Loading Loading @@ -196,10 +200,46 @@ static void meridian_init(struct oxygen *chip) ak5385_init(chip); } static void claro_enable_hp(struct oxygen *chip) { msleep(300); oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CLARO_HP); oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_HP); } static void claro_init(struct oxygen *chip) { ak4396_init(chip); wm8785_init(chip); claro_enable_hp(chip); } static void claro_halo_init(struct oxygen *chip) { ak4396_init(chip); ak5385_init(chip); claro_enable_hp(chip); } static void generic_cleanup(struct oxygen *chip) { } static void claro_disable_hp(struct oxygen *chip) { oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_HP); } static void claro_cleanup(struct oxygen *chip) { claro_disable_hp(chip); } static void claro_suspend(struct oxygen *chip) { claro_disable_hp(chip); } static void generic_resume(struct oxygen *chip) { ak4396_registers_init(chip); Loading @@ -211,6 +251,12 @@ static void meridian_resume(struct oxygen *chip) ak4396_registers_init(chip); } static void claro_resume(struct oxygen *chip) { ak4396_registers_init(chip); claro_enable_hp(chip); } static void set_ak4396_params(struct oxygen *chip, struct snd_pcm_hw_params *params) { Loading Loading @@ -293,30 +339,10 @@ static void set_ak5385_params(struct oxygen *chip, static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); static int generic_probe(struct oxygen *chip, unsigned long driver_data) { if (driver_data == MODEL_MERIDIAN) { chip->model.init = meridian_init; chip->model.resume = meridian_resume; chip->model.set_adc_params = set_ak5385_params; chip->model.device_config = PLAYBACK_0_TO_I2S | PLAYBACK_1_TO_SPDIF | CAPTURE_0_FROM_I2S_2 | CAPTURE_1_FROM_SPDIF; } if (driver_data == MODEL_MERIDIAN || driver_data == MODEL_HALO) { chip->model.misc_flags = OXYGEN_MISC_MIDI; chip->model.device_config |= MIDI_OUTPUT | MIDI_INPUT; } return 0; } static const struct oxygen_model model_generic = { .shortname = "C-Media CMI8788", .longname = "C-Media Oxygen HD Audio", .chip = "CMI8788", .owner = THIS_MODULE, .probe = generic_probe, .init = generic_init, .cleanup = generic_cleanup, .resume = generic_resume, Loading @@ -341,6 +367,42 @@ static const struct oxygen_model model_generic = { .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, }; static int __devinit get_oxygen_model(struct oxygen *chip, const struct pci_device_id *id) { chip->model = model_generic; switch (id->driver_data) { case MODEL_MERIDIAN: chip->model.init = meridian_init; chip->model.resume = meridian_resume; chip->model.set_adc_params = set_ak5385_params; chip->model.device_config = PLAYBACK_0_TO_I2S | PLAYBACK_1_TO_SPDIF | CAPTURE_0_FROM_I2S_2 | CAPTURE_1_FROM_SPDIF; break; case MODEL_CLARO: chip->model.init = claro_init; chip->model.cleanup = claro_cleanup; chip->model.suspend = claro_suspend; chip->model.resume = claro_resume; break; case MODEL_CLARO_HALO: chip->model.init = claro_halo_init; chip->model.cleanup = claro_cleanup; chip->model.suspend = claro_suspend; chip->model.resume = claro_resume; chip->model.set_adc_params = set_ak5385_params; break; } if (id->driver_data == MODEL_MERIDIAN || id->driver_data == MODEL_CLARO_HALO) { chip->model.misc_flags = OXYGEN_MISC_MIDI; chip->model.device_config |= MIDI_OUTPUT | MIDI_INPUT; } return 0; } static int __devinit generic_oxygen_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { Loading @@ -353,8 +415,8 @@ static int __devinit generic_oxygen_probe(struct pci_dev *pci, ++dev; return -ENOENT; } err = oxygen_pci_probe(pci, index[dev], id[dev], &model_generic, pci_id->driver_data); err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, oxygen_ids, get_oxygen_model); if (err >= 0) ++dev; return err; Loading sound/pci/oxygen/oxygen.h +18 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ #define OXYGEN_IO_SIZE 0x100 #define OXYGEN_EEPROM_ID 0x434d /* "CM" */ /* model-specific configuration of outputs/inputs */ #define PLAYBACK_0_TO_I2S 0x0001 /* PLAYBACK_0_TO_AC97_0 not implemented */ Loading Loading @@ -49,7 +51,13 @@ enum { .subvendor = sv, \ .subdevice = sd #define BROKEN_EEPROM_DRIVER_DATA ((unsigned long)-1) #define OXYGEN_PCI_SUBID_BROKEN_EEPROM \ OXYGEN_PCI_SUBID(PCI_VENDOR_ID_CMEDIA, 0x8788), \ .driver_data = BROKEN_EEPROM_DRIVER_DATA struct pci_dev; struct pci_device_id; struct snd_card; struct snd_pcm_substream; struct snd_pcm_hardware; Loading @@ -62,8 +70,6 @@ struct oxygen_model { const char *shortname; const char *longname; const char *chip; struct module *owner; int (*probe)(struct oxygen *chip, unsigned long driver_data); void (*init)(struct oxygen *chip); int (*control_filter)(struct snd_kcontrol_new *template); int (*mixer_init)(struct oxygen *chip); Loading @@ -83,6 +89,7 @@ struct oxygen_model { void (*ac97_switch)(struct oxygen *chip, unsigned int reg, unsigned int mute); const unsigned int *dac_tlv; unsigned long private_data; size_t model_data_size; unsigned int device_config; u8 dac_channels; Loading Loading @@ -134,8 +141,12 @@ struct oxygen { /* oxygen_lib.c */ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, const struct oxygen_model *model, unsigned long driver_data); struct module *owner, const struct pci_device_id *ids, int (*get_model)(struct oxygen *chip, const struct pci_device_id *id ) ); void oxygen_pci_remove(struct pci_dev *pci); #ifdef CONFIG_PM int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state); Loading Loading @@ -180,6 +191,9 @@ void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data); void oxygen_reset_uart(struct oxygen *chip); void oxygen_write_uart(struct oxygen *chip, u8 data); u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index); void oxygen_write_eeprom(struct oxygen *chip, unsigned int index, u16 value); static inline void oxygen_set_bits8(struct oxygen *chip, unsigned int reg, u8 value) { Loading Loading
Documentation/sound/alsa/ALSA-Configuration.txt +1 −1 Original line number Diff line number Diff line Loading @@ -1859,7 +1859,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ------------------- Module for sound cards based on the Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X and HDAV1.3 (Deluxe). i.e., Xonar D1, DX, D2, D2X, HDAV1.3 (Deluxe), and Essence STX. This module supports autoprobe and multiple cards. Loading
sound/pci/Kconfig +2 −1 Original line number Diff line number Diff line Loading @@ -764,7 +764,8 @@ config SND_VIRTUOSO select SND_OXYGEN_LIB help Say Y here to include support for sound cards based on the Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2 and D2X. Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, and Essence STX. Support for the HDAV1.3 (Deluxe) is very experimental. To compile this driver as a module, choose M here: the module Loading
sound/pci/oxygen/hifier.c +10 −2 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ MODULE_PARM_DESC(enable, "enable card"); static struct pci_device_id hifier_ids[] __devinitdata = { { OXYGEN_PCI_SUBID(0x14c3, 0x1710) }, { OXYGEN_PCI_SUBID(0x14c3, 0x1711) }, { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, { } }; MODULE_DEVICE_TABLE(pci, hifier_ids); Loading Loading @@ -151,7 +152,6 @@ static const struct oxygen_model model_hifier = { .shortname = "C-Media CMI8787", .longname = "C-Media Oxygen HD Audio", .chip = "CMI8788", .owner = THIS_MODULE, .init = hifier_init, .control_filter = hifier_control_filter, .cleanup = hifier_cleanup, Loading @@ -173,6 +173,13 @@ static const struct oxygen_model model_hifier = { .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, }; static int __devinit get_hifier_model(struct oxygen *chip, const struct pci_device_id *id) { chip->model = model_hifier; return 0; } static int __devinit hifier_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { Loading @@ -185,7 +192,8 @@ static int __devinit hifier_probe(struct pci_dev *pci, ++dev; return -ENOENT; } err = oxygen_pci_probe(pci, index[dev], id[dev], &model_hifier, 0); err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, hifier_ids, get_hifier_model); if (err >= 0) ++dev; return err; Loading
sound/pci/oxygen/oxygen.c +88 −26 Original line number Diff line number Diff line /* * C-Media CMI8788 driver for C-Media's reference design and for the X-Meridian * C-Media CMI8788 driver for C-Media's reference design and similar models * * Copyright (c) Clemens Ladisch <clemens@ladisch.de> * Loading @@ -26,6 +26,7 @@ * * GPIO 0 -> DFS0 of AK5385 * GPIO 1 -> DFS1 of AK5385 * GPIO 8 -> enable headphone amplifier on HT-Omega models */ #include <linux/delay.h> Loading Loading @@ -61,7 +62,8 @@ MODULE_PARM_DESC(enable, "enable card"); enum { MODEL_CMEDIA_REF, /* C-Media's reference design */ MODEL_MERIDIAN, /* AuzenTech X-Meridian */ MODEL_HALO, /* HT-Omega Claro halo */ MODEL_CLARO, /* HT-Omega Claro */ MODEL_CLARO_HALO, /* HT-Omega Claro halo */ }; static struct pci_device_id oxygen_ids[] __devinitdata = { Loading @@ -74,8 +76,8 @@ static struct pci_device_id oxygen_ids[] __devinitdata = { { OXYGEN_PCI_SUBID(0x147a, 0xa017), .driver_data = MODEL_CMEDIA_REF }, { OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF }, { OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN }, { OXYGEN_PCI_SUBID(0x7284, 0x9761), .driver_data = MODEL_CMEDIA_REF }, { OXYGEN_PCI_SUBID(0x7284, 0x9781), .driver_data = MODEL_HALO }, { OXYGEN_PCI_SUBID(0x7284, 0x9761), .driver_data = MODEL_CLARO }, { OXYGEN_PCI_SUBID(0x7284, 0x9781), .driver_data = MODEL_CLARO_HALO }, { } }; MODULE_DEVICE_TABLE(pci, oxygen_ids); Loading @@ -86,6 +88,8 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids); #define GPIO_AK5385_DFS_DOUBLE 0x0001 #define GPIO_AK5385_DFS_QUAD 0x0002 #define GPIO_CLARO_HP 0x0100 struct generic_data { u8 ak4396_ctl2; u16 saved_wm8785_registers[2]; Loading Loading @@ -196,10 +200,46 @@ static void meridian_init(struct oxygen *chip) ak5385_init(chip); } static void claro_enable_hp(struct oxygen *chip) { msleep(300); oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CLARO_HP); oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_HP); } static void claro_init(struct oxygen *chip) { ak4396_init(chip); wm8785_init(chip); claro_enable_hp(chip); } static void claro_halo_init(struct oxygen *chip) { ak4396_init(chip); ak5385_init(chip); claro_enable_hp(chip); } static void generic_cleanup(struct oxygen *chip) { } static void claro_disable_hp(struct oxygen *chip) { oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_HP); } static void claro_cleanup(struct oxygen *chip) { claro_disable_hp(chip); } static void claro_suspend(struct oxygen *chip) { claro_disable_hp(chip); } static void generic_resume(struct oxygen *chip) { ak4396_registers_init(chip); Loading @@ -211,6 +251,12 @@ static void meridian_resume(struct oxygen *chip) ak4396_registers_init(chip); } static void claro_resume(struct oxygen *chip) { ak4396_registers_init(chip); claro_enable_hp(chip); } static void set_ak4396_params(struct oxygen *chip, struct snd_pcm_hw_params *params) { Loading Loading @@ -293,30 +339,10 @@ static void set_ak5385_params(struct oxygen *chip, static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); static int generic_probe(struct oxygen *chip, unsigned long driver_data) { if (driver_data == MODEL_MERIDIAN) { chip->model.init = meridian_init; chip->model.resume = meridian_resume; chip->model.set_adc_params = set_ak5385_params; chip->model.device_config = PLAYBACK_0_TO_I2S | PLAYBACK_1_TO_SPDIF | CAPTURE_0_FROM_I2S_2 | CAPTURE_1_FROM_SPDIF; } if (driver_data == MODEL_MERIDIAN || driver_data == MODEL_HALO) { chip->model.misc_flags = OXYGEN_MISC_MIDI; chip->model.device_config |= MIDI_OUTPUT | MIDI_INPUT; } return 0; } static const struct oxygen_model model_generic = { .shortname = "C-Media CMI8788", .longname = "C-Media Oxygen HD Audio", .chip = "CMI8788", .owner = THIS_MODULE, .probe = generic_probe, .init = generic_init, .cleanup = generic_cleanup, .resume = generic_resume, Loading @@ -341,6 +367,42 @@ static const struct oxygen_model model_generic = { .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, }; static int __devinit get_oxygen_model(struct oxygen *chip, const struct pci_device_id *id) { chip->model = model_generic; switch (id->driver_data) { case MODEL_MERIDIAN: chip->model.init = meridian_init; chip->model.resume = meridian_resume; chip->model.set_adc_params = set_ak5385_params; chip->model.device_config = PLAYBACK_0_TO_I2S | PLAYBACK_1_TO_SPDIF | CAPTURE_0_FROM_I2S_2 | CAPTURE_1_FROM_SPDIF; break; case MODEL_CLARO: chip->model.init = claro_init; chip->model.cleanup = claro_cleanup; chip->model.suspend = claro_suspend; chip->model.resume = claro_resume; break; case MODEL_CLARO_HALO: chip->model.init = claro_halo_init; chip->model.cleanup = claro_cleanup; chip->model.suspend = claro_suspend; chip->model.resume = claro_resume; chip->model.set_adc_params = set_ak5385_params; break; } if (id->driver_data == MODEL_MERIDIAN || id->driver_data == MODEL_CLARO_HALO) { chip->model.misc_flags = OXYGEN_MISC_MIDI; chip->model.device_config |= MIDI_OUTPUT | MIDI_INPUT; } return 0; } static int __devinit generic_oxygen_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { Loading @@ -353,8 +415,8 @@ static int __devinit generic_oxygen_probe(struct pci_dev *pci, ++dev; return -ENOENT; } err = oxygen_pci_probe(pci, index[dev], id[dev], &model_generic, pci_id->driver_data); err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, oxygen_ids, get_oxygen_model); if (err >= 0) ++dev; return err; Loading
sound/pci/oxygen/oxygen.h +18 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ #define OXYGEN_IO_SIZE 0x100 #define OXYGEN_EEPROM_ID 0x434d /* "CM" */ /* model-specific configuration of outputs/inputs */ #define PLAYBACK_0_TO_I2S 0x0001 /* PLAYBACK_0_TO_AC97_0 not implemented */ Loading Loading @@ -49,7 +51,13 @@ enum { .subvendor = sv, \ .subdevice = sd #define BROKEN_EEPROM_DRIVER_DATA ((unsigned long)-1) #define OXYGEN_PCI_SUBID_BROKEN_EEPROM \ OXYGEN_PCI_SUBID(PCI_VENDOR_ID_CMEDIA, 0x8788), \ .driver_data = BROKEN_EEPROM_DRIVER_DATA struct pci_dev; struct pci_device_id; struct snd_card; struct snd_pcm_substream; struct snd_pcm_hardware; Loading @@ -62,8 +70,6 @@ struct oxygen_model { const char *shortname; const char *longname; const char *chip; struct module *owner; int (*probe)(struct oxygen *chip, unsigned long driver_data); void (*init)(struct oxygen *chip); int (*control_filter)(struct snd_kcontrol_new *template); int (*mixer_init)(struct oxygen *chip); Loading @@ -83,6 +89,7 @@ struct oxygen_model { void (*ac97_switch)(struct oxygen *chip, unsigned int reg, unsigned int mute); const unsigned int *dac_tlv; unsigned long private_data; size_t model_data_size; unsigned int device_config; u8 dac_channels; Loading Loading @@ -134,8 +141,12 @@ struct oxygen { /* oxygen_lib.c */ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, const struct oxygen_model *model, unsigned long driver_data); struct module *owner, const struct pci_device_id *ids, int (*get_model)(struct oxygen *chip, const struct pci_device_id *id ) ); void oxygen_pci_remove(struct pci_dev *pci); #ifdef CONFIG_PM int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state); Loading Loading @@ -180,6 +191,9 @@ void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data); void oxygen_reset_uart(struct oxygen *chip); void oxygen_write_uart(struct oxygen *chip, u8 data); u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index); void oxygen_write_eeprom(struct oxygen *chip, unsigned int index, u16 value); static inline void oxygen_set_bits8(struct oxygen *chip, unsigned int reg, u8 value) { Loading