aboutsummaryrefslogtreecommitdiffstats
path: root/sound/isa/wss/wss_lib.c
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2008-07-31 15:10:47 -0400
committerJaroslav Kysela <perex@perex.cz>2008-08-06 09:40:02 -0400
commit760fc6b838d8c783c363e8bdb3714bd92a8945c4 (patch)
treebe50fd4d3e3c3d561d62a369066f9ea62d348fbc /sound/isa/wss/wss_lib.c
parentead893c0deeec165524cc8a06e7e739d7d84b4c4 (diff)
ALSA: wss_lib: use wss detection code instead of ad1848 one
Use the wss detection code and kill the ad1848 library. The library is fully assimilated into the new wss library. This required reworking of the AD1848 family code so the code is changed to correctly detect chips from the AD1848 and CS4231 families. I have tested it on following cards: Gallant SC-6600 (codec: AD1848, driver: snd-sc6600) SoundScape VIVO/90 (codec: AD1845, driver: snd-sscape) SG Waverider (codec: CS4231A, driver: Rene Herman's snd-galaxy) Opti930 (codec: built-in - CS4231 compatible, driver: snd-opti93x) Opti931 (codec: built-in - CS4231 compatible, driver: snd-opti93x) Gallant SC-70P (chip/codec: CS4237B, driver: snd-cs4236) Audio Plus 3D (chip/codec: CMI8330A, driver: snd-cmi8330) Dell Latitude CP (chip/codec: cs4236, driver snd-cs4232) Sound playback and recording works on all these cards. 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/wss_lib.c')
-rw-r--r--sound/isa/wss/wss_lib.c150
1 files changed, 120 insertions, 30 deletions
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c
index 57d1e8ee6bbb..a5602f515f49 100644
--- a/sound/isa/wss/wss_lib.c
+++ b/sound/isa/wss/wss_lib.c
@@ -1073,7 +1073,11 @@ irqreturn_t snd_wss_interrupt(int irq, void *dev_id)
1073 struct snd_wss *chip = dev_id; 1073 struct snd_wss *chip = dev_id;
1074 unsigned char status; 1074 unsigned char status;
1075 1075
1076 status = snd_wss_in(chip, CS4231_IRQ_STATUS); 1076 if (chip->hardware & WSS_HW_AD1848_MASK)
1077 /* pretend it was the only possible irq for AD1848 */
1078 status = CS4231_PLAYBACK_IRQ;
1079 else
1080 status = snd_wss_in(chip, CS4231_IRQ_STATUS);
1077 if (status & CS4231_TIMER_IRQ) { 1081 if (status & CS4231_TIMER_IRQ) {
1078 if (chip->timer) 1082 if (chip->timer)
1079 snd_timer_interrupt(chip->timer, chip->timer->sticks); 1083 snd_timer_interrupt(chip->timer, chip->timer->sticks);
@@ -1105,7 +1109,11 @@ irqreturn_t snd_wss_interrupt(int irq, void *dev_id)
1105 } 1109 }
1106 1110
1107 spin_lock(&chip->reg_lock); 1111 spin_lock(&chip->reg_lock);
1108 snd_wss_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0); 1112 status = ~CS4231_ALL_IRQS | ~status;
1113 if (chip->hardware & WSS_HW_AD1848_MASK)
1114 wss_outb(chip, CS4231P(STATUS), 0);
1115 else
1116 snd_wss_outm(chip, CS4231_IRQ_STATUS, status, 0);
1109 spin_unlock(&chip->reg_lock); 1117 spin_unlock(&chip->reg_lock);
1110 return IRQ_HANDLED; 1118 return IRQ_HANDLED;
1111} 1119}
@@ -1137,36 +1145,112 @@ static snd_pcm_uframes_t snd_wss_capture_pointer(struct snd_pcm_substream *subst
1137 1145
1138 */ 1146 */
1139 1147
1140static int snd_wss_probe(struct snd_wss *chip) 1148static int snd_ad1848_probe(struct snd_wss *chip)
1141{ 1149{
1142 unsigned long flags; 1150 unsigned long flags;
1143 int i, id, rev; 1151 int i, id, rev, ad1847;
1144 unsigned char *ptr;
1145 unsigned int hw;
1146 1152
1147#if 0
1148 snd_wss_debug(chip);
1149#endif
1150 id = 0; 1153 id = 0;
1151 for (i = 0; i < 50; i++) { 1154 ad1847 = 0;
1155 for (i = 0; i < 1000; i++) {
1152 mb(); 1156 mb();
1153 if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) 1157 if (inb(chip->port + CS4231P(REGSEL)) & CS4231_INIT)
1154 udelay(2000); 1158 msleep(1);
1155 else { 1159 else {
1156 spin_lock_irqsave(&chip->reg_lock, flags); 1160 spin_lock_irqsave(&chip->reg_lock, flags);
1157 snd_wss_out(chip, CS4231_MISC_INFO, CS4231_MODE2); 1161 snd_wss_out(chip, CS4231_MISC_INFO, 0x00);
1158 id = snd_wss_in(chip, CS4231_MISC_INFO) & 0x0f; 1162 snd_wss_out(chip, CS4231_LEFT_INPUT, 0xaa);
1163 snd_wss_out(chip, CS4231_RIGHT_INPUT, 0x45);
1164 rev = snd_wss_in(chip, CS4231_RIGHT_INPUT);
1165 if (rev == 0x65) {
1166 spin_unlock_irqrestore(&chip->reg_lock, flags);
1167 id = 1;
1168 ad1847 = 1;
1169 break;
1170 }
1171 if (snd_wss_in(chip, CS4231_LEFT_INPUT) == 0xaa &&
1172 rev == 0x45) {
1173 spin_unlock_irqrestore(&chip->reg_lock, flags);
1174 id = 1;
1175 break;
1176 }
1159 spin_unlock_irqrestore(&chip->reg_lock, flags); 1177 spin_unlock_irqrestore(&chip->reg_lock, flags);
1160 if (id == 0x0a)
1161 break; /* this is valid value */
1162 } 1178 }
1163 } 1179 }
1164 snd_printdd("wss: port = 0x%lx, id = 0x%x\n", chip->port, id); 1180 if (id != 1)
1165 if (id != 0x0a)
1166 return -ENODEV; /* no valid device found */ 1181 return -ENODEV; /* no valid device found */
1182 id = 0;
1183 if (chip->hardware == WSS_HW_DETECT)
1184 id = ad1847 ? WSS_HW_AD1847 : WSS_HW_AD1848;
1185
1186 spin_lock_irqsave(&chip->reg_lock, flags);
1187 inb(chip->port + CS4231P(STATUS)); /* clear any pendings IRQ */
1188 outb(0, chip->port + CS4231P(STATUS));
1189 mb();
1190 if (id == WSS_HW_AD1848) {
1191 /* check if there are more than 16 registers */
1192 rev = snd_wss_in(chip, CS4231_MISC_INFO);
1193 snd_wss_out(chip, CS4231_MISC_INFO, 0x40);
1194 for (i = 0; i < 16; ++i) {
1195 if (snd_wss_in(chip, i) != snd_wss_in(chip, i + 16)) {
1196 id = WSS_HW_CMI8330;
1197 break;
1198 }
1199 }
1200 snd_wss_out(chip, CS4231_MISC_INFO, 0x00);
1201 if (id != WSS_HW_CMI8330 && (rev & 0x80))
1202 id = WSS_HW_CS4248;
1203 if (id == WSS_HW_CMI8330 && (rev & 0x0f) != 0x0a)
1204 id = 0;
1205 }
1206 if (id == WSS_HW_CMI8330) {
1207 /* verify it is not CS4231 by changing the version register */
1208 /* on CMI8330 it is volume control register and can be set 0 */
1209 snd_wss_out(chip, CS4231_MISC_INFO, CS4231_MODE2);
1210 snd_wss_dout(chip, CS4231_VERSION, 0x00);
1211 rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7;
1212 if (rev)
1213 id = 0;
1214 snd_wss_out(chip, CS4231_MISC_INFO, 0);
1215 }
1216 if (id)
1217 chip->hardware = id;
1218
1219 spin_unlock_irqrestore(&chip->reg_lock, flags);
1220 return 0; /* all things are ok.. */
1221}
1222
1223static int snd_wss_probe(struct snd_wss *chip)
1224{
1225 unsigned long flags;
1226 int i, id, rev, regnum;
1227 unsigned char *ptr;
1228 unsigned int hw;
1229
1230 id = snd_ad1848_probe(chip);
1231 if (id < 0)
1232 return id;
1167 1233
1168 hw = chip->hardware; 1234 hw = chip->hardware;
1169 if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) { 1235 if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) {
1236 for (i = 0; i < 50; i++) {
1237 mb();
1238 if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
1239 msleep(2);
1240 else {
1241 spin_lock_irqsave(&chip->reg_lock, flags);
1242 snd_wss_out(chip, CS4231_MISC_INFO,
1243 CS4231_MODE2);
1244 id = snd_wss_in(chip, CS4231_MISC_INFO) & 0x0f;
1245 spin_unlock_irqrestore(&chip->reg_lock, flags);
1246 if (id == 0x0a)
1247 break; /* this is valid value */
1248 }
1249 }
1250 snd_printdd("wss: port = 0x%lx, id = 0x%x\n", chip->port, id);
1251 if (id != 0x0a)
1252 return -ENODEV; /* no valid device found */
1253
1170 rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7; 1254 rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7;
1171 snd_printdd("CS4231: VERSION (I25) = 0x%x\n", rev); 1255 snd_printdd("CS4231: VERSION (I25) = 0x%x\n", rev);
1172 if (rev == 0x80) { 1256 if (rev == 0x80) {
@@ -1197,7 +1281,8 @@ static int snd_wss_probe(struct snd_wss *chip)
1197 mb(); 1281 mb();
1198 spin_unlock_irqrestore(&chip->reg_lock, flags); 1282 spin_unlock_irqrestore(&chip->reg_lock, flags);
1199 1283
1200 chip->image[CS4231_MISC_INFO] = CS4231_MODE2; 1284 if (!(chip->hardware & WSS_HW_AD1848_MASK))
1285 chip->image[CS4231_MISC_INFO] = CS4231_MODE2;
1201 switch (chip->hardware) { 1286 switch (chip->hardware) {
1202 case WSS_HW_INTERWAVE: 1287 case WSS_HW_INTERWAVE:
1203 chip->image[CS4231_MISC_INFO] = CS4231_IW_MODE3; 1288 chip->image[CS4231_MISC_INFO] = CS4231_IW_MODE3;
@@ -1223,9 +1308,10 @@ static int snd_wss_probe(struct snd_wss *chip)
1223 chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01; 1308 chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01;
1224 } 1309 }
1225 ptr = (unsigned char *) &chip->image; 1310 ptr = (unsigned char *) &chip->image;
1311 regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32;
1226 snd_wss_mce_down(chip); 1312 snd_wss_mce_down(chip);
1227 spin_lock_irqsave(&chip->reg_lock, flags); 1313 spin_lock_irqsave(&chip->reg_lock, flags);
1228 for (i = 0; i < 32; i++) /* ok.. fill all CS4231 registers */ 1314 for (i = 0; i < regnum; i++) /* ok.. fill all registers */
1229 snd_wss_out(chip, i, *ptr++); 1315 snd_wss_out(chip, i, *ptr++);
1230 spin_unlock_irqrestore(&chip->reg_lock, flags); 1316 spin_unlock_irqrestore(&chip->reg_lock, flags);
1231 snd_wss_mce_up(chip); 1317 snd_wss_mce_up(chip);
@@ -1635,6 +1721,10 @@ static int snd_wss_new(struct snd_card *card,
1635 else 1721 else
1636 memcpy(&chip->image, &snd_wss_original_image, 1722 memcpy(&chip->image, &snd_wss_original_image,
1637 sizeof(snd_wss_original_image)); 1723 sizeof(snd_wss_original_image));
1724 if (chip->hardware & WSS_HW_AD1848_MASK) {
1725 chip->image[CS4231_PIN_CTRL] = 0;
1726 chip->image[CS4231_TEST_INIT] = 0;
1727 }
1638 1728
1639 *rchip = chip; 1729 *rchip = chip;
1640 return 0; 1730 return 0;
@@ -1662,7 +1752,7 @@ int snd_wss_create(struct snd_card *card,
1662 chip->dma1 = -1; 1752 chip->dma1 = -1;
1663 chip->dma2 = -1; 1753 chip->dma2 = -1;
1664 1754
1665 chip->res_port = request_region(port, 4, "CS4231"); 1755 chip->res_port = request_region(port, 4, "WSS");
1666 if (!chip->res_port) { 1756 if (!chip->res_port) {
1667 snd_printk(KERN_ERR "wss: can't grab port 0x%lx\n", port); 1757 snd_printk(KERN_ERR "wss: can't grab port 0x%lx\n", port);
1668 snd_wss_free(chip); 1758 snd_wss_free(chip);
@@ -1681,20 +1771,20 @@ int snd_wss_create(struct snd_card *card,
1681 chip->cport = cport; 1771 chip->cport = cport;
1682 if (!(hwshare & WSS_HWSHARE_IRQ)) 1772 if (!(hwshare & WSS_HWSHARE_IRQ))
1683 if (request_irq(irq, snd_wss_interrupt, IRQF_DISABLED, 1773 if (request_irq(irq, snd_wss_interrupt, IRQF_DISABLED,
1684 "CS4231", (void *) chip)) { 1774 "WSS", (void *) chip)) {
1685 snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq); 1775 snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq);
1686 snd_wss_free(chip); 1776 snd_wss_free(chip);
1687 return -EBUSY; 1777 return -EBUSY;
1688 } 1778 }
1689 chip->irq = irq; 1779 chip->irq = irq;
1690 if (!(hwshare & WSS_HWSHARE_DMA1) && request_dma(dma1, "CS4231 - 1")) { 1780 if (!(hwshare & WSS_HWSHARE_DMA1) && request_dma(dma1, "WSS - 1")) {
1691 snd_printk(KERN_ERR "wss: can't grab DMA1 %d\n", dma1); 1781 snd_printk(KERN_ERR "wss: can't grab DMA1 %d\n", dma1);
1692 snd_wss_free(chip); 1782 snd_wss_free(chip);
1693 return -EBUSY; 1783 return -EBUSY;
1694 } 1784 }
1695 chip->dma1 = dma1; 1785 chip->dma1 = dma1;
1696 if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 && 1786 if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 &&
1697 dma2 >= 0 && request_dma(dma2, "CS4231 - 2")) { 1787 dma2 >= 0 && request_dma(dma2, "WSS - 2")) {
1698 snd_printk(KERN_ERR "wss: can't grab DMA2 %d\n", dma2); 1788 snd_printk(KERN_ERR "wss: can't grab DMA2 %d\n", dma2);
1699 snd_wss_free(chip); 1789 snd_wss_free(chip);
1700 return -EBUSY; 1790 return -EBUSY;
@@ -1705,6 +1795,12 @@ int snd_wss_create(struct snd_card *card,
1705 } else 1795 } else
1706 chip->dma2 = dma2; 1796 chip->dma2 = dma2;
1707 1797
1798 if (hardware == WSS_HW_THINKPAD) {
1799 chip->thinkpad_flag = 1;
1800 chip->hardware = WSS_HW_DETECT; /* reset */
1801 snd_wss_thinkpad_twiddle(chip, 1);
1802 }
1803
1708 /* global setup */ 1804 /* global setup */
1709 if (snd_wss_probe(chip) < 0) { 1805 if (snd_wss_probe(chip) < 0) {
1710 snd_wss_free(chip); 1806 snd_wss_free(chip);
@@ -1775,12 +1871,6 @@ int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
1775 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops); 1871 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops);
1776 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops); 1872 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops);
1777 1873
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 }
1784 /* global setup */ 1874 /* global setup */
1785 pcm->private_data = chip; 1875 pcm->private_data = chip;
1786 pcm->info_flags = 0; 1876 pcm->info_flags = 0;