From patchwork Sun Jun 5 10:33:20 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Young X-Patchwork-Id: 9155349 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 1511460574 for ; Sun, 5 Jun 2016 10:33:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 06D8427B13 for ; Sun, 5 Jun 2016 10:33:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EF76B281DB; Sun, 5 Jun 2016 10:33:42 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, T_DKIM_INVALID autolearn=no version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 27A1E27B13 for ; Sun, 5 Jun 2016 10:33:41 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 918C2261294; Sun, 5 Jun 2016 12:33:39 +0200 (CEST) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 40EB226512D; Sun, 5 Jun 2016 12:33:31 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 04F2E26513A; Sun, 5 Jun 2016 12:33:28 +0200 (CEST) Received: from mail-wm0-f65.google.com (mail-wm0-f65.google.com [74.125.82.65]) by alsa0.perex.cz (Postfix) with ESMTP id B2858261294 for ; Sun, 5 Jun 2016 12:33:21 +0200 (CEST) Received: by mail-wm0-f65.google.com with SMTP id m124so8435538wme.3 for ; Sun, 05 Jun 2016 03:33:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=subject:to:references:cc:from:message-id:date:user-agent :mime-version:in-reply-to; bh=ErruAjTBX+p+NIJ4SxOTZ3PmnSgRD6rPov7PS1NqM6U=; b=cWhsGstxroT/WGi5HbxRjAxHgbKNpIlTnYsFxJGN5ik+pMcrVb7wCVxMgF0SrcJbXc iEAMwhLDiG4SjSJobSvase4dDQ0b0f+EAw6trdM1OAZ/9mafG7wq73T0ejQ4RLSnlI2Y owWfWDe8ra/hqUG2U57VgnOpA1QyUpPGSodiJrs1UqQFT9WwlYBzI2U39o/4Adfxhm/+ L075exiIMenBRlTgfpHcAYg5pUH1xVnx5F6s9aXxuEqzbzULR6eWuNuZyKrSxTrRvBCQ ixcSrVLfZlLdlrscNWHp8Cy9ie13TCW7NTCn6s9X/RRblYMRBDd/k8Q8QTlTuZrKSP3o 7VpA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:subject:to:references:cc:from:message-id:date :user-agent:mime-version:in-reply-to; bh=ErruAjTBX+p+NIJ4SxOTZ3PmnSgRD6rPov7PS1NqM6U=; b=OyQRASaz45dexU6Yvq6g6UagPFHwYfMFM21aN5qCJj+EQgsNGKCaDONedrpktm5v7B PIEVVIOLij6SWFInDjLbAQVrM3RlLL7WbYKoOttECibZD73v8+HKDupA1/hVoitOV6PI EM7n7D4yImibzuhjf0NMoqeK5Mqsc+9yXtSku28FSVxxVRyw9BJ87ifW0ByPc3zPRDDv FuTcdX++TTeNlUjqkDQ9Gm+czdINkdrOug2q+TWdy5Qtkdav4l+tfV0kdwOJC1v5WDQy PgpBJrHpJBqTWvPFCShQQbPUD8TnAPJxEdOleYCxWM6QntB11W6VMIRs8Et0Bm3ZaKAp NCgA== X-Gm-Message-State: ALyK8tJpuHCL9WkOSLUFlJzzRaNUQ88YitbzKCgLZsRDE/Cm/+YbhfZc05El3LNCnDeyqw== X-Received: by 10.194.172.36 with SMTP id az4mr3750771wjc.114.1465122801347; Sun, 05 Jun 2016 03:33:21 -0700 (PDT) Received: from [192.168.11.11] (175.64.199.146.dyn.plus.net. [146.199.64.175]) by smtp.googlemail.com with ESMTPSA id b207sm8694318wmb.0.2016.06.05.03.33.20 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 05 Jun 2016 03:33:20 -0700 (PDT) To: Raymond Yau References: <5752A005.2050309@gmail.com> From: Alan Young Message-ID: <5753FFF0.3050200@gmail.com> Date: Sun, 5 Jun 2016 11:33:20 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.6.0 MIME-Version: 1.0 In-Reply-To: X-Content-Filtered-By: Mailman/MimeDel 2.1.14 Cc: alsa-devel@alsa-project.org Subject: Re: [alsa-devel] Improving status timestamp accuracy X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP On 05/06/16 02:14, Raymond Yau wrote: > the point only increment in DMA brust size , so it is not sample accurate > > https://git.kernel.org/cgit/linux/kernel/git/tiwai/sound.git/tree/include/linux/dmaengine.h > > |* @DMA_RESIDUE_GRANULARITY_BURST: |Residue is updated after each > transferred > |* burst. This is typically only supported if the hardware has a > progress * register of some sort (E.g. a register with the current > read/write address * or a register with the amount of > bursts/beats/bytes that have been * transferred or still need to be > transferred).| > || > |if the driver point callback does not read from hardware register , it > should use | > || > | > |DMA_RESIDUE_GRANULARITY_DESCRIPTOR: Residue reporting is not support. > The * DMA channel is only able to tell whether a descriptor has been > completed or * not, which means residue reporting is not supported by > this channel. The * residue field of the dma_tx_state field will > always be 0.| > | Yes, I understand that. And that is exactly my point. Because of this a pcm_status() result is only accurate to a granularity of period in most cases. In fact, some drivers, for example imx sdma, declare DMA_RESIDUE_GRANULARITY_BURST accuracy because sometimes they may have such an accuracy but in practice, at least for audio, they only actually achieve period accuracy. Regardless of what value of DMA_RESIDUE_GRANULARITY_xxx that a driver claims to support, it is not really defined how fine a burst might be. So the end result is, from the point of view of audio, that the resulting position obtained by the pointer() call is pretty inaccurate. Hence my proposal to attempt to improve the accuracy of the pcm_status() result given the above constraints. The following patch gives an idea of what I am considering: u64 audio_frames, audio_nsecs; @@ -252,17 +253,23 @@ static void update_audio_tstamp(struct snd_pcm_substream *substream, * add delay only if requested */ - audio_frames = runtime->hw_ptr_wrap + runtime->status->hw_ptr; + if (adjust_existing_audio_tstamp && runtime->status->tstamp->tv_sec) { + struct timespec delta = + timespec_sub(*curr_tstamp, runtime->status->tstamp); + *audio_tstamp = timespec_add(*audio_tstamp, delta); + } else { + audio_frames = runtime->hw_ptr_wrap + runtime->status->hw_ptr; - if (runtime->audio_tstamp_config.report_delay) { - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - audio_frames -= runtime->delay; - else - audio_frames += runtime->delay; + if (runtime->audio_tstamp_config.report_delay) { + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + audio_frames -= runtime->delay; + else + audio_frames += runtime->delay; + } + audio_nsecs = div_u64(audio_frames * 1000000000LL, + runtime->rate); + *audio_tstamp = ns_to_timespec(audio_nsecs); } - audio_nsecs = div_u64(audio_frames * 1000000000LL, - runtime->rate); - *audio_tstamp = ns_to_timespec(audio_nsecs); } runtime->status->audio_tstamp = *audio_tstamp; runtime->status->tstamp = *curr_tstamp; @@ -454,7 +461,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, no_delta_check: if (runtime->status->hw_ptr == new_hw_ptr) { - update_audio_tstamp(substream, &curr_tstamp, &audio_tstamp); + update_audio_tstamp(substream, &curr_tstamp, &audio_tstamp, !in_interrupt); return 0; } @@ -479,7 +486,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, runtime->hw_ptr_wrap += runtime->boundary; } - update_audio_tstamp(substream, &curr_tstamp, &audio_tstamp); + update_audio_tstamp(substream, &curr_tstamp, &audio_tstamp, !in_interrupt); return snd_pcm_update_state(substream, runtime); } diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 6b5a811..ea5b525 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -234,7 +234,8 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream, static void update_audio_tstamp(struct snd_pcm_substream *substream, struct timespec *curr_tstamp, - struct timespec *audio_tstamp) + struct timespec *audio_tstamp, + unsigned int adjust_existing_audio_tstamp) { struct snd_pcm_runtime *runtime = substream->runtime;