From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751031AbWDXR5W (ORCPT ); Mon, 24 Apr 2006 13:57:22 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751034AbWDXR5W (ORCPT ); Mon, 24 Apr 2006 13:57:22 -0400 Received: from mail.suse.de ([195.135.220.2]:64189 "EHLO mx1.suse.de") by vger.kernel.org with ESMTP id S1751026AbWDXR5W (ORCPT ); Mon, 24 Apr 2006 13:57:22 -0400 Date: Mon, 24 Apr 2006 19:57:15 +0200 Message-ID: From: Takashi Iwai To: Adrian McMenamin Cc: Alsa-devel , linux-sh , LKML , Lee Revell , Paul Mundt Subject: Re: [linuxsh-dev] Re: [Alsa-devel] [PATCH] Add Dreamcast AICA driver to alsa-driver In-Reply-To: <1145900695.9243.4.camel@localhost.localdomain> References: <1145831786.9242.38.camel@localhost.localdomain> <1145832383.9242.41.camel@localhost.localdomain> <1145900695.9243.4.camel@localhost.localdomain> User-Agent: Wanderlust/2.12.0 (Your Wildest Dreams) SEMI/1.14.6 (Maruoka) FLIM/1.14.7 (=?ISO-8859-4?Q?Sanj=F2?=) APEL/10.6 MULE XEmacs/21.5 (beta25) (eggplant) (+CVS-20060326) (i386-suse-linux) MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: text/plain; charset=US-ASCII Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org At Mon, 24 Apr 2006 18:44:55 +0100, Adrian McMenamin wrote: > > > > > > +static int stereo_buffer_transfer(struct snd_pcm_substream > > > + *substream, int buffer_size, int period) > > > +{ > > > > I feel this transfer-and-wait could be done more efficiently using > > workq than doing it in timer callback. The trigger(start) and > > aica_period_elapsed() calls queue_work() at each time. > > > > The most work of spu_begin_dma() should be put in the workq, too. > > > > heh. If you remember, a couple of months ago I had this in a kernel > thread - ie much the same - and you or Lee said I should absolutely not > use that mechanism :) Well, a source code tell you better than hundreds words :) > > You can write a single function for both mono and two-channel > > streams. > > > > How can I do that given the dma has to be serialised? The second dma_xfer() can be in if (channels > 1) block (in addition to different transfer bytes). Something like below: static int buffer_transfer(struct snd_pcm_substream*substream, int buffer_size, int period) { int transferred; int dma_countout; struct snd_pcm_runtime *runtime; int period_offset; long dma_flags; period_offset = period; period_offset %= (AICA_PERIOD_NUMBER / runtime->channels); runtime = substream->runtime; /* transfer left and then right */ dma_flags = claim_dma_lock(); dma_countout = 0; dma_xfer(0, runtime->dma_area + (AICA_PERIOD_SIZE * period_offset), AICA_CHANNEL0_OFFSET + (AICA_PERIOD_SIZE * period_offset), buffer_size / 2, 5); /* wait for completion */ do { udelay(5); transferred = get_dma_residue(0); dma_countout++; if (dma_countout > 0x10000) break; /* Approx 1/3 sec timeout in case of hardware failure */ } while (transferred < buffer_size / 2); if (runtime->channels > 1) { dma_xfer(0, AICA_BUFFER_SIZE / 2 + runtime->dma_area + (AICA_PERIOD_SIZE * period_offset), AICA_CHANNEL1_OFFSET + (AICA_PERIOD_SIZE * period_offset), buffer_size / 2, 5); /* have to wait again */ dma_countout = 0; do { udelay(5); transferred = get_dma_residue(0); dma_countout++; if (dma_countout > 0x10000) break; } while (transferred < buffer_size / 2); } release_dma_lock(dma_flags); return 0; } Takashi