From 4dfd79546dfed83bf756f5c912f686ebac187c16 Mon Sep 17 00:00:00 2001 From: Stas Sergeev Date: Sat, 17 May 2008 08:44:41 +0200 Subject: snd-pcsp: put back the compatibility code for the older alsa-libs The attached patch adds back the compatibility code, allowing the driver to work with older alsa-libs. The removal was premature, it breaks the real-life configs. Signed-off-by: Stas Sergeev Signed-off-by: Takashi Iwai --- sound/drivers/pcsp/pcsp_lib.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'sound/drivers/pcsp/pcsp_lib.c') diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c index ac6238e93513..54253e9b4b02 100644 --- a/sound/drivers/pcsp/pcsp_lib.c +++ b/sound/drivers/pcsp/pcsp_lib.c @@ -18,6 +18,8 @@ module_param(nforce_wa, bool, 0444); MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround " "(expect bad sound)"); +#define DMIX_WANTS_S16 1 + static void pcsp_start_timer(unsigned long dummy) { hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL); @@ -47,7 +49,7 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) { unsigned long flags; unsigned char timer_cnt, val; - int periods_elapsed; + int fmt_size, periods_elapsed; u64 ns; size_t period_bytes, buffer_bytes; struct snd_pcm_substream *substream; @@ -92,8 +94,11 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) goto exit_nr_unlock2; runtime = substream->runtime; - /* assume it is u8 mono */ - val = runtime->dma_area[chip->playback_ptr]; + fmt_size = snd_pcm_format_physical_width(runtime->format) >> 3; + /* assume it is mono! */ + val = runtime->dma_area[chip->playback_ptr + fmt_size - 1]; + if (snd_pcm_format_signed(runtime->format)) + val ^= 0x80; timer_cnt = val * CUR_DIV() / 256; if (timer_cnt && chip->enable) { @@ -111,7 +116,7 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) period_bytes = snd_pcm_lib_period_bytes(substream); buffer_bytes = snd_pcm_lib_buffer_bytes(substream); - chip->playback_ptr += PCSP_INDEX_INC(); + chip->playback_ptr += PCSP_INDEX_INC() * fmt_size; periods_elapsed = chip->playback_ptr - chip->period_ptr; if (periods_elapsed < 0) { printk(KERN_WARNING "PCSP: playback_ptr inconsistent " @@ -270,7 +275,11 @@ static struct snd_pcm_hardware snd_pcsp_playback = { .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_HALF_DUPLEX | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_U8, + .formats = (SNDRV_PCM_FMTBIT_U8 +#if DMIX_WANTS_S16 + | SNDRV_PCM_FMTBIT_S16_LE +#endif + ), .rates = SNDRV_PCM_RATE_KNOT, .rate_min = PCSP_DEFAULT_SRATE, .rate_max = PCSP_DEFAULT_SRATE, -- cgit v1.2.3 From 42ece6c1f8162cd782b44dc4863679e888531df5 Mon Sep 17 00:00:00 2001 From: Stas Sergeev Date: Sun, 18 May 2008 18:30:03 +0200 Subject: snd-pcsp: silent misleading warning It appears that alsa allows a sound buffer with size not evenly devided by the period size. This triggers a warning in snd-pcsp and floods the log. As a quick fix, the warning should be disabled. Signed-off-by: Stas Sergeev Signed-off-by: Takashi Iwai --- sound/drivers/pcsp/pcsp_lib.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sound/drivers/pcsp/pcsp_lib.c') diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c index 54253e9b4b02..7ad4a1534b2b 100644 --- a/sound/drivers/pcsp/pcsp_lib.c +++ b/sound/drivers/pcsp/pcsp_lib.c @@ -119,9 +119,11 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) chip->playback_ptr += PCSP_INDEX_INC() * fmt_size; periods_elapsed = chip->playback_ptr - chip->period_ptr; if (periods_elapsed < 0) { - printk(KERN_WARNING "PCSP: playback_ptr inconsistent " +#if PCSP_DEBUG + printk(KERN_INFO "PCSP: buffer_bytes mod period_bytes != 0 ? " "(%zi %zi %zi)\n", chip->playback_ptr, period_bytes, buffer_bytes); +#endif periods_elapsed += buffer_bytes; } periods_elapsed /= period_bytes; -- cgit v1.2.3 From 4b7afb0d0d23b298a7e6d30eaba0679449542d2e Mon Sep 17 00:00:00 2001 From: Stas Sergeev Date: Tue, 20 May 2008 11:47:29 +0200 Subject: snd-pcsp: use HRTIMER_CB_SOFTIRQ Change HRTIMER_CB_IRQSAFE to HRTIMER_CB_SOFTIRQ, as suggested by Thomas Gleixner. That solves the lock dependancy reported in Bug #10701. That also allows to call hrtimer_start() directly, tasklet "stupid hack" removed. Signed-off-by: Stas Sergeev Acked-by: Thomas Gleixner Signed-off-by: Takashi Iwai --- sound/drivers/pcsp/pcsp_lib.c | 37 ++++--------------------------------- 1 file changed, 4 insertions(+), 33 deletions(-) (limited to 'sound/drivers/pcsp/pcsp_lib.c') diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c index 7ad4a1534b2b..e341f3f83b6a 100644 --- a/sound/drivers/pcsp/pcsp_lib.c +++ b/sound/drivers/pcsp/pcsp_lib.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include "pcsp.h" @@ -20,34 +19,8 @@ MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround " #define DMIX_WANTS_S16 1 -static void pcsp_start_timer(unsigned long dummy) -{ - hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL); -} - -/* - * We need the hrtimer_start as a tasklet to avoid - * the nasty locking problem. :( - * The problem: - * - The timer handler is called with the cpu_base->lock - * already held by hrtimer code. - * - snd_pcm_period_elapsed() takes the - * substream->self_group.lock. - * So far so good. - * But the snd_pcsp_trigger() is called with the - * substream->self_group.lock held, and it calls - * hrtimer_start(), which takes the cpu_base->lock. - * You see the problem. We have the code pathes - * which take two locks in a reverse order. This - * can deadlock and the lock validator complains. - * The only solution I could find was to move the - * hrtimer_start() into a tasklet. -stsp - */ -static DECLARE_TASKLET(pcsp_start_timer_tasklet, pcsp_start_timer, 0); - enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) { - unsigned long flags; unsigned char timer_cnt, val; int fmt_size, periods_elapsed; u64 ns; @@ -66,9 +39,7 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) return HRTIMER_RESTART; } - /* hrtimer calls us from both hardirq and softirq contexts, - * so irqsave :( */ - spin_lock_irqsave(&chip->substream_lock, flags); + spin_lock_irq(&chip->substream_lock); /* Takashi Iwai says regarding this extra lock: If the irq handler handles some data on the DMA buffer, it should @@ -139,7 +110,7 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) chip->period_ptr %= buffer_bytes; } - spin_unlock_irqrestore(&chip->substream_lock, flags); + spin_unlock_irq(&chip->substream_lock); if (!atomic_read(&chip->timer_active)) return HRTIMER_NORESTART; @@ -153,7 +124,7 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) exit_nr_unlock2: snd_pcm_stream_unlock(substream); exit_nr_unlock1: - spin_unlock_irqrestore(&chip->substream_lock, flags); + spin_unlock_irq(&chip->substream_lock); return HRTIMER_NORESTART; } @@ -174,7 +145,7 @@ static void pcsp_start_playing(struct snd_pcsp *chip) atomic_set(&chip->timer_active, 1); chip->thalf = 0; - tasklet_schedule(&pcsp_start_timer_tasklet); + hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL); } static void pcsp_stop_playing(struct snd_pcsp *chip) -- cgit v1.2.3