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.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;