diff options
author | Rene Herman <rene.herman@gmail.com> | 2008-08-06 02:09:34 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2008-08-06 09:40:31 -0400 |
commit | c9a7dc2c5279830c0ad77715c0ace3e1edb07f4c (patch) | |
tree | cde63fb72a1ee02a2c3d1826ebebd2ca68d3454a /sound/isa | |
parent | 8f4f4ef6fed55a3636db3146a3e50b7febcbd7de (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/isa')
-rw-r--r-- | sound/isa/wss/wss_lib.c | 133 |
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 | ||
1148 | static int snd_ad1848_probe(struct snd_wss *chip) | 1148 | static 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; | ||
1223 | out_mode: | ||
1224 | snd_wss_out(chip, CS4231_MISC_INFO, 0); | ||
1225 | out: | ||
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 | ||
1225 | static int snd_wss_probe(struct snd_wss *chip) | 1230 | static int snd_wss_probe(struct snd_wss *chip) |