aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/azt3328.c
diff options
context:
space:
mode:
authorAndreas Mohr <andi@lisas.de>2010-12-27 15:17:26 -0500
committerTakashi Iwai <tiwai@suse.de>2011-01-02 05:11:24 -0500
commitda237f35a8a503fb8893fb3b9d0622a991bcebef (patch)
tree36c9ad6accec05028e9e7ab0ef62cccede0aaa6b /sound/pci/azt3328.c
parent345855951a7d36eed815fd129c49b7ee2b7a6864 (diff)
ALSA: azt3328: use proper private_data hookup for codec identification
- much improved implementation due to clean codec hierarchy - preparation for potential per-codec spinlock change NOTE: additionally removes a chip->pcm[codec_type] NULL ptr check (due to it requiring access to external chip struct), however I believe this to be ok since this condition should not occur and most drivers don't check against that either. Signed-off-by: Andreas Mohr <andi@lisas.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/azt3328.c')
-rw-r--r--sound/pci/azt3328.c234
1 files changed, 90 insertions, 144 deletions
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index b1fad46a7b02..76ff5fdb4838 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -292,14 +292,6 @@ static int seqtimer_scaling = 128;
292module_param(seqtimer_scaling, int, 0444); 292module_param(seqtimer_scaling, int, 0444);
293MODULE_PARM_DESC(seqtimer_scaling, "Set 1024000Hz sequencer timer scale factor (lockup danger!). Default 128."); 293MODULE_PARM_DESC(seqtimer_scaling, "Set 1024000Hz sequencer timer scale factor (lockup danger!). Default 128.");
294 294
295struct snd_azf3328_codec_data {
296 unsigned long io_base;
297 unsigned int dma_base; /* helper to avoid an indirection in hotpath */
298 struct snd_pcm_substream *substream;
299 bool running;
300 const char *name;
301};
302
303enum snd_azf3328_codec_type { 295enum snd_azf3328_codec_type {
304 /* warning: fixed indices (also used for bitmask checks!) */ 296 /* warning: fixed indices (also used for bitmask checks!) */
305 AZF_CODEC_PLAYBACK = 0, 297 AZF_CODEC_PLAYBACK = 0,
@@ -307,6 +299,16 @@ enum snd_azf3328_codec_type {
307 AZF_CODEC_I2S_OUT = 2, 299 AZF_CODEC_I2S_OUT = 2,
308}; 300};
309 301
302struct snd_azf3328_codec_data {
303 unsigned long io_base; /* keep first! (avoid offset calc) */
304 unsigned int dma_base; /* helper to avoid an indirection in hotpath */
305 spinlock_t *lock; /* TODO: convert to our own per-codec lock member */
306 struct snd_pcm_substream *substream;
307 bool running;
308 enum snd_azf3328_codec_type type;
309 const char *name;
310};
311
310struct snd_azf3328 { 312struct snd_azf3328 {
311 /* often-used fields towards beginning, then grouped */ 313 /* often-used fields towards beginning, then grouped */
312 314
@@ -949,15 +951,13 @@ snd_azf3328_hw_free(struct snd_pcm_substream *substream)
949} 951}
950 952
951static void 953static void
952snd_azf3328_codec_setfmt(struct snd_azf3328 *chip, 954snd_azf3328_codec_setfmt(struct snd_azf3328_codec_data *codec,
953 enum snd_azf3328_codec_type codec_type,
954 enum azf_freq_t bitrate, 955 enum azf_freq_t bitrate,
955 unsigned int format_width, 956 unsigned int format_width,
956 unsigned int channels 957 unsigned int channels
957) 958)
958{ 959{
959 unsigned long flags; 960 unsigned long flags;
960 const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
961 u16 val = 0xff00; 961 u16 val = 0xff00;
962 u8 freq = 0; 962 u8 freq = 0;
963 963
@@ -1007,7 +1007,7 @@ snd_azf3328_codec_setfmt(struct snd_azf3328 *chip,
1007 if (format_width == 16) 1007 if (format_width == 16)
1008 val |= SOUNDFORMAT_FLAG_16BIT; 1008 val |= SOUNDFORMAT_FLAG_16BIT;
1009 1009
1010 spin_lock_irqsave(&chip->reg_lock, flags); 1010 spin_lock_irqsave(codec->lock, flags);
1011 1011
1012 /* set bitrate/format */ 1012 /* set bitrate/format */
1013 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_SOUNDFORMAT, val); 1013 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_SOUNDFORMAT, val);
@@ -1020,7 +1020,7 @@ snd_azf3328_codec_setfmt(struct snd_azf3328 *chip,
1020 * FIXME: does this have some side effects for full-duplex 1020 * FIXME: does this have some side effects for full-duplex
1021 * or other dramatic side effects? */ 1021 * or other dramatic side effects? */
1022 /* do it for non-capture codecs only */ 1022 /* do it for non-capture codecs only */
1023 if (codec_type == AZF_CODEC_PLAYBACK) 1023 if (codec->type != AZF_CODEC_CAPTURE)
1024 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, 1024 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
1025 snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS) | 1025 snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS) |
1026 DMA_RUN_SOMETHING1 | 1026 DMA_RUN_SOMETHING1 |
@@ -1030,20 +1030,19 @@ snd_azf3328_codec_setfmt(struct snd_azf3328 *chip,
1030 DMA_SOMETHING_ELSE 1030 DMA_SOMETHING_ELSE
1031 ); 1031 );
1032 1032
1033 spin_unlock_irqrestore(&chip->reg_lock, flags); 1033 spin_unlock_irqrestore(codec->lock, flags);
1034 snd_azf3328_dbgcallleave(); 1034 snd_azf3328_dbgcallleave();
1035} 1035}
1036 1036
1037static inline void 1037static inline void
1038snd_azf3328_codec_setfmt_lowpower(struct snd_azf3328 *chip, 1038snd_azf3328_codec_setfmt_lowpower(struct snd_azf3328_codec_data *codec
1039 enum snd_azf3328_codec_type codec_type
1040) 1039)
1041{ 1040{
1042 /* choose lowest frequency for low power consumption. 1041 /* choose lowest frequency for low power consumption.
1043 * While this will cause louder noise due to rather coarse frequency, 1042 * While this will cause louder noise due to rather coarse frequency,
1044 * it should never matter since output should always 1043 * it should never matter since output should always
1045 * get disabled properly when idle anyway. */ 1044 * get disabled properly when idle anyway. */
1046 snd_azf3328_codec_setfmt(chip, codec_type, AZF_FREQ_4000, 8, 1); 1045 snd_azf3328_codec_setfmt(codec, AZF_FREQ_4000, 8, 1);
1047} 1046}
1048 1047
1049static void 1048static void
@@ -1117,23 +1116,18 @@ snd_azf3328_ctrl_codec_activity(struct snd_azf3328 *chip,
1117 /* ...and adjust clock, too 1116 /* ...and adjust clock, too
1118 * (reduce noise and power consumption) */ 1117 * (reduce noise and power consumption) */
1119 if (!enable) 1118 if (!enable)
1120 snd_azf3328_codec_setfmt_lowpower( 1119 snd_azf3328_codec_setfmt_lowpower(codec);
1121 chip,
1122 codec_type
1123 );
1124 codec->running = enable; 1120 codec->running = enable;
1125 } 1121 }
1126} 1122}
1127 1123
1128static void 1124static void
1129snd_azf3328_codec_setdmaa(struct snd_azf3328 *chip, 1125snd_azf3328_codec_setdmaa(struct snd_azf3328_codec_data *codec,
1130 enum snd_azf3328_codec_type codec_type,
1131 unsigned long addr, 1126 unsigned long addr,
1132 unsigned int count, 1127 unsigned int count,
1133 unsigned int size 1128 unsigned int size
1134) 1129)
1135{ 1130{
1136 const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
1137 snd_azf3328_dbgcallenter(); 1131 snd_azf3328_dbgcallenter();
1138 if (!codec->running) { 1132 if (!codec->running) {
1139 /* AZF3328 uses a two buffer pointer DMA transfer approach */ 1133 /* AZF3328 uses a two buffer pointer DMA transfer approach */
@@ -1152,22 +1146,22 @@ snd_azf3328_codec_setdmaa(struct snd_azf3328 *chip,
1152 1146
1153 /* build combined I/O buffer length word */ 1147 /* build combined I/O buffer length word */
1154 lengths = (count_areas << 16) | (count_areas); 1148 lengths = (count_areas << 16) | (count_areas);
1155 spin_lock_irqsave(&chip->reg_lock, flags); 1149 spin_lock_irqsave(codec->lock, flags);
1156 snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_1, addr); 1150 snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_1, addr);
1157 snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_2, 1151 snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_2,
1158 addr_area2); 1152 addr_area2);
1159 snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_LENGTHS, 1153 snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_LENGTHS,
1160 lengths); 1154 lengths);
1161 spin_unlock_irqrestore(&chip->reg_lock, flags); 1155 spin_unlock_irqrestore(codec->lock, flags);
1162 } 1156 }
1163 snd_azf3328_dbgcallleave(); 1157 snd_azf3328_dbgcallleave();
1164} 1158}
1165 1159
1166static int 1160static int
1167snd_azf3328_codec_prepare(struct snd_pcm_substream *substream) 1161snd_azf3328_pcm_prepare(struct snd_pcm_substream *substream)
1168{ 1162{
1169 struct snd_pcm_runtime *runtime = substream->runtime; 1163 struct snd_pcm_runtime *runtime = substream->runtime;
1170 struct snd_azf3328_codec *codec = runtime->private_data; 1164 struct snd_azf3328_codec_data *codec = runtime->private_data;
1171#if 0 1165#if 0
1172 unsigned int size = snd_pcm_lib_buffer_bytes(substream); 1166 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
1173 unsigned int count = snd_pcm_lib_period_bytes(substream); 1167 unsigned int count = snd_pcm_lib_period_bytes(substream);
@@ -1178,11 +1172,11 @@ snd_azf3328_codec_prepare(struct snd_pcm_substream *substream)
1178 codec->dma_base = runtime->dma_addr; 1172 codec->dma_base = runtime->dma_addr;
1179 1173
1180#if 0 1174#if 0
1181 snd_azf3328_codec_setfmt(chip, AZF_CODEC_..., 1175 snd_azf3328_codec_setfmt(codec,
1182 runtime->rate, 1176 runtime->rate,
1183 snd_pcm_format_width(runtime->format), 1177 snd_pcm_format_width(runtime->format),
1184 runtime->channels); 1178 runtime->channels);
1185 snd_azf3328_codec_setdmaa(chip, AZF_CODEC_..., 1179 snd_azf3328_codec_setdmaa(codec,
1186 runtime->dma_addr, count, size); 1180 runtime->dma_addr, count, size);
1187#endif 1181#endif
1188 snd_azf3328_dbgcallleave(); 1182 snd_azf3328_dbgcallleave();
@@ -1190,24 +1184,23 @@ snd_azf3328_codec_prepare(struct snd_pcm_substream *substream)
1190} 1184}
1191 1185
1192static int 1186static int
1193snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type, 1187snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
1194 struct snd_pcm_substream *substream, int cmd)
1195{ 1188{
1196 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1189 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
1197 const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
1198 struct snd_pcm_runtime *runtime = substream->runtime; 1190 struct snd_pcm_runtime *runtime = substream->runtime;
1191 struct snd_azf3328_codec_data *codec = runtime->private_data;
1199 int result = 0; 1192 int result = 0;
1200 u16 flags1; 1193 u16 flags1;
1201 bool previously_muted = 0; 1194 bool previously_muted = 0;
1202 bool is_playback_codec = (AZF_CODEC_PLAYBACK == codec_type); 1195 bool is_main_mixer_playback_codec = (AZF_CODEC_PLAYBACK == codec->type);
1203 1196
1204 snd_azf3328_dbgcalls("snd_azf3328_codec_trigger cmd %d\n", cmd); 1197 snd_azf3328_dbgcalls("snd_azf3328_pcm_trigger cmd %d\n", cmd);
1205 1198
1206 switch (cmd) { 1199 switch (cmd) {
1207 case SNDRV_PCM_TRIGGER_START: 1200 case SNDRV_PCM_TRIGGER_START:
1208 snd_azf3328_dbgcodec("START %s\n", codec->name); 1201 snd_azf3328_dbgcodec("START %s\n", codec->name);
1209 1202
1210 if (is_playback_codec) { 1203 if (is_main_mixer_playback_codec) {
1211 /* mute WaveOut (avoid clicking during setup) */ 1204 /* mute WaveOut (avoid clicking during setup) */
1212 previously_muted = 1205 previously_muted =
1213 snd_azf3328_mixer_set_mute( 1206 snd_azf3328_mixer_set_mute(
@@ -1215,12 +1208,12 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type,
1215 ); 1208 );
1216 } 1209 }
1217 1210
1218 snd_azf3328_codec_setfmt(chip, codec_type, 1211 snd_azf3328_codec_setfmt(codec,
1219 runtime->rate, 1212 runtime->rate,
1220 snd_pcm_format_width(runtime->format), 1213 snd_pcm_format_width(runtime->format),
1221 runtime->channels); 1214 runtime->channels);
1222 1215
1223 spin_lock(&chip->reg_lock); 1216 spin_lock(codec->lock);
1224 /* first, remember current value: */ 1217 /* first, remember current value: */
1225 flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS); 1218 flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS);
1226 1219
@@ -1230,14 +1223,14 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type,
1230 1223
1231 /* FIXME: clear interrupts or what??? */ 1224 /* FIXME: clear interrupts or what??? */
1232 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_IRQTYPE, 0xffff); 1225 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_IRQTYPE, 0xffff);
1233 spin_unlock(&chip->reg_lock); 1226 spin_unlock(codec->lock);
1234 1227
1235 snd_azf3328_codec_setdmaa(chip, codec_type, runtime->dma_addr, 1228 snd_azf3328_codec_setdmaa(codec, runtime->dma_addr,
1236 snd_pcm_lib_period_bytes(substream), 1229 snd_pcm_lib_period_bytes(substream),
1237 snd_pcm_lib_buffer_bytes(substream) 1230 snd_pcm_lib_buffer_bytes(substream)
1238 ); 1231 );
1239 1232
1240 spin_lock(&chip->reg_lock); 1233 spin_lock(codec->lock);
1241#ifdef WIN9X 1234#ifdef WIN9X
1242 /* FIXME: enable playback/recording??? */ 1235 /* FIXME: enable playback/recording??? */
1243 flags1 |= DMA_RUN_SOMETHING1 | DMA_RUN_SOMETHING2; 1236 flags1 |= DMA_RUN_SOMETHING1 | DMA_RUN_SOMETHING2;
@@ -1261,10 +1254,10 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type,
1261 DMA_EPILOGUE_SOMETHING | 1254 DMA_EPILOGUE_SOMETHING |
1262 DMA_SOMETHING_ELSE); 1255 DMA_SOMETHING_ELSE);
1263#endif 1256#endif
1264 spin_unlock(&chip->reg_lock); 1257 spin_unlock(codec->lock);
1265 snd_azf3328_ctrl_codec_activity(chip, codec_type, 1); 1258 snd_azf3328_ctrl_codec_activity(chip, codec->type, 1);
1266 1259
1267 if (is_playback_codec) { 1260 if (is_main_mixer_playback_codec) {
1268 /* now unmute WaveOut */ 1261 /* now unmute WaveOut */
1269 if (!previously_muted) 1262 if (!previously_muted)
1270 snd_azf3328_mixer_set_mute( 1263 snd_azf3328_mixer_set_mute(
@@ -1277,19 +1270,19 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type,
1277 case SNDRV_PCM_TRIGGER_RESUME: 1270 case SNDRV_PCM_TRIGGER_RESUME:
1278 snd_azf3328_dbgcodec("RESUME %s\n", codec->name); 1271 snd_azf3328_dbgcodec("RESUME %s\n", codec->name);
1279 /* resume codec if we were active */ 1272 /* resume codec if we were active */
1280 spin_lock(&chip->reg_lock); 1273 spin_lock(codec->lock);
1281 if (codec->running) 1274 if (codec->running)
1282 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, 1275 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
1283 snd_azf3328_codec_inw( 1276 snd_azf3328_codec_inw(
1284 codec, IDX_IO_CODEC_DMA_FLAGS 1277 codec, IDX_IO_CODEC_DMA_FLAGS
1285 ) | DMA_RESUME 1278 ) | DMA_RESUME
1286 ); 1279 );
1287 spin_unlock(&chip->reg_lock); 1280 spin_unlock(codec->lock);
1288 break; 1281 break;
1289 case SNDRV_PCM_TRIGGER_STOP: 1282 case SNDRV_PCM_TRIGGER_STOP:
1290 snd_azf3328_dbgcodec("STOP %s\n", codec->name); 1283 snd_azf3328_dbgcodec("STOP %s\n", codec->name);
1291 1284
1292 if (is_playback_codec) { 1285 if (is_main_mixer_playback_codec) {
1293 /* mute WaveOut (avoid clicking during setup) */ 1286 /* mute WaveOut (avoid clicking during setup) */
1294 previously_muted = 1287 previously_muted =
1295 snd_azf3328_mixer_set_mute( 1288 snd_azf3328_mixer_set_mute(
@@ -1297,7 +1290,7 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type,
1297 ); 1290 );
1298 } 1291 }
1299 1292
1300 spin_lock(&chip->reg_lock); 1293 spin_lock(codec->lock);
1301 /* first, remember current value: */ 1294 /* first, remember current value: */
1302 flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS); 1295 flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS);
1303 1296
@@ -1312,10 +1305,10 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type,
1312 1305
1313 flags1 &= ~DMA_RUN_SOMETHING1; 1306 flags1 &= ~DMA_RUN_SOMETHING1;
1314 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); 1307 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);
1315 spin_unlock(&chip->reg_lock); 1308 spin_unlock(codec->lock);
1316 snd_azf3328_ctrl_codec_activity(chip, codec_type, 0); 1309 snd_azf3328_ctrl_codec_activity(chip, codec->type, 0);
1317 1310
1318 if (is_playback_codec) { 1311 if (is_main_mixer_playback_codec) {
1319 /* now unmute WaveOut */ 1312 /* now unmute WaveOut */
1320 if (!previously_muted) 1313 if (!previously_muted)
1321 snd_azf3328_mixer_set_mute( 1314 snd_azf3328_mixer_set_mute(
@@ -1349,31 +1342,12 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type,
1349 return result; 1342 return result;
1350} 1343}
1351 1344
1352static int
1353snd_azf3328_codec_playback_trigger(struct snd_pcm_substream *substream, int cmd)
1354{
1355 return snd_azf3328_codec_trigger(AZF_CODEC_PLAYBACK, substream, cmd);
1356}
1357
1358static int
1359snd_azf3328_codec_capture_trigger(struct snd_pcm_substream *substream, int cmd)
1360{
1361 return snd_azf3328_codec_trigger(AZF_CODEC_CAPTURE, substream, cmd);
1362}
1363
1364static int
1365snd_azf3328_codec_i2s_out_trigger(struct snd_pcm_substream *substream, int cmd)
1366{
1367 return snd_azf3328_codec_trigger(AZF_CODEC_I2S_OUT, substream, cmd);
1368}
1369
1370static snd_pcm_uframes_t 1345static snd_pcm_uframes_t
1371snd_azf3328_codec_pointer(struct snd_pcm_substream *substream, 1346snd_azf3328_pcm_pointer(struct snd_pcm_substream *substream
1372 enum snd_azf3328_codec_type codec_type
1373) 1347)
1374{ 1348{
1375 const struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1349 const struct snd_azf3328_codec_data *codec =
1376 const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; 1350 substream->runtime->private_data;
1377 unsigned long result; 1351 unsigned long result;
1378 snd_pcm_uframes_t frmres; 1352 snd_pcm_uframes_t frmres;
1379 1353
@@ -1391,24 +1365,6 @@ snd_azf3328_codec_pointer(struct snd_pcm_substream *substream,
1391 return frmres; 1365 return frmres;
1392} 1366}
1393 1367
1394static snd_pcm_uframes_t
1395snd_azf3328_codec_playback_pointer(struct snd_pcm_substream *substream)
1396{
1397 return snd_azf3328_codec_pointer(substream, AZF_CODEC_PLAYBACK);
1398}
1399
1400static snd_pcm_uframes_t
1401snd_azf3328_codec_capture_pointer(struct snd_pcm_substream *substream)
1402{
1403 return snd_azf3328_codec_pointer(substream, AZF_CODEC_CAPTURE);
1404}
1405
1406static snd_pcm_uframes_t
1407snd_azf3328_codec_i2s_out_pointer(struct snd_pcm_substream *substream)
1408{
1409 return snd_azf3328_codec_pointer(substream, AZF_CODEC_I2S_OUT);
1410}
1411
1412/******************************************************************/ 1368/******************************************************************/
1413 1369
1414#ifdef SUPPORT_GAMEPORT 1370#ifdef SUPPORT_GAMEPORT
@@ -1642,29 +1598,29 @@ snd_azf3328_irq_log_unknown_type(u8 which)
1642} 1598}
1643 1599
1644static inline void 1600static inline void
1645snd_azf3328_codec_interrupt(struct snd_azf3328 *chip, u8 status) 1601snd_azf3328_pcm_interrupt(const struct snd_azf3328_codec_data *first_codec,
1602 u8 status
1603)
1646{ 1604{
1647 u8 which; 1605 u8 which;
1648 enum snd_azf3328_codec_type codec_type; 1606 enum snd_azf3328_codec_type codec_type;
1649 const struct snd_azf3328_codec_data *codec; 1607 const struct snd_azf3328_codec_data *codec = first_codec;
1650 1608
1651 for (codec_type = AZF_CODEC_PLAYBACK; 1609 for (codec_type = AZF_CODEC_PLAYBACK;
1652 codec_type <= AZF_CODEC_I2S_OUT; 1610 codec_type <= AZF_CODEC_I2S_OUT;
1653 ++codec_type) { 1611 ++codec_type, ++codec) {
1654 1612
1655 /* skip codec if there's no interrupt for it */ 1613 /* skip codec if there's no interrupt for it */
1656 if (!(status & (1 << codec_type))) 1614 if (!(status & (1 << codec_type)))
1657 continue; 1615 continue;
1658 1616
1659 codec = &chip->codecs[codec_type]; 1617 spin_lock(codec->lock);
1660
1661 spin_lock(&chip->reg_lock);
1662 which = snd_azf3328_codec_inb(codec, IDX_IO_CODEC_IRQTYPE); 1618 which = snd_azf3328_codec_inb(codec, IDX_IO_CODEC_IRQTYPE);
1663 /* ack all IRQ types immediately */ 1619 /* ack all IRQ types immediately */
1664 snd_azf3328_codec_outb(codec, IDX_IO_CODEC_IRQTYPE, which); 1620 snd_azf3328_codec_outb(codec, IDX_IO_CODEC_IRQTYPE, which);
1665 spin_unlock(&chip->reg_lock); 1621 spin_unlock(codec->lock);
1666 1622
1667 if ((chip->pcm[codec_type]) && (codec->substream)) { 1623 if (codec->substream) {
1668 snd_pcm_period_elapsed(codec->substream); 1624 snd_pcm_period_elapsed(codec->substream);
1669 snd_azf3328_dbgcodec("%s period done (#%x), @ %x\n", 1625 snd_azf3328_dbgcodec("%s period done (#%x), @ %x\n",
1670 codec->name, 1626 codec->name,
@@ -1719,7 +1675,7 @@ snd_azf3328_interrupt(int irq, void *dev_id)
1719 } 1675 }
1720 1676
1721 if (status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT)) 1677 if (status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT))
1722 snd_azf3328_codec_interrupt(chip, status); 1678 snd_azf3328_pcm_interrupt(chip->codecs, status);
1723 1679
1724 if (status & IRQ_GAMEPORT) 1680 if (status & IRQ_GAMEPORT)
1725 snd_azf3328_gameport_interrupt(chip); 1681 snd_azf3328_gameport_interrupt(chip);
@@ -1807,101 +1763,85 @@ snd_azf3328_pcm_open(struct snd_pcm_substream *substream,
1807{ 1763{
1808 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1764 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
1809 struct snd_pcm_runtime *runtime = substream->runtime; 1765 struct snd_pcm_runtime *runtime = substream->runtime;
1766 struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
1810 1767
1811 snd_azf3328_dbgcallenter(); 1768 snd_azf3328_dbgcallenter();
1812 chip->codecs[codec_type].substream = substream; 1769 codec->substream = substream;
1813 1770
1814 /* same parameters for all our codecs - at least we think so... */ 1771 /* same parameters for all our codecs - at least we think so... */
1815 runtime->hw = snd_azf3328_hardware; 1772 runtime->hw = snd_azf3328_hardware;
1816 1773
1817 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 1774 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
1818 &snd_azf3328_hw_constraints_rates); 1775 &snd_azf3328_hw_constraints_rates);
1776 runtime->private_data = codec;
1819 snd_azf3328_dbgcallleave(); 1777 snd_azf3328_dbgcallleave();
1820 return 0; 1778 return 0;
1821} 1779}
1822 1780
1823static int 1781static int
1824snd_azf3328_playback_open(struct snd_pcm_substream *substream) 1782snd_azf3328_pcm_playback_open(struct snd_pcm_substream *substream)
1825{ 1783{
1826 return snd_azf3328_pcm_open(substream, AZF_CODEC_PLAYBACK); 1784 return snd_azf3328_pcm_open(substream, AZF_CODEC_PLAYBACK);
1827} 1785}
1828 1786
1829static int 1787static int
1830snd_azf3328_capture_open(struct snd_pcm_substream *substream) 1788snd_azf3328_pcm_capture_open(struct snd_pcm_substream *substream)
1831{ 1789{
1832 return snd_azf3328_pcm_open(substream, AZF_CODEC_CAPTURE); 1790 return snd_azf3328_pcm_open(substream, AZF_CODEC_CAPTURE);
1833} 1791}
1834 1792
1835static int 1793static int
1836snd_azf3328_i2s_out_open(struct snd_pcm_substream *substream) 1794snd_azf3328_pcm_i2s_out_open(struct snd_pcm_substream *substream)
1837{ 1795{
1838 return snd_azf3328_pcm_open(substream, AZF_CODEC_I2S_OUT); 1796 return snd_azf3328_pcm_open(substream, AZF_CODEC_I2S_OUT);
1839} 1797}
1840 1798
1841static int 1799static int
1842snd_azf3328_pcm_close(struct snd_pcm_substream *substream, 1800snd_azf3328_pcm_close(struct snd_pcm_substream *substream
1843 enum snd_azf3328_codec_type codec_type
1844) 1801)
1845{ 1802{
1846 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1803 struct snd_azf3328_codec_data *codec =
1804 substream->runtime->private_data;
1847 1805
1848 snd_azf3328_dbgcallenter(); 1806 snd_azf3328_dbgcallenter();
1849 chip->codecs[codec_type].substream = NULL; 1807 codec->substream = NULL;
1850 snd_azf3328_dbgcallleave(); 1808 snd_azf3328_dbgcallleave();
1851 return 0; 1809 return 0;
1852} 1810}
1853 1811
1854static int
1855snd_azf3328_playback_close(struct snd_pcm_substream *substream)
1856{
1857 return snd_azf3328_pcm_close(substream, AZF_CODEC_PLAYBACK);
1858}
1859
1860static int
1861snd_azf3328_capture_close(struct snd_pcm_substream *substream)
1862{
1863 return snd_azf3328_pcm_close(substream, AZF_CODEC_CAPTURE);
1864}
1865
1866static int
1867snd_azf3328_i2s_out_close(struct snd_pcm_substream *substream)
1868{
1869 return snd_azf3328_pcm_close(substream, AZF_CODEC_I2S_OUT);
1870}
1871
1872/******************************************************************/ 1812/******************************************************************/
1873 1813
1874static struct snd_pcm_ops snd_azf3328_playback_ops = { 1814static struct snd_pcm_ops snd_azf3328_playback_ops = {
1875 .open = snd_azf3328_playback_open, 1815 .open = snd_azf3328_pcm_playback_open,
1876 .close = snd_azf3328_playback_close, 1816 .close = snd_azf3328_pcm_close,
1877 .ioctl = snd_pcm_lib_ioctl, 1817 .ioctl = snd_pcm_lib_ioctl,
1878 .hw_params = snd_azf3328_hw_params, 1818 .hw_params = snd_azf3328_hw_params,
1879 .hw_free = snd_azf3328_hw_free, 1819 .hw_free = snd_azf3328_hw_free,
1880 .prepare = snd_azf3328_codec_prepare, 1820 .prepare = snd_azf3328_pcm_prepare,
1881 .trigger = snd_azf3328_codec_playback_trigger, 1821 .trigger = snd_azf3328_pcm_trigger,
1882 .pointer = snd_azf3328_codec_playback_pointer 1822 .pointer = snd_azf3328_pcm_pointer
1883}; 1823};
1884 1824
1885static struct snd_pcm_ops snd_azf3328_capture_ops = { 1825static struct snd_pcm_ops snd_azf3328_capture_ops = {
1886 .open = snd_azf3328_capture_open, 1826 .open = snd_azf3328_pcm_capture_open,
1887 .close = snd_azf3328_capture_close, 1827 .close = snd_azf3328_pcm_close,
1888 .ioctl = snd_pcm_lib_ioctl, 1828 .ioctl = snd_pcm_lib_ioctl,
1889 .hw_params = snd_azf3328_hw_params, 1829 .hw_params = snd_azf3328_hw_params,
1890 .hw_free = snd_azf3328_hw_free, 1830 .hw_free = snd_azf3328_hw_free,
1891 .prepare = snd_azf3328_codec_prepare, 1831 .prepare = snd_azf3328_pcm_prepare,
1892 .trigger = snd_azf3328_codec_capture_trigger, 1832 .trigger = snd_azf3328_pcm_trigger,
1893 .pointer = snd_azf3328_codec_capture_pointer 1833 .pointer = snd_azf3328_pcm_pointer
1894}; 1834};
1895 1835
1896static struct snd_pcm_ops snd_azf3328_i2s_out_ops = { 1836static struct snd_pcm_ops snd_azf3328_i2s_out_ops = {
1897 .open = snd_azf3328_i2s_out_open, 1837 .open = snd_azf3328_pcm_i2s_out_open,
1898 .close = snd_azf3328_i2s_out_close, 1838 .close = snd_azf3328_pcm_close,
1899 .ioctl = snd_pcm_lib_ioctl, 1839 .ioctl = snd_pcm_lib_ioctl,
1900 .hw_params = snd_azf3328_hw_params, 1840 .hw_params = snd_azf3328_hw_params,
1901 .hw_free = snd_azf3328_hw_free, 1841 .hw_free = snd_azf3328_hw_free,
1902 .prepare = snd_azf3328_codec_prepare, 1842 .prepare = snd_azf3328_pcm_prepare,
1903 .trigger = snd_azf3328_codec_i2s_out_trigger, 1843 .trigger = snd_azf3328_pcm_trigger,
1904 .pointer = snd_azf3328_codec_i2s_out_pointer 1844 .pointer = snd_azf3328_pcm_pointer
1905}; 1845};
1906 1846
1907static int __devinit 1847static int __devinit
@@ -2198,7 +2138,7 @@ snd_azf3328_create(struct snd_card *card,
2198 }; 2138 };
2199 u8 dma_init; 2139 u8 dma_init;
2200 enum snd_azf3328_codec_type codec_type; 2140 enum snd_azf3328_codec_type codec_type;
2201 struct snd_azf3328_codec *codec_setup; 2141 struct snd_azf3328_codec_data *codec_setup;
2202 2142
2203 *rchip = NULL; 2143 *rchip = NULL;
2204 2144
@@ -2238,14 +2178,20 @@ snd_azf3328_create(struct snd_card *card,
2238 2178
2239 codec_setup = &chip->codecs[AZF_CODEC_PLAYBACK]; 2179 codec_setup = &chip->codecs[AZF_CODEC_PLAYBACK];
2240 codec_setup->io_base = chip->ctrl_io + AZF_IO_OFFS_CODEC_PLAYBACK; 2180 codec_setup->io_base = chip->ctrl_io + AZF_IO_OFFS_CODEC_PLAYBACK;
2181 codec_setup->lock = &chip->reg_lock;
2182 codec_setup->type = AZF_CODEC_PLAYBACK;
2241 codec_setup->name = "PLAYBACK"; 2183 codec_setup->name = "PLAYBACK";
2242 2184
2243 codec_setup = &chip->codecs[AZF_CODEC_CAPTURE]; 2185 codec_setup = &chip->codecs[AZF_CODEC_CAPTURE];
2244 codec_setup->io_base = chip->ctrl_io + AZF_IO_OFFS_CODEC_CAPTURE; 2186 codec_setup->io_base = chip->ctrl_io + AZF_IO_OFFS_CODEC_CAPTURE;
2187 codec_setup->lock = &chip->reg_lock;
2188 codec_setup->type = AZF_CODEC_CAPTURE;
2245 codec_setup->name = "CAPTURE"; 2189 codec_setup->name = "CAPTURE";
2246 2190
2247 codec_setup = &chip->codecs[AZF_CODEC_I2S_OUT]; 2191 codec_setup = &chip->codecs[AZF_CODEC_I2S_OUT];
2248 codec_setup->io_base = chip->ctrl_io + AZF_IO_OFFS_CODEC_I2S_OUT; 2192 codec_setup->io_base = chip->ctrl_io + AZF_IO_OFFS_CODEC_I2S_OUT;
2193 codec_setup->lock = &chip->reg_lock;
2194 codec_setup->type = AZF_CODEC_I2S_OUT;
2249 codec_setup->name = "I2S_OUT"; 2195 codec_setup->name = "I2S_OUT";
2250 2196
2251 if (request_irq(pci->irq, snd_azf3328_interrupt, 2197 if (request_irq(pci->irq, snd_azf3328_interrupt,
@@ -2283,10 +2229,10 @@ snd_azf3328_create(struct snd_card *card,
2283 codec->running = 1; 2229 codec->running = 1;
2284 snd_azf3328_ctrl_codec_activity(chip, codec_type, 0); 2230 snd_azf3328_ctrl_codec_activity(chip, codec_type, 0);
2285 2231
2286 spin_lock_irq(&chip->reg_lock); 2232 spin_lock_irq(codec->lock);
2287 snd_azf3328_codec_outb(codec, IDX_IO_CODEC_DMA_FLAGS, 2233 snd_azf3328_codec_outb(codec, IDX_IO_CODEC_DMA_FLAGS,
2288 dma_init); 2234 dma_init);
2289 spin_unlock_irq(&chip->reg_lock); 2235 spin_unlock_irq(codec->lock);
2290 } 2236 }
2291 2237
2292 snd_card_set_dev(card, &pci->dev); 2238 snd_card_set_dev(card, &pci->dev);