diff options
author | Christian Pointner <equinox@helsinki.at> | 2025-03-29 11:20:29 (GMT) |
---|---|---|
committer | Christian Pointner <equinox@helsinki.at> | 2025-03-29 11:20:29 (GMT) |
commit | 2f0f51426a2331873c2f3795c2ea2290ad04fcab (patch) | |
tree | c32f0fba22c91457a6dd0459a3b67af321de982a /snd-pcxhr-dkms/src/pcxhr_core.c | |
parent | 73b1ed36085870e0cf1abf892479b47404ca23f4 (diff) |
snd-pcxhr: import refreshed version of patchset
Diffstat (limited to 'snd-pcxhr-dkms/src/pcxhr_core.c')
-rw-r--r-- | snd-pcxhr-dkms/src/pcxhr_core.c | 244 |
1 files changed, 127 insertions, 117 deletions
diff --git a/snd-pcxhr-dkms/src/pcxhr_core.c b/snd-pcxhr-dkms/src/pcxhr_core.c index 7ef9b6d..020088b 100644 --- a/snd-pcxhr-dkms/src/pcxhr_core.c +++ b/snd-pcxhr-dkms/src/pcxhr_core.c @@ -1,30 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Driver for Digigram pcxhr compatible soundcards * * low level interface with interrupt and message handling implementation * * Copyright (c) 2004 by Digigram <alsa@digigram.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <linux/delay.h> #include <linux/firmware.h> #include <linux/interrupt.h> #include <linux/pci.h> -#include <asm/io.h> +#include <linux/io.h> #include <sound/core.h> #include "pcxhr.h" #include "pcxhr_mixer.h" @@ -89,14 +76,14 @@ static int pcxhr_check_reg_bit(struct pcxhr_mgr *mgr, unsigned int bar, unsigned *read = PCXHR_INPB(mgr, bar, reg); if ((*read & mask) == bit) { if (i > 100) - snd_printdd("ATTENTION! check_reg(%x) " - "loopcount=%d\n", + dev_dbg(&mgr->pci->dev, + "ATTENTION! check_reg(%x) loopcount=%d\n", reg, i); return 0; } i++; } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR + dev_err(&mgr->pci->dev, "pcxhr_check_reg_bit: timeout, bar=%x reg=%x, mask=0x%x, val=%x\n", bar, reg, mask, *read); return -EIO; @@ -173,7 +160,7 @@ static int pcxhr_send_it_dsp(struct pcxhr_mgr *mgr, err = pcxhr_check_reg_bit(mgr, PCXHR_DSP, PCXHR_DSP_CVR, PCXHR_CVR_HI08_HC, 0, PCXHR_TIMEOUT_DSP, ®); if (err) { - snd_printk(KERN_ERR "pcxhr_send_it_dsp : TIMEOUT CVR\n"); + dev_err(&mgr->pci->dev, "pcxhr_send_it_dsp : TIMEOUT CVR\n"); return err; } if (itdsp & PCXHR_MASK_IT_MANAGE_HF5) { @@ -184,7 +171,7 @@ static int pcxhr_send_it_dsp(struct pcxhr_mgr *mgr, PCXHR_TIMEOUT_DSP, ®); if (err) { - snd_printk(KERN_ERR + dev_err(&mgr->pci->dev, "pcxhr_send_it_dsp : TIMEOUT HF5\n"); return err; } @@ -265,7 +252,7 @@ int pcxhr_load_xilinx_binary(struct pcxhr_mgr *mgr, */ if(second) { if ((chipsc & PCXHR_CHIPSC_GPI_USERI) == 0) { - snd_printk(KERN_ERR "error loading first xilinx\n"); + dev_err(&mgr->pci->dev, "error loading first xilinx\n"); return -EINVAL; } /* activate second xilinx */ @@ -331,7 +318,7 @@ static int pcxhr_download_dsp(struct pcxhr_mgr *mgr, const struct firmware *dsp) PCXHR_ISR_HI08_TRDY, PCXHR_TIMEOUT_DSP, &dummy); if (err) { - snd_printk(KERN_ERR + dev_err(&mgr->pci->dev, "dsp loading error at position %d\n", i); return err; } @@ -367,7 +354,7 @@ int pcxhr_load_eeprom_binary(struct pcxhr_mgr *mgr, msleep(PCXHR_WAIT_DEFAULT); PCXHR_OUTPB(mgr, PCXHR_DSP, PCXHR_DSP_ICR, reg); msleep(PCXHR_WAIT_DEFAULT); - snd_printdd("no need to load eeprom boot\n"); + dev_dbg(&mgr->pci->dev, "no need to load eeprom boot\n"); return 0; } PCXHR_OUTPB(mgr, PCXHR_DSP, PCXHR_DSP_ICR, reg); @@ -449,7 +436,7 @@ enum { /* * Array of DSP commands */ -static struct pcxhr_cmd_info pcxhr_dsp_cmds[] = { +static const struct pcxhr_cmd_info pcxhr_dsp_cmds[] = { [CMD_VERSION] = { 0x010000, 1, RMH_SSIZE_FIXED }, [CMD_SUPPORTED] = { 0x020000, 4, RMH_SSIZE_FIXED }, [CMD_TEST_IT] = { 0x040000, 1, RMH_SSIZE_FIXED }, @@ -480,7 +467,7 @@ static struct pcxhr_cmd_info pcxhr_dsp_cmds[] = { }; #ifdef CONFIG_SND_DEBUG_VERBOSE -static char* cmd_names[] = { +static const char * const cmd_names[] = { [CMD_VERSION] = "CMD_VERSION", [CMD_SUPPORTED] = "CMD_SUPPORTED", [CMD_TEST_IT] = "CMD_TEST_IT", @@ -532,9 +519,9 @@ static int pcxhr_read_rmh_status(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) PCXHR_ISR_HI08_RXDF, PCXHR_TIMEOUT_DSP, ®); if (err) { - snd_printk(KERN_ERR "ERROR RMH stat: " - "ISR:RXDF=1 (ISR = %x; i=%d )\n", - reg, i); + dev_err(&mgr->pci->dev, + "ERROR RMH stat: ISR:RXDF=1 (ISR = %x; i=%d )\n", + reg, i); return err; } /* read data */ @@ -562,13 +549,13 @@ static int pcxhr_read_rmh_status(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) } #ifdef CONFIG_SND_DEBUG_VERBOSE if (rmh->cmd_idx < CMD_LAST_INDEX) - snd_printdd(" stat[%d]=%x\n", i, data); + dev_dbg(&mgr->pci->dev, " stat[%d]=%x\n", i, data); #endif if (i < max_stat_len) rmh->stat[i] = data; } if (rmh->stat_len > max_stat_len) { - snd_printdd("PCXHR : rmh->stat_len=%x too big\n", + dev_dbg(&mgr->pci->dev, "PCXHR : rmh->stat_len=%x too big\n", rmh->stat_len); rmh->stat_len = max_stat_len; } @@ -586,7 +573,8 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) return -EINVAL; err = pcxhr_send_it_dsp(mgr, PCXHR_IT_MESSAGE, 1); if (err) { - snd_printk(KERN_ERR "pcxhr_send_message : ED_DSP_CRASHED\n"); + dev_err(&mgr->pci->dev, + "pcxhr_send_message : ED_DSP_CRASHED\n"); return err; } /* wait for chk bit */ @@ -612,7 +600,7 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) data &= 0xff7fff; /* MASK_1_WORD_COMMAND */ #ifdef CONFIG_SND_DEBUG_VERBOSE if (rmh->cmd_idx < CMD_LAST_INDEX) - snd_printdd("MSG cmd[0]=%x (%s)\n", + dev_dbg(&mgr->pci->dev, "MSG cmd[0]=%x (%s)\n", data, cmd_names[rmh->cmd_idx]); #endif @@ -642,7 +630,8 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) data = rmh->cmd[i]; #ifdef CONFIG_SND_DEBUG_VERBOSE if (rmh->cmd_idx < CMD_LAST_INDEX) - snd_printdd(" cmd[%d]=%x\n", i, data); + dev_dbg(&mgr->pci->dev, + " cmd[%d]=%x\n", i, data); #endif err = pcxhr_check_reg_bit(mgr, PCXHR_DSP, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY, @@ -668,14 +657,15 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) PCXHR_ISR_HI08_RXDF, PCXHR_TIMEOUT_DSP, ®); if (err) { - snd_printk(KERN_ERR "ERROR RMH: ISR:RXDF=1 (ISR = %x)\n", reg); + dev_err(&mgr->pci->dev, + "ERROR RMH: ISR:RXDF=1 (ISR = %x)\n", reg); return err; } /* read error code */ data = PCXHR_INPB(mgr, PCXHR_DSP, PCXHR_DSP_TXH) << 16; data |= PCXHR_INPB(mgr, PCXHR_DSP, PCXHR_DSP_TXM) << 8; data |= PCXHR_INPB(mgr, PCXHR_DSP, PCXHR_DSP_TXL); - snd_printk(KERN_ERR "ERROR RMH(%d): 0x%x\n", + dev_err(&mgr->pci->dev, "ERROR RMH(%d): 0x%x\n", rmh->cmd_idx, data); err = -EINVAL; } else { @@ -734,11 +724,11 @@ void pcxhr_set_pipe_cmd_params(struct pcxhr_rmh *rmh, int capture, */ int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) { - unsigned long flags; int err; - spin_lock_irqsave(&mgr->msg_lock, flags); + + mutex_lock(&mgr->msg_lock); err = pcxhr_send_msg_nolock(mgr, rmh); - spin_unlock_irqrestore(&mgr->msg_lock, flags); + mutex_unlock(&mgr->msg_lock); return err; } @@ -751,7 +741,7 @@ static inline int pcxhr_pipes_running(struct pcxhr_mgr *mgr) * (PCXHR_PIPE_STATE_CAPTURE_OFFSET) */ start_mask &= 0x00ffffff; - snd_printdd("CMD_PIPE_STATE MBOX2=0x%06x\n", start_mask); + dev_dbg(&mgr->pci->dev, "CMD_PIPE_STATE MBOX2=0x%06x\n", start_mask); return start_mask; } @@ -780,7 +770,7 @@ static int pcxhr_prepair_pipe_start(struct pcxhr_mgr *mgr, } err = pcxhr_send_msg(mgr, &rmh); if (err) { - snd_printk(KERN_ERR + dev_err(&mgr->pci->dev, "error pipe start " "(CMD_CAN_START_PIPE) err=%x!\n", err); @@ -818,7 +808,7 @@ static int pcxhr_stop_pipes(struct pcxhr_mgr *mgr, int audio_mask) } err = pcxhr_send_msg(mgr, &rmh); if (err) { - snd_printk(KERN_ERR + dev_err(&mgr->pci->dev, "error pipe stop " "(CMD_STOP_PIPE) err=%x!\n", err); return err; @@ -847,7 +837,7 @@ static int pcxhr_toggle_pipes(struct pcxhr_mgr *mgr, int audio_mask) 1 << (audio - PCXHR_PIPE_STATE_CAPTURE_OFFSET)); err = pcxhr_send_msg(mgr, &rmh); if (err) { - snd_printk(KERN_ERR + dev_err(&mgr->pci->dev, "error pipe start " "(CMD_CONF_PIPE) err=%x!\n", err); return err; @@ -860,7 +850,7 @@ static int pcxhr_toggle_pipes(struct pcxhr_mgr *mgr, int audio_mask) pcxhr_init_rmh(&rmh, CMD_SEND_IRQA); err = pcxhr_send_msg(mgr, &rmh); if (err) { - snd_printk(KERN_ERR + dev_err(&mgr->pci->dev, "error pipe start (CMD_SEND_IRQA) err=%x!\n", err); return err; @@ -877,15 +867,16 @@ int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, int audio_mask; #ifdef CONFIG_SND_DEBUG_VERBOSE - struct timespec64 start_date, end_date, delta_t; - ktime_get_real_ts64(&start_date); + ktime_t start_time, stop_time, diff_time; + + start_time = ktime_get(); #endif - audio_mask = (playback_mask | (capture_mask << PCXHR_PIPE_STATE_CAPTURE_OFFSET)); /* current pipe state (playback + record) */ state = pcxhr_pipes_running(mgr); - snd_printdd("pcxhr_set_pipe_state %s (mask %x current %x)\n", + dev_dbg(&mgr->pci->dev, + "pcxhr_set_pipe_state %s (mask %x current %x)\n", start ? "START" : "STOP", audio_mask, state); if (start) { /* start only pipes that are not yet started */ @@ -916,7 +907,7 @@ int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, if ((state & audio_mask) == (start ? audio_mask : 0)) break; if (++i >= MAX_WAIT_FOR_DSP * 100) { - snd_printk(KERN_ERR "error pipe start/stop\n"); + dev_err(&mgr->pci->dev, "error pipe start/stop\n"); return -EBUSY; } udelay(10); /* wait 10 microseconds */ @@ -927,10 +918,10 @@ int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, return err; } #ifdef CONFIG_SND_DEBUG_VERBOSE - ktime_get_real_ts64(&end_date); - delta_t = timespec64_sub(end_date, start_date); - snd_printdd("***SET PIPE STATE*** TIME = %ld (err = %x)\n", - (long)delta_t.tv_nsec/1000, err); + stop_time = ktime_get(); + diff_time = ktime_sub(stop_time, start_time); + dev_dbg(&mgr->pci->dev, "***SET PIPE STATE*** TIME = %ld (err = %x)\n", + (long)(ktime_to_ns(diff_time)), err); #endif return 0; } @@ -939,16 +930,16 @@ int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask, unsigned int value, int *changed) { struct pcxhr_rmh rmh; - unsigned long flags; int err; - spin_lock_irqsave(&mgr->msg_lock, flags); + mutex_lock(&mgr->msg_lock); if ((mgr->io_num_reg_cont & mask) == value) { - snd_printdd("IO_NUM_REG_CONT mask %x already is set to %x\n", + dev_dbg(&mgr->pci->dev, + "IO_NUM_REG_CONT mask %x already is set to %x\n", mask, value); if (changed) *changed = 0; - spin_unlock_irqrestore(&mgr->msg_lock, flags); + mutex_unlock(&mgr->msg_lock); return 0; /* already programmed */ } pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); @@ -963,7 +954,7 @@ int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask, if (changed) *changed = 1; } - spin_unlock_irqrestore(&mgr->msg_lock, flags); + mutex_unlock(&mgr->msg_lock); return err; } @@ -985,7 +976,7 @@ static int pcxhr_handle_async_err(struct pcxhr_mgr *mgr, u32 err, enum pcxhr_async_err_src err_src, int pipe, int is_capture) { - static char* err_src_name[] = { + static const char * const err_src_name[] = { [PCXHR_ERR_PIPE] = "Pipe", [PCXHR_ERR_STREAM] = "Stream", [PCXHR_ERR_AUDIO] = "Audio" @@ -997,7 +988,7 @@ static int pcxhr_handle_async_err(struct pcxhr_mgr *mgr, u32 err, err = ((err >> 12) & 0xfff); if (!err) return 0; - snd_printdd("CMD_ASYNC : Error %s %s Pipe %d err=%x\n", + dev_dbg(&mgr->pci->dev, "CMD_ASYNC : Error %s %s Pipe %d err=%x\n", err_src_name[err_src], is_capture ? "Record" : "Play", pipe, err); if (err == 0xe01) @@ -1010,28 +1001,31 @@ static int pcxhr_handle_async_err(struct pcxhr_mgr *mgr, u32 err, } -void pcxhr_msg_tasklet(unsigned long arg) +static void pcxhr_msg_thread(struct pcxhr_mgr *mgr) { - struct pcxhr_mgr *mgr = (struct pcxhr_mgr *)(arg); struct pcxhr_rmh *prmh = mgr->prmh; int err; int i, j; if (mgr->src_it_dsp & PCXHR_IRQ_FREQ_CHANGE) -// printk(KERN_WARNING "TASKLET : PCXHR_IRQ_FREQ_CHANGE event occurred\n"); + dev_dbg(&mgr->pci->dev, + "PCXHR_IRQ_FREQ_CHANGE event occurred\n"); if (mgr->src_it_dsp & PCXHR_IRQ_TIME_CODE) -// printk(KERN_WARNING "TASKLET : PCXHR_IRQ_TIME_CODE event occurred\n"); + dev_dbg(&mgr->pci->dev, + "PCXHR_IRQ_TIME_CODE event occurred\n"); if (mgr->src_it_dsp & PCXHR_IRQ_NOTIFY) -// printk(KERN_WARNING "TASKLET : PCXHR_IRQ_NOTIFY event occurred\n"); + dev_dbg(&mgr->pci->dev, + "PCXHR_IRQ_NOTIFY event occurred\n"); if (mgr->src_it_dsp & (PCXHR_IRQ_FREQ_CHANGE | PCXHR_IRQ_TIME_CODE)) { /* clear events FREQ_CHANGE and TIME_CODE */ pcxhr_init_rmh(prmh, CMD_TEST_IT); err = pcxhr_send_msg(mgr, prmh); -// printk(KERN_ERR "CMD_TEST_IT : err=%x, stat=%x\n", -// err, prmh->stat[0]); + dev_dbg(&mgr->pci->dev, "CMD_TEST_IT : err=%x, stat=%x\n", + err, prmh->stat[0]); } if (mgr->src_it_dsp & PCXHR_IRQ_ASYNC) { - printk(KERN_ERR "TASKLET : PCXHR_IRQ_ASYNC event occurred\n"); + dev_dbg(&mgr->pci->dev, + "PCXHR_IRQ_ASYNC event occurred\n"); pcxhr_init_rmh(prmh, CMD_ASYNC); prmh->cmd[0] |= 1; /* add SEL_ASYNC_EVENTS */ @@ -1039,7 +1033,7 @@ void pcxhr_msg_tasklet(unsigned long arg) prmh->stat_len = PCXHR_SIZE_MAX_LONG_STATUS; err = pcxhr_send_msg(mgr, prmh); if (err) - snd_printk(KERN_ERR "ERROR pcxhr_msg_tasklet=%x;\n", + dev_err(&mgr->pci->dev, "ERROR pcxhr_msg_thread=%x;\n", err); i = 1; while (i < prmh->stat_len) { @@ -1052,7 +1046,8 @@ void pcxhr_msg_tasklet(unsigned long arg) u32 err2; if (prmh->stat[i] & 0x800000) { /* if BIT_END */ - printk(KERN_WARNING "TASKLET : End%sPipe %d\n", + dev_dbg(&mgr->pci->dev, + "TASKLET : End%sPipe %d\n", is_capture ? "Record" : "Play", pipe); } @@ -1109,7 +1104,8 @@ static u_int64_t pcxhr_stream_read_position(struct pcxhr_mgr *mgr, hw_sample_count = ((u_int64_t)rmh.stat[0]) << 24; hw_sample_count += (u_int64_t)rmh.stat[1]; - snd_printdd("stream %c%d : abs samples real(%llu) timer(%llu)\n", + dev_dbg(&mgr->pci->dev, + "stream %c%d : abs samples real(%llu) timer(%llu)\n", stream->pipe->is_capture ? 'C' : 'P', stream->substream->number, hw_sample_count, @@ -1120,7 +1116,7 @@ static u_int64_t pcxhr_stream_read_position(struct pcxhr_mgr *mgr, static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr, struct pcxhr_stream *stream, - int samples_to_add, unsigned long flags) + int samples_to_add) { if (stream->substream && (stream->status == PCXHR_STREAM_STATUS_RUNNING)) { @@ -1175,15 +1171,15 @@ static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr, (u_int32_t)(new_sample_count - stream->timer_abs_periods); } else { - snd_printk(KERN_ERR + dev_err(&mgr->pci->dev, "ERROR new_sample_count too small ??? %ld\n", (long unsigned int)new_sample_count); } if (elapsed) { - spin_unlock_irqrestore(&mgr->lock, flags); + mutex_unlock(&mgr->lock); snd_pcm_period_elapsed(stream->substream); - spin_lock_irqsave(&mgr->lock, flags); + mutex_lock(&mgr->lock); } } } @@ -1191,11 +1187,9 @@ static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr, irqreturn_t pcxhr_interrupt(int irq, void *dev_id) { struct pcxhr_mgr *mgr = dev_id; - unsigned long flags; unsigned int reg = 0; unsigned int tmp; - int i, j; - struct snd_pcxhr *chip; + bool wake_thread = false; mgr->dbg_cpt.interrupts_all++; @@ -1208,15 +1202,11 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id) //*************************ATTENTION*************************// - spin_lock_irqsave(&mgr->lock, flags); - //spin_lock(&mgr->lock); //mgr->dbg_cpt.interrupts_all++; if (irq) { reg = PCXHR_INPL(mgr, PCXHR_PLX, PCXHR_PLX_IRQCS); if (! (reg & PCXHR_IRQCS_ACTIVE_PCIDB)) { - spin_unlock_irqrestore(&mgr->lock, flags); - //spin_unlock(&mgr->lock); mgr->dbg_cpt.interrupts_none++; /* this device did not cause the interrupt */ return IRQ_NONE; @@ -1240,6 +1230,44 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id) /* timer irq occurred */ if (reg & PCXHR_IRQ_TIMER) { int timer_toggle = reg & PCXHR_IRQ_TIMER; + if (timer_toggle == mgr->timer_toggle) { + dev_dbg(&mgr->pci->dev, "ERROR TIMER TOGGLE\n"); + mgr->dsp_time_err++; + } + + mgr->timer_toggle = timer_toggle; + mgr->src_it_dsp = reg; + wake_thread = true; + } + + /* other irq's handled in the thread */ + if (reg & PCXHR_IRQ_MASK) { + if (reg & PCXHR_IRQ_ASYNC) { + /* as we didn't request any async notifications, + * some kind of xrun error will probably occurred + */ + /* better resynchronize all streams next interrupt : */ + mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID; + } + mgr->src_it_dsp = reg; + wake_thread = true; + } +#ifdef CONFIG_SND_DEBUG_VERBOSE + if (reg & PCXHR_FATAL_DSP_ERR) + dev_dbg(&mgr->pci->dev, "FATAL DSP ERROR : %x\n", reg); +#endif + + return wake_thread ? IRQ_WAKE_THREAD : IRQ_HANDLED; +} + +irqreturn_t pcxhr_threaded_irq(int irq, void *dev_id) +{ + struct pcxhr_mgr *mgr = dev_id; + int i, j; + struct snd_pcxhr *chip; + + mutex_lock(&mgr->lock); + if (mgr->src_it_dsp & PCXHR_IRQ_TIMER) { /* is a 24 bit counter */ int dsp_time_new = PCXHR_INPL(mgr, PCXHR_PLX, PCXHR_PLX_MBOX4) & PCXHR_DSP_TIME_MASK; @@ -1249,72 +1277,54 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id) (mgr->dsp_time_last != PCXHR_DSP_TIME_INVALID)) { /* handle dsp counter wraparound without resync */ int tmp_diff = dsp_time_diff + PCXHR_DSP_TIME_MASK + 1; - snd_printdd("WARNING DSP timestamp old(%d) new(%d)", + dev_dbg(&mgr->pci->dev, + "WARNING DSP timestamp old(%d) new(%d)", mgr->dsp_time_last, dsp_time_new); if (tmp_diff > 0 && tmp_diff <= (2*mgr->granularity)) { - snd_printdd("-> timestamp wraparound OK: " + dev_dbg(&mgr->pci->dev, + "-> timestamp wraparound OK: " "diff=%d\n", tmp_diff); dsp_time_diff = tmp_diff; } else { - snd_printdd("-> resynchronize all streams\n"); + dev_dbg(&mgr->pci->dev, + "-> resynchronize all streams\n"); mgr->dsp_time_err++; } } #ifdef CONFIG_SND_DEBUG_VERBOSE if (dsp_time_diff == 0) - snd_printdd("ERROR DSP TIME NO DIFF time(%d)\n", + dev_dbg(&mgr->pci->dev, + "ERROR DSP TIME NO DIFF time(%d)\n", dsp_time_new); else if (dsp_time_diff >= (2*mgr->granularity)) - snd_printdd("ERROR DSP TIME TOO BIG old(%d) add(%d)\n", + dev_dbg(&mgr->pci->dev, + "ERROR DSP TIME TOO BIG old(%d) add(%d)\n", mgr->dsp_time_last, dsp_time_new - mgr->dsp_time_last); else if (dsp_time_diff % mgr->granularity) - snd_printdd("ERROR DSP TIME increased by %d\n", + dev_dbg(&mgr->pci->dev, + "ERROR DSP TIME increased by %d\n", dsp_time_diff); #endif mgr->dsp_time_last = dsp_time_new; - if (timer_toggle == mgr->timer_toggle) { - snd_printdd("ERROR TIMER TOGGLE\n"); - mgr->dsp_time_err++; - } - mgr->timer_toggle = timer_toggle; - - reg &= ~PCXHR_IRQ_TIMER; for (i = 0; i < mgr->num_cards; i++) { chip = mgr->chip[i]; for (j = 0; j < chip->nb_streams_capt; j++) pcxhr_update_timer_pos(mgr, &chip->capture_stream[j], - dsp_time_diff, flags); + dsp_time_diff); } for (i = 0; i < mgr->num_cards; i++) { chip = mgr->chip[i]; for (j = 0; j < chip->nb_streams_play; j++) pcxhr_update_timer_pos(mgr, &chip->playback_stream[j], - dsp_time_diff, flags); + dsp_time_diff); } } - /* other irq's handled in the tasklet */ - if (reg & PCXHR_IRQ_MASK) { - mgr->dbg_cpt.interrupts_irq++; - if (reg & PCXHR_IRQ_ASYNC) { - /* as we didn't request any async notifications, - * some kind of xrun error will probably occurred - */ - /* better resynchronize all streams next interrupt : */ - mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID; - mgr->dbg_cpt.interrupts_async++; - } - mgr->src_it_dsp = reg; - tasklet_schedule(&mgr->msg_taskq); - } -#ifdef CONFIG_SND_DEBUG_VERBOSE - if (reg & PCXHR_FATAL_DSP_ERR) - snd_printdd("FATAL DSP ERROR : %x\n", reg); -#endif - spin_unlock_irqrestore(&mgr->lock, flags); - mgr->dbg_cpt.interrupts_handled++; - return IRQ_HANDLED; /* this device caused the interrupt */ + + pcxhr_msg_thread(mgr); + mutex_unlock(&mgr->lock); + return IRQ_HANDLED; } |