From patchwork Thu Nov 15 18:13:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 151235 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp7327851ljp; Thu, 15 Nov 2018 10:15:37 -0800 (PST) X-Google-Smtp-Source: AJdET5eNyHbGPQ8/YI326yVBJbhV6QejnasuaeACejX8VmQ2nZripoMgo/c0S+9V87lmKNHCoRNC X-Received: by 2002:a17:902:33c1:: with SMTP id b59-v6mr7188888plc.71.1542305737656; Thu, 15 Nov 2018 10:15:37 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542305737; cv=none; d=google.com; s=arc-20160816; b=p14ZVinUB5hK5U7wch25oIldayHo85PsZ9yJusEKk4tcOQI5D5gNpAodNxi924bSGJ 9X9Kn7ytMBhCUo/CgINs4tBdgwS9hzllm3dPCPSxxRLB14v483TIbhAnxRRhqjpCfRWn 2P7CMkrM6Wrbyces3P6ID6eYnVfMUiUiC2XrFxCy9G2S0ZKcYUsqPwiBV8YjKdrY/Wmm TH1KdV5XjOIsPoBtpSUvwgD6lwv4vA7q2+g4fJftf1LTg+HZdrsMyLUnVDzBhit20Dpc JRbqlMkbJOrxdkhwzSh6qyO7YXQqXwwEDjeR44xl54M8ZZWR1PlqeFtTEVDfR01kZA5d wvZw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=avO3Jb5XTMv2tnrPkaTW5Kc01HF/m3+otreEVZeHHFk=; b=meNh+u4mRZnfeDMUlXecTgkZKTEVYbQfG/Abc7cv8O0iSIb0i4NMqackXvtjfftZgs EUjUhPItgEDEHz+4bw7yMR6vgowZZtK4C4C0O7vgP8gjEHe5VdCcgHWpBDVDAW45Z60J 3PLweRThKcS0WPiHZWQupqpcaGMI3YYfjBJNDzkTaS7GU8pmccmoIrU2VKV10vtRTvFo uCv9F57Ex+Ib5pw0v037B2yqa5hjjJ6hMC96CbJLwo/8PKoSEP6wYytryFZeOXX5f2yt H5VHQT441y8Guru96C5VuyI2dGB3JFe5GFJ1y5wMuJXChIOIePEptDA9jTpZfciCPC36 0SzQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=VTDD3gwh; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y3-v6si27465221pfe.42.2018.11.15.10.15.37; Thu, 15 Nov 2018 10:15:37 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=VTDD3gwh; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388865AbeKPEY1 (ORCPT + 6 others); Thu, 15 Nov 2018 23:24:27 -0500 Received: from mail-wr1-f65.google.com ([209.85.221.65]:36822 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388861AbeKPEY0 (ORCPT ); Thu, 15 Nov 2018 23:24:26 -0500 Received: by mail-wr1-f65.google.com with SMTP id z13-v6so22244798wrs.3 for ; Thu, 15 Nov 2018 10:15:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=avO3Jb5XTMv2tnrPkaTW5Kc01HF/m3+otreEVZeHHFk=; b=VTDD3gwhgDIPz5nedhd5G093CeMP5MBrm1dIUNevSVuqkvu9dAj1O1Jgm2m1UQoZId WiiTINybGZ58hv2HZ2GWUPIQI5aWUN8B/02y9504NHQa1YmsC86NdhciT/s2aZp/m02l C4YPO9PAY6yaB3fwN1evcMZR0acfLeD8D9JBY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=avO3Jb5XTMv2tnrPkaTW5Kc01HF/m3+otreEVZeHHFk=; b=sciRbAAKvuKsih4cNZfBCUlz90WbkV3B62odV2ukE7gsRejR0zLReopsDsYdi7xI+p mUKVR6sYsFRKcDgpbHZHJlxlynlPOsAhBJinU1IDYJxTmRGtJE4Mme0dfmh6wtZoy5pA Bp6/SGWfmV8LkkoThR+nu9gszgipul3zPcYZWlWeTfguzG5uhD2dgRJS8CzINq+THNUU dDn4kFlo72S8Ybw68jAvtE3uW4m2jfx2hU6f2P+TgXCieUrkLJ3/zboz4+Fr8ILeKNPm TXeIkhHzL9jlUHxWwt6xMOXCIW/5d9AzxLD+iMlIzb4aPofAD0cw0bDJOxVff8tESYdO q6zA== X-Gm-Message-State: AGRZ1gKq/BRvvKaUXERGWo6QWz49vbeXx1iWMg1suYWzNZmfn/5HjtIn Ai4xQ/35AhT2K5Ol62KPfI/iuQ== X-Received: by 2002:a5d:4b8b:: with SMTP id b11-v6mr6964115wrt.72.1542305732679; Thu, 15 Nov 2018 10:15:32 -0800 (PST) Received: from localhost.localdomain (cpc90716-aztw32-2-0-cust92.18-1.cable.virginm.net. [86.26.100.93]) by smtp.gmail.com with ESMTPSA id r76-v6sm20934737wmb.21.2018.11.15.10.15.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 15 Nov 2018 10:15:31 -0800 (PST) From: Srinivas Kandagatla To: broonie@kernel.org, vkoul@kernel.org Cc: alsa-devel@alsa-project.org, robh+dt@kernel.org, linux-kernel@vger.kernel.org, bgoswami@codeaurora.org, rohitkr@codeaurora.org, lgirdwood@gmail.com, tiwai@suse.com, devicetree@vger.kernel.org, srini@kernel.org, Srinivas Kandagatla Subject: [PATCH v3 3/5] ASoC: q6asm-dai: dt-bindings: Add support to compress dais Date: Thu, 15 Nov 2018 18:13:22 +0000 Message-Id: <20181115181324.26784-4-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181115181324.26784-1-srinivas.kandagatla@linaro.org> References: <20181115181324.26784-1-srinivas.kandagatla@linaro.org> MIME-Version: 1.0 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org This patch adds board specific bindings required for dais, In particular for compressed dais and dai direction. Board specific setup involves setting up some of dais as compressed dais and also specify direction of any dai. Some of the dais might only support capture/playback depending on the board level wiring. These two new dt properties will allow such flexibilty at board level dts. Signed-off-by: Srinivas Kandagatla Reviewed-by: Vinod Koul Reviewed-by: Rob Herring --- .../devicetree/bindings/sound/qcom,q6asm.txt | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) -- 2.19.1 diff --git a/Documentation/devicetree/bindings/sound/qcom,q6asm.txt b/Documentation/devicetree/bindings/sound/qcom,q6asm.txt index f9c7bd8c1bc0..9f5378c51686 100644 --- a/Documentation/devicetree/bindings/sound/qcom,q6asm.txt +++ b/Documentation/devicetree/bindings/sound/qcom,q6asm.txt @@ -27,6 +27,28 @@ used by the apr service device. Value type: Definition: Must be 1 +== ASM DAI is subnode of "dais" and represent a dai, it includes board specific +configuration of each dai. Must contain the following properties. + +- reg + Usage: required + Value type: + Definition: Must be dai id + +- direction: + Usage: Required for Compress offload dais + Value type: + Definition: Specifies the direction of the dai stream + 0 for both tx and rx + 1 for only tx (Capture/Encode) + 2 for only rx (Playback/Decode) + +- is-compress-dai: + Usage: Required for Compress offload dais + Value type: + Definition: present for Compress offload dais + + = EXAMPLE q6asm@7 { @@ -35,5 +57,10 @@ q6asm@7 { q6asmdai: dais { compatible = "qcom,q6asm-dais"; #sound-dai-cells = <1>; + mm@0 { + reg = <0>; + direction = <2>; + is-compress-dai; + }; }; }; From patchwork Thu Nov 15 18:13:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 151237 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp7327914ljp; Thu, 15 Nov 2018 10:15:40 -0800 (PST) X-Google-Smtp-Source: AJdET5dd5vowNghSfecttKfjUgDDu/OJFu9VnAxiRjoBwlWDFbNoioc5OXNhZjr1Uq0RP9zCeYhC X-Received: by 2002:a17:902:45:: with SMTP id 63mr4758229pla.272.1542305740557; Thu, 15 Nov 2018 10:15:40 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542305740; cv=none; d=google.com; s=arc-20160816; b=tUB+yR0YLaqPURjaSp4z4+acYcgQBwmKVl8jx5agU1smB6xoiyXc0tGEsLyjzSWfkj oyXQ/G0PADITUjzfgIHJPF2qFVMIaXUeYj5EGqkthXys+P5mTMpK4wvpLrcR74BuTe5p SRVAbhbVRyqgS6zsN0Xt3OWlWHRUaDljE+KR7qa3WeDTFQ+aMwmHkQ73yx8o0BYfDp7r 5deTlW9uIZRL7EOgejjR9DhLbXU2okssunKNgyV7+Kaml651hKLNXhpIKVXNy1uSQhzN haA5fNyM/3CvBdnfEmRPusBhDgDOgPVMDrd3AAF4C9n3kcWVUOmW86sU+vkIDgCXSYO8 RBSw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=NW69DdTSPNYV0ujgweJZqtp1aIdzG5jy5Fk3t4Z1YFg=; b=Gg6JkKVzsYmoy/4l7ip6TJf7ZUaC5m6xdCzrWEomQnThXb8PbznfoqqyrMRco+Nbrx C89oUtrdU418alRhJOKBadaoY1CjSt0ZMvF0WxUL4GrPXJsszQdLj4Frg9BaPc+NYEn2 vd4Kp+DeEAC7ZBSwcjqVnTxZDqD6dDapJmKW16KMQIBn6VuekiVsVf1sI2HR7BFup+xj T4aYKezpTflMMcpK9n/yA/VNuYqrpAFFys4hg7Gh4S9x0ckS/hzYk7DH6ZQOsRel5u1K arEqX5hU30nhUih8H0SpOGmVSnRy/Gw7BmK66lkAmzNOFsk7jZRLGRAKIuJiw7aKHhPe QWVw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=VrMtNYes; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id z21-v6si27859476plo.89.2018.11.15.10.15.40; Thu, 15 Nov 2018 10:15:40 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=VrMtNYes; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388454AbeKPEYb (ORCPT + 6 others); Thu, 15 Nov 2018 23:24:31 -0500 Received: from mail-wm1-f65.google.com ([209.85.128.65]:50397 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388919AbeKPEYa (ORCPT ); Thu, 15 Nov 2018 23:24:30 -0500 Received: by mail-wm1-f65.google.com with SMTP id 124-v6so19868459wmw.0 for ; Thu, 15 Nov 2018 10:15:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=NW69DdTSPNYV0ujgweJZqtp1aIdzG5jy5Fk3t4Z1YFg=; b=VrMtNYesRaKrjG6W0zv+D9vNBMgTEzVIgcW0MudBIhxp/+RX1Qpvdq+NjH1xMD4xhl D6384/5hwMteNHeQxsGPDOVvkHdKJ3NjJn/ZwoHXy1f8Qm3U6yp7ig5xUPmBQZIcX94b S24desv9gYRbGvC1V04Ou/ez3k7I5gs5kbZ9k= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=NW69DdTSPNYV0ujgweJZqtp1aIdzG5jy5Fk3t4Z1YFg=; b=ZUGgDrdYsPVkq3CaHtVwH6ExcVY9VKK/t0AkpVvKsQOqYgTFiRbELeZUZ/6L2sjcwv RH1TEhiLzhPPq/AUV1suxyfbnssYRlBbRsJCjy7qx42DafmWWqZce7gmv9tGiFTNwB/c SP5CVQuEYtIt5zLYgxQ4mFgaX924u4rrXuLgpmI2XFZUuvoUhqMvgkFv0c/C+qBfb7FS TlAz2VE6wMgYIyrJHH5lej7IHRYKxUcdk+ITO/X1OKHWAJG2k+MCyHv3AS4WAJJdUPkD uuOfkNYs0FqQuUHvodjXL35kKSvCckpu7lvhRR2Yo7xxOrjPjt8pKoFfumxWcFjqJoxc ISFQ== X-Gm-Message-State: AGRZ1gKB2l0oCqglD3Yo3iEzukuCN69p6QJtxCFBHn6jQBbSzJhPtbpZ npyz6iRFgLilLz/dcbRdR3cQN3v5Hw8= X-Received: by 2002:a1c:ef19:: with SMTP id n25-v6mr6051385wmh.12.1542305735456; Thu, 15 Nov 2018 10:15:35 -0800 (PST) Received: from localhost.localdomain (cpc90716-aztw32-2-0-cust92.18-1.cable.virginm.net. [86.26.100.93]) by smtp.gmail.com with ESMTPSA id r76-v6sm20934737wmb.21.2018.11.15.10.15.34 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 15 Nov 2018 10:15:34 -0800 (PST) From: Srinivas Kandagatla To: broonie@kernel.org, vkoul@kernel.org Cc: alsa-devel@alsa-project.org, robh+dt@kernel.org, linux-kernel@vger.kernel.org, bgoswami@codeaurora.org, rohitkr@codeaurora.org, lgirdwood@gmail.com, tiwai@suse.com, devicetree@vger.kernel.org, srini@kernel.org, Srinivas Kandagatla Subject: [PATCH v3 5/5] ASoC: qdsp6: q6asm-dai: Add support to compress offload Date: Thu, 15 Nov 2018 18:13:24 +0000 Message-Id: <20181115181324.26784-6-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181115181324.26784-1-srinivas.kandagatla@linaro.org> References: <20181115181324.26784-1-srinivas.kandagatla@linaro.org> MIME-Version: 1.0 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org This patch adds MP3 playback support in q6asm dais, adding other codec support should be pretty trivial. Signed-off-by: Srinivas Kandagatla --- sound/soc/qcom/Kconfig | 1 + sound/soc/qcom/qdsp6/q6asm-dai.c | 372 ++++++++++++++++++++++++++++++- 2 files changed, 372 insertions(+), 1 deletion(-) -- 2.19.1 diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 2a4c912d1e48..ebf991bb546c 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -66,6 +66,7 @@ config SND_SOC_QDSP6_ASM tristate config SND_SOC_QDSP6_ASM_DAI + select SND_SOC_COMPRESS tristate config SND_SOC_QDSP6 diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index 86115de5c1b2..5b986b74dd36 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include #include @@ -30,6 +32,15 @@ #define CAPTURE_MIN_PERIOD_SIZE 320 #define SID_MASK_DEFAULT 0xF +/* Default values used if user space does not set */ +#define COMPR_PLAYBACK_MIN_FRAGMENT_SIZE (8 * 1024) +#define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024) +#define COMPR_PLAYBACK_MIN_NUM_FRAGMENTS (4) +#define COMPR_PLAYBACK_MAX_NUM_FRAGMENTS (16 * 4) +#define Q6ASM_DAI_TX_RX 0 +#define Q6ASM_DAI_TX 1 +#define Q6ASM_DAI_RX 2 + enum stream_state { Q6ASM_STREAM_IDLE = 0, Q6ASM_STREAM_STOPPED, @@ -38,11 +49,18 @@ enum stream_state { struct q6asm_dai_rtd { struct snd_pcm_substream *substream; + struct snd_compr_stream *cstream; + struct snd_compr_params codec_param; + struct snd_dma_buffer dma_buffer; + spinlock_t lock; phys_addr_t phys; unsigned int pcm_size; unsigned int pcm_count; unsigned int pcm_irq_pos; /* IRQ position */ unsigned int periods; + unsigned int bytes_sent; + unsigned int bytes_received; + unsigned int copied_total; uint16_t bits_per_sample; uint16_t source; /* Encoding source bit mask */ struct audio_client *audio_client; @@ -137,6 +155,21 @@ static struct snd_pcm_hw_constraint_list constraints_sample_rates = { .mask = 0, }; +static const struct snd_compr_codec_caps q6asm_compr_caps = { + .num_descriptors = 1, + .descriptor[0].max_ch = 2, + .descriptor[0].sample_rates = { 8000, 11025, 12000, 16000, 22050, + 24000, 32000, 44100, 48000, 88200, + 96000, 176400, 192000 }, + .descriptor[0].num_sample_rates = 13, + .descriptor[0].bit_rate[0] = 320, + .descriptor[0].bit_rate[1] = 128, + .descriptor[0].num_bitrates = 2, + .descriptor[0].profiles = 0, + .descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO, + .descriptor[0].formats = 0, +}; + static void event_handler(uint32_t opcode, uint32_t token, uint32_t *payload, void *priv) { @@ -460,6 +493,306 @@ static struct snd_pcm_ops q6asm_dai_ops = { .mmap = q6asm_dai_mmap, }; +static void compress_event_handler(uint32_t opcode, uint32_t token, + uint32_t *payload, void *priv) +{ + struct q6asm_dai_rtd *prtd = priv; + struct snd_compr_stream *substream = prtd->cstream; + unsigned long flags; + uint64_t avail; + + switch (opcode) { + case ASM_CLIENT_EVENT_CMD_RUN_DONE: + spin_lock_irqsave(&prtd->lock, flags); + if (!prtd->bytes_sent) { + q6asm_write_async(prtd->audio_client, prtd->pcm_count, + 0, 0, NO_TIMESTAMP); + prtd->bytes_sent += prtd->pcm_count; + } + + spin_unlock_irqrestore(&prtd->lock, flags); + break; + + case ASM_CLIENT_EVENT_CMD_EOS_DONE: + prtd->state = Q6ASM_STREAM_STOPPED; + break; + + case ASM_CLIENT_EVENT_DATA_WRITE_DONE: + spin_lock_irqsave(&prtd->lock, flags); + + prtd->copied_total += prtd->pcm_count; + snd_compr_fragment_elapsed(substream); + + if (prtd->state != Q6ASM_STREAM_RUNNING) { + spin_unlock_irqrestore(&prtd->lock, flags); + break; + } + + avail = prtd->bytes_received - prtd->bytes_sent; + + if (avail >= prtd->pcm_count) { + q6asm_write_async(prtd->audio_client, + prtd->pcm_count, 0, 0, NO_TIMESTAMP); + prtd->bytes_sent += prtd->pcm_count; + } + + spin_unlock_irqrestore(&prtd->lock, flags); + break; + + default: + break; + } +} + +static int q6asm_dai_compr_open(struct snd_compr_stream *stream) +{ + struct snd_soc_pcm_runtime *rtd = stream->private_data; + struct snd_soc_component *c = snd_soc_rtdcom_lookup(rtd, DRV_NAME); + struct snd_compr_runtime *runtime = stream->runtime; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct q6asm_dai_data *pdata; + struct device *dev = c->dev; + struct q6asm_dai_rtd *prtd; + int stream_id, size, ret; + + stream_id = cpu_dai->driver->id; + pdata = snd_soc_component_get_drvdata(c); + if (!pdata) { + dev_err(dev, "Drv data not found ..\n"); + return -EINVAL; + } + + prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); + if (!prtd) + return -ENOMEM; + + prtd->cstream = stream; + prtd->audio_client = q6asm_audio_client_alloc(dev, + (q6asm_cb)compress_event_handler, + prtd, stream_id, LEGACY_PCM_MODE); + if (!prtd->audio_client) { + dev_err(dev, "Could not allocate memory\n"); + kfree(prtd); + return -ENOMEM; + } + + size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE * + COMPR_PLAYBACK_MAX_NUM_FRAGMENTS; + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, + &prtd->dma_buffer); + if (ret) { + dev_err(dev, "Cannot allocate buffer(s)\n"); + return ret; + } + + if (pdata->sid < 0) + prtd->phys = prtd->dma_buffer.addr; + else + prtd->phys = prtd->dma_buffer.addr | (pdata->sid << 32); + + snd_compr_set_runtime_buffer(stream, &prtd->dma_buffer); + spin_lock_init(&prtd->lock); + runtime->private_data = prtd; + + return 0; +} + +static int q6asm_dai_compr_free(struct snd_compr_stream *stream) +{ + struct snd_compr_runtime *runtime = stream->runtime; + struct q6asm_dai_rtd *prtd = runtime->private_data; + struct snd_soc_pcm_runtime *rtd = stream->private_data; + + if (prtd->audio_client) { + if (prtd->state) + q6asm_cmd(prtd->audio_client, CMD_CLOSE); + + snd_dma_free_pages(&prtd->dma_buffer); + q6asm_unmap_memory_regions(stream->direction, + prtd->audio_client); + q6asm_audio_client_free(prtd->audio_client); + prtd->audio_client = NULL; + } + q6routing_stream_close(rtd->dai_link->id, stream->direction); + kfree(prtd); + + return 0; +} + +static int q6asm_dai_compr_set_params(struct snd_compr_stream *stream, + struct snd_compr_params *params) +{ + struct snd_compr_runtime *runtime = stream->runtime; + struct q6asm_dai_rtd *prtd = runtime->private_data; + struct snd_soc_pcm_runtime *rtd = stream->private_data; + struct snd_soc_component *c = snd_soc_rtdcom_lookup(rtd, DRV_NAME); + int dir = stream->direction; + struct q6asm_dai_data *pdata; + struct device *dev = c->dev; + int ret; + + memcpy(&prtd->codec_param, params, sizeof(*params)); + + pdata = snd_soc_component_get_drvdata(c); + if (!pdata) + return -EINVAL; + + if (!prtd || !prtd->audio_client) { + dev_err(dev, "private data null or audio client freed\n"); + return -EINVAL; + } + + prtd->periods = runtime->fragments; + prtd->pcm_count = runtime->fragment_size; + prtd->pcm_size = runtime->fragments * runtime->fragment_size; + prtd->bits_per_sample = 16; + if (dir == SND_COMPRESS_PLAYBACK) { + ret = q6asm_open_write(prtd->audio_client, params->codec.id, + prtd->bits_per_sample); + + if (ret < 0) { + dev_err(dev, "q6asm_open_write failed\n"); + q6asm_audio_client_free(prtd->audio_client); + prtd->audio_client = NULL; + return ret; + } + } + + prtd->session_id = q6asm_get_session_id(prtd->audio_client); + ret = q6routing_stream_open(rtd->dai_link->id, LEGACY_PCM_MODE, + prtd->session_id, dir); + if (ret) { + dev_err(dev, "Stream reg failed ret:%d\n", ret); + return ret; + } + + ret = q6asm_map_memory_regions(dir, prtd->audio_client, prtd->phys, + (prtd->pcm_size / prtd->periods), + prtd->periods); + + if (ret < 0) { + dev_err(dev, "Buffer Mapping failed ret:%d\n", ret); + return -ENOMEM; + } + + prtd->state = Q6ASM_STREAM_RUNNING; + + return 0; +} + +static int q6asm_dai_compr_trigger(struct snd_compr_stream *stream, int cmd) +{ + struct snd_compr_runtime *runtime = stream->runtime; + struct q6asm_dai_rtd *prtd = runtime->private_data; + int ret = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ret = q6asm_run_nowait(prtd->audio_client, 0, 0, 0); + break; + case SNDRV_PCM_TRIGGER_STOP: + prtd->state = Q6ASM_STREAM_STOPPED; + ret = q6asm_cmd_nowait(prtd->audio_client, CMD_EOS); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ret = q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static int q6asm_dai_compr_pointer(struct snd_compr_stream *stream, + struct snd_compr_tstamp *tstamp) +{ + struct snd_compr_runtime *runtime = stream->runtime; + struct q6asm_dai_rtd *prtd = runtime->private_data; + unsigned long flags; + + spin_lock_irqsave(&prtd->lock, flags); + + tstamp->copied_total = prtd->copied_total; + tstamp->byte_offset = prtd->copied_total % prtd->pcm_size; + + spin_unlock_irqrestore(&prtd->lock, flags); + + return 0; +} + +static int q6asm_dai_compr_ack(struct snd_compr_stream *stream, + size_t count) +{ + struct snd_compr_runtime *runtime = stream->runtime; + struct q6asm_dai_rtd *prtd = runtime->private_data; + unsigned long flags; + + spin_lock_irqsave(&prtd->lock, flags); + prtd->bytes_received += count; + spin_unlock_irqrestore(&prtd->lock, flags); + + return count; +} + +static int q6asm_dai_compr_mmap(struct snd_compr_stream *stream, + struct vm_area_struct *vma) +{ + struct snd_compr_runtime *runtime = stream->runtime; + struct q6asm_dai_rtd *prtd = runtime->private_data; + struct snd_soc_pcm_runtime *rtd = stream->private_data; + struct snd_soc_component *c = snd_soc_rtdcom_lookup(rtd, DRV_NAME); + struct device *dev = c->dev; + + return dma_mmap_coherent(dev, vma, + prtd->dma_buffer.area, prtd->dma_buffer.addr, + prtd->dma_buffer.bytes); +} + +static int q6asm_dai_compr_get_caps(struct snd_compr_stream *stream, + struct snd_compr_caps *caps) +{ + caps->direction = SND_COMPRESS_PLAYBACK; + caps->min_fragment_size = COMPR_PLAYBACK_MIN_FRAGMENT_SIZE; + caps->max_fragment_size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE; + caps->min_fragments = COMPR_PLAYBACK_MIN_NUM_FRAGMENTS; + caps->max_fragments = COMPR_PLAYBACK_MAX_NUM_FRAGMENTS; + caps->num_codecs = 1; + caps->codecs[0] = SND_AUDIOCODEC_MP3; + + return 0; +} + +static int q6asm_dai_compr_get_codec_caps(struct snd_compr_stream *stream, + struct snd_compr_codec_caps *codec) +{ + switch (codec->codec) { + case SND_AUDIOCODEC_MP3: + *codec = q6asm_compr_caps; + break; + default: + break; + } + + return 0; +} + +static struct snd_compr_ops q6asm_dai_compr_ops = { + .open = q6asm_dai_compr_open, + .free = q6asm_dai_compr_free, + .set_params = q6asm_dai_compr_set_params, + .pointer = q6asm_dai_compr_pointer, + .trigger = q6asm_dai_compr_trigger, + .get_caps = q6asm_dai_compr_get_caps, + .get_codec_caps = q6asm_dai_compr_get_codec_caps, + .mmap = q6asm_dai_compr_mmap, + .ack = q6asm_dai_compr_ack, +}; + static int q6asm_dai_pcm_new(struct snd_soc_pcm_runtime *rtd) { struct snd_pcm_substream *psubstream, *csubstream; @@ -515,7 +848,7 @@ static const struct snd_soc_component_driver q6asm_fe_dai_component = { .ops = &q6asm_dai_ops, .pcm_new = q6asm_dai_pcm_new, .pcm_free = q6asm_dai_pcm_free, - + .compr_ops = &q6asm_dai_compr_ops, }; static struct snd_soc_dai_driver q6asm_fe_dais[] = { @@ -529,6 +862,41 @@ static struct snd_soc_dai_driver q6asm_fe_dais[] = { Q6ASM_FEDAI_DRIVER(8), }; +static int of_q6asm_parse_dai_data(struct device *dev, + struct q6asm_dai_data *pdata) +{ + static struct snd_soc_dai_driver *dai_drv; + struct snd_soc_pcm_stream empty_stream; + struct device_node *node; + int ret, id, dir; + + memset(&empty_stream, 0, sizeof(empty_stream)); + + for_each_child_of_node(dev->of_node, node) { + ret = of_property_read_u32(node, "reg", &id); + if (ret || id > MAX_SESSIONS || id < 0) { + dev_err(dev, "valid dai id not found:%d\n", ret); + continue; + } + + dai_drv = &q6asm_fe_dais[id]; + + ret = of_property_read_u32(node, "direction", &dir); + if (ret) + continue; + + if (dir == Q6ASM_DAI_RX) + dai_drv->capture = empty_stream; + else if (dir == Q6ASM_DAI_TX) + dai_drv->playback = empty_stream; + + if (of_property_read_bool(node, "is-compress-dai")) + dai_drv->compress_new = snd_soc_new_compress; + } + + return 0; +} + static int q6asm_dai_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -549,6 +917,8 @@ static int q6asm_dai_probe(struct platform_device *pdev) dev_set_drvdata(dev, pdata); + of_q6asm_parse_dai_data(dev, pdata); + return devm_snd_soc_register_component(dev, &q6asm_fe_dai_component, q6asm_fe_dais, ARRAY_SIZE(q6asm_fe_dais));