From patchwork Thu Apr 26 13:20:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vinod Koul X-Patchwork-Id: 141606 Delivered-To: patch@linaro.org Received: by 10.46.151.6 with SMTP id r6csp2316895lji; Thu, 26 Apr 2018 06:17:16 -0700 (PDT) X-Google-Smtp-Source: AB8JxZpe5ThG5ptjey5TscwxblDutFJtodn0rd9Tb+1pmGbFKlYc3jbBv7ZoGPvScyqHwzbAYHm+ X-Received: by 2002:a19:aacd:: with SMTP id t196-v6mr17674358lfe.60.1524748636335; Thu, 26 Apr 2018 06:17:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524748636; cv=none; d=google.com; s=arc-20160816; b=T7F7CiBJkQQ4Wp05JojY9PA2URJz+E47tvsFHZb0j/Et9ir7J7PNw/Cd12QKReKVJb ym1RiLmTMinks/sD/VYVLenYpISxjMkghYR/3lrp4cvPz1omvQsU2EACYKmpq+iTK6/k trLzRrmKt8hkqpwrLdknkiqQEzILNFlmG39FBC5prbNqJyMvYJNcR2Cpr2S+NYJqh4hn XSgecBkIlCxMj6PA5vblhkddoytAivgjtfDpW+/3N28S474+II0E7TA+3seDYVaSRCJy 4FYtoHZSS/up3Y1yUwMEoLh8Qo08m1ZH19uLhkccOlxYFj7HWJTfyT43wKpsDlrnnTb/ g3+A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:cc:references:in-reply-to:message-id :date:to:from:delivered-to:arc-authentication-results; bh=/EyDYm6hWMJt9YLt1O3v9OtEGf021e3A+wozA+ng8ug=; b=j7igORn0o3cmulnj+G7F3n+8JmlbbQdZbkPKsZ4deEfSJZKj7Malmz3g3QVvVywbT7 tVqVHVeD3vkh8qa0ItTesMRsKUVs7k7cY9iMdAE0FoFj0WWvVrN+N/jokgMRbW2OxFEP daCwCHC5zHcQfRWrMx24WVqhbtjflltJ+LkO/SpO+wvv+8vOnnqt8KH2lky/EtEjIhX5 cceVRec0fHpFy8hRKNXAl7Mtc+2h0iYU6We2oAzSuYcmwCf7YtVhKO2zNV5NS7Jrxib/ 5sRzMUI2DDPUfeiOcWQRkcZTsI4J6fDcn1gX+ibIBN5vF9COhdRz19CZ7QtJ+Jom8+Kx xu9w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org Return-Path: Received: from alsa0.perex.cz (alsa0.perex.cz. [77.48.224.243]) by mx.google.com with ESMTP id q188si1317077wma.135.2018.04.26.06.17.16; Thu, 26 Apr 2018 06:17:16 -0700 (PDT) Received-SPF: pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) client-ip=77.48.224.243; Authentication-Results: mx.google.com; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 56B4A26783B; Thu, 26 Apr 2018 15:16:26 +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 234EC2678C0; Thu, 26 Apr 2018 15:16:24 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail1.perex.cz X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=RCVD_IN_DNSWL_MED autolearn=disabled version=3.4.0 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by alsa0.perex.cz (Postfix) with ESMTP id EA78D267893 for ; Thu, 26 Apr 2018 15:16:12 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 26 Apr 2018 06:16:12 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.49,330,1520924400"; d="scan'208";a="51009994" Received: from vkoul-udesk7.iind.intel.com ([10.223.84.143]) by orsmga001.jf.intel.com with ESMTP; 26 Apr 2018 06:16:09 -0700 From: Vinod Koul To: Greg KH Date: Thu, 26 Apr 2018 18:50:07 +0530 Message-Id: <1524748809-21860-12-git-send-email-vkoul@kernel.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1524748809-21860-1-git-send-email-vkoul@kernel.org> References: <1524748809-21860-1-git-send-email-vkoul@kernel.org> Cc: ALSA , tiwai@suse.de, Pierre-Louis Bossart , liam.r.girdwood@linux.intel.com, patches.audio@intel.com, Vinod Koul , broonie@kernel.org Subject: [alsa-devel] [PATCH v6 11/13] soundwire: cdns: Add stream routines 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: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org Add support for Cadence stream initialization and implement stream APIs. Signed-off-by: Sanyog Kale Signed-off-by: Shreyas NC Signed-off-by: Vinod Koul --- drivers/soundwire/cadence_master.c | 195 +++++++++++++++++++++++++++++++++++++ drivers/soundwire/cadence_master.h | 43 ++++++++ 2 files changed, 238 insertions(+) -- 2.7.4 _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c index 112479294d53..cb6a331f448a 100644 --- a/drivers/soundwire/cadence_master.c +++ b/drivers/soundwire/cadence_master.c @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include "bus.h" #include "cadence_master.h" @@ -985,5 +987,198 @@ int sdw_cdns_probe(struct sdw_cdns *cdns) } EXPORT_SYMBOL(sdw_cdns_probe); +int cdns_set_sdw_stream(struct snd_soc_dai *dai, + void *stream, bool pcm, int direction) +{ + struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai); + struct sdw_cdns_dma_data *dma; + + dma = kzalloc(sizeof(*dma), GFP_KERNEL); + if (!dma) + return -ENOMEM; + + if (pcm) + dma->stream_type = SDW_STREAM_PCM; + else + dma->stream_type = SDW_STREAM_PDM; + + dma->bus = &cdns->bus; + dma->link_id = cdns->instance; + + dma->stream = stream; + + if (direction == SNDRV_PCM_STREAM_PLAYBACK) + dai->playback_dma_data = dma; + else + dai->capture_dma_data = dma; + + return 0; +} +EXPORT_SYMBOL(cdns_set_sdw_stream); + +/** + * cdns_find_pdi() - Find a free PDI + * + * @cdns: Cadence instance + * @num: Number of PDIs + * @pdi: PDI instances + * + * Find and return a free PDI for a given PDI array + */ +static struct sdw_cdns_pdi *cdns_find_pdi(struct sdw_cdns *cdns, + unsigned int num, struct sdw_cdns_pdi *pdi) +{ + int i; + + for (i = 0; i < num; i++) { + if (pdi[i].assigned == true) + continue; + pdi[i].assigned = true; + return &pdi[i]; + } + + return NULL; +} + +/** + * sdw_cdns_config_stream: Configure a stream + * + * @cdns: Cadence instance + * @port: Cadence data port + * @ch: Channel count + * @dir: Data direction + * @pdi: PDI to be used + */ +void sdw_cdns_config_stream(struct sdw_cdns *cdns, + struct sdw_cdns_port *port, + u32 ch, u32 dir, struct sdw_cdns_pdi *pdi) +{ + u32 offset, val = 0; + + if (dir == SDW_DATA_DIR_RX) + val = CDNS_PORTCTRL_DIRN; + + offset = CDNS_PORTCTRL + port->num * CDNS_PORT_OFFSET; + cdns_updatel(cdns, offset, CDNS_PORTCTRL_DIRN, val); + + val = port->num; + val |= ((1 << ch) - 1) << SDW_REG_SHIFT(CDNS_PDI_CONFIG_CHANNEL); + cdns_writel(cdns, CDNS_PDI_CONFIG(pdi->num), val); +} +EXPORT_SYMBOL(sdw_cdns_config_stream); + +/** + * cdns_get_num_pdi() - Get number of PDIs required + * + * @cdns: Cadence instance + * @pdi: PDI to be used + * @num: Number of PDIs + * @ch_count: Channel count + */ +static int cdns_get_num_pdi(struct sdw_cdns *cdns, + struct sdw_cdns_pdi *pdi, + unsigned int num, u32 ch_count) +{ + int i, pdis = 0; + + for (i = 0; i < num; i++) { + if (pdi[i].assigned == true) + continue; + + if (pdi[i].ch_count < ch_count) + ch_count -= pdi[i].ch_count; + else + ch_count = 0; + + pdis++; + + if (!ch_count) + break; + } + + if (ch_count) + return 0; + + return pdis; +} + +/** + * sdw_cdns_get_stream() - Get stream information + * + * @cdns: Cadence instance + * @stream: Stream to be allocated + * @ch: Channel count + * @dir: Data direction + */ +int sdw_cdns_get_stream(struct sdw_cdns *cdns, + struct sdw_cdns_streams *stream, + u32 ch, u32 dir) +{ + int pdis = 0; + + if (dir == SDW_DATA_DIR_RX) + pdis = cdns_get_num_pdi(cdns, stream->in, stream->num_in, ch); + else + pdis = cdns_get_num_pdi(cdns, stream->out, stream->num_out, ch); + + /* check if we found PDI, else find in bi-directional */ + if (!pdis) + pdis = cdns_get_num_pdi(cdns, stream->bd, stream->num_bd, ch); + + return pdis; +} +EXPORT_SYMBOL(sdw_cdns_get_stream); + +/** + * sdw_cdns_alloc_stream() - Allocate a stream + * + * @cdns: Cadence instance + * @stream: Stream to be allocated + * @port: Cadence data port + * @ch: Channel count + * @dir: Data direction + */ +int sdw_cdns_alloc_stream(struct sdw_cdns *cdns, + struct sdw_cdns_streams *stream, + struct sdw_cdns_port *port, u32 ch, u32 dir) +{ + struct sdw_cdns_pdi *pdi = NULL; + + if (dir == SDW_DATA_DIR_RX) + pdi = cdns_find_pdi(cdns, stream->num_in, stream->in); + else + pdi = cdns_find_pdi(cdns, stream->num_out, stream->out); + + /* check if we found a PDI, else find in bi-directional */ + if (!pdi) + pdi = cdns_find_pdi(cdns, stream->num_bd, stream->bd); + + if (!pdi) + return -EIO; + + port->pdi = pdi; + pdi->l_ch_num = 0; + pdi->h_ch_num = ch - 1; + pdi->dir = dir; + pdi->ch_count = ch; + + return 0; +} +EXPORT_SYMBOL(sdw_cdns_alloc_stream); + +void sdw_cdns_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct sdw_cdns_dma_data *dma; + + dma = snd_soc_dai_get_dma_data(dai, substream); + if (!dma) + return; + + snd_soc_dai_set_dma_data(dai, substream, NULL); + kfree(dma); +} +EXPORT_SYMBOL(sdw_cdns_shutdown); + MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION("Cadence Soundwire Library"); diff --git a/drivers/soundwire/cadence_master.h b/drivers/soundwire/cadence_master.h index 98a17f57918f..eb902b19c5a4 100644 --- a/drivers/soundwire/cadence_master.h +++ b/drivers/soundwire/cadence_master.h @@ -1,5 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) // Copyright(c) 2015-17 Intel Corporation. +#include #ifndef __SDW_CADENCE_H #define __SDW_CADENCE_H @@ -91,6 +92,26 @@ struct sdw_cdns_stream_config { }; /** + * struct sdw_cdns_dma_data: Cadence DMA data + * + * @name: SoundWire stream name + * @nr_ports: Number of ports + * @port: Ports + * @bus: Bus handle + * @stream_type: Stream type + * @link_id: Master link id + */ +struct sdw_cdns_dma_data { + char *name; + struct sdw_stream_runtime *stream; + int nr_ports; + struct sdw_cdns_port **port; + struct sdw_bus *bus; + enum sdw_stream_type stream_type; + int link_id; +}; + +/** * struct sdw_cdns - Cadence driver context * @dev: Linux device * @bus: Bus handle @@ -142,6 +163,25 @@ int sdw_cdns_pdi_init(struct sdw_cdns *cdns, struct sdw_cdns_stream_config config); int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns); +int sdw_cdns_get_stream(struct sdw_cdns *cdns, + struct sdw_cdns_streams *stream, + u32 ch, u32 dir); +int sdw_cdns_alloc_stream(struct sdw_cdns *cdns, + struct sdw_cdns_streams *stream, + struct sdw_cdns_port *port, u32 ch, u32 dir); +void sdw_cdns_config_stream(struct sdw_cdns *cdns, struct sdw_cdns_port *port, + u32 ch, u32 dir, struct sdw_cdns_pdi *pdi); + +void sdw_cdns_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai); +int sdw_cdns_pcm_set_stream(struct snd_soc_dai *dai, + void *stream, int direction); +int sdw_cdns_pdm_set_stream(struct snd_soc_dai *dai, + void *stream, int direction); + +enum sdw_command_response +cdns_reset_page_addr(struct sdw_bus *bus, unsigned int dev_num); + enum sdw_command_response cdns_xfer_msg(struct sdw_bus *bus, struct sdw_msg *msg); @@ -153,4 +193,7 @@ enum sdw_command_response cdns_reset_page_addr(struct sdw_bus *bus, unsigned int dev_num); int cdns_bus_conf(struct sdw_bus *bus, struct sdw_bus_params *params); + +int cdns_set_sdw_stream(struct snd_soc_dai *dai, + void *stream, bool pcm, int direction); #endif /* __SDW_CADENCE_H */