aboutsummaryrefslogtreecommitdiffstats
path: root/sound/isa/wss/wss_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/isa/wss/wss_lib.c')
-rw-r--r--sound/isa/wss/wss_lib.c126
1 files changed, 100 insertions, 26 deletions
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c
index 1688f07a14b0..57d1e8ee6bbb 100644
--- a/sound/isa/wss/wss_lib.c
+++ b/sound/isa/wss/wss_lib.c
@@ -380,7 +380,7 @@ static void snd_wss_busy_wait(struct snd_wss *chip)
380 for (timeout = 5; timeout > 0; timeout--) 380 for (timeout = 5; timeout > 0; timeout--)
381 wss_inb(chip, CS4231P(REGSEL)); 381 wss_inb(chip, CS4231P(REGSEL));
382 /* end of cleanup sequence */ 382 /* end of cleanup sequence */
383 for (timeout = 250; 383 for (timeout = 25000;
384 timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); 384 timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
385 timeout--) 385 timeout--)
386 udelay(10); 386 udelay(10);
@@ -413,6 +413,7 @@ void snd_wss_mce_down(struct snd_wss *chip)
413 unsigned long flags; 413 unsigned long flags;
414 unsigned long end_time; 414 unsigned long end_time;
415 int timeout; 415 int timeout;
416 int hw_mask = WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK | WSS_HW_AD1848;
416 417
417 snd_wss_busy_wait(chip); 418 snd_wss_busy_wait(chip);
418 419
@@ -427,10 +428,8 @@ void snd_wss_mce_down(struct snd_wss *chip)
427 spin_unlock_irqrestore(&chip->reg_lock, flags); 428 spin_unlock_irqrestore(&chip->reg_lock, flags);
428 if (timeout == 0x80) 429 if (timeout == 0x80)
429 snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port); 430 snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port);
430 if ((timeout & CS4231_MCE) == 0 || 431 if ((timeout & CS4231_MCE) == 0 || !(chip->hardware & hw_mask))
431 !(chip->hardware & (WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK))) {
432 return; 432 return;
433 }
434 433
435 /* 434 /*
436 * Wait for (possible -- during init auto-calibration may not be set) 435 * Wait for (possible -- during init auto-calibration may not be set)
@@ -601,12 +600,14 @@ static void snd_wss_calibrate_mute(struct snd_wss *chip, int mute)
601 mute ? 0x80 : chip->image[CS4231_LEFT_OUTPUT]); 600 mute ? 0x80 : chip->image[CS4231_LEFT_OUTPUT]);
602 snd_wss_dout(chip, CS4231_RIGHT_OUTPUT, 601 snd_wss_dout(chip, CS4231_RIGHT_OUTPUT,
603 mute ? 0x80 : chip->image[CS4231_RIGHT_OUTPUT]); 602 mute ? 0x80 : chip->image[CS4231_RIGHT_OUTPUT]);
604 snd_wss_dout(chip, CS4231_LEFT_LINE_IN, 603 if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
605 mute ? 0x80 : chip->image[CS4231_LEFT_LINE_IN]); 604 snd_wss_dout(chip, CS4231_LEFT_LINE_IN,
606 snd_wss_dout(chip, CS4231_RIGHT_LINE_IN, 605 mute ? 0x80 : chip->image[CS4231_LEFT_LINE_IN]);
607 mute ? 0x80 : chip->image[CS4231_RIGHT_LINE_IN]); 606 snd_wss_dout(chip, CS4231_RIGHT_LINE_IN,
608 snd_wss_dout(chip, CS4231_MONO_CTRL, 607 mute ? 0x80 : chip->image[CS4231_RIGHT_LINE_IN]);
609 mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]); 608 snd_wss_dout(chip, CS4231_MONO_CTRL,
609 mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]);
610 }
610 if (chip->hardware == WSS_HW_INTERWAVE) { 611 if (chip->hardware == WSS_HW_INTERWAVE) {
611 snd_wss_dout(chip, CS4231_LEFT_MIC_INPUT, 612 snd_wss_dout(chip, CS4231_LEFT_MIC_INPUT,
612 mute ? 0x80 : chip->image[CS4231_LEFT_MIC_INPUT]); 613 mute ? 0x80 : chip->image[CS4231_LEFT_MIC_INPUT]);
@@ -706,7 +707,10 @@ static void snd_wss_capture_format(struct snd_wss *chip,
706 snd_wss_mce_up(chip); 707 snd_wss_mce_up(chip);
707 spin_lock_irqsave(&chip->reg_lock, flags); 708 spin_lock_irqsave(&chip->reg_lock, flags);
708 } 709 }
709 snd_wss_out(chip, CS4231_REC_FORMAT, cdfr); 710 if (chip->hardware & WSS_HW_AD1848_MASK)
711 snd_wss_out(chip, CS4231_PLAYBK_FORMAT, cdfr);
712 else
713 snd_wss_out(chip, CS4231_REC_FORMAT, cdfr);
710 spin_unlock_irqrestore(&chip->reg_lock, flags); 714 spin_unlock_irqrestore(&chip->reg_lock, flags);
711 snd_wss_mce_down(chip); 715 snd_wss_mce_down(chip);
712 } 716 }
@@ -818,7 +822,9 @@ static void snd_wss_init(struct snd_wss *chip)
818 822
819 snd_wss_mce_up(chip); 823 snd_wss_mce_up(chip);
820 spin_lock_irqsave(&chip->reg_lock, flags); 824 spin_lock_irqsave(&chip->reg_lock, flags);
821 snd_wss_out(chip, CS4231_REC_FORMAT, chip->image[CS4231_REC_FORMAT]); 825 if (!(chip->hardware & WSS_HW_AD1848_MASK))
826 snd_wss_out(chip, CS4231_REC_FORMAT,
827 chip->image[CS4231_REC_FORMAT]);
822 spin_unlock_irqrestore(&chip->reg_lock, flags); 828 spin_unlock_irqrestore(&chip->reg_lock, flags);
823 snd_wss_mce_down(chip); 829 snd_wss_mce_down(chip);
824 830
@@ -844,20 +850,24 @@ static int snd_wss_open(struct snd_wss *chip, unsigned int mode)
844 } 850 }
845 /* ok. now enable and ack CODEC IRQ */ 851 /* ok. now enable and ack CODEC IRQ */
846 spin_lock_irqsave(&chip->reg_lock, flags); 852 spin_lock_irqsave(&chip->reg_lock, flags);
847 snd_wss_out(chip, CS4231_IRQ_STATUS, 853 if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
848 CS4231_PLAYBACK_IRQ | 854 snd_wss_out(chip, CS4231_IRQ_STATUS,
849 CS4231_RECORD_IRQ | 855 CS4231_PLAYBACK_IRQ |
850 CS4231_TIMER_IRQ); 856 CS4231_RECORD_IRQ |
851 snd_wss_out(chip, CS4231_IRQ_STATUS, 0); 857 CS4231_TIMER_IRQ);
858 snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
859 }
852 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ 860 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
853 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ 861 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
854 chip->image[CS4231_PIN_CTRL] |= CS4231_IRQ_ENABLE; 862 chip->image[CS4231_PIN_CTRL] |= CS4231_IRQ_ENABLE;
855 snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]); 863 snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
856 snd_wss_out(chip, CS4231_IRQ_STATUS, 864 if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
857 CS4231_PLAYBACK_IRQ | 865 snd_wss_out(chip, CS4231_IRQ_STATUS,
858 CS4231_RECORD_IRQ | 866 CS4231_PLAYBACK_IRQ |
859 CS4231_TIMER_IRQ); 867 CS4231_RECORD_IRQ |
860 snd_wss_out(chip, CS4231_IRQ_STATUS, 0); 868 CS4231_TIMER_IRQ);
869 snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
870 }
861 spin_unlock_irqrestore(&chip->reg_lock, flags); 871 spin_unlock_irqrestore(&chip->reg_lock, flags);
862 872
863 chip->mode = mode; 873 chip->mode = mode;
@@ -879,7 +889,8 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode)
879 889
880 /* disable IRQ */ 890 /* disable IRQ */
881 spin_lock_irqsave(&chip->reg_lock, flags); 891 spin_lock_irqsave(&chip->reg_lock, flags);
882 snd_wss_out(chip, CS4231_IRQ_STATUS, 0); 892 if (!(chip->hardware & WSS_HW_AD1848_MASK))
893 snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
883 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ 894 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
884 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ 895 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
885 chip->image[CS4231_PIN_CTRL] &= ~CS4231_IRQ_ENABLE; 896 chip->image[CS4231_PIN_CTRL] &= ~CS4231_IRQ_ENABLE;
@@ -902,7 +913,8 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode)
902 } 913 }
903 914
904 /* clear IRQ again */ 915 /* clear IRQ again */
905 snd_wss_out(chip, CS4231_IRQ_STATUS, 0); 916 if (!(chip->hardware & WSS_HW_AD1848_MASK))
917 snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
906 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ 918 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
907 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ 919 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
908 spin_unlock_irqrestore(&chip->reg_lock, flags); 920 spin_unlock_irqrestore(&chip->reg_lock, flags);
@@ -1023,7 +1035,13 @@ static int snd_wss_capture_prepare(struct snd_pcm_substream *substream)
1023 chip->c_dma_size = size; 1035 chip->c_dma_size = size;
1024 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | CS4231_RECORD_PIO); 1036 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);
1025 snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT); 1037 snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);
1026 count = snd_wss_get_count(chip->image[CS4231_REC_FORMAT], count) - 1; 1038 if (chip->hardware & WSS_HW_AD1848_MASK)
1039 count = snd_wss_get_count(chip->image[CS4231_PLAYBK_FORMAT],
1040 count);
1041 else
1042 count = snd_wss_get_count(chip->image[CS4231_REC_FORMAT],
1043 count);
1044 count--;
1027 if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) { 1045 if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) {
1028 snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count); 1046 snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count);
1029 snd_wss_out(chip, CS4231_PLY_UPR_CNT, 1047 snd_wss_out(chip, CS4231_PLY_UPR_CNT,
@@ -1341,6 +1359,11 @@ static int snd_wss_playback_open(struct snd_pcm_substream *substream)
1341 1359
1342 runtime->hw = snd_wss_playback; 1360 runtime->hw = snd_wss_playback;
1343 1361
1362 /* hardware limitation of older chipsets */
1363 if (chip->hardware & WSS_HW_AD1848_MASK)
1364 runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM |
1365 SNDRV_PCM_FMTBIT_S16_BE);
1366
1344 /* hardware bug in InterWave chipset */ 1367 /* hardware bug in InterWave chipset */
1345 if (chip->hardware == WSS_HW_INTERWAVE && chip->dma1 > 3) 1368 if (chip->hardware == WSS_HW_INTERWAVE && chip->dma1 > 3)
1346 runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_MU_LAW; 1369 runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_MU_LAW;
@@ -1379,6 +1402,11 @@ static int snd_wss_capture_open(struct snd_pcm_substream *substream)
1379 1402
1380 runtime->hw = snd_wss_capture; 1403 runtime->hw = snd_wss_capture;
1381 1404
1405 /* hardware limitation of older chipsets */
1406 if (chip->hardware & WSS_HW_AD1848_MASK)
1407 runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM |
1408 SNDRV_PCM_FMTBIT_S16_BE);
1409
1382 /* hardware limitation of cheap chips */ 1410 /* hardware limitation of cheap chips */
1383 if (chip->hardware == WSS_HW_CS4235 || 1411 if (chip->hardware == WSS_HW_CS4235 ||
1384 chip->hardware == WSS_HW_CS4239) 1412 chip->hardware == WSS_HW_CS4239)
@@ -1423,6 +1451,26 @@ static int snd_wss_capture_close(struct snd_pcm_substream *substream)
1423 return 0; 1451 return 0;
1424} 1452}
1425 1453
1454static void snd_wss_thinkpad_twiddle(struct snd_wss *chip, int on)
1455{
1456 int tmp;
1457
1458 if (!chip->thinkpad_flag)
1459 return;
1460
1461 outb(0x1c, AD1848_THINKPAD_CTL_PORT1);
1462 tmp = inb(AD1848_THINKPAD_CTL_PORT2);
1463
1464 if (on)
1465 /* turn it on */
1466 tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT;
1467 else
1468 /* turn it off */
1469 tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT;
1470
1471 outb(tmp, AD1848_THINKPAD_CTL_PORT2);
1472}
1473
1426#ifdef CONFIG_PM 1474#ifdef CONFIG_PM
1427 1475
1428/* lowlevel suspend callback for CS4231 */ 1476/* lowlevel suspend callback for CS4231 */
@@ -1436,6 +1484,8 @@ static void snd_wss_suspend(struct snd_wss *chip)
1436 for (reg = 0; reg < 32; reg++) 1484 for (reg = 0; reg < 32; reg++)
1437 chip->image[reg] = snd_wss_in(chip, reg); 1485 chip->image[reg] = snd_wss_in(chip, reg);
1438 spin_unlock_irqrestore(&chip->reg_lock, flags); 1486 spin_unlock_irqrestore(&chip->reg_lock, flags);
1487 if (chip->thinkpad_flag)
1488 snd_wss_thinkpad_twiddle(chip, 0);
1439} 1489}
1440 1490
1441/* lowlevel resume callback for CS4231 */ 1491/* lowlevel resume callback for CS4231 */
@@ -1445,6 +1495,8 @@ static void snd_wss_resume(struct snd_wss *chip)
1445 unsigned long flags; 1495 unsigned long flags;
1446 /* int timeout; */ 1496 /* int timeout; */
1447 1497
1498 if (chip->thinkpad_flag)
1499 snd_wss_thinkpad_twiddle(chip, 1);
1448 snd_wss_mce_up(chip); 1500 snd_wss_mce_up(chip);
1449 spin_lock_irqsave(&chip->reg_lock, flags); 1501 spin_lock_irqsave(&chip->reg_lock, flags);
1450 for (reg = 0; reg < 32; reg++) { 1502 for (reg = 0; reg < 32; reg++) {
@@ -1542,6 +1594,14 @@ const char *snd_wss_chip_id(struct snd_wss *chip)
1542 return "AD1845"; 1594 return "AD1845";
1543 case WSS_HW_OPTI93X: 1595 case WSS_HW_OPTI93X:
1544 return "OPTi 93x"; 1596 return "OPTi 93x";
1597 case WSS_HW_AD1847:
1598 return "AD1847";
1599 case WSS_HW_AD1848:
1600 return "AD1848";
1601 case WSS_HW_CS4248:
1602 return "CS4248";
1603 case WSS_HW_CMI8330:
1604 return "CMI8330/C3D";
1545 default: 1605 default:
1546 return "???"; 1606 return "???";
1547 } 1607 }
@@ -1704,7 +1764,8 @@ int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
1704 struct snd_pcm *pcm; 1764 struct snd_pcm *pcm;
1705 int err; 1765 int err;
1706 1766
1707 if ((err = snd_pcm_new(chip->card, "CS4231", device, 1, 1, &pcm)) < 0) 1767 err = snd_pcm_new(chip->card, "WSS", device, 1, 1, &pcm);
1768 if (err < 0)
1708 return err; 1769 return err;
1709 1770
1710 spin_lock_init(&chip->reg_lock); 1771 spin_lock_init(&chip->reg_lock);
@@ -1714,6 +1775,12 @@ int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
1714 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops); 1775 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops);
1715 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops); 1776 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops);
1716 1777
1778 /* temporary */
1779 if (chip->hardware & WSS_HW_AD1848_MASK) {
1780 chip->rate_constraint = snd_wss_xrate;
1781 chip->set_playback_format = snd_wss_playback_format;
1782 chip->set_capture_format = snd_wss_capture_format;
1783 }
1717 /* global setup */ 1784 /* global setup */
1718 pcm->private_data = chip; 1785 pcm->private_data = chip;
1719 pcm->info_flags = 0; 1786 pcm->info_flags = 0;
@@ -2134,6 +2201,13 @@ int snd_wss_mixer(struct snd_wss *chip)
2134} 2201}
2135EXPORT_SYMBOL(snd_wss_mixer); 2202EXPORT_SYMBOL(snd_wss_mixer);
2136 2203
2204const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction)
2205{
2206 return direction == SNDRV_PCM_STREAM_PLAYBACK ?
2207 &snd_wss_playback_ops : &snd_wss_capture_ops;
2208}
2209EXPORT_SYMBOL(snd_wss_get_pcm_ops);
2210
2137/* 2211/*
2138 * INIT part 2212 * INIT part
2139 */ 2213 */