aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/azt3328.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/azt3328.c')
-rw-r--r--sound/pci/azt3328.c70
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(&reg, kcontrol->private_value); 581 snd_azf3328_mixer_reg_decode(&reg, 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(&reg, kcontrol->private_value); 603 snd_azf3328_mixer_reg_decode(&reg, 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) */