[ARM] tegra_i2s_audio: add more elaborate error counts

This patch replaces the error counter with two separate error counters, one for
late dma callbacks, and another for overruns (during recording) or underruns
(during playback).  The ioctls TEGRA_AUDIO_IN_GET_ERROR_COUNT and
TEGRA_AUDIO_OUT_GET_ERROR_COUNT now take a pointer to a struct containing both
error counters.

Signed-off-by: Iliyan Malchev <malchev@google.com>
This commit is contained in:
Iliyan Malchev
2010-10-04 12:10:29 -07:00
committed by Colin Cross
parent d25a67d8d2
commit 49c9a88333
2 changed files with 16 additions and 11 deletions

View File

@@ -72,7 +72,7 @@ struct audio_stream {
struct completion fifo_completion;
struct scatterlist sg;
unsigned errors;
struct tegra_audio_error_counts errors;
int i2s_fifo_atn_level;
@@ -559,7 +559,7 @@ static bool stop_playback_if_necessary(struct audio_stream *aos)
if (kfifo_is_empty(&aos->fifo)) {
sound_ops->stop_playback(aos);
if (aos->active)
aos->errors++;
aos->errors.full_empty++; /* underflow */
spin_unlock_irqrestore(&aos->dma_req_lock, flags);
pm_qos_update_request(aos->pm_qos, PM_QOS_DEFAULT_VALUE);
return true;
@@ -575,7 +575,7 @@ static bool stop_recording_if_necessary_nosync(struct audio_stream *ais)
if (ads->recording_cancelled || kfifo_is_full(&ais->fifo)) {
if (kfifo_is_full(&ais->fifo))
ais->errors++;
ais->errors.full_empty++; /* overflow */
sound_ops->stop_recording(ais);
return true;
}
@@ -697,7 +697,7 @@ static void dma_tx_complete_callback(struct tegra_dma_req *req)
if (delta_us > max_delay_us) {
pr_debug("%s: too late by %lld us\n", __func__,
delta_us - max_delay_us);
aos->errors++;
aos->errors.late_dma++;
}
kfifo_dma_out_finish(&aos->fifo, count);
@@ -1074,7 +1074,7 @@ static irqreturn_t i2s_interrupt(int irq, void *data)
if (status & I2S_I2S_FIFO_RX_ERR) {
ads->pio_stats.rx_fifo_errors++;
ads->in.errors++;
ads->in.errors.full_empty++;
}
if (status & I2S_FIFO_ERR)
@@ -1283,7 +1283,7 @@ static long tegra_audio_out_ioctl(struct file *file,
sizeof(aos->errors)))
rc = -EFAULT;
if (!rc)
aos->errors = 0;
memset(&aos->errors, 0, sizeof(aos->errors));
break;
case TEGRA_AUDIO_OUT_PRELOAD_FIFO: {
struct tegra_audio_out_preload preload;
@@ -1422,7 +1422,7 @@ static long tegra_audio_in_ioctl(struct file *file,
sizeof(ais->errors)))
rc = -EFAULT;
if (!rc)
ais->errors = 0;
memset(&ais->errors, 0, sizeof(ais->errors));
break;
default:
rc = -EINVAL;
@@ -1698,7 +1698,7 @@ static int tegra_audio_out_open(struct inode *inode, struct file *file)
mutex_lock(&ads->out.lock);
if (!ads->out.opened++) {
pr_info("%s: resetting fifo and error count\n", __func__);
ads->out.errors = 0;
memset(&ads->out.errors, 0, sizeof(ads->out.errors));
kfifo_reset(&ads->out.fifo);
}
mutex_unlock(&ads->out.lock);
@@ -1735,7 +1735,7 @@ static int tegra_audio_in_open(struct inode *inode, struct file *file)
* input device.
*/
ads->recording_cancelled = false;
ads->in.errors = 0;
memset(&ads->in.errors, 0, sizeof(ads->in.errors));
kfifo_reset(&ads->in.fifo);
}
mutex_unlock(&ads->in.lock);

View File

@@ -52,11 +52,16 @@ struct tegra_audio_buf_config {
#define TEGRA_AUDIO_OUT_GET_BUF_CONFIG _IOR(TEGRA_AUDIO_MAGIC, 7, \
struct tegra_audio_buf_config *)
struct tegra_audio_error_counts {
unsigned late_dma;
unsigned full_empty; /* empty for playback, full for recording */
};
#define TEGRA_AUDIO_IN_GET_ERROR_COUNT _IOR(TEGRA_AUDIO_MAGIC, 8, \
unsigned *)
struct tegra_audio_error_counts *)
#define TEGRA_AUDIO_OUT_GET_ERROR_COUNT _IOR(TEGRA_AUDIO_MAGIC, 9, \
unsigned *)
struct tegra_audio_error_counts *)
struct tegra_audio_out_preload {
void *data;