From patchwork Thu Jan 20 14:37:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Daniel Baluta (OSS)" X-Patchwork-Id: 12718735 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6A872C433EF for ; Thu, 20 Jan 2022 14:39:26 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 945EC2EDD; Thu, 20 Jan 2022 15:38:34 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 945EC2EDD DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1642689564; bh=yP7tXJBVa0rwC0JMFSAQMSL7zlcXlvQkKfEcr5S1Jw0=; h=From:To:Subject:Date:Cc:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From; b=C3Hdb/Kn604uaaYZtXkae8d7/FkKo7yXlsRSA5IufZXWfTl5izEvKwns3fmexrexr 7KG+DF47zdatOzHYxxxNfNixO4PrrGdieQZHvogEK5ZRlE4fuhFwpBMuD4GsnfBWNW RP5T+D29aP00vgidoUFejPOWPlu5lA6oSkWkdKwU= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 04CB1F80134; Thu, 20 Jan 2022 15:38:13 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id B2D7BF800F2; Thu, 20 Jan 2022 15:38:11 +0100 (CET) Received: from EUR05-AM6-obe.outbound.protection.outlook.com (mail-am6eur05on2060b.outbound.protection.outlook.com [IPv6:2a01:111:f400:7e1b::60b]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 8698AF800F2 for ; Thu, 20 Jan 2022 15:38:01 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 8698AF800F2 Authentication-Results: alsa1.perex.cz; dkim=pass (1024-bit key) header.d=NXP1.onmicrosoft.com header.i=@NXP1.onmicrosoft.com header.b="kHPFFKV9" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=JlnNjWtks9otblEAX9hnfd8M4sDdokpDVm5JZ4UtiuqgfS7OufkkSYP83G1KVf+Cqssb2Rkbt+56yEyryXnu3mactzG5EFf5m0QOoJ6dTW5PDL3RwA4owFYIGZ32UMuDDq/xdOVtf4MTorFQdt1TUy+5Hl+UojXxlk9aV6YAZT76sEIte2oT+EeuGii8z9IF7e+QBkyI69Uehyp//rNhl7LlabXJTHCRdwWzXPE5bkq7pnZ/fChtauON4BWaVFOLMUOGlDKcim2VjUm5nJTBjBL21lZUtmJVm2Zhz13ALyLHMxahFtMCItZM05smK+RGKsE2LHHetfLL1baY5t1O7w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=iQaPSJdDi/c7ikxWVSunY8RlwC/j4O7iaF/624+FKSM=; b=GckOevw4moPGDddDjYi05UWI/ixCFpTgtLa4ag97OBnKotvfy/5DQex8nW/SgKNQnkuEoYDRdHeoebpnBr7zBpxq83Muy2yl7taqUMJpcx/8EyzAljeT7EevNHpBTe5yYJcr4+PDPY63xLC5JVNNnzgJE4y7FogazIyc6InR2hgVIqkzFXxxr7UmlBjF97SOe0oEprxP6eWoyjFofVQKZnZniKB9blKRdEUiwXHkfOm2kc1kDRQL5st/1wY61MABwDlSwAlHW/Ok79PPYgFnFXqY3lxQJ9NbsTT9wPm3oWJ+W0B6EXeCA31tlYKJneSpf7Dx/5b1ex0079soojUHoQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=NXP1.onmicrosoft.com; s=selector2-NXP1-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=iQaPSJdDi/c7ikxWVSunY8RlwC/j4O7iaF/624+FKSM=; b=kHPFFKV92jvL2tewGYnjz2HGXmYday8zAriWp+KrWrhOT5INBMDTMXxvWUA94jq2YLu5RsAk9kC0oZnmjRVMHni3ed3JgkLsxF1mu+6aFfzzIiuj5bhvgfE48sjNjxpuf1mzgjusYc4vQ3w4vAzNwpKuYnttjgtxQUL39E5DHK0= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=oss.nxp.com; Received: from VI1PR04MB5151.eurprd04.prod.outlook.com (2603:10a6:803:61::28) by AM6PR04MB4167.eurprd04.prod.outlook.com (2603:10a6:209:4e::25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4888.11; Thu, 20 Jan 2022 14:37:55 +0000 Received: from VI1PR04MB5151.eurprd04.prod.outlook.com ([fe80::3de6:806c:e71:2a2f]) by VI1PR04MB5151.eurprd04.prod.outlook.com ([fe80::3de6:806c:e71:2a2f%5]) with mapi id 15.20.4888.014; Thu, 20 Jan 2022 14:37:55 +0000 From: Daniel Baluta To: broonie@kernel.org, kai.vehmanen@linux.intel.com, ranjani.sridharan@linux.intel.com, lgirdwood@gmail.com, pierre-louis.bossart@linux.intel.com Subject: [PATCH v3] ASoC: SOF: compr: Add compress ops implementation Date: Thu, 20 Jan 2022 16:37:41 +0200 Message-Id: <20220120143741.492634-1-daniel.baluta@oss.nxp.com> X-Mailer: git-send-email 2.27.0 X-ClientProxiedBy: AM0PR03CA0031.eurprd03.prod.outlook.com (2603:10a6:208:14::44) To VI1PR04MB5151.eurprd04.prod.outlook.com (2603:10a6:803:61::28) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: a8c5a2f6-42fd-4a05-8dca-08d9dc2271fc X-MS-TrafficTypeDiagnostic: AM6PR04MB4167:EE_ X-MS-Exchange-SharedMailbox-RoutingAgent-Processed: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:374; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: dtbfnbcRF579ueWq0hfYm9jP2fyNHEZBRS0lRnD0y0ryFy6cy52k6UmPeOzvYEJ7YNMoR6jlq2/paX7655NfPAHaCq+V2dj1nZ7se/YmVNoulBJgiBI48fv4PHlHoIZu7rwVSJwovTmC91buOgiUiB0odtPWJmUcFo2oKr6EO5GFvjj6vUAWthyPbNR02GPGh9TqLBjVN9s+Osc0nLCIUmZwGJB3ryCNywU9re0yg1aPsm90yccpb4rtrO33kH0vN3dQGkXAfVMV/naBb+9zxpr/fYY+LHdwB3yNuHZnUYP9oAkDyNku8+l45fmiigdHIeOy1wpyBDsuKlbH/qy2WeAXDzgVVeoEVG1PT0ZgkH+j3GAuWNGqCNjEJZV5an3lwlrvBCXjoyyOSxRjnd/5857P7QxNQ4jt33IeKDdne7m8CzHRcdAAWu1xXazHHVc/3cutvtt2hqK0QprkkEhF2khPcd8gypNM3SncVDGCaXA0t4WxjC0Ns23ENobAstuBSIM6E+FDmSHjY/i0bZnPxjBb/JpUegl2J3UOOFpc1vO61D34e8dr7yvZ5bypx7diRnpgdsZ+t1ljuP+Z/ZwxYA4h7Hgwd1vGLU1LeqYsOvZVdak6ByFThIqdwkFpeFPixtSke3MTGN3+q/RxitI2qckdwFLlOCuGD8fOKnjaJhjcX+R5i5ooanQhWE5eE+58TTpmmZKMkjTm4b2TBF6hbn4p6zjJx0wfkf4mhsX7Njc= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:VI1PR04MB5151.eurprd04.prod.outlook.com; PTR:; CAT:NONE; SFS:(4636009)(366004)(66556008)(2906002)(8936002)(6512007)(86362001)(6506007)(30864003)(38100700002)(1076003)(4326008)(508600001)(186003)(52116002)(6486002)(66476007)(44832011)(2616005)(66946007)(316002)(5660300002)(6666004)(83380400001)(8676002); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?q?5paTNd629yrhh6lWaE6x6x+DQJFs?= =?utf-8?q?QNQ690AJfeW6juVf3OBc8tA8sJ4NzFmvocNxufCBoFpD8SaiU6kCmJE13sA2nkzCC?= =?utf-8?q?CQpG58PKI7NbYELEBPa1m9n/7Ha2KhEVBpPBPKVdn29y1PkOwlPJsfjDDn+7eizbD?= =?utf-8?q?XwvvU69PGyzz2BsuebIzhLaXvMe8DhtZjpUQ0VqLaLYjo0WfgeSZArW+qkduiBtRT?= =?utf-8?q?PGuG2zeqax8NiYYMECNb5E89yuj5QotlGs5WLXnOXGgh7EiL/p+Ml+bfxKBj6DSC8?= =?utf-8?q?BbCwNcrjH2p3vRnTXRaqkB7dRAgM7VS5kzWXmPG+FuI6of23WcytqfWwTJ8D2PaOI?= =?utf-8?q?ru2rJVI91849XCU6iKHvRQ8ZSRaN63BqZxNkaNRed0/sgtJXwCEWmtE7UKSKinK/5?= =?utf-8?q?SuQFNKCWiwc++gDf4Y8eHgmOTLwgZid3nxYPPQZApwRlJsx3lLWHjA6olyC15Q62n?= =?utf-8?q?AsIJKFWe03gC1l8hvZwWA49nWiipQbmnFdez0knD6g3vGWcG2fSmVv+1p00XCTw1z?= =?utf-8?q?VkXXeCBdIs74ywwgDt60zgNF6BUrChUdtbm2xY+MIpGKLwko9fdL/+v8J1VoRJVoZ?= =?utf-8?q?qUJfZb6YwMXliZMAiYVtfXxBRbxX5DRPg/vc4G5B6uWfEO8XDdXhaVWFmnjH6fZsE?= =?utf-8?q?Hy3aRsNHWlvLKJ60jt2lYSPoOMg6lLYdugmdy8hIDdJVfW6P9ggMe/HzroGSigBXv?= =?utf-8?q?nqDNB2gvZ6gpV4wmng3k7cbRdhDphAH9o9WdYl9+IK24+QixDAwRqILljkN0xBC/3?= =?utf-8?q?iPsFNbBrN97tNecYWIGBkrlw785XSlWE72BGtUZhqL8VfKDnNNexs7+qZDFkATzKu?= =?utf-8?q?QuJcqGaHIsX4Zv4cHxkpwKxHA7v3xswrLglbQOrfjmb9v3nZo23Y3TwMAJ+kolYX1?= =?utf-8?q?U6Mx6U6UEzKpJ5FfMXbKR6EGk3y+TECPHTbE75ypL+pBY5JhBD45rgO4f9YzGdFp6?= =?utf-8?q?+ITwUrB0SYbbA9cMOhQ8KH0mUziGIKmC8YKrONrUVSj05qu2J6o1zRV5+LHzEj9Br?= =?utf-8?q?yUXjAgDfCGfetL8xLWm+w+mVBeY21w25rAbUqtPIES3tzZGn+E52L/XCd0F+xSnb5?= =?utf-8?q?b2qaFLCfdNHb1+GHWbiswP9uCKuy7gAPT456FtHMQcfhLGHywd4K0NgwxirAwGsET?= =?utf-8?q?QO3Pqbru3tHagMWnxK5A0OJpXyIbCKNGM/90VyhY87my+oKJaueX1P6fKZqcTc71m?= =?utf-8?q?COhH85X+nVz+g4hcZ3asLW42iGF9zczWH8PXTqh1hO3h/smOMapmtbV8NOnYTnjO4?= =?utf-8?q?C7ZOwoSS9nEmiaWVb4zEJx2OCf3STDg54KP7IdgLpHz758DQ3xiM62XNodIlMYicB?= =?utf-8?q?XRqVd1GEB7AeMrt9SFp+SrtjJ6jOYOouT5CZqJyYwmr4WqyMWk+yYfMjTWH7/8/u9?= =?utf-8?q?AT4ghAvSF+GUWL6n/MR8zREJB/L4ueoPAJCXZij7kedgZ+qN2BbbYTdafkv1E6+1t?= =?utf-8?q?3GBByn1dZSOvaU3tR7wUV2lBEGLjJ+v5kOl9uZapf9w1RD4EZ9KkPLOpmVlqUmLrN?= =?utf-8?q?0JcNr5LcfbjeDqUZ+ZuPLMR8fz89+WrzlkV4F2adrC1yES5PfgIuN2YsLwGemDRbD?= =?utf-8?q?I/IL3qqmxLKL1oW5ayqr7TOKR4aB6OMAHvQFrVLdpfgXgdYPfOwkJg=3D?= X-OriginatorOrg: oss.nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: a8c5a2f6-42fd-4a05-8dca-08d9dc2271fc X-MS-Exchange-CrossTenant-AuthSource: VI1PR04MB5151.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Jan 2022 14:37:55.2419 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: d8joJXq4tkIhbOkOMlNqAwJVgIhfq5DPU3vOhYZk3fy/zQ4324AJzAtQqxLVfrzAw2rsbtRf9B9dZX4DJNV6mQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM6PR04MB4167 Cc: paul.olaru@nxp.com, cezary.rojewski@intel.com, alsa-devel@alsa-project.org, daniel.baluta@nxp.com, linux-kernel@vger.kernel.org X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 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" From: Daniel Baluta Implement snd_compress_ops. There are a lot of similarities with PCM implementation. For now we use sof_ipc_pcm_params to transfer compress parameters to SOF firmware. This will be changed in the future once we either add new compress parameters to SOF or enhance existing sof_ipc_pcm_params structure to support all native compress params. Note that get_caps and get_codec_caps are missing and will be added later. This is because we need to find a way to advertise DSP capabilities depending on supported platforms. Signed-off-by: Daniel Baluta --- Changes since v2: - dropped patch 2/2 because deciding on how to support get_caps and get_codec_caps needs some rework. - annotated commit message for 1/2 to mention about get_caps and get_codec_caps Changes since v1: (https://lore.kernel.org/lkml/20220113161341.371345-1-daniel.baluta@oss.nxp.com/T/) - Addressed review from Cezary and Pierre - fixed layout of declaration blocks to be more consistent - avoid using rtd and runtime simultaneously inside a function (always used rtd and crtd) - check return code for create_page_table - completely remove sof_compr_stream and use snd_compr_tstmap instead to keep compress stream related info.· - add get_caps and get_codec_caps implementations (in patch 2)· sound/soc/sof/compress.c | 273 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 271 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/compress.c b/sound/soc/sof/compress.c index 01ca85f0b87f..91a9c95929cd 100644 --- a/sound/soc/sof/compress.c +++ b/sound/soc/sof/compress.c @@ -10,6 +10,22 @@ #include "sof-audio.h" #include "sof-priv.h" +static void sof_set_transferred_bytes(struct snd_compr_tstamp *tstamp, + u64 host_pos, u64 buffer_size) +{ + u64 prev_pos; + unsigned int copied; + + div64_u64_rem(tstamp->copied_total, buffer_size, &prev_pos); + + if (host_pos < prev_pos) + copied = (buffer_size - prev_pos) + host_pos; + else + copied = host_pos - prev_pos; + + tstamp->copied_total += copied; +} + static void snd_sof_compr_fragment_elapsed_work(struct work_struct *work) { struct snd_sof_pcm_stream *sps = @@ -29,14 +45,16 @@ void snd_sof_compr_init_elapsed_work(struct work_struct *work) */ void snd_sof_compr_fragment_elapsed(struct snd_compr_stream *cstream) { + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct snd_compr_runtime *crtd = cstream->runtime; struct snd_soc_component *component; - struct snd_soc_pcm_runtime *rtd; + struct snd_compr_tstamp *tstamp; struct snd_sof_pcm *spcm; if (!cstream) return; - rtd = cstream->private_data; + tstamp = crtd->private_data; component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); spcm = snd_sof_find_spcm_dai(component, rtd); @@ -46,6 +64,257 @@ void snd_sof_compr_fragment_elapsed(struct snd_compr_stream *cstream) return; } + sof_set_transferred_bytes(tstamp, spcm->stream[cstream->direction].posn.host_posn, + crtd->buffer_size); + /* use the same workqueue-based solution as for PCM, cf. snd_sof_pcm_elapsed */ schedule_work(&spcm->stream[cstream->direction].period_elapsed_work); } + +static int create_page_table(struct snd_soc_component *component, + struct snd_compr_stream *cstream, + unsigned char *dma_area, size_t size) +{ + struct snd_dma_buffer *dmab = cstream->runtime->dma_buffer_p; + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + int dir = cstream->direction; + struct snd_sof_pcm *spcm; + + spcm = snd_sof_find_spcm_dai(component, rtd); + if (!spcm) + return -EINVAL; + + return snd_sof_create_page_table(component->dev, dmab, + spcm->stream[dir].page_table.area, size); +} + +int sof_compr_open(struct snd_soc_component *component, + struct snd_compr_stream *cstream) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct snd_compr_runtime *crtd = cstream->runtime; + struct snd_compr_tstamp *tstamp; + struct snd_sof_pcm *spcm; + int dir; + + tstamp = kzalloc(sizeof(*tstamp), GFP_KERNEL); + if (!tstamp) + return -ENOMEM; + + spcm = snd_sof_find_spcm_dai(component, rtd); + if (!spcm) { + kfree(tstamp); + return -EINVAL; + } + + dir = cstream->direction; + + if (spcm->stream[dir].cstream) { + kfree(tstamp); + return -EBUSY; + } + + spcm->stream[dir].cstream = cstream; + spcm->stream[dir].posn.host_posn = 0; + spcm->stream[dir].posn.dai_posn = 0; + spcm->prepared[dir] = false; + + crtd->private_data = tstamp; + + return 0; +} + +int sof_compr_free(struct snd_soc_component *component, + struct snd_compr_stream *cstream) +{ + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); + struct snd_compr_tstamp *tstamp = cstream->runtime->private_data; + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct sof_ipc_stream stream; + struct sof_ipc_reply reply; + struct snd_sof_pcm *spcm; + int ret = 0; + + spcm = snd_sof_find_spcm_dai(component, rtd); + if (!spcm) + return -EINVAL; + + stream.hdr.size = sizeof(stream); + stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE; + stream.comp_id = spcm->stream[cstream->direction].comp_id; + + if (spcm->prepared[cstream->direction]) { + ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, + &stream, sizeof(stream), + &reply, sizeof(reply)); + if (!ret) + spcm->prepared[cstream->direction] = false; + } + + cancel_work_sync(&spcm->stream[cstream->direction].period_elapsed_work); + spcm->stream[cstream->direction].cstream = NULL; + kfree(tstamp); + + return ret; +} + +int sof_compr_set_params(struct snd_soc_component *component, + struct snd_compr_stream *cstream, struct snd_compr_params *params) +{ + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct snd_compr_runtime *crtd = cstream->runtime; + struct sof_ipc_pcm_params_reply ipc_params_reply; + struct snd_compr_tstamp *tstamp; + struct sof_ipc_pcm_params pcm; + struct snd_sof_pcm *spcm; + int ret; + + tstamp = crtd->private_data; + + spcm = snd_sof_find_spcm_dai(component, rtd); + + if (!spcm) + return -EINVAL; + + cstream->dma_buffer.dev.type = SNDRV_DMA_TYPE_DEV_SG; + cstream->dma_buffer.dev.dev = sdev->dev; + ret = snd_compr_malloc_pages(cstream, crtd->buffer_size); + if (ret < 0) + return ret; + + ret = create_page_table(component, cstream, crtd->dma_area, crtd->dma_bytes); + if (ret < 0) + return ret; + + memset(&pcm, 0, sizeof(pcm)); + + pcm.params.buffer.pages = PFN_UP(crtd->dma_bytes); + pcm.hdr.size = sizeof(pcm); + pcm.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_PARAMS; + + pcm.comp_id = spcm->stream[cstream->direction].comp_id; + pcm.params.hdr.size = sizeof(pcm.params); + pcm.params.buffer.phy_addr = spcm->stream[cstream->direction].page_table.addr; + pcm.params.buffer.size = crtd->dma_bytes; + pcm.params.direction = cstream->direction; + pcm.params.channels = params->codec.ch_out; + pcm.params.rate = params->codec.sample_rate; + pcm.params.buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; + pcm.params.frame_fmt = SOF_IPC_FRAME_S32_LE; + pcm.params.sample_container_bytes = + snd_pcm_format_physical_width(SNDRV_PCM_FORMAT_S32) >> 3; + pcm.params.host_period_bytes = params->buffer.fragment_size; + + ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm), + &ipc_params_reply, sizeof(ipc_params_reply)); + if (ret < 0) { + dev_err(component->dev, "error ipc failed\n"); + return ret; + } + + tstamp->byte_offset = sdev->stream_box.offset + ipc_params_reply.posn_offset; + tstamp->sampling_rate = params->codec.sample_rate; + + spcm->prepared[cstream->direction] = true; + + return 0; +} + +int sof_compr_get_params(struct snd_soc_component *component, + struct snd_compr_stream *cstream, struct snd_codec *params) +{ + /* TODO: we don't query the supported codecs for now, if the + * application asks for an unsupported codec the set_params() will fail. + */ + return 0; +} + +int sof_compr_trigger(struct snd_soc_component *component, + struct snd_compr_stream *cstream, int cmd) +{ + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct sof_ipc_stream stream; + struct sof_ipc_reply reply; + struct snd_sof_pcm *spcm; + + spcm = snd_sof_find_spcm_dai(component, rtd); + if (!spcm) + return -EINVAL; + + stream.hdr.size = sizeof(stream); + stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG; + stream.comp_id = spcm->stream[cstream->direction].comp_id; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_START; + break; + case SNDRV_PCM_TRIGGER_STOP: + stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP; + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_PAUSE; + break; + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_RELEASE; + break; + default: + dev_err(component->dev, "error: unhandled trigger cmd %d\n", cmd); + break; + } + + return sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, + &stream, sizeof(stream), + &reply, sizeof(reply)); +} + +int sof_compr_copy(struct snd_soc_component *component, + struct snd_compr_stream *cstream, + char __user *buf, size_t count) +{ + struct snd_compr_runtime *rtd = cstream->runtime; + unsigned int offset, n; + void *ptr; + int ret; + + if (count > rtd->buffer_size) + count = rtd->buffer_size; + + div_u64_rem(rtd->total_bytes_available, rtd->buffer_size, &offset); + ptr = rtd->dma_area + offset; + n = rtd->buffer_size - offset; + + if (count < n) { + ret = copy_from_user(ptr, buf, count); + } else { + ret = copy_from_user(ptr, buf, n); + ret += copy_from_user(rtd->dma_area, buf + n, count - n); + } + + return count - ret; +} + +static int sof_compr_pointer(struct snd_soc_component *component, + struct snd_compr_stream *cstream, + struct snd_compr_tstamp *tstamp) +{ + struct snd_compr_tstamp *pstamp = cstream->runtime->private_data; + + tstamp->sampling_rate = pstamp->sampling_rate; + tstamp->copied_total = pstamp->copied_total; + + return 0; +} + +struct snd_compress_ops sof_compressed_ops = { + .open = sof_compr_open, + .free = sof_compr_free, + .set_params = sof_compr_set_params, + .get_params = sof_compr_get_params, + .trigger = sof_compr_trigger, + .pointer = sof_compr_pointer, + .copy = sof_compr_copy, +}; +EXPORT_SYMBOL(sof_compressed_ops);