[ALSA] hda-intel - Support multiple devices

It turned out that there can be multiple HD-audio devices on a single
machine (e.g. on-board audio and HDMI on graphic cards), so we need to
support multiple devices with snd-hda-intel driver.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
Takashi Iwai 2008-01-07 15:16:37 +01:00 коммит произвёл Jaroslav Kysela
Родитель f11b799282
Коммит 5aba4f8ec7
2 изменённых файлов: 40 добавлений и 29 удалений

Просмотреть файл

@ -744,9 +744,12 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
VIA VT8251/VT8237A, VIA VT8251/VT8237A,
SIS966, ULI M5461 SIS966, ULI M5461
[Multiple options for each card instance]
model - force the model name model - force the model name
position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size) position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)
probe_mask - Bitmask to probe codecs (default = -1, meaning all slots) probe_mask - Bitmask to probe codecs (default = -1, meaning all slots)
[Single (global) options]
single_cmd - Use single immediate commands to communicate with single_cmd - Use single immediate commands to communicate with
codecs (for debugging only) codecs (for debugging only)
enable_msi - Enable Message Signaled Interrupt (MSI) (default = off) enable_msi - Enable Message Signaled Interrupt (MSI) (default = off)
@ -755,8 +758,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
power_save_controller - Reset HD-audio controller in power-saving mode power_save_controller - Reset HD-audio controller in power-saving mode
(default = on) (default = on)
This module supports one card and autoprobe. This module supports multiple cards and autoprobe.
Each codec may have a model table for different configurations. Each codec may have a model table for different configurations.
If your machine isn't listed there, the default (usually minimal) If your machine isn't listed there, the default (usually minimal)
configuration is set up. You can pass "model=<name>" option to configuration is set up. You can pass "model=<name>" option to

Просмотреть файл

