aboutsummaryrefslogtreecommitdiffstats
path: root/sound/isa/wss
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2008-07-31 15:09:32 -0400
committerJaroslav Kysela <perex@perex.cz>2008-08-06 09:39:56 -0400
commitead893c0deeec165524cc8a06e7e739d7d84b4c4 (patch)
tree86881775a9f4e7052eded95747fd8854d043fdda /sound/isa/wss
parent5664daa1c1fa250dd7f6b336278b0402638e8edc (diff)
ALSA: wss_lib: use wss pcm code instead of ad1848 one
Use the wss pcm code and kill the ad1848 pcm code. The AD1848 chip is much slower than CS4231 chips so the waiting loop was increased 100x (10x is not enough). Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Reviewed-by: Rene Herman <rene.herman@gmail.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/isa/wss')
-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 */