aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorRene Herman <rene.herman@gmail.com>2008-08-06 02:09:34 -0400
committerJaroslav Kysela <perex@perex.cz>2008-08-06 09:40:31 -0400
commitc9a7dc2c5279830c0ad77715c0ace3e1edb07f4c (patch)
treecde63fb72a1ee02a2c3d1826ebebd2ca68d3454a /sound
parent8f4f4ef6fed55a3636db3146a3e50b7febcbd7de (diff)
ALSA: wss_lib: rework snd_ad1848_probe()
Make snd_ad1848_probe() easier to follow. With an exception for only trying once as soon as the codec is out of init (which should be all that's needed) the detection logic should be unchanged. Signed-off-by: Rene Herman <rene.herman@gmail.com> Acked-by: Krzysztof Helt <krzysztof.h1@wp.pl> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound')
-rw-r--r--sound/isa/wss/wss_lib.c133
1 files changed, 69 insertions, 64 deletions
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c
index 866e8686dbe7..011da7a2315d 100644
--- a/sound/isa/wss/wss_lib.c
+++ b/sound/isa/wss/wss_lib.c
@@ -1147,79 +1147,84 @@ static snd_pcm_uframes_t snd_wss_capture_pointer(struct snd_pcm_substream *subst
1147 1147
1148static int snd_ad1848_probe(struct snd_wss *chip) 1148static int snd_ad1848_probe(struct snd_wss *chip)
1149{ 1149{
1150 unsigned long timeout = jiffies + msecs_to_jiffies(1000);
1150 unsigned long flags; 1151 unsigned long flags;
1151 int i, id, rev, ad1847; 1152 unsigned char r;
1153 unsigned short hardware = 0;
1154 int err = 0;
1155 int i;
1152 1156
1153 id = 0; 1157 while (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) {
1154 ad1847 = 0; 1158 if (time_after(jiffies, timeout))
1155 for (i = 0; i < 1000; i++) { 1159 return -ENODEV;
1156 mb(); 1160 cond_resched();
1157 if (inb(chip->port + CS4231P(REGSEL)) & CS4231_INIT)
1158 msleep(1);
1159 else {
1160 spin_lock_irqsave(&chip->reg_lock, flags);
1161 snd_wss_out(chip, CS4231_MISC_INFO, 0x00);
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 (rev == 0x45) {
1172 rev = snd_wss_in(chip, CS4231_LEFT_INPUT);
1173 if (rev == 0xaa || rev == 0x8a) {
1174 spin_unlock_irqrestore(&chip->reg_lock, flags);
1175 id = 1;
1176 break;
1177 }
1178 }
1179 spin_unlock_irqrestore(&chip->reg_lock, flags);
1180 }
1181 } 1161 }
1182 if (id != 1)
1183 return -ENODEV; /* no valid device found */
1184 id = 0;
1185 if (chip->hardware == WSS_HW_DETECT)
1186 id = ad1847 ? WSS_HW_AD1847 : WSS_HW_AD1848;
1187
1188 spin_lock_irqsave(&chip->reg_lock, flags); 1162 spin_lock_irqsave(&chip->reg_lock, flags);
1189 inb(chip->port + CS4231P(STATUS)); /* clear any pendings IRQ */ 1163
1190 outb(0, chip->port + CS4231P(STATUS)); 1164 /* set CS423x MODE 1 */
1191 mb(); 1165 snd_wss_out(chip, CS4231_MISC_INFO, 0);
1192 if (id == WSS_HW_AD1848) { 1166
1193 /* check if there are more than 16 registers */ 1167 snd_wss_out(chip, CS4231_RIGHT_INPUT, 0x45); /* 0x55 & ~0x10 */
1194 rev = snd_wss_in(chip, CS4231_MISC_INFO); 1168 r = snd_wss_in(chip, CS4231_RIGHT_INPUT);
1195 snd_wss_out(chip, CS4231_MISC_INFO, 0x40); 1169 if (r != 0x45) {
1196 for (i = 0; i < 16; ++i) { 1170 /* RMGE always high on AD1847 */
1197 if (snd_wss_in(chip, i) != snd_wss_in(chip, i + 16)) { 1171 if ((r & ~CS4231_ENABLE_MIC_GAIN) != 0x45) {
1198 id = WSS_HW_CMI8330; 1172 err = -ENODEV;
1199 break; 1173 goto out;
1200 } 1174 }
1175 hardware = WSS_HW_AD1847;
1176 } else {
1177 snd_wss_out(chip, CS4231_LEFT_INPUT, 0xaa);
1178 r = snd_wss_in(chip, CS4231_LEFT_INPUT);
1179 /* L/RMGE always low on AT2320 */
1180 if ((r | CS4231_ENABLE_MIC_GAIN) != 0xaa) {
1181 err = -ENODEV;
1182 goto out;
1201 } 1183 }
1202 snd_wss_out(chip, CS4231_MISC_INFO, 0x00);
1203 if (id != WSS_HW_CMI8330 && (rev & 0x80))
1204 id = WSS_HW_CS4248;
1205 if (id == WSS_HW_CMI8330 && (rev & 0x0f) != 0x0a)
1206 id = 0;
1207 } 1184 }
1208 if (id == WSS_HW_CMI8330) { 1185
1209 /* verify it is not CS4231 by changing the version register */ 1186 /* clear pending IRQ */
1210 /* on CMI8330 it is volume control register and can be set 0 */ 1187 wss_inb(chip, CS4231P(STATUS));
1211 snd_wss_out(chip, CS4231_MISC_INFO, CS4231_MODE2); 1188 wss_outb(chip, CS4231P(STATUS), 0);
1212 snd_wss_dout(chip, CS4231_VERSION, 0x00); 1189 mb();
1213 rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7; 1190
1214 if (rev) 1191 if ((chip->hardware & WSS_HW_TYPE_MASK) != WSS_HW_DETECT)
1215 id = 0; 1192 goto out;
1216 snd_wss_out(chip, CS4231_MISC_INFO, 0); 1193
1194 if (hardware) {
1195 chip->hardware = hardware;
1196 goto out;
1217 } 1197 }
1218 if (id)
1219 chip->hardware = id;
1220 1198
1199 r = snd_wss_in(chip, CS4231_MISC_INFO);
1200
1201 /* set CS423x MODE 2 */
1202 snd_wss_out(chip, CS4231_MISC_INFO, CS4231_MODE2);
1203 for (i = 0; i < 16; i++) {
1204 if (snd_wss_in(chip, i) != snd_wss_in(chip, 16 + i)) {
1205 /* we have more than 16 registers: check ID */
1206 if ((r & 0xf) != 0xa)
1207 goto out_mode;
1208 /*
1209 * on CMI8330, CS4231_VERSION is volume control and
1210 * can be set to 0
1211 */
1212 snd_wss_dout(chip, CS4231_VERSION, 0);
1213 r = snd_wss_in(chip, CS4231_VERSION) & 0xe7;
1214 if (!r)
1215 chip->hardware = WSS_HW_CMI8330;
1216 goto out_mode;
1217 }
1218 }
1219 if (r & 0x80)
1220 chip->hardware = WSS_HW_CS4248;
1221 else
1222 chip->hardware = WSS_HW_AD1848;
1223out_mode:
1224 snd_wss_out(chip, CS4231_MISC_INFO, 0);
1225out:
1221 spin_unlock_irqrestore(&chip->reg_lock, flags); 1226 spin_unlock_irqrestore(&chip->reg_lock, flags);
1222 return 0; /* all things are ok.. */ 1227 return err;
1223} 1228}
1224 1229
1225static int snd_wss_probe(struct snd_wss *chip) 1230static int snd_wss_probe(struct snd_wss *chip)