[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:
Родитель
f11b799282
Коммит
5aba4f8ec7
|
@ -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;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче