diff options
Diffstat (limited to 'sound/pci/azt3328.c')
-rw-r--r-- | sound/pci/azt3328.c | 70 |
1 files changed, 23 insertions, 47 deletions
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index c9af04ed200f..e68056c81580 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c | |||
@@ -33,7 +33,7 @@ | |||
33 | * in the first place >:-P}), | 33 | * in the first place >:-P}), |
34 | * I was forced to base this driver on reverse engineering | 34 | * I was forced to base this driver on reverse engineering |
35 | * (3 weeks' worth of evenings filled with driver work). | 35 | * (3 weeks' worth of evenings filled with driver work). |
36 | * (and no, I did NOT go the easy way: to pick up a PCI128 for 9 Euros) | 36 | * (and no, I did NOT go the easy way: to pick up a SB PCI128 for 9 Euros) |
37 | * | 37 | * |
38 | * The AZF3328 chip (note: AZF3328, *not* AZT3328, that's just the driver name | 38 | * The AZF3328 chip (note: AZF3328, *not* AZT3328, that's just the driver name |
39 | * for compatibility reasons) has the following features: | 39 | * for compatibility reasons) has the following features: |
@@ -339,10 +339,8 @@ snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip, int reg | |||
339 | else | 339 | else |
340 | dst_vol_left &= ~0x80; | 340 | dst_vol_left &= ~0x80; |
341 | 341 | ||
342 | do | 342 | do { |
343 | { | 343 | if (!left_done) { |
344 | if (!left_done) | ||
345 | { | ||
346 | if (curr_vol_left > dst_vol_left) | 344 | if (curr_vol_left > dst_vol_left) |
347 | curr_vol_left--; | 345 | curr_vol_left--; |
348 | else | 346 | else |
@@ -352,8 +350,7 @@ snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip, int reg | |||
352 | left_done = 1; | 350 | left_done = 1; |
353 | outb(curr_vol_left, portbase + 1); | 351 | outb(curr_vol_left, portbase + 1); |
354 | } | 352 | } |
355 | if (!right_done) | 353 | if (!right_done) { |
356 | { | ||
357 | if (curr_vol_right > dst_vol_right) | 354 | if (curr_vol_right > dst_vol_right) |
358 | curr_vol_right--; | 355 | curr_vol_right--; |
359 | else | 356 | else |
@@ -368,8 +365,7 @@ snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip, int reg | |||
368 | } | 365 | } |
369 | if (delay) | 366 | if (delay) |
370 | mdelay(delay); | 367 | mdelay(delay); |
371 | } | 368 | } while ((!left_done) || (!right_done)); |
372 | while ((!left_done) || (!right_done)); | ||
373 | snd_azf3328_dbgcallleave(); | 369 | snd_azf3328_dbgcallleave(); |
374 | } | 370 | } |
375 | 371 | ||
@@ -556,8 +552,7 @@ snd_azf3328_info_mixer_enum(struct snd_kcontrol *kcontrol, | |||
556 | uinfo->value.enumerated.items = reg.enum_c; | 552 | uinfo->value.enumerated.items = reg.enum_c; |
557 | if (uinfo->value.enumerated.item > reg.enum_c - 1U) | 553 | if (uinfo->value.enumerated.item > reg.enum_c - 1U) |
558 | uinfo->value.enumerated.item = reg.enum_c - 1U; | 554 | uinfo->value.enumerated.item = reg.enum_c - 1U; |
559 | if (reg.reg == IDX_MIXER_ADVCTL2) | 555 | if (reg.reg == IDX_MIXER_ADVCTL2) { |
560 | { | ||
561 | switch(reg.lchan_shift) { | 556 | switch(reg.lchan_shift) { |
562 | case 8: /* modem out sel */ | 557 | case 8: /* modem out sel */ |
563 | strcpy(uinfo->value.enumerated.name, texts1[uinfo->value.enumerated.item]); | 558 | strcpy(uinfo->value.enumerated.name, texts1[uinfo->value.enumerated.item]); |
@@ -569,8 +564,7 @@ snd_azf3328_info_mixer_enum(struct snd_kcontrol *kcontrol, | |||
569 | strcpy(uinfo->value.enumerated.name, texts4[uinfo->value.enumerated.item]); | 564 | strcpy(uinfo->value.enumerated.name, texts4[uinfo->value.enumerated.item]); |
570 | break; | 565 | break; |
571 | } | 566 | } |
572 | } | 567 | } else |
573 | else | ||
574 | strcpy(uinfo->value.enumerated.name, texts3[uinfo->value.enumerated.item] | 568 | strcpy(uinfo->value.enumerated.name, texts3[uinfo->value.enumerated.item] |
575 | ); | 569 | ); |
576 | return 0; | 570 | return 0; |
@@ -586,12 +580,10 @@ snd_azf3328_get_mixer_enum(struct snd_kcontrol *kcontrol, | |||
586 | 580 | ||
587 | snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); | 581 | snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); |
588 | val = snd_azf3328_mixer_inw(chip, reg.reg); | 582 | val = snd_azf3328_mixer_inw(chip, reg.reg); |
589 | if (reg.reg == IDX_MIXER_REC_SELECT) | 583 | if (reg.reg == IDX_MIXER_REC_SELECT) { |
590 | { | ||
591 | ucontrol->value.enumerated.item[0] = (val >> 8) & (reg.enum_c - 1); | 584 | ucontrol->value.enumerated.item[0] = (val >> 8) & (reg.enum_c - 1); |
592 | ucontrol->value.enumerated.item[1] = (val >> 0) & (reg.enum_c - 1); | 585 | ucontrol->value.enumerated.item[1] = (val >> 0) & (reg.enum_c - 1); |
593 | } | 586 | } else |
594 | else | ||
595 | ucontrol->value.enumerated.item[0] = (val >> reg.lchan_shift) & (reg.enum_c - 1); | 587 | ucontrol->value.enumerated.item[0] = (val >> reg.lchan_shift) & (reg.enum_c - 1); |
596 | 588 | ||
597 | snd_azf3328_dbgmixer("get_enum: %02x is %04x -> %d|%d (shift %02d, enum_c %d)\n", | 589 | snd_azf3328_dbgmixer("get_enum: %02x is %04x -> %d|%d (shift %02d, enum_c %d)\n", |
@@ -611,16 +603,13 @@ snd_azf3328_put_mixer_enum(struct snd_kcontrol *kcontrol, | |||
611 | snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); | 603 | snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); |
612 | oreg = snd_azf3328_mixer_inw(chip, reg.reg); | 604 | oreg = snd_azf3328_mixer_inw(chip, reg.reg); |
613 | val = oreg; | 605 | val = oreg; |
614 | if (reg.reg == IDX_MIXER_REC_SELECT) | 606 | if (reg.reg == IDX_MIXER_REC_SELECT) { |
615 | { | ||
616 | if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U || | 607 | if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U || |
617 | ucontrol->value.enumerated.item[1] > reg.enum_c - 1U) | 608 | ucontrol->value.enumerated.item[1] > reg.enum_c - 1U) |
618 | return -EINVAL; | 609 | return -EINVAL; |
619 | val = (ucontrol->value.enumerated.item[0] << 8) | | 610 | val = (ucontrol->value.enumerated.item[0] << 8) | |
620 | (ucontrol->value.enumerated.item[1] << 0); | 611 | (ucontrol->value.enumerated.item[1] << 0); |
621 | } | 612 | } else { |
622 | else | ||
623 | { | ||
624 | if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U) | 613 | if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U) |
625 | return -EINVAL; | 614 | return -EINVAL; |
626 | val &= ~((reg.enum_c - 1) << reg.lchan_shift); | 615 | val &= ~((reg.enum_c - 1) << reg.lchan_shift); |
@@ -846,22 +835,18 @@ snd_azf3328_setdmaa(struct snd_azf3328 *chip, | |||
846 | unsigned int is_running; | 835 | unsigned int is_running; |
847 | 836 | ||
848 | snd_azf3328_dbgcallenter(); | 837 | snd_azf3328_dbgcallenter(); |
849 | if (do_recording) | 838 | if (do_recording) { |
850 | { | ||
851 | /* access capture registers, i.e. skip playback reg section */ | 839 | /* access capture registers, i.e. skip playback reg section */ |
852 | portbase = chip->codec_port + 0x20; | 840 | portbase = chip->codec_port + 0x20; |
853 | is_running = chip->is_recording; | 841 | is_running = chip->is_recording; |
854 | } | 842 | } else { |
855 | else | ||
856 | { | ||
857 | /* access the playback register section */ | 843 | /* access the playback register section */ |
858 | portbase = chip->codec_port + 0x00; | 844 | portbase = chip->codec_port + 0x00; |
859 | is_running = chip->is_playing; | 845 | is_running = chip->is_playing; |
860 | } | 846 | } |
861 | 847 | ||
862 | /* AZF3328 uses a two buffer pointer DMA playback approach */ | 848 | /* AZF3328 uses a two buffer pointer DMA playback approach */ |
863 | if (!is_running) | 849 | if (!is_running) { |
864 | { | ||
865 | unsigned long addr_area2; | 850 | unsigned long addr_area2; |
866 | unsigned long count_areas, count_tmp; /* width 32bit -- overflow!! */ | 851 | unsigned long count_areas, count_tmp; /* width 32bit -- overflow!! */ |
867 | count_areas = size/2; | 852 | count_areas = size/2; |
@@ -1224,8 +1209,7 @@ snd_azf3328_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
1224 | snd_azf3328_codec_inw(chip, IDX_IO_PLAY_IRQTYPE), | 1209 | snd_azf3328_codec_inw(chip, IDX_IO_PLAY_IRQTYPE), |
1225 | status); | 1210 | status); |
1226 | 1211 | ||
1227 | if (status & IRQ_TIMER) | 1212 | if (status & IRQ_TIMER) { |
1228 | { | ||
1229 | /* snd_azf3328_dbgplay("timer %ld\n", inl(chip->codec_port+IDX_IO_TIMER_VALUE) & TIMER_VALUE_MASK); */ | 1213 | /* snd_azf3328_dbgplay("timer %ld\n", inl(chip->codec_port+IDX_IO_TIMER_VALUE) & TIMER_VALUE_MASK); */ |
1230 | if (chip->timer) | 1214 | if (chip->timer) |
1231 | snd_timer_interrupt(chip->timer, chip->timer->sticks); | 1215 | snd_timer_interrupt(chip->timer, chip->timer->sticks); |
@@ -1235,50 +1219,43 @@ snd_azf3328_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
1235 | spin_unlock(&chip->reg_lock); | 1219 | spin_unlock(&chip->reg_lock); |
1236 | snd_azf3328_dbgplay("azt3328: timer IRQ\n"); | 1220 | snd_azf3328_dbgplay("azt3328: timer IRQ\n"); |
1237 | } | 1221 | } |
1238 | if (status & IRQ_PLAYBACK) | 1222 | if (status & IRQ_PLAYBACK) { |
1239 | { | ||
1240 | spin_lock(&chip->reg_lock); | 1223 | spin_lock(&chip->reg_lock); |
1241 | which = snd_azf3328_codec_inb(chip, IDX_IO_PLAY_IRQTYPE); | 1224 | which = snd_azf3328_codec_inb(chip, IDX_IO_PLAY_IRQTYPE); |
1242 | /* ack all IRQ types immediately */ | 1225 | /* ack all IRQ types immediately */ |
1243 | snd_azf3328_codec_outb(chip, IDX_IO_PLAY_IRQTYPE, which); | 1226 | snd_azf3328_codec_outb(chip, IDX_IO_PLAY_IRQTYPE, which); |
1244 | spin_unlock(&chip->reg_lock); | 1227 | spin_unlock(&chip->reg_lock); |
1245 | 1228 | ||
1246 | if (chip->pcm && chip->playback_substream) | 1229 | if (chip->pcm && chip->playback_substream) { |
1247 | { | ||
1248 | snd_pcm_period_elapsed(chip->playback_substream); | 1230 | snd_pcm_period_elapsed(chip->playback_substream); |
1249 | snd_azf3328_dbgplay("PLAY period done (#%x), @ %x\n", | 1231 | snd_azf3328_dbgplay("PLAY period done (#%x), @ %x\n", |
1250 | which, | 1232 | which, |
1251 | inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS)); | 1233 | inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS)); |
1252 | } | 1234 | } else |
1253 | else | ||
1254 | snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n"); | 1235 | snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n"); |
1255 | if (which & IRQ_PLAY_SOMETHING) | 1236 | if (which & IRQ_PLAY_SOMETHING) |
1256 | snd_azf3328_dbgplay("azt3328: unknown play IRQ type occurred, please report!\n"); | 1237 | snd_azf3328_dbgplay("azt3328: unknown play IRQ type occurred, please report!\n"); |
1257 | } | 1238 | } |
1258 | if (status & IRQ_RECORDING) | 1239 | if (status & IRQ_RECORDING) { |
1259 | { | ||
1260 | spin_lock(&chip->reg_lock); | 1240 | spin_lock(&chip->reg_lock); |
1261 | which = snd_azf3328_codec_inb(chip, IDX_IO_REC_IRQTYPE); | 1241 | which = snd_azf3328_codec_inb(chip, IDX_IO_REC_IRQTYPE); |
1262 | /* ack all IRQ types immediately */ | 1242 | /* ack all IRQ types immediately */ |
1263 | snd_azf3328_codec_outb(chip, IDX_IO_REC_IRQTYPE, which); | 1243 | snd_azf3328_codec_outb(chip, IDX_IO_REC_IRQTYPE, which); |
1264 | spin_unlock(&chip->reg_lock); | 1244 | spin_unlock(&chip->reg_lock); |
1265 | 1245 | ||
1266 | if (chip->pcm && chip->capture_substream) | 1246 | if (chip->pcm && chip->capture_substream) { |
1267 | { | ||
1268 | snd_pcm_period_elapsed(chip->capture_substream); | 1247 | snd_pcm_period_elapsed(chip->capture_substream); |
1269 | snd_azf3328_dbgplay("REC period done (#%x), @ %x\n", | 1248 | snd_azf3328_dbgplay("REC period done (#%x), @ %x\n", |
1270 | which, | 1249 | which, |
1271 | inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS)); | 1250 | inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS)); |
1272 | } | 1251 | } else |
1273 | else | ||
1274 | snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n"); | 1252 | snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n"); |
1275 | if (which & IRQ_REC_SOMETHING) | 1253 | if (which & IRQ_REC_SOMETHING) |
1276 | snd_azf3328_dbgplay("azt3328: unknown rec IRQ type occurred, please report!\n"); | 1254 | snd_azf3328_dbgplay("azt3328: unknown rec IRQ type occurred, please report!\n"); |
1277 | } | 1255 | } |
1278 | /* MPU401 has less critical IRQ requirements | 1256 | /* MPU401 has less critical IRQ requirements |
1279 | * than timer and playback/recording, right? */ | 1257 | * than timer and playback/recording, right? */ |
1280 | if (status & IRQ_MPU401) | 1258 | if (status & IRQ_MPU401) { |
1281 | { | ||
1282 | snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs); | 1259 | snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs); |
1283 | 1260 | ||
1284 | /* hmm, do we have to ack the IRQ here somehow? | 1261 | /* hmm, do we have to ack the IRQ here somehow? |
@@ -1572,8 +1549,7 @@ snd_azf3328_timer_start(struct snd_timer *timer) | |||
1572 | snd_azf3328_dbgcallenter(); | 1549 | snd_azf3328_dbgcallenter(); |
1573 | chip = snd_timer_chip(timer); | 1550 | chip = snd_timer_chip(timer); |
1574 | delay = ((timer->sticks * seqtimer_scaling) - 1) & TIMER_VALUE_MASK; | 1551 | delay = ((timer->sticks * seqtimer_scaling) - 1) & TIMER_VALUE_MASK; |
1575 | if (delay < 49) | 1552 | if (delay < 49) { |
1576 | { | ||
1577 | /* uhoh, that's not good, since user-space won't know about | 1553 | /* uhoh, that's not good, since user-space won't know about |
1578 | * this timing tweak | 1554 | * this timing tweak |
1579 | * (we need to do it to avoid a lockup, though) */ | 1555 | * (we need to do it to avoid a lockup, though) */ |