diff options
author | Takashi Iwai <tiwai@suse.de> | 2005-05-12 08:26:27 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2005-05-29 04:08:30 -0400 |
commit | c74db86bcf0897cdd4dc1f85ae0d76ef59aaeb20 (patch) | |
tree | 07ca89ae966291074bdf5eea73aaaed14edb89dd /sound/pci/hda/hda_intel.c | |
parent | 091bf4dcab10b083f944d4eafbe0c734786485fe (diff) |
[ALSA] Add position_fix module option
Documentation,HDA Intel driver
Added position_fix module option to HDA-intel driver for fixing up
the DMA position (possibly hardware-) bugs.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_intel.c')
-rw-r--r-- | sound/pci/hda/hda_intel.c | 85 |
1 files changed, 48 insertions, 37 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index cbc9ca73c2ab..104593fa08eb 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -51,6 +51,7 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | |||
51 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; | 51 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; |
52 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | 52 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; |
53 | static char *model[SNDRV_CARDS]; | 53 | static char *model[SNDRV_CARDS]; |
54 | static int position_fix[SNDRV_CARDS]; | ||
54 | 55 | ||
55 | module_param_array(index, int, NULL, 0444); | 56 | module_param_array(index, int, NULL, 0444); |
56 | MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); | 57 | MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); |
@@ -60,6 +61,8 @@ module_param_array(enable, bool, NULL, 0444); | |||
60 | MODULE_PARM_DESC(enable, "Enable Intel HD audio interface."); | 61 | MODULE_PARM_DESC(enable, "Enable Intel HD audio interface."); |
61 | module_param_array(model, charp, NULL, 0444); | 62 | module_param_array(model, charp, NULL, 0444); |
62 | MODULE_PARM_DESC(model, "Use the given board model."); | 63 | MODULE_PARM_DESC(model, "Use the given board model."); |
64 | module_param_array(position_fix, bool, NULL, 0444); | ||
65 | MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF)."); | ||
63 | 66 | ||
64 | MODULE_LICENSE("GPL"); | 67 | MODULE_LICENSE("GPL"); |
65 | MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," | 68 | MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," |
@@ -183,6 +186,12 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
183 | #define ICH6_MAX_CORB_ENTRIES 256 | 186 | #define ICH6_MAX_CORB_ENTRIES 256 |
184 | #define ICH6_MAX_RIRB_ENTRIES 256 | 187 | #define ICH6_MAX_RIRB_ENTRIES 256 |
185 | 188 | ||
189 | /* position fix mode */ | ||
190 | enum { | ||
191 | POS_FIX_FIFO, | ||
192 | POS_FIX_NONE, | ||
193 | POS_FIX_POSBUF | ||
194 | }; | ||
186 | 195 | ||
187 | /* | 196 | /* |
188 | * Use CORB/RIRB for communication from/to codecs. | 197 | * Use CORB/RIRB for communication from/to codecs. |
@@ -191,12 +200,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
191 | #define USE_CORB_RIRB | 200 | #define USE_CORB_RIRB |
192 | 201 | ||
193 | /* | 202 | /* |
194 | * Define this if use the position buffer instead of reading SD_LPIB | ||
195 | * It's not used as default since SD_LPIB seems to give more accurate position | ||
196 | */ | ||
197 | /* #define USE_POSBUF */ | ||
198 | |||
199 | /* | ||
200 | */ | 203 | */ |
201 | 204 | ||
202 | typedef struct snd_azx azx_t; | 205 | typedef struct snd_azx azx_t; |
@@ -271,6 +274,9 @@ struct snd_azx { | |||
271 | struct snd_dma_buffer bdl; | 274 | struct snd_dma_buffer bdl; |
272 | struct snd_dma_buffer rb; | 275 | struct snd_dma_buffer rb; |
273 | struct snd_dma_buffer posbuf; | 276 | struct snd_dma_buffer posbuf; |
277 | |||
278 | /* flags */ | ||
279 | int position_fix; | ||
274 | }; | 280 | }; |
275 | 281 | ||
276 | /* | 282 | /* |
@@ -657,11 +663,11 @@ static void azx_init_chip(azx_t *chip) | |||
657 | /* initialize the codec command I/O */ | 663 | /* initialize the codec command I/O */ |
658 | azx_init_cmd_io(chip); | 664 | azx_init_cmd_io(chip); |
659 | 665 | ||
660 | #ifdef USE_POSBUF | 666 | if (chip->position_fix == POS_FIX_POSBUF) { |
661 | /* program the position buffer */ | 667 | /* program the position buffer */ |
662 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); | 668 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); |
663 | azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr)); | 669 | azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr)); |
664 | #endif | 670 | } |
665 | } | 671 | } |
666 | 672 | ||
667 | 673 | ||
@@ -791,11 +797,12 @@ static int azx_setup_controller(azx_t *chip, azx_dev_t *azx_dev) | |||
791 | /* upper BDL address */ | 797 | /* upper BDL address */ |
792 | azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr)); | 798 | azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr)); |
793 | 799 | ||
794 | #ifdef USE_POSBUF | 800 | if (chip->position_fix == POS_FIX_POSBUF) { |
795 | /* enable the position buffer */ | 801 | /* enable the position buffer */ |
796 | if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) | 802 | if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) |
797 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); | 803 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); |
798 | #endif | 804 | } |
805 | |||
799 | /* set the interrupt enable bits in the descriptor control register */ | 806 | /* set the interrupt enable bits in the descriptor control register */ |
800 | azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK); | 807 | azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK); |
801 | 808 | ||
@@ -1036,16 +1043,20 @@ static int azx_pcm_trigger(snd_pcm_substream_t *substream, int cmd) | |||
1036 | 1043 | ||
1037 | static snd_pcm_uframes_t azx_pcm_pointer(snd_pcm_substream_t *substream) | 1044 | static snd_pcm_uframes_t azx_pcm_pointer(snd_pcm_substream_t *substream) |
1038 | { | 1045 | { |
1046 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | ||
1047 | azx_t *chip = apcm->chip; | ||
1039 | azx_dev_t *azx_dev = get_azx_dev(substream); | 1048 | azx_dev_t *azx_dev = get_azx_dev(substream); |
1040 | unsigned int pos; | 1049 | unsigned int pos; |
1041 | 1050 | ||
1042 | #ifdef USE_POSBUF | 1051 | if (chip->position_fix == POS_FIX_POSBUF) { |
1043 | /* use the position buffer */ | 1052 | /* use the position buffer */ |
1044 | pos = *azx_dev->posbuf; | 1053 | pos = *azx_dev->posbuf; |
1045 | #else | 1054 | } else { |
1046 | /* read LPIB */ | 1055 | /* read LPIB */ |
1047 | pos = azx_sd_readl(azx_dev, SD_LPIB) + azx_dev->fifo_size; | 1056 | pos = azx_sd_readl(azx_dev, SD_LPIB); |
1048 | #endif | 1057 | if (chip->position_fix == POS_FIX_FIFO) |
1058 | pos += azx_dev->fifo_size; | ||
1059 | } | ||
1049 | if (pos >= azx_dev->bufsize) | 1060 | if (pos >= azx_dev->bufsize) |
1050 | pos = 0; | 1061 | pos = 0; |
1051 | return bytes_to_frames(substream->runtime, pos); | 1062 | return bytes_to_frames(substream->runtime, pos); |
@@ -1155,9 +1166,8 @@ static int __devinit azx_init_stream(azx_t *chip) | |||
1155 | azx_dev_t *azx_dev = &chip->azx_dev[i]; | 1166 | azx_dev_t *azx_dev = &chip->azx_dev[i]; |
1156 | azx_dev->bdl = (u32 *)(chip->bdl.area + off); | 1167 | azx_dev->bdl = (u32 *)(chip->bdl.area + off); |
1157 | azx_dev->bdl_addr = chip->bdl.addr + off; | 1168 | azx_dev->bdl_addr = chip->bdl.addr + off; |
1158 | #ifdef USE_POSBUF | 1169 | if (chip->position_fix == POS_FIX_POSBUF) |
1159 | azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8); | 1170 | azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8); |
1160 | #endif | ||
1161 | /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ | 1171 | /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ |
1162 | azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); | 1172 | azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); |
1163 | /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ | 1173 | /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ |
@@ -1237,10 +1247,8 @@ static int azx_free(azx_t *chip) | |||
1237 | snd_dma_free_pages(&chip->bdl); | 1247 | snd_dma_free_pages(&chip->bdl); |
1238 | if (chip->rb.area) | 1248 | if (chip->rb.area) |
1239 | snd_dma_free_pages(&chip->rb); | 1249 | snd_dma_free_pages(&chip->rb); |
1240 | #ifdef USE_POSBUF | ||
1241 | if (chip->posbuf.area) | 1250 | if (chip->posbuf.area) |
1242 | snd_dma_free_pages(&chip->posbuf); | 1251 | snd_dma_free_pages(&chip->posbuf); |
1243 | #endif | ||
1244 | pci_release_regions(chip->pci); | 1252 | pci_release_regions(chip->pci); |
1245 | pci_disable_device(chip->pci); | 1253 | pci_disable_device(chip->pci); |
1246 | kfree(chip); | 1254 | kfree(chip); |
@@ -1256,7 +1264,8 @@ static int azx_dev_free(snd_device_t *device) | |||
1256 | /* | 1264 | /* |
1257 | * constructor | 1265 | * constructor |
1258 | */ | 1266 | */ |
1259 | static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **rchip) | 1267 | static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, |
1268 | int posfix, azx_t **rchip) | ||
1260 | { | 1269 | { |
1261 | azx_t *chip; | 1270 | azx_t *chip; |
1262 | int err = 0; | 1271 | int err = 0; |
@@ -1283,6 +1292,8 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **r | |||
1283 | chip->pci = pci; | 1292 | chip->pci = pci; |
1284 | chip->irq = -1; | 1293 | chip->irq = -1; |
1285 | 1294 | ||
1295 | chip->position_fix = posfix; | ||
1296 | |||
1286 | if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) { | 1297 | if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) { |
1287 | kfree(chip); | 1298 | kfree(chip); |
1288 | pci_disable_device(pci); | 1299 | pci_disable_device(pci); |
@@ -1314,14 +1325,14 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **r | |||
1314 | snd_printk(KERN_ERR SFX "cannot allocate BDL\n"); | 1325 | snd_printk(KERN_ERR SFX "cannot allocate BDL\n"); |
1315 | goto errout; | 1326 | goto errout; |
1316 | } | 1327 | } |
1317 | #ifdef USE_POSBUF | 1328 | if (chip->position_fix == POS_FIX_POSBUF) { |
1318 | /* allocate memory for the position buffer */ | 1329 | /* allocate memory for the position buffer */ |
1319 | if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), | 1330 | if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), |
1320 | MAX_ICH6_DEV * 8, &chip->posbuf)) < 0) { | 1331 | MAX_ICH6_DEV * 8, &chip->posbuf)) < 0) { |
1321 | snd_printk(KERN_ERR SFX "cannot allocate posbuf\n"); | 1332 | snd_printk(KERN_ERR SFX "cannot allocate posbuf\n"); |
1322 | goto errout; | 1333 | goto errout; |
1334 | } | ||
1323 | } | 1335 | } |
1324 | #endif | ||
1325 | /* allocate CORB/RIRB */ | 1336 | /* allocate CORB/RIRB */ |
1326 | if ((err = azx_alloc_cmd_io(chip)) < 0) | 1337 | if ((err = azx_alloc_cmd_io(chip)) < 0) |
1327 | goto errout; | 1338 | goto errout; |
@@ -1372,7 +1383,7 @@ static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id * | |||
1372 | return -ENOMEM; | 1383 | return -ENOMEM; |
1373 | } | 1384 | } |
1374 | 1385 | ||
1375 | if ((err = azx_create(card, pci, &chip)) < 0) { | 1386 | if ((err = azx_create(card, pci, position_fix[dev], &chip)) < 0) { |
1376 | snd_card_free(card); | 1387 | snd_card_free(card); |
1377 | return err; | 1388 | return err; |
1378 | } | 1389 | } |