All of lore.kernel.org
 help / color / mirror / Atom feed
From: Takashi Iwai <tiwai@suse.de>
To: iain@psand.net
Cc: alsa-devel@lists.sourceforge.net
Subject: Re: Re: hdspmixer issues
Date: Wed, 22 Sep 2004 17:10:56 +0200	[thread overview]
Message-ID: <s5h3c1az6db.wl@alsa2.suse.de> (raw)
In-Reply-To: <Pine.LNX.4.58.0409221545340.2696@tallow.psand.net>

[-- Attachment #1: Type: text/plain, Size: 1993 bytes --]

At Wed, 22 Sep 2004 15:46:41 +0100 (BST),
Iain Kennedy wrote:
> 
> On Tue, 21 Sep 2004, Takashi Iwai wrote:
> 
> > At Mon, 20 Sep 2004 21:09:18 +0100 (BST),
> > Iain Kennedy wrote:
> > >
> > > > > I"ve been messing with hdsp (again :-) and found out that my hdspmixer
> > > > > has very oddly behaving sound meters. While the input (2nd row)
> > > > > appears to be more or less ok (the yellow peak things kind of fly all
> > > > > over the place and often drop off below green lines or even completely
> > > > > dissapear), the analog outputs as well as combined monitoring output
> > > > > (front 1/4" phono jack on the multiface) only occassionally spike with
> > > > > a line input (usually only one channel). I am wondering why this is so
> > > > > since the audio is definitely working ok, but the monitoring of the
> > > > > outputs simply isn"t working (at least not visually).
> > > >
> > > > i"ve been experiencing similar spikes on the analog outputs as ico
> > > > described. since we had a somehow similar problem with screwed up pci
> > > > cycles that was caused by incorrect initialisation of the cardbus briges
> > > > on our machines, i somehow doubt that it"s related to the problem we
> > > > had.
> > >
> > > > cheers...
> > >
> > > I've been experiencing lack of/sporadic metering on hdspmixer too..
> > > I'm running Debian testing with kernel 2.6.8 (same effect with 2.6.3),
> > > with both the debian alsa packages and a locally compiled latest alsa
> > > version...
> > >
> > > I had no such problem using 2.4.xx series kernels, although I was using a
> > > pre-1.06 version of the alsa drivers..
> >
> > Are you using ppc?  I found a bug in hdsp driver that it doesn't
> > handle big-endian correctly in the metering mmap.
> > Could you try the CVS version?
> >
> >
> > Takashi
> >
> 
> I'm using intel architecture... (Inspiron 8500 with 2GHz P4 M)
> 
> I've tried the CVS version, and still get the same results.

How about the attached patch (to cvs) ?


Takashi

[-- Attachment #2: Type: text/plain, Size: 10121 bytes --]

Index: alsa-kernel/pci/rme9652/hdsp.c
===================================================================
RCS file: /home/tiwai/cvs/alsa/alsa-kernel/pci/rme9652/hdsp.c,v
retrieving revision 1.70
diff -u -r1.70 hdsp.c
--- alsa-kernel/pci/rme9652/hdsp.c	21 Sep 2004 10:27:41 -0000	1.70
+++ alsa-kernel/pci/rme9652/hdsp.c	22 Sep 2004 15:08:43 -0000
@@ -4434,6 +4434,117 @@
 }
 
 
+static int hdsp_9652_get_peak(hdsp_t *hdsp, hdsp_peak_rms_t __user *peak_rms)
+{
+	u32 rms_low, rms_high;
+	u64 rms;
+	int doublespeed = 0;
+	int i, j, channels, ofs;
+
+	if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
+		doublespeed = 1;
+	channels = doublespeed ? 14 : 26;
+	for (i = 0, j = 0; i < 26; ++i) {
+		if (doublespeed && (i & 4))
+			continue;
+		ofs = HDSP_9652_peakBase - j * 4;
+		if (copy_to_user_fromio(&peak_rms->input_peaks[i], hdsp->iobase+ofs, 4))
+			return -EFAULT;
+		ofs -= channels * 4;
+		if (copy_to_user_fromio(&peak_rms->playback_peaks[i], hdsp->iobase+ofs, 4))
+			return -EFAULT;
+		ofs -= channels * 4;
+		if (copy_to_user_fromio(&peak_rms->output_peaks[i], hdsp->iobase+ofs, 4))
+			return -EFAULT;
+		ofs = HDSP_9652_rmsBase + j * 8;
+		rms_low = readl(hdsp->iobase+ofs) & 0xFFFFFF00;
+		rms_high = readl(hdsp->iobase+ofs+4) & 0xFFFFFF00;
+		rms = ((u64)rms_high << 32) | ((u64)rms_low << 8);
+		if (copy_to_user(&peak_rms->input_rms[i], &rms, 8))
+			return -EFAULT;
+		ofs += channels * 8;
+		rms_low = readl(hdsp->iobase+ofs) & 0xFFFFFF00;
+		rms_high = readl(hdsp->iobase+ofs+4) & 0xFFFFFF00;
+		rms = ((u64)rms_high << 32) | ((u64)rms_low << 8);
+		if (copy_to_user(&peak_rms->playback_rms[i], &rms, 8))
+			return -EFAULT;
+		ofs += channels * 8;
+		rms_low = readl(hdsp->iobase+ofs) & 0xFFFFFF00;
+		rms_high = readl(hdsp->iobase+ofs+4) & 0xFFFFFF00;
+		rms = ((u64)rms_high << 32) | ((u64)rms_low << 8);
+		if (copy_to_user(&peak_rms->output_rms[i], &rms, 8))
+			return -EFAULT;
+		j++;
+	}
+	return 0;
+}
+
+static int hdsp_9632_get_peak(hdsp_t *hdsp, hdsp_peak_rms_t __user *peak_rms)
+{
+	u32 rms_low, rms_high;
+	u64 rms;
+	int i, j;
+	hdsp_9632_meters_t __iomem *m;
+	int doublespeed = 0;
+
+	if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
+		doublespeed = 1;
+	m = (hdsp_9632_meters_t __iomem *)(hdsp->iobase+HDSP_9632_metersBase);
+	for (i = 0, j = 0; i < 16; ++i, ++j) {
+		if (copy_to_user_fromio(&peak_rms->input_peaks[i], &m->input_peak[j], 4))
+			return -EFAULT;
+		if (copy_to_user_fromio(&peak_rms->playback_peaks[i], &m->playback_peak[j], 4))
+			return -EFAULT;
+		if (copy_to_user_fromio(&peak_rms->output_peaks[i], &m->output_peak[j], 4))
+			return -EFAULT;
+		rms_low = readl(&m->input_rms_low[j]);
+		rms_high = readl(&m->input_rms_high[j]);
+		rms = ((u64)rms_high << 32) | rms_low;
+		if (copy_to_user(&peak_rms->input_rms[i], &rms, 8))
+			return -EFAULT;
+		rms_low = readl(&m->playback_rms_low[j]);
+		rms_high = readl(&m->playback_rms_high[j]);
+		rms = ((u64)rms_high << 32) | rms_low;
+		if (copy_to_user(&peak_rms->playback_rms[i], &rms, 8))
+			return -EFAULT;
+		rms_low = readl(&m->output_rms_low[j]);
+		rms_high = readl(&m->output_rms_high[j]);
+		rms = ((u64)rms_high << 32) | rms_low;
+		if (copy_to_user(&peak_rms->output_rms[i], &rms, 8))
+			return -EFAULT;
+		if (doublespeed && i == 3) i += 4;
+	}
+	return 0;
+}
+
+static int hdsp_get_peak(hdsp_t *hdsp, hdsp_peak_rms_t __user *peak_rms)
+{
+	int i;
+
+	if (copy_to_user_fromio(peak_rms->playback_peaks, hdsp->iobase+HDSP_playbackPeakLevel, 26*4))
+		return -EFAULT;
+	if (copy_to_user_fromio(peak_rms->input_peaks, hdsp->iobase+HDSP_inputPeakLevel, 26*4))
+		return -EFAULT;
+	if (copy_to_user_fromio(peak_rms->output_peaks, hdsp->iobase+HDSP_outputPeakLevel, 28*4))
+		return -EFAULT;
+	for (i = 0; i < 26; ++i) {
+		u32 rms_low, rms_high;
+		u64 rms;
+		/* FIXME: is this order correct? */
+		rms_low = readl(hdsp->iobase+HDSP_playbackRmsLevel+i*8);
+		rms_high = readl(hdsp->iobase+HDSP_playbackRmsLevel+i*8+4);
+		rms = ((u64)rms_high << 32) | rms_low;
+		if (copy_to_user(&peak_rms->playback_rms[i], &rms, 8))
+			return -EFAULT;
+		rms_low = readl(hdsp->iobase+HDSP_inputRmsLevel+i*8);
+		rms_high = readl(hdsp->iobase+HDSP_inputRmsLevel+i*8+4);
+		rms = ((u64)rms_high << 32) | rms_low;
+		if (copy_to_user(&peak_rms->input_rms[i], &rms, 8))
+			return -EFAULT;
+	}
+	return 0;
+}
+
 static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int cmd, unsigned long arg)
 {
 	hdsp_t *hdsp = (hdsp_t *)hw->private_data;	
@@ -4441,108 +4552,21 @@
 
 	switch (cmd) {
 	case SNDRV_HDSP_IOCTL_GET_PEAK_RMS: {
-		hdsp_peak_rms_t __user *peak_rms;
-		int i;
-		
-		if (hdsp->io_type == H9652) {
-			u32 rms_low, rms_high;
-			int doublespeed = 0;
-			if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
-				doublespeed = 1;
-			peak_rms = (hdsp_peak_rms_t __user *)arg;
-			for (i = 0; i < 26; ++i) {
-				if (!(doublespeed && (i & 4))) {
-					if (copy_to_user_fromio((void __user *)peak_rms->input_peaks+i*4, hdsp->iobase+HDSP_9652_peakBase-i*4, 4) != 0)
-						return -EFAULT;
-					if (copy_to_user_fromio((void __user *)peak_rms->playback_peaks+i*4, hdsp->iobase+HDSP_9652_peakBase-(doublespeed ? 14 : 26)*4-i*4, 4) != 0)
-						return -EFAULT;
-					if (copy_to_user_fromio((void __user *)peak_rms->output_peaks+i*4, hdsp->iobase+HDSP_9652_peakBase-2*(doublespeed ? 14 : 26)*4-i*4, 4) != 0)
-						return -EFAULT;
-					rms_low = readl(hdsp->iobase+HDSP_9652_rmsBase+i*8) & 0xFFFFFF00;
-					rms_high = readl(hdsp->iobase+HDSP_9652_rmsBase+i*8+4) & 0xFFFFFF00;
-					rms_high += (rms_low >> 24);
-					rms_low <<= 8;
-					if (copy_to_user((void __user *)peak_rms->input_rms+i*8, &rms_low, 4) != 0)
-						return -EFAULT;
-					if (copy_to_user((void __user *)peak_rms->input_rms+i*8+4, &rms_high, 4) != 0)
-						return -EFAULT;					
-					rms_low = readl(hdsp->iobase+HDSP_9652_rmsBase+(doublespeed ? 14 : 26)*8+i*8) & 0xFFFFFF00;
-					rms_high = readl(hdsp->iobase+HDSP_9652_rmsBase+(doublespeed ? 14 : 26)*8+i*8+4) & 0xFFFFFF00;
-					rms_high += (rms_low >> 24);
-					rms_low <<= 8;
-					if (copy_to_user((void __user *)peak_rms->playback_rms+i*8, &rms_low, 4) != 0)
-						return -EFAULT;
-					if (copy_to_user((void __user *)peak_rms->playback_rms+i*8+4, &rms_high, 4) != 0)
-						return -EFAULT;					
-					rms_low = readl(hdsp->iobase+HDSP_9652_rmsBase+2*(doublespeed ? 14 : 26)*8+i*8) & 0xFFFFFF00;
-					rms_high = readl(hdsp->iobase+HDSP_9652_rmsBase+2*(doublespeed ? 14 : 26)*8+i*8+4) & 0xFFFFFF00;
-					rms_high += (rms_low >> 24);
-					rms_low <<= 8;
-					if (copy_to_user((void __user *)peak_rms->output_rms+i*8, &rms_low, 4) != 0)
-						return -EFAULT;
-					if (copy_to_user((void __user *)peak_rms->output_rms+i*8+4, &rms_high, 4) != 0)
-						return -EFAULT;					
-				}
-			}
-			return 0;
-		}
-		if (hdsp->io_type == H9632) {
-			int j;
-			hdsp_9632_meters_t __iomem *m;
-			int doublespeed = 0;
-			if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
-				doublespeed = 1;
-			m = (hdsp_9632_meters_t __iomem *)(hdsp->iobase+HDSP_9632_metersBase);
-			peak_rms = (hdsp_peak_rms_t __user *)arg;
-			for (i = 0, j = 0; i < 16; ++i, ++j) {
-				if (copy_to_user_fromio((void __user *)peak_rms->input_peaks+i*4, &(m->input_peak[j]), 4) != 0)
-					return -EFAULT;
-				if (copy_to_user_fromio((void __user *)peak_rms->playback_peaks+i*4, &(m->playback_peak[j]), 4) != 0)
-					return -EFAULT;
-				if (copy_to_user_fromio((void __user *)peak_rms->output_peaks+i*4, &(m->output_peak[j]), 4) != 0)
-					return -EFAULT;
-				if (copy_to_user_fromio((void __user *)peak_rms->input_rms+i*8, &(m->input_rms_low[j]), 4) != 0)
-					return -EFAULT;
-				if (copy_to_user_fromio((void __user *)peak_rms->playback_rms+i*8, &(m->playback_rms_low[j]), 4) != 0)
-					return -EFAULT;
-				if (copy_to_user_fromio((void __user *)peak_rms->output_rms+i*8, &(m->output_rms_low[j]), 4) != 0)
-					return -EFAULT;
-				if (copy_to_user_fromio((void __user *)peak_rms->input_rms+i*8+4, &(m->input_rms_high[j]), 4) != 0)
-					return -EFAULT;
-				if (copy_to_user_fromio((void __user *)peak_rms->playback_rms+i*8+4, &(m->playback_rms_high[j]), 4) != 0)
-					return -EFAULT;
-				if (copy_to_user_fromio((void __user *)peak_rms->output_rms+i*8+4, &(m->output_rms_high[j]), 4) != 0)
-					return -EFAULT;
-				if (doublespeed && i == 3) i += 4;
-			}
-			return 0;
-		}
+		hdsp_peak_rms_t __user *peak_rms = (hdsp_peak_rms_t __user *)arg;
+
 		if (!(hdsp->state & HDSP_FirmwareLoaded)) {
-			snd_printk("firmware needs to be uploaded to the card.\n");	
+			snd_printk(KERN_ERR "firmware needs to be uploaded to the card.\n");
 			return -EINVAL;
 		}
-		peak_rms = (hdsp_peak_rms_t __user *)arg;
-		for (i = 0; i < 26; ++i) {
-		    if (copy_to_user_fromio((void __user *)peak_rms->playback_peaks+i*4, hdsp->iobase+HDSP_playbackPeakLevel+i*4, 4) != 0)
-			    return -EFAULT;
-		    if (copy_to_user_fromio((void __user *)peak_rms->input_peaks+i*4, hdsp->iobase+HDSP_inputPeakLevel+i*4, 4) != 0)
-			    return -EFAULT;
-		}
-		for (i = 0; i < 26; ++i) {
-			if (copy_to_user_fromio((void __user *)peak_rms->playback_rms+i*8+4, hdsp->iobase+HDSP_playbackRmsLevel+i*8, 4) != 0)
-				return -EFAULT;
-			if (copy_to_user_fromio((void __user *)peak_rms->playback_rms+i*8, hdsp->iobase+HDSP_playbackRmsLevel+i*8+4, 4) != 0)
-				return -EFAULT;
-			if (copy_to_user_fromio((void __user *)peak_rms->input_rms+i*8+4, hdsp->iobase+HDSP_inputRmsLevel+i*8, 4) != 0)
-				return -EFAULT;
-			if (copy_to_user_fromio((void __user *)peak_rms->input_rms+i*8, hdsp->iobase+HDSP_inputRmsLevel+i*8+4, 4) != 0)
-				return -EFAULT;
-		}
-		for (i = 0; i < 28; ++i) {
-		    if (copy_to_user_fromio((void __user *)peak_rms->output_peaks+i*4, hdsp->iobase+HDSP_outputPeakLevel+i*4, 4) != 0)
-			    return -EFAULT;
+
+		switch (hdsp->io_type) {
+		case H9652:
+			return hdsp_9652_get_peak(hdsp, peak_rms);
+		case H9632:
+			return hdsp_9632_get_peak(hdsp, peak_rms);
+		default:
+			return hdsp_get_peak(hdsp, peak_rms);
 		}
-		break;
 	}
 	case SNDRV_HDSP_IOCTL_GET_CONFIG_INFO: {
 		hdsp_config_info_t info;

  reply	other threads:[~2004-09-22 15:10 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-09-20 20:09 hdspmixer issues Iain Kennedy
2004-09-21 10:08 ` Takashi Iwai
2004-09-22 14:46   ` Iain Kennedy
2004-09-22 15:10     ` Takashi Iwai [this message]
2004-09-22 19:13       ` iain
2004-09-22 22:48         ` Iain Kennedy
2004-09-23 10:56           ` Takashi Iwai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=s5h3c1az6db.wl@alsa2.suse.de \
    --to=tiwai@suse.de \
    --cc=alsa-devel@lists.sourceforge.net \
    --cc=iain@psand.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.