From mboxrd@z Thu Jan 1 00:00:00 1970 From: Takashi Iwai Subject: Re: Re: hdspmixer issues Date: Wed, 22 Sep 2004 17:10:56 +0200 Sender: alsa-devel-admin@lists.sourceforge.net Message-ID: References: Mime-Version: 1.0 (generated by SEMI 1.14.5 - "Awara-Onsen") Content-Type: multipart/mixed; boundary="Multipart_Wed_Sep_22_17:10:56_2004-1" Return-path: In-Reply-To: Errors-To: alsa-devel-admin@lists.sourceforge.net List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , List-Archive: To: iain@psand.net Cc: alsa-devel@lists.sourceforge.net List-Id: alsa-devel@alsa-project.org --Multipart_Wed_Sep_22_17:10:56_2004-1 Content-Type: text/plain; charset=US-ASCII 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 --Multipart_Wed_Sep_22_17:10:56_2004-1 Content-Type: text/plain; charset=US-ASCII 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; --Multipart_Wed_Sep_22_17:10:56_2004-1-- ------------------------------------------------------- This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM. Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php