@ -50,29 +50,32 @@
#include "hda_codec.h" #include "hda_codec.h"
static int index = SNDRV_DEFAULT_IDX1; static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id = SNDRV_DEFAULT_STR1; static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
static char *model; static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
static int position_fix; static char *model[SNDRV_CARDS];
static int probe_mask = -1; static int position_fix[SNDRV_CARDS];
static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
static int single_cmd; static int single_cmd;
static int enable_msi; static int enable_msi;
module_param(index, int, 0444); module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
module_param(id, charp, 0444); module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for Intel HD audio interface."); MODULE_PARM_DESC(id, "ID string for Intel HD audio interface.");
module_param(model, charp, 0444); module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable Intel HD audio interface.");
module_param_array(model, charp, NULL, 0444);
MODULE_PARM_DESC(model, "Use the given board model."); MODULE_PARM_DESC(model, "Use the given board model.");
module_param(position_fix, int, 0444); module_param_array(position_fix, int, NULL, 0444);
MODULE_PARM_DESC(position_fix, "Fix DMA pointer " MODULE_PARM_DESC(position_fix, "Fix DMA pointer "
"(0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)."); "(0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size).");
module_param(probe_mask, int, 0444); module_param_array(probe_mask, int, NULL, 0444);
MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1).");
module_param(single_cmd, bool, 0444); module_param(single_cmd, bool, 0444);
MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs " MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs "
"(for debugging only)."); "(for debugging only).");
module_param(enable_msi, int, 0); module_param(enable_msi, int, 0444);
MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)"); MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)");
#ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE
@ -87,10 +90,6 @@ module_param(power_save_controller, bool, 0644);
MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode."); MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode.");
#endif #endif
/* just for backward compatibility */
static int enable;
module_param(enable, bool, 0444);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
"{Intel, ICH6M}," "{Intel, ICH6M},"
@ -1038,7 +1037,8 @@ static unsigned int azx_max_codecs[] __devinitdata = {
[AZX_DRIVER_NVIDIA] = 3, /* FIXME: correct? */ [AZX_DRIVER_NVIDIA] = 3, /* FIXME: correct? */
}; };
static int __devinit azx_codec_create(struct azx *chip, const char *model) static int __devinit azx_codec_create(struct azx *chip, const char *model,
unsigned int codec_probe_mask)
{ {
struct hda_bus_template bus_temp; struct hda_bus_template bus_temp;
int c, codecs, audio_codecs, err; int c, codecs, audio_codecs, err;
@ -1059,7 +1059,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
codecs = audio_codecs = 0; codecs = audio_codecs = 0;
for (c = 0; c < AZX_MAX_CODECS; c++) { for (c = 0; c < AZX_MAX_CODECS; c++) {
if ((chip->codec_mask & (1 << c)) & probe_mask) { if ((chip->codec_mask & (1 << c)) & codec_probe_mask) {
struct hda_codec *codec; struct hda_codec *codec;
err = snd_hda_codec_new(chip->bus, c, &codec); err = snd_hda_codec_new(chip->bus, c, &codec);
if (err < 0) if (err < 0)
@ -1072,7 +1072,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
if (!audio_codecs) { if (!audio_codecs) {
/* probe additional slots if no codec is found */ /* probe additional slots if no codec is found */
for (; c < azx_max_codecs[chip->driver_type]; c++) { for (; c < azx_max_codecs[chip->driver_type]; c++) {
if ((chip->codec_mask & (1 << c)) & probe_mask) { if ((chip->codec_mask & (1 << c)) & codec_probe_mask) {
err = snd_hda_codec_new(chip->bus, c, NULL); err = snd_hda_codec_new(chip->bus, c, NULL);
if (err < 0) if (err < 0)
continue; continue;
@ -1683,18 +1683,18 @@ static struct snd_pci_quirk probe_mask_list[] __devinitdata = {
{} {}
}; };
static void __devinit check_probe_mask(struct azx *chip) static void __devinit check_probe_mask(struct azx *chip, int dev)
{ {
const struct snd_pci_quirk *q; const struct snd_pci_quirk *q;
if (probe_mask == -1) { if (probe_mask[dev] == -1) {
q = snd_pci_quirk_lookup(chip->pci, probe_mask_list); q = snd_pci_quirk_lookup(chip->pci, probe_mask_list);
if (q) { if (q) {
printk(KERN_INFO printk(KERN_INFO
"hda_intel: probe_mask set to 0x%x " "hda_intel: probe_mask set to 0x%x "
"for device %04x:%04x\n", "for device %04x:%04x\n",
q->value, q->subvendor, q->subdevice); q->value, q->subvendor, q->subdevice);
probe_mask = q->value; probe_mask[dev] = q->value;
} }
} }
} }
@ -1704,7 +1704,7 @@ static void __devinit check_probe_mask(struct azx *chip)
* constructor * constructor
*/ */
static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
int driver_type, int dev, int driver_type,
struct azx **rchip) struct azx **rchip)
{ {
struct azx *chip; struct azx *chip;
@ -1734,8 +1734,8 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
chip->driver_type = driver_type; chip->driver_type = driver_type;
chip->msi = enable_msi; chip->msi = enable_msi;
chip->position_fix = check_position_fix(chip, position_fix); chip->position_fix = check_position_fix(chip, position_fix[dev]);
check_probe_mask(chip); check_probe_mask(chip, dev);
chip->single_cmd = single_cmd; chip->single_cmd = single_cmd;
@ -1876,17 +1876,25 @@ static void power_down_all_codecs(struct azx *chip)
static int __devinit azx_probe(struct pci_dev *pci, static int __devinit azx_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id) const struct pci_device_id *pci_id)
{ {
static int dev;
struct snd_card *card; struct snd_card *card;
struct azx *chip; struct azx *chip;
int err; int err;
card = snd_card_new(index, id, THIS_MODULE, 0); if (dev >= SNDRV_CARDS)
return -ENODEV;
if (!enable[dev]) {
dev++;
return -ENOENT;
}
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
if (!card) { if (!card) {
snd_printk(KERN_ERR SFX "Error creating card!\n"); snd_printk(KERN_ERR SFX "Error creating card!\n");
return -ENOMEM; return -ENOMEM;
} }
err = azx_create(card, pci, pci_id->driver_data, &chip); err = azx_create(card, pci, dev, pci_id->driver_data, &chip);
if (err < 0) { if (err < 0) {
snd_card_free(card); snd_card_free(card);
return err; return err;
@ -1894,7 +1902,7 @@ static int __devinit azx_probe(struct pci_dev *pci,
card->private_data = chip; card->private_data = chip;
/* create codec instances */ /* create codec instances */
err = azx_codec_create(chip, model); err = azx_codec_create(chip, model[dev], probe_mask[dev]);
if (err < 0) { if (err < 0) {
snd_card_free(card); snd_card_free(card);
return err; return err;