aboutsummaryrefslogtreecommitdiffstats
path: root/sound/drivers/pcsp/pcsp_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/drivers/pcsp/pcsp_lib.c')
-rw-r--r--sound/drivers/pcsp/pcsp_lib.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c
index ac6238e9351..7ad4a1534b2 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);
18MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround " 18MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround "
19 "(expect bad sound)"); 19 "(expect bad sound)");
20 20
21#define DMIX_WANTS_S16 1
22
21static void pcsp_start_timer(unsigned long dummy) 23static void pcsp_start_timer(unsigned long dummy)
22{ 24{
23 hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL); 25 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)
47{ 49{
48 unsigned long flags; 50 unsigned long flags;
49 unsigned char timer_cnt, val; 51 unsigned char timer_cnt, val;
50 int periods_elapsed; 52 int fmt_size, periods_elapsed;
51 u64 ns; 53 u64 ns;
52 size_t period_bytes, buffer_bytes; 54 size_t period_bytes, buffer_bytes;
53 struct snd_pcm_substream *substream; 55 struct snd_pcm_substream *substream;
@@ -92,8 +94,11 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
92 goto exit_nr_unlock2; 94 goto exit_nr_unlock2;
93 95
94 runtime = substream->runtime; 96 runtime = substream->runtime;
95 /* assume it is u8 mono */ 97 fmt_size = snd_pcm_format_physical_width(runtime->format) >> 3;
96 val = runtime->dma_area[chip->playback_ptr]; 98 /* assume it is mono! */
99 val = runtime->dma_area[chip->playback_ptr + fmt_size - 1];
100 if (snd_pcm_format_signed(runtime->format))
101 val ^= 0x80;
97 timer_cnt = val * CUR_DIV() / 256; 102 timer_cnt = val * CUR_DIV() / 256;
98 103
99 if (timer_cnt && chip->enable) { 104 if (timer_cnt && chip->enable) {
@@ -111,12 +116,14 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
111 116
112 period_bytes = snd_pcm_lib_period_bytes(substream); 117 period_bytes = snd_pcm_lib_period_bytes(substream);
113 buffer_bytes = snd_pcm_lib_buffer_bytes(substream); 118 buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
114 chip->playback_ptr += PCSP_INDEX_INC(); 119 chip->playback_ptr += PCSP_INDEX_INC() * fmt_size;
115 periods_elapsed = chip->playback_ptr - chip->period_ptr; 120 periods_elapsed = chip->playback_ptr - chip->period_ptr;
116 if (periods_elapsed < 0) { 121 if (periods_elapsed < 0) {
117 printk(KERN_WARNING "PCSP: playback_ptr inconsistent " 122#if PCSP_DEBUG
123 printk(KERN_INFO "PCSP: buffer_bytes mod period_bytes != 0 ? "
118 "(%zi %zi %zi)\n", 124 "(%zi %zi %zi)\n",
119 chip->playback_ptr, period_bytes, buffer_bytes); 125 chip->playback_ptr, period_bytes, buffer_bytes);
126#endif
120 periods_elapsed += buffer_bytes; 127 periods_elapsed += buffer_bytes;
121 } 128 }
122 periods_elapsed /= period_bytes; 129 periods_elapsed /= period_bytes;
@@ -270,7 +277,11 @@ static struct snd_pcm_hardware snd_pcsp_playback = {
270 .info = (SNDRV_PCM_INFO_INTERLEAVED | 277 .info = (SNDRV_PCM_INFO_INTERLEAVED |
271 SNDRV_PCM_INFO_HALF_DUPLEX | 278 SNDRV_PCM_INFO_HALF_DUPLEX |
272 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID), 279 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
273 .formats = SNDRV_PCM_FMTBIT_U8, 280 .formats = (SNDRV_PCM_FMTBIT_U8
281#if DMIX_WANTS_S16
282 | SNDRV_PCM_FMTBIT_S16_LE
283#endif
284 ),
274 .rates = SNDRV_PCM_RATE_KNOT, 285 .rates = SNDRV_PCM_RATE_KNOT,
275 .rate_min = PCSP_DEFAULT_SRATE, 286 .rate_min = PCSP_DEFAULT_SRATE,
276 .rate_max = PCSP_DEFAULT_SRATE, 287 .rate_max = PCSP_DEFAULT_SRATE,