diff options
Diffstat (limited to 'sound/pci/sis7019.c')
| -rw-r--r-- | sound/pci/sis7019.c | 64 |
1 files changed, 53 insertions, 11 deletions
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index a391e622a192..28dfafb56dd1 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c | |||
| @@ -41,6 +41,7 @@ MODULE_SUPPORTED_DEVICE("{{SiS,SiS7019 Audio Accelerator}}"); | |||
| 41 | static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ | 41 | static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ |
| 42 | static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ | 42 | static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ |
| 43 | static int enable = 1; | 43 | static int enable = 1; |
| 44 | static int codecs = 1; | ||
| 44 | 45 | ||
| 45 | module_param(index, int, 0444); | 46 | module_param(index, int, 0444); |
| 46 | MODULE_PARM_DESC(index, "Index value for SiS7019 Audio Accelerator."); | 47 | MODULE_PARM_DESC(index, "Index value for SiS7019 Audio Accelerator."); |
| @@ -48,6 +49,8 @@ module_param(id, charp, 0444); | |||
| 48 | MODULE_PARM_DESC(id, "ID string for SiS7019 Audio Accelerator."); | 49 | MODULE_PARM_DESC(id, "ID string for SiS7019 Audio Accelerator."); |
| 49 | module_param(enable, bool, 0444); | 50 | module_param(enable, bool, 0444); |
| 50 | MODULE_PARM_DESC(enable, "Enable SiS7019 Audio Accelerator."); | 51 | MODULE_PARM_DESC(enable, "Enable SiS7019 Audio Accelerator."); |
| 52 | module_param(codecs, int, 0444); | ||
| 53 | MODULE_PARM_DESC(codecs, "Set bit to indicate that codec number is expected to be present (default 1)"); | ||
| 51 | 54 | ||
| 52 | static DEFINE_PCI_DEVICE_TABLE(snd_sis7019_ids) = { | 55 | static DEFINE_PCI_DEVICE_TABLE(snd_sis7019_ids) = { |
| 53 | { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x7019) }, | 56 | { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x7019) }, |
| @@ -140,6 +143,9 @@ struct sis7019 { | |||
| 140 | dma_addr_t silence_dma_addr; | 143 | dma_addr_t silence_dma_addr; |
| 141 | }; | 144 | }; |
| 142 | 145 | ||
| 146 | /* These values are also used by the module param 'codecs' to indicate | ||
| 147 | * which codecs should be present. | ||
| 148 | */ | ||
| 143 | #define SIS_PRIMARY_CODEC_PRESENT 0x0001 | 149 | #define SIS_PRIMARY_CODEC_PRESENT 0x0001 |
| 144 | #define SIS_SECONDARY_CODEC_PRESENT 0x0002 | 150 | #define SIS_SECONDARY_CODEC_PRESENT 0x0002 |
| 145 | #define SIS_TERTIARY_CODEC_PRESENT 0x0004 | 151 | #define SIS_TERTIARY_CODEC_PRESENT 0x0004 |
| @@ -1078,6 +1084,7 @@ static int sis_chip_init(struct sis7019 *sis) | |||
| 1078 | { | 1084 | { |
| 1079 | unsigned long io = sis->ioport; | 1085 | unsigned long io = sis->ioport; |
| 1080 | void __iomem *ioaddr = sis->ioaddr; | 1086 | void __iomem *ioaddr = sis->ioaddr; |
| 1087 | unsigned long timeout; | ||
| 1081 | u16 status; | 1088 | u16 status; |
| 1082 | int count; | 1089 | int count; |
| 1083 | int i; | 1090 | int i; |
| @@ -1104,21 +1111,45 @@ static int sis_chip_init(struct sis7019 *sis) | |||
| 1104 | while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count) | 1111 | while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count) |
| 1105 | udelay(1); | 1112 | udelay(1); |
| 1106 | 1113 | ||
| 1114 | /* Command complete, we can let go of the semaphore now. | ||
| 1115 | */ | ||
| 1116 | outl(SIS_AC97_SEMA_RELEASE, io + SIS_AC97_SEMA); | ||
| 1117 | if (!count) | ||
| 1118 | return -EIO; | ||
| 1119 | |||
| 1107 | /* Now that we've finished the reset, find out what's attached. | 1120 | /* Now that we've finished the reset, find out what's attached. |
| 1121 | * There are some codec/board combinations that take an extremely | ||
| 1122 | * long time to come up. 350+ ms has been observed in the field, | ||
| 1123 | * so we'll give them up to 500ms. | ||
| 1108 | */ | 1124 | */ |
| 1109 | status = inl(io + SIS_AC97_STATUS); | 1125 | sis->codecs_present = 0; |
| 1110 | if (status & SIS_AC97_STATUS_CODEC_READY) | 1126 | timeout = msecs_to_jiffies(500) + jiffies; |
| 1111 | sis->codecs_present |= SIS_PRIMARY_CODEC_PRESENT; | 1127 | while (time_before_eq(jiffies, timeout)) { |
| 1112 | if (status & SIS_AC97_STATUS_CODEC2_READY) | 1128 | status = inl(io + SIS_AC97_STATUS); |
| 1113 | sis->codecs_present |= SIS_SECONDARY_CODEC_PRESENT; | 1129 | if (status & SIS_AC97_STATUS_CODEC_READY) |
| 1114 | if (status & SIS_AC97_STATUS_CODEC3_READY) | 1130 | sis->codecs_present |= SIS_PRIMARY_CODEC_PRESENT; |
| 1115 | sis->codecs_present |= SIS_TERTIARY_CODEC_PRESENT; | 1131 | if (status & SIS_AC97_STATUS_CODEC2_READY) |
| 1116 | 1132 | sis->codecs_present |= SIS_SECONDARY_CODEC_PRESENT; | |
| 1117 | /* All done, let go of the semaphore, and check for errors | 1133 | if (status & SIS_AC97_STATUS_CODEC3_READY) |
| 1134 | sis->codecs_present |= SIS_TERTIARY_CODEC_PRESENT; | ||
| 1135 | |||
| 1136 | if (sis->codecs_present == codecs) | ||
| 1137 | break; | ||
| 1138 | |||
| 1139 | msleep(1); | ||
| 1140 | } | ||
| 1141 | |||
| 1142 | /* All done, check for errors. | ||
| 1118 | */ | 1143 | */ |
| 1119 | outl(SIS_AC97_SEMA_RELEASE, io + SIS_AC97_SEMA); | 1144 | if (!sis->codecs_present) { |
| 1120 | if (!sis->codecs_present || !count) | 1145 | printk(KERN_ERR "sis7019: could not find any codecs\n"); |
| 1121 | return -EIO; | 1146 | return -EIO; |
| 1147 | } | ||
| 1148 | |||
| 1149 | if (sis->codecs_present != codecs) { | ||
| 1150 | printk(KERN_WARNING "sis7019: missing codecs, found %0x, expected %0x\n", | ||
| 1151 | sis->codecs_present, codecs); | ||
| 1152 | } | ||
| 1122 | 1153 | ||
| 1123 | /* Let the hardware know that the audio driver is alive, | 1154 | /* Let the hardware know that the audio driver is alive, |
| 1124 | * and enable PCM slots on the AC-link for L/R playback (3 & 4) and | 1155 | * and enable PCM slots on the AC-link for L/R playback (3 & 4) and |
| @@ -1390,6 +1421,17 @@ static int __devinit snd_sis7019_probe(struct pci_dev *pci, | |||
| 1390 | if (!enable) | 1421 | if (!enable) |
| 1391 | goto error_out; | 1422 | goto error_out; |
| 1392 | 1423 | ||
| 1424 | /* The user can specify which codecs should be present so that we | ||
| 1425 | * can wait for them to show up if they are slow to recover from | ||
| 1426 | * the AC97 cold reset. We default to a single codec, the primary. | ||
| 1427 | * | ||
| 1428 | * We assume that SIS_PRIMARY_*_PRESENT matches bits 0-2. | ||
| 1429 | */ | ||
| 1430 | codecs &= SIS_PRIMARY_CODEC_PRESENT | SIS_SECONDARY_CODEC_PRESENT | | ||
| 1431 | SIS_TERTIARY_CODEC_PRESENT; | ||
| 1432 | if (!codecs) | ||
| 1433 | codecs = SIS_PRIMARY_CODEC_PRESENT; | ||
| 1434 | |||
| 1393 | rc = snd_card_create(index, id, THIS_MODULE, sizeof(*sis), &card); | 1435 | rc = snd_card_create(index, id, THIS_MODULE, sizeof(*sis), &card); |
| 1394 | if (rc < 0) | 1436 | if (rc < 0) |
| 1395 | goto error_out; | 1437 | goto error_out; |
