aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/pcxhr/pcxhr_core.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2014-09-10 06:21:38 -0400
committerTakashi Iwai <tiwai@suse.de>2014-09-15 09:52:09 -0400
commit9bef72bdb26e291d6dffb04768741a0e49582666 (patch)
tree84d04d67bd5b9c2a7785ae4e9dc65f3e125fe548 /sound/pci/pcxhr/pcxhr_core.c
parent8d3a8b5cb57da4e327bdaf7c81a90d4105b73205 (diff)
ALSA: pcxhr: Use nonatomic PCM ops
This time PCXHR, another Digigram boards: like the previous patches, the conversion is straightforward, replacing spinlocks with mutexes, merging the irq tasklet into the threaded irq handler and the PCM trigger tasklet back to the trigger callback. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/pcxhr/pcxhr_core.c')
-rw-r--r--sound/pci/pcxhr/pcxhr_core.c102
1 files changed, 56 insertions, 46 deletions
diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c
index df9371918601..a584acb61c00 100644
--- a/sound/pci/pcxhr/pcxhr_core.c
+++ b/sound/pci/pcxhr/pcxhr_core.c
@@ -767,11 +767,11 @@ void pcxhr_set_pipe_cmd_params(struct pcxhr_rmh *rmh, int capture,
767 */ 767 */
768int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) 768int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
769{ 769{
770 unsigned long flags;
771 int err; 770 int err;
772 spin_lock_irqsave(&mgr->msg_lock, flags); 771
772 mutex_lock(&mgr->msg_lock);
773 err = pcxhr_send_msg_nolock(mgr, rmh); 773 err = pcxhr_send_msg_nolock(mgr, rmh);
774 spin_unlock_irqrestore(&mgr->msg_lock, flags); 774 mutex_unlock(&mgr->msg_lock);
775 return err; 775 return err;
776} 776}
777 777
@@ -971,17 +971,16 @@ int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask,
971 unsigned int value, int *changed) 971 unsigned int value, int *changed)
972{ 972{
973 struct pcxhr_rmh rmh; 973 struct pcxhr_rmh rmh;
974 unsigned long flags;
975 int err; 974 int err;
976 975
977 spin_lock_irqsave(&mgr->msg_lock, flags); 976 mutex_lock(&mgr->msg_lock);
978 if ((mgr->io_num_reg_cont & mask) == value) { 977 if ((mgr->io_num_reg_cont & mask) == value) {
979 dev_dbg(&mgr->pci->dev, 978 dev_dbg(&mgr->pci->dev,
980 "IO_NUM_REG_CONT mask %x already is set to %x\n", 979 "IO_NUM_REG_CONT mask %x already is set to %x\n",
981 mask, value); 980 mask, value);
982 if (changed) 981 if (changed)
983 *changed = 0; 982 *changed = 0;
984 spin_unlock_irqrestore(&mgr->msg_lock, flags); 983 mutex_unlock(&mgr->msg_lock);
985 return 0; /* already programmed */ 984 return 0; /* already programmed */
986 } 985 }
987 pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); 986 pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
@@ -996,7 +995,7 @@ int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask,
996 if (changed) 995 if (changed)
997 *changed = 1; 996 *changed = 1;
998 } 997 }
999 spin_unlock_irqrestore(&mgr->msg_lock, flags); 998 mutex_unlock(&mgr->msg_lock);
1000 return err; 999 return err;
1001} 1000}
1002 1001
@@ -1043,22 +1042,21 @@ static int pcxhr_handle_async_err(struct pcxhr_mgr *mgr, u32 err,
1043} 1042}
1044 1043
1045 1044
1046void pcxhr_msg_tasklet(unsigned long arg) 1045static void pcxhr_msg_thread(struct pcxhr_mgr *mgr)
1047{ 1046{
1048 struct pcxhr_mgr *mgr = (struct pcxhr_mgr *)(arg);
1049 struct pcxhr_rmh *prmh = mgr->prmh; 1047 struct pcxhr_rmh *prmh = mgr->prmh;
1050 int err; 1048 int err;
1051 int i, j; 1049 int i, j;
1052 1050
1053 if (mgr->src_it_dsp & PCXHR_IRQ_FREQ_CHANGE) 1051 if (mgr->src_it_dsp & PCXHR_IRQ_FREQ_CHANGE)
1054 dev_dbg(&mgr->pci->dev, 1052 dev_dbg(&mgr->pci->dev,
1055 "TASKLET : PCXHR_IRQ_FREQ_CHANGE event occurred\n"); 1053 "PCXHR_IRQ_FREQ_CHANGE event occurred\n");
1056 if (mgr->src_it_dsp & PCXHR_IRQ_TIME_CODE) 1054 if (mgr->src_it_dsp & PCXHR_IRQ_TIME_CODE)
1057 dev_dbg(&mgr->pci->dev, 1055 dev_dbg(&mgr->pci->dev,
1058 "TASKLET : PCXHR_IRQ_TIME_CODE event occurred\n"); 1056 "PCXHR_IRQ_TIME_CODE event occurred\n");
1059 if (mgr->src_it_dsp & PCXHR_IRQ_NOTIFY) 1057 if (mgr->src_it_dsp & PCXHR_IRQ_NOTIFY)
1060 dev_dbg(&mgr->pci->dev, 1058 dev_dbg(&mgr->pci->dev,
1061 "TASKLET : PCXHR_IRQ_NOTIFY event occurred\n"); 1059 "PCXHR_IRQ_NOTIFY event occurred\n");
1062 if (mgr->src_it_dsp & (PCXHR_IRQ_FREQ_CHANGE | PCXHR_IRQ_TIME_CODE)) { 1060 if (mgr->src_it_dsp & (PCXHR_IRQ_FREQ_CHANGE | PCXHR_IRQ_TIME_CODE)) {
1063 /* clear events FREQ_CHANGE and TIME_CODE */ 1061 /* clear events FREQ_CHANGE and TIME_CODE */
1064 pcxhr_init_rmh(prmh, CMD_TEST_IT); 1062 pcxhr_init_rmh(prmh, CMD_TEST_IT);
@@ -1068,7 +1066,7 @@ void pcxhr_msg_tasklet(unsigned long arg)
1068 } 1066 }
1069 if (mgr->src_it_dsp & PCXHR_IRQ_ASYNC) { 1067 if (mgr->src_it_dsp & PCXHR_IRQ_ASYNC) {
1070 dev_dbg(&mgr->pci->dev, 1068 dev_dbg(&mgr->pci->dev,
1071 "TASKLET : PCXHR_IRQ_ASYNC event occurred\n"); 1069 "PCXHR_IRQ_ASYNC event occurred\n");
1072 1070
1073 pcxhr_init_rmh(prmh, CMD_ASYNC); 1071 pcxhr_init_rmh(prmh, CMD_ASYNC);
1074 prmh->cmd[0] |= 1; /* add SEL_ASYNC_EVENTS */ 1072 prmh->cmd[0] |= 1; /* add SEL_ASYNC_EVENTS */
@@ -1076,7 +1074,7 @@ void pcxhr_msg_tasklet(unsigned long arg)
1076 prmh->stat_len = PCXHR_SIZE_MAX_LONG_STATUS; 1074 prmh->stat_len = PCXHR_SIZE_MAX_LONG_STATUS;
1077 err = pcxhr_send_msg(mgr, prmh); 1075 err = pcxhr_send_msg(mgr, prmh);
1078 if (err) 1076 if (err)
1079 dev_err(&mgr->pci->dev, "ERROR pcxhr_msg_tasklet=%x;\n", 1077 dev_err(&mgr->pci->dev, "ERROR pcxhr_msg_thread=%x;\n",
1080 err); 1078 err);
1081 i = 1; 1079 i = 1;
1082 while (i < prmh->stat_len) { 1080 while (i < prmh->stat_len) {
@@ -1220,9 +1218,9 @@ static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr,
1220 } 1218 }
1221 1219
1222 if (elapsed) { 1220 if (elapsed) {
1223 spin_unlock(&mgr->lock); 1221 mutex_unlock(&mgr->lock);
1224 snd_pcm_period_elapsed(stream->substream); 1222 snd_pcm_period_elapsed(stream->substream);
1225 spin_lock(&mgr->lock); 1223 mutex_lock(&mgr->lock);
1226 } 1224 }
1227 } 1225 }
1228} 1226}
@@ -1231,14 +1229,10 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
1231{ 1229{
1232 struct pcxhr_mgr *mgr = dev_id; 1230 struct pcxhr_mgr *mgr = dev_id;
1233 unsigned int reg; 1231 unsigned int reg;
1234 int i, j; 1232 bool wake_thread = false;
1235 struct snd_pcxhr *chip;
1236
1237 spin_lock(&mgr->lock);
1238 1233
1239 reg = PCXHR_INPL(mgr, PCXHR_PLX_IRQCS); 1234 reg = PCXHR_INPL(mgr, PCXHR_PLX_IRQCS);
1240 if (! (reg & PCXHR_IRQCS_ACTIVE_PCIDB)) { 1235 if (! (reg & PCXHR_IRQCS_ACTIVE_PCIDB)) {
1241 spin_unlock(&mgr->lock);
1242 /* this device did not cause the interrupt */ 1236 /* this device did not cause the interrupt */
1243 return IRQ_NONE; 1237 return IRQ_NONE;
1244 } 1238 }
@@ -1250,6 +1244,44 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
1250 /* timer irq occurred */ 1244 /* timer irq occurred */
1251 if (reg & PCXHR_IRQ_TIMER) { 1245 if (reg & PCXHR_IRQ_TIMER) {
1252 int timer_toggle = reg & PCXHR_IRQ_TIMER; 1246 int timer_toggle = reg & PCXHR_IRQ_TIMER;
1247 if (timer_toggle == mgr->timer_toggle) {
1248 dev_dbg(&mgr->pci->dev, "ERROR TIMER TOGGLE\n");
1249 mgr->dsp_time_err++;
1250 }
1251
1252 mgr->timer_toggle = timer_toggle;
1253 mgr->src_it_dsp = reg;
1254 wake_thread = true;
1255 }
1256
1257 /* other irq's handled in the thread */
1258 if (reg & PCXHR_IRQ_MASK) {
1259 if (reg & PCXHR_IRQ_ASYNC) {
1260 /* as we didn't request any async notifications,
1261 * some kind of xrun error will probably occurred
1262 */
1263 /* better resynchronize all streams next interrupt : */
1264 mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID;
1265 }
1266 mgr->src_it_dsp = reg;
1267 wake_thread = true;
1268 }
1269#ifdef CONFIG_SND_DEBUG_VERBOSE
1270 if (reg & PCXHR_FATAL_DSP_ERR)
1271 dev_dbg(&mgr->pci->dev, "FATAL DSP ERROR : %x\n", reg);
1272#endif
1273
1274 return wake_thread ? IRQ_WAKE_THREAD : IRQ_HANDLED;
1275}
1276
1277irqreturn_t pcxhr_threaded_irq(int irq, void *dev_id)
1278{
1279 struct pcxhr_mgr *mgr = dev_id;
1280 int i, j;
1281 struct snd_pcxhr *chip;
1282
1283 mutex_lock(&mgr->lock);
1284 if (mgr->src_it_dsp & PCXHR_IRQ_TIMER) {
1253 /* is a 24 bit counter */ 1285 /* is a 24 bit counter */
1254 int dsp_time_new = 1286 int dsp_time_new =
1255 PCXHR_INPL(mgr, PCXHR_PLX_MBOX4) & PCXHR_DSP_TIME_MASK; 1287 PCXHR_INPL(mgr, PCXHR_PLX_MBOX4) & PCXHR_DSP_TIME_MASK;
@@ -1290,13 +1322,6 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
1290#endif 1322#endif
1291 mgr->dsp_time_last = dsp_time_new; 1323 mgr->dsp_time_last = dsp_time_new;
1292 1324
1293 if (timer_toggle == mgr->timer_toggle) {
1294 dev_dbg(&mgr->pci->dev, "ERROR TIMER TOGGLE\n");
1295 mgr->dsp_time_err++;
1296 }
1297 mgr->timer_toggle = timer_toggle;
1298
1299 reg &= ~PCXHR_IRQ_TIMER;
1300 for (i = 0; i < mgr->num_cards; i++) { 1325 for (i = 0; i < mgr->num_cards; i++) {
1301 chip = mgr->chip[i]; 1326 chip = mgr->chip[i];
1302 for (j = 0; j < chip->nb_streams_capt; j++) 1327 for (j = 0; j < chip->nb_streams_capt; j++)
@@ -1312,22 +1337,7 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
1312 dsp_time_diff); 1337 dsp_time_diff);
1313 } 1338 }
1314 } 1339 }
1315 /* other irq's handled in the tasklet */ 1340
1316 if (reg & PCXHR_IRQ_MASK) { 1341 pcxhr_msg_thread(mgr);
1317 if (reg & PCXHR_IRQ_ASYNC) { 1342 return IRQ_HANDLED;
1318 /* as we didn't request any async notifications,
1319 * some kind of xrun error will probably occurred
1320 */
1321 /* better resynchronize all streams next interrupt : */
1322 mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID;
1323 }
1324 mgr->src_it_dsp = reg;
1325 tasklet_schedule(&mgr->msg_taskq);
1326 }
1327#ifdef CONFIG_SND_DEBUG_VERBOSE
1328 if (reg & PCXHR_FATAL_DSP_ERR)
1329 dev_dbg(&mgr->pci->dev, "FATAL DSP ERROR : %x\n", reg);
1330#endif
1331 spin_unlock(&mgr->lock);
1332 return IRQ_HANDLED; /* this device caused the interrupt */
1333} 1343}