From patchwork Tue Aug 13 08:35:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 171177 Delivered-To: patch@linaro.org Received: by 2002:a92:d204:0:0:0:0:0 with SMTP id y4csp604911ily; Tue, 13 Aug 2019 01:36:17 -0700 (PDT) X-Google-Smtp-Source: APXvYqyxm4s7AohZgcrY9QFu5wgYWn7ZA/lu4ZPiWim0jcUgdjxTj6nug83ZFH0ekl1iT7lGPuY8 X-Received: by 2002:a17:90a:cb12:: with SMTP id z18mr1125348pjt.82.1565685377863; Tue, 13 Aug 2019 01:36:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1565685377; cv=none; d=google.com; s=arc-20160816; b=kFFDesgje67n9tNVWTEEg1VBbc4fj1icg6F8XIlZblBnoDu42wRsSTx8d4qWHCc3Qb 5OPjioB1kd3nVgopETFJwIJ24FlCmynRmGT1J/sHSopGpW2AR2bXAoTDmECpW4qG63tK ZrR9VZL5XojRjkbj6u+ODk7nNi4++aIi8Vq5L8ppNbtev++axn523fHDZD1003CzTLkO dy8+rYhBCbZaK5U7Pxzt3zTQSQlfcb74kqqTIp4Pylnv8NyOY2OLli1Tf2aZM6X4hZw6 3Cxi5I/B2mhwhNHc4qYBQW4RjousJ6zpRLvH6sOWjIrjegj+BBzUYGsKHYxuyWJ6770n LFSQ== 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=yY3j+tzAidsewEpOKH7pvngWyOrXZYN1znzf8G8c2/o=; b=mVvdb/UD1gggEemyFtMw6uy2oH8Gtgsa9vA2xQajt/pmd4Bn1XlNdkEpJsFMVll2QY wDUOU4opGg2/jObywkYRZEkpoQCmLqZaUssMxh4338k5RKGBy1jBnJyDCWnSbenIvS13 uoi1MMbI1EljZ8YBSb2e4eNGS8U0JebZlLWtmpMgJ4aMkwB7IRnzgJwAx8N9p5sTgkn5 pLWEUeZJUoaxpiHME0DT1aq9P385zryhv+OBB8JRYYCM/pP3Y4qeoXenw4AtLV4c9rHZ tXzr/eGXb5+htNlaq01TfZzA0SyEBDO7Aku+UsbNBjArSaVH7iVFcmpg7dOwrW3AURog gtyQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=z1KFlnpe; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-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 1si15200465ple.275.2019.08.13.01.36.17; Tue, 13 Aug 2019 01:36:17 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-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=z1KFlnpe; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-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 S1728288AbfHMIgQ (ORCPT + 28 others); Tue, 13 Aug 2019 04:36:16 -0400 Received: from mail-wr1-f67.google.com ([209.85.221.67]:34034 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728048AbfHMIf7 (ORCPT ); Tue, 13 Aug 2019 04:35:59 -0400 Received: by mail-wr1-f67.google.com with SMTP id 31so106982939wrm.1 for ; Tue, 13 Aug 2019 01:35:57 -0700 (PDT) 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=yY3j+tzAidsewEpOKH7pvngWyOrXZYN1znzf8G8c2/o=; b=z1KFlnpe7m6oruIQ8cwwyUe0xYtx70XatCj0QTT3fQG0wWPqOetxuINiLncLjFTWTm 99H1BtzfFj+UnuZcErc7bAJTBHGV4j1+4Z5/JyC7VOEUNZIcuuvAzstG9O1gv1RCckId TzAMy2Yy5ely6dY38GSWw68qaAwxhYG8sqLPPCksZXgXydyiUuJ0K3sGK/2ut4K19N5Y 1RF8aEmiY8gLCqkR3QzdAwpqB9f7CbTOvf5THnii6yVLwT6BZA0ObfQ3ZdJYT2W8rKoY ZD6dc/JtTu+Oukif2+WVSMwzax90gO1e/MjO1I4Phxk/93Ispzxbp3zCuDhM3ZTKwCEt bcFA== 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=yY3j+tzAidsewEpOKH7pvngWyOrXZYN1znzf8G8c2/o=; b=X/WkpvHe1wIbUi81PVe9UC3QD9IjuANxOL1Tp7xO+ACMwmisnvMkgt1E9nuJwnV4nc mkryDLRXzWS/gz19I/Sxsbc0Jf4TXYbPfORSUjjC422Xr4vkLFlxfg3N0AAOO+7SpDmA QDiaNIN/LfdIsCHNsN64ioebLmTbfkCJtdq7wWkgRNEXO1UeJ7/+5M2D3EaJ4gQijp4t 4Xmlbgt7ojee0KYgLP+jphQHyPSEpce/8uq0q2L+0h+J8nJAC6TnIxWT7Dw7vTe2rSpR nWUv9qTQMA0ApvJckdbWU32XG1u32lYzdxjEoN2G7OTtvZn+VPR3SWnVqzLEagwvpPTm KDRg== X-Gm-Message-State: APjAAAWha3rj/0Ku9ez22mf4+j+FZ+R57u5m2C1w6/etITxT0OoLDRrY tbv3ox4M1IjZLIaNmAwctNmfNQ== X-Received: by 2002:adf:dc51:: with SMTP id m17mr47047026wrj.256.1565685356898; Tue, 13 Aug 2019 01:35:56 -0700 (PDT) Received: from srini-hackbox.lan (cpc89974-aztw32-2-0-cust43.18-1.cable.virginm.net. [86.30.250.44]) by smtp.gmail.com with ESMTPSA id o11sm8651822wrw.19.2019.08.13.01.35.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 13 Aug 2019 01:35:56 -0700 (PDT) From: Srinivas Kandagatla To: vkoul@kernel.org, broonie@kernel.org Cc: bgoswami@codeaurora.org, plai@codeaurora.org, pierre-louis.bossart@linux.intel.com, robh+dt@kernel.org, devicetree@vger.kernel.org, lgirdwood@gmail.com, alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org, spapothi@codeaurora.org, Srinivas Kandagatla Subject: [PATCH v2 2/5] soundwire: stream: make stream name a const pointer Date: Tue, 13 Aug 2019 09:35:47 +0100 Message-Id: <20190813083550.5877-3-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190813083550.5877-1-srinivas.kandagatla@linaro.org> References: <20190813083550.5877-1-srinivas.kandagatla@linaro.org> MIME-Version: 1.0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Make stream name const pointer Signed-off-by: Srinivas Kandagatla --- drivers/soundwire/stream.c | 2 +- include/linux/soundwire/sdw.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) -- 2.21.0 diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c index 60bc2fe42928..49ce21320f52 100644 --- a/drivers/soundwire/stream.c +++ b/drivers/soundwire/stream.c @@ -863,7 +863,7 @@ EXPORT_SYMBOL(sdw_release_stream); * sdw_alloc_stream should be called only once per stream. Typically * invoked from ALSA/ASoC machine/platform driver. */ -struct sdw_stream_runtime *sdw_alloc_stream(char *stream_name) +struct sdw_stream_runtime *sdw_alloc_stream(const char *stream_name) { struct sdw_stream_runtime *stream; diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index aac68e879fae..5e61ad065d32 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -830,7 +830,7 @@ struct sdw_stream_params { * @m_rt_count: Count of Master runtime(s) in this stream */ struct sdw_stream_runtime { - char *name; + const char *name; struct sdw_stream_params params; enum sdw_stream_state state; enum sdw_stream_type type; @@ -838,7 +838,7 @@ struct sdw_stream_runtime { int m_rt_count; }; -struct sdw_stream_runtime *sdw_alloc_stream(char *stream_name); +struct sdw_stream_runtime *sdw_alloc_stream(const char *stream_name); void sdw_release_stream(struct sdw_stream_runtime *stream); int sdw_stream_add_master(struct sdw_bus *bus, struct sdw_stream_config *stream_config, From patchwork Tue Aug 13 08:35:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 171174 Delivered-To: patch@linaro.org Received: by 2002:a92:d204:0:0:0:0:0 with SMTP id y4csp604701ily; Tue, 13 Aug 2019 01:36:03 -0700 (PDT) X-Google-Smtp-Source: APXvYqw3QTNKqZFJojaqMsnBZBPLn5v2VYoOV81aln3T33ctyPTReCQATdKTDzptZDAZlS03vFnI X-Received: by 2002:a65:6281:: with SMTP id f1mr31640638pgv.400.1565685363408; Tue, 13 Aug 2019 01:36:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1565685363; cv=none; d=google.com; s=arc-20160816; b=vIBuDNCaD82D4V49zJSSWyNk+f/0hGqHwDYTJNPNzemVGE31dbGLugc2EF7e/wMAlY vP3IHJtUCdt72YEDNQubZLlt1q1CbfONvO9+G4Dvga0ImbsHvK/NG7381XdjV+cG9Sb4 FDCb8Jwt+sz5Cq5P76ep+pG3a9s9ahA1CENT/VdMzxlOF5Sv1giiWIlt7HH+hqDY0vla 9BC9KnGhQoopILXEN4H0FKQPXbqwIJlG/5wLovhUxLJldLFrOTq6w5v10TGKxJzuQQW/ Yp8qB7ET7fUDQ4j4zamvsPXgUqnWsvbsl+ELWYkU7jie8/d+dZZV36ZNz13itZnolyDq R8RQ== 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=B9rsr1/dgfaWkUD61V9rwU3U5jz+C8FjG7cuo0AJp/Q=; b=enHUI3PpXvXdyV54OMP1p6YP7/35EfGdIHKayMGw0KgBZcNDUWYF6gsmp0TwuUagoZ /H7gFNi1G7eM2KD6FybcS5wM7hiRTQPs20fpXTqRbwL4WeH7qz+qiWXb/fjaZ5B0+xnk BsO7cYL9LJGOSkFi2jb1c3zGw3PJ85DyTYHQ+CEqu/qeKgABxGX+gASr3oLOuoHmPUjE cxYgFb804LG0s0plGcDtohPVIRcJAiIKhOCTZpb5ZNa6fqIZ8QLUMEisHq3wpD8+JK+K lyh3aH7G+vrsHyI4H1Ag4rkPs4GtTLcSWBrgRubzxVsYdHK7lSTjSAfo7ShDD44dOkFm eZbg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=NIbQsuQ2; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-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 k98si548029pje.41.2019.08.13.01.36.03; Tue, 13 Aug 2019 01:36:03 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-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=NIbQsuQ2; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-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 S1728255AbfHMIgB (ORCPT + 28 others); Tue, 13 Aug 2019 04:36:01 -0400 Received: from mail-wm1-f65.google.com ([209.85.128.65]:39521 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728192AbfHMIf7 (ORCPT ); Tue, 13 Aug 2019 04:35:59 -0400 Received: by mail-wm1-f65.google.com with SMTP id i63so692241wmg.4 for ; Tue, 13 Aug 2019 01:35:58 -0700 (PDT) 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=B9rsr1/dgfaWkUD61V9rwU3U5jz+C8FjG7cuo0AJp/Q=; b=NIbQsuQ2GpNnu739xoBeBF5FbMINwGQO+uIiIC0oSLND+QmbFVEfIMFPovy+35DF/K wg++6jFE3Z9x5YLYZzPdq3Td/haqQlmOjOe2kkrJEYAeG2DEXu1cUrNyCr8UXuRtNjJ2 M8cpQ+NGVZzfmBjrrbQVSi09Fk1hcLN0wTa2gbd8aT6C4hJ/bV1Ty/wgvnZIzTzLNq1C GMCi/GaYWG04/R8YjyoIM97doonDiD9mxrNim+ql2pMM+zsPLw2Il2hxXPIg5EMx5Sva 4N/VaFxQyREtZdPogXXXuqNfJn5TUJyO7KtYv/4svBoYj4qUzg1iZ2KBR5awYOXaAwFI NSeg== 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=B9rsr1/dgfaWkUD61V9rwU3U5jz+C8FjG7cuo0AJp/Q=; b=XdV6lk+2Hvd8EjY6T2yvYGjdMtsSMDtU5LavmyzgccclHpkNh7/eHb7jr6ICMfOGl/ XznzndzKcEm3mX28/rlHCwJolIyXzwSp0tlkNLitaWH2PCbD/ZdYj5Ol5zQvNharHm9I Kjllnf5Vw6Fp1wyVPZ9lU978j6tRDwTUUxgPBYyZ2yvuvEdtjERPQGxuYqo0cu5TvZQW xIIzsOAR5LVvLZUC7U3EkV+D/uzK6oDyN44IwzlUTDNtYx7MpejM/B5n5KENKNeosoXW 0P9zQ6WQXzhEOSZXXVQhLj0mg2pBn561BrGhhCZw+TLNS0d1AxBwwuKivQ+aYEK11z7n Zu9w== X-Gm-Message-State: APjAAAWMMrOp828Xg3vEnPJB5dcZdt2cq9IxzGlJgK1l/8o1OrH7wU3H zt9lQawVhQUWdCpgxHwFF5SSNA== X-Received: by 2002:a1c:7a12:: with SMTP id v18mr1765791wmc.56.1565685358047; Tue, 13 Aug 2019 01:35:58 -0700 (PDT) Received: from srini-hackbox.lan (cpc89974-aztw32-2-0-cust43.18-1.cable.virginm.net. [86.30.250.44]) by smtp.gmail.com with ESMTPSA id o11sm8651822wrw.19.2019.08.13.01.35.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 13 Aug 2019 01:35:57 -0700 (PDT) From: Srinivas Kandagatla To: vkoul@kernel.org, broonie@kernel.org Cc: bgoswami@codeaurora.org, plai@codeaurora.org, pierre-louis.bossart@linux.intel.com, robh+dt@kernel.org, devicetree@vger.kernel.org, lgirdwood@gmail.com, alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org, spapothi@codeaurora.org, Srinivas Kandagatla Subject: [PATCH v2 3/5] ASoC: core: add support to snd_soc_dai_get_sdw_stream() Date: Tue, 13 Aug 2019 09:35:48 +0100 Message-Id: <20190813083550.5877-4-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190813083550.5877-1-srinivas.kandagatla@linaro.org> References: <20190813083550.5877-1-srinivas.kandagatla@linaro.org> MIME-Version: 1.0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On platforms which have smart speaker amplifiers connected via soundwire and modeled as aux devices in ASoC, in such usecases machine driver should be able to get sdw master stream from dai so that it can use the runtime stream to setup slave streams. soundwire already as a set function, get function would provide more flexibility to above configurations. Signed-off-by: Srinivas Kandagatla --- include/sound/soc-dai.h | 10 ++++++++++ 1 file changed, 10 insertions(+) -- 2.21.0 diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index dc48fe081a20..1e01f4a302e0 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -202,6 +202,7 @@ struct snd_soc_dai_ops { int (*set_sdw_stream)(struct snd_soc_dai *dai, void *stream, int direction); + void *(*get_sdw_stream)(struct snd_soc_dai *dai, int direction); /* * DAI digital mute - optional. * Called by soc-core to minimise any pops. @@ -410,4 +411,13 @@ static inline int snd_soc_dai_set_sdw_stream(struct snd_soc_dai *dai, return -ENOTSUPP; } +static inline void *snd_soc_dai_get_sdw_stream(struct snd_soc_dai *dai, + int direction) +{ + if (dai->driver->ops->get_sdw_stream) + return dai->driver->ops->get_sdw_stream(dai, direction); + else + return ERR_PTR(-ENOTSUPP); +} + #endif From patchwork Tue Aug 13 08:35:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 171175 Delivered-To: patch@linaro.org Received: by 2002:a92:d204:0:0:0:0:0 with SMTP id y4csp604744ily; Tue, 13 Aug 2019 01:36:06 -0700 (PDT) X-Google-Smtp-Source: APXvYqw/diu3z8Q2rfUKv6QyVNhhbaUCSFG4ZdIzUAGJ64Stv3Z1pSehJzOgXhcqYEjRgrgtY+U0 X-Received: by 2002:a17:902:1004:: with SMTP id b4mr26016802pla.340.1565685366160; Tue, 13 Aug 2019 01:36:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1565685366; cv=none; d=google.com; s=arc-20160816; b=QvjGFV87IpjAldPJveU8qR4hBe66Bd0ZirbYbmm0EPKvPGU6sv5s/CjsAu9qkB33gn EBopR81qjueyEapElNcRTmYbVvBMO2aDEMTF8bpG/VjZO+xaq1o7+IzT0eb6j8eQl968 ysI/4MYuwydKqf4pgTokmdVwUSOcdK1fE7WjsJo7ZM5LU6lx3m2erC/gnqkENSD097eI AAq8+AJIW4Ixww+XPUNumjT0VV5BFFESyicoY6h6mC2qdlOmopE3YMxWTtnR46nJgBuM kQSt+1IyJYwOnPh9l2m1hXFBjFtaOzsY//vjsojNFol1OS9r99PJr1oieUZ3/PSkfdA/ eaug== 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=z0kO6qx1UAc/uP1SKgjN6XAyjR6GuCSBuxXXjXMIpxU=; b=SYiRDj1O22Y/3ELiUmU6fldO1UgOap0XepOnUtxS8TMWjHp4fR0vt1pGkCLRhHiAe6 puBNk6VsnaR7VD4J4xH1VHx11Yyizkkamq20P24c1y4Tfd/zVUQPjvkDXRLzEP+OFxSw uIX4BuoS1kt7DF+JIq22uB97vXIu3Snw3VAWfxY6nCApD38nX6CxUUUjf2waOOphE/aX FXVpX6zKiKCnhNVHiLAEeZM0dZ6Z+98bFtWREh0cAf7CGrvxMxMFO9WyolxivZOHgzGi rjFQmnjsthzRwcKKU+XEDPVsUQ/KvsmepMkidBTsu0t4lYy+KihXOO+75UXWmouf0gPH fycw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=S6PR9JzX; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-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 k98si548029pje.41.2019.08.13.01.36.05; Tue, 13 Aug 2019 01:36:06 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-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=S6PR9JzX; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-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 S1728267AbfHMIgF (ORCPT + 28 others); Tue, 13 Aug 2019 04:36:05 -0400 Received: from mail-wr1-f66.google.com ([209.85.221.66]:37952 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728213AbfHMIgB (ORCPT ); Tue, 13 Aug 2019 04:36:01 -0400 Received: by mail-wr1-f66.google.com with SMTP id g17so106936151wrr.5 for ; Tue, 13 Aug 2019 01:35:59 -0700 (PDT) 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=z0kO6qx1UAc/uP1SKgjN6XAyjR6GuCSBuxXXjXMIpxU=; b=S6PR9JzXSPICGc9iX7ScIdI+yvEgDwS07KOePIvb4JNCloS52ZiFkiLkD0SrbfSAlr tx+/bexwbgnzgqHPM1NMAbmla6cWVfq2lIQn4vIURLvrZI2DNMbE+E+Eo0Ozhz2z7Nww 19hwZyd2ta+oIAZrZ7C1Za8PfHj7+xiKLRngp9xGfXtitOnq2aXayuAZ/e+lPUJe8Xvb ucVaLMhkE0mn/Ehdnhut6Wb9yDDiGmLIuH89xPc/Qc97HWuqcLLazqUq2qiFPJsrl+ZD RXfVcnR9j2nd0RoRoibqQU8tc4a+UcOSR13GQ5I7ySC3EaUZu+FIOidQ4xASL32v2XD2 FAFw== 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=z0kO6qx1UAc/uP1SKgjN6XAyjR6GuCSBuxXXjXMIpxU=; b=bRrZxYtouKuhz/Th6FUTpc/JhhvtlLQE9e1CGaO6nYOm9zze8jsL5aBo2evTCkOQJS qpV1QDQ+ChjxZH16JQTVmJNdHfhf7Nbgx3WFjWK2GDwEm1+bf0A0c9hoLAYqLHLa2R9i jHmtSvi3/6Zv7ZO1sFbMA8vbGEqpye5TR1cBTi/AMvnKxArD4sT1idYOQfjYQhepSHi9 oJyh4CrvRDPpVbt74Kgvng2zptxsgW95P5Ivcc+7bnV+oR6KjwDa3FxSGOnWoT8GcXhQ B5qaE4KOtAUE3e6dyx6YoLbM/cM6evOj6T11dcwx1JzvDjd4LlGA5yGfoA0lTMAOSyNQ 09wQ== X-Gm-Message-State: APjAAAU4j9nL9ZujqwglVPa6WrlZbE0agB70/Z9GEczkNC0l/cmPH+rh X/TfS1pWmOPrdyy/IwccNvnexA== X-Received: by 2002:adf:90e7:: with SMTP id i94mr42458207wri.224.1565685359159; Tue, 13 Aug 2019 01:35:59 -0700 (PDT) Received: from srini-hackbox.lan (cpc89974-aztw32-2-0-cust43.18-1.cable.virginm.net. [86.30.250.44]) by smtp.gmail.com with ESMTPSA id o11sm8651822wrw.19.2019.08.13.01.35.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 13 Aug 2019 01:35:58 -0700 (PDT) From: Srinivas Kandagatla To: vkoul@kernel.org, broonie@kernel.org Cc: bgoswami@codeaurora.org, plai@codeaurora.org, pierre-louis.bossart@linux.intel.com, robh+dt@kernel.org, devicetree@vger.kernel.org, lgirdwood@gmail.com, alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org, spapothi@codeaurora.org, Srinivas Kandagatla Subject: [PATCH v2 4/5] dt-bindings: soundwire: add bindings for Qcom controller Date: Tue, 13 Aug 2019 09:35:49 +0100 Message-Id: <20190813083550.5877-5-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190813083550.5877-1-srinivas.kandagatla@linaro.org> References: <20190813083550.5877-1-srinivas.kandagatla@linaro.org> MIME-Version: 1.0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch adds bindings for Qualcomm soundwire controller. Qualcomm SoundWire Master controller is present in most Qualcomm SoCs either integrated as part of WCD audio codecs via slimbus or as part of SOC I/O. Signed-off-by: Srinivas Kandagatla --- .../bindings/soundwire/qcom,sdw.txt | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 Documentation/devicetree/bindings/soundwire/qcom,sdw.txt -- 2.21.0 diff --git a/Documentation/devicetree/bindings/soundwire/qcom,sdw.txt b/Documentation/devicetree/bindings/soundwire/qcom,sdw.txt new file mode 100644 index 000000000000..436547f3b155 --- /dev/null +++ b/Documentation/devicetree/bindings/soundwire/qcom,sdw.txt @@ -0,0 +1,167 @@ +Qualcomm SoundWire Controller Bindings + + +This binding describes the Qualcomm SoundWire Controller along with its +board specific bus parameters. + +- compatible: + Usage: required + Value type: + Definition: must be "qcom,soundwire-v..", + Example: + "qcom,soundwire-v1.3.0" + "qcom,soundwire-v1.5.0" + "qcom,soundwire-v1.6.0" +- reg: + Usage: required + Value type: + Definition: the base address and size of SoundWire controller + address space. + +- interrupts: + Usage: required + Value type: + Definition: should specify the SoundWire Controller IRQ + +- clock-names: + Usage: required + Value type: + Definition: should be "iface" for SoundWire Controller interface clock + +- clocks: + Usage: required + Value type: + Definition: should specify the SoundWire Controller interface clock + +- #sound-dai-cells: + Usage: required + Value type: + Definition: must be 1 for digital audio interfaces on the controller. + +- qcom,dout-ports: + Usage: required + Value type: + Definition: must be count of data out ports + +- qcom,din-ports: + Usage: required + Value type: + Definition: must be count of data in ports + +- qcom,ports-offset1: + Usage: required + Value type: + Definition: should specify payload transport window offset1 of each + data port. Out ports followed by In ports. + More info in MIPI Alliance SoundWire 1.0 Specifications. + +- qcom,ports-offset2: + Usage: required + Value type: + Definition: should specify payload transport window offset2 of each + data port. Out ports followed by In ports. + More info in MIPI Alliance SoundWire 1.0 Specifications. + +- qcom,ports-sinterval-low: + Usage: required + Value type: + Definition: should be sample interval low of each data port. + Out ports followed by In ports. Used for Sample Interval + calculation. + More info in MIPI Alliance SoundWire 1.0 Specifications. + +- qcom,ports-word-length: + Usage: optional + Value type: + Definition: should be size of payload channel sample. + More info in MIPI Alliance SoundWire 1.0 Specifications. + +- qcom,ports-block-pack-mode: + Usage: optional + Value type: + Definition: should be 0 or 1 to indicate the block packing mode. + 0 to indicate Blocks are per Channel + 1 to indicate Blocks are per Port. + Out ports followed by In ports. + More info in MIPI Alliance SoundWire 1.0 Specifications. + +- qcom,ports-block-group-count: + Usage: optional + Value type: + Definition: should be in range 1 to 4 to indicate how many sample + intervals are combined into a payload. + Out ports followed by In ports. + More info in MIPI Alliance SoundWire 1.0 Specifications. + +- qcom,ports-lane-control: + Usage: optional + Value type: + Definition: should be in range 0 to 7 to identify which data lane + the data port uses. + Out ports followed by In ports. + More info in MIPI Alliance SoundWire 1.0 Specifications. + +- qcom,ports-hstart: + Usage: optional + Value type: + Definition: should be number identifying lowerst numbered coloum in + SoundWire Frame, i.e. left edge of the Transport sub-frame + for each port. Values between 0 and 15 are valid. + Out ports followed by In ports. + More info in MIPI Alliance SoundWire 1.0 Specifications. + +- qcom,ports-hstop: + Usage: optional + Value type: + Definition: should be number identifying highest numbered coloum in + SoundWire Frame, i.e. the right edge of the Transport + sub-frame for each port. Values between 0 and 15 are valid. + Out ports followed by In ports. + More info in MIPI Alliance SoundWire 1.0 Specifications. + +- qcom,dports-type: + Usage: optional + Value type: + Definition: should be one of the following types + 0 for reduced port + 1 for simple ports + 2 for full port + Out ports followed by In ports. + More info in MIPI Alliance SoundWire 1.0 Specifications. + +Note: + More Information on detail of encoding of these fields can be +found in MIPI Alliance SoundWire 1.0 Specifications. + += SoundWire devices +Each subnode of the bus represents SoundWire device attached to it. +The properties of these nodes are defined by the individual bindings. + += EXAMPLE +The following example represents a SoundWire controller on DB845c board +which has controller integrated inside WCD934x codec on SDM845 SoC. + +soundwire: soundwire@c85 { + compatible = "qcom,soundwire-v1.3.0"; + reg = <0xc85 0x20>; + interrupts = <20 IRQ_TYPE_EDGE_RISING>; + clocks = <&wcc>; + clock-names = "iface"; + #sound-dai-cells = <1>; + qcom,dports-type = <0>; + qcom,dout-ports = <6>; + qcom,din-ports = <2>; + qcom,ports-sinterval-low = /bits/ 8 <0x07 0x1F 0x3F 0x7 0x1F 0x3F 0x0F 0x0F>; + qcom,ports-offset1 = /bits/ 8 <0x01 0x02 0x0C 0x6 0x12 0x0D 0x07 0x0A >; + qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x1F 0x00 0x00 0x1F 0x00 0x00>; + + /* Left Speaker */ + left{ + .... + }; + + /* Right Speaker */ + right{ + .... + }; +}; From patchwork Tue Aug 13 08:35:50 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 171176 Delivered-To: patch@linaro.org Received: by 2002:a92:d204:0:0:0:0:0 with SMTP id y4csp604793ily; Tue, 13 Aug 2019 01:36:09 -0700 (PDT) X-Google-Smtp-Source: APXvYqxIYJgYBWYTlWI2CKCO1B3b3h9MrKBT3kCEZGB0bKsKwpHwV4RkVRTF4bLnDD7hn0i7BKSO X-Received: by 2002:aa7:9682:: with SMTP id f2mr19297863pfk.256.1565685369365; Tue, 13 Aug 2019 01:36:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1565685369; cv=none; d=google.com; s=arc-20160816; b=0pdEeJDNmp2bktiPhtVrQUlA04PJdrwIK9OEPd0Hv5lGWf6I9HQ8pjDBEgDRseyjDB ZPatbe3btnGKPhu8Vw7wf/Ttc0QhET2nXqc08vRjKuaJVFA/126fepYUSC69CgE/q8hP ZAkckDP3Z/k/OxirHC3hehbS4jxfobxUCJxX+1XbAOW5sKNHKz4CElyWx7mmAbg5VgRD qfF2VsAO7RSVnxdNOPpnzZYvnkbj/Kcb01bLzR1LYdbREmjfdgGu6nQnwkV2EgSTInb9 iALEc943NFf53tciPF8lrVUOxqbUjw3+PTfSw//N8nsd1vZvsa64NgdhsF3Vm9qnbgOJ pHYQ== 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=YGM7Gxwst0XYXuH0LX9D8gBnYmP3aL5yoOPWvgwMokU=; b=Z2ywLkxR4e41B44Pbm3pd+q+xI5GqpVP/XuM1XI7cl0xCDSbZzwnsmzO66D6uZXPFH 2WJeoIj1hiqAsS27Kzlm+fpi/2TuV1X9J11MJ0Sm5PjQFNP/Z96oDjYaaRIq6xzRgo5/ htYti1RZM47TEqYkSxYHg0ZHIKZhB38VsayIDfPqqoM1Aw5fdEYIruHzUf2mJFysrfAX KTdBDBQaaQ/q9ENNrJUbJeuhaUlfHIrBOcL5Vaa8HMX77mwGwEq+ZXMi14CYWsdkw4sr FEKDM8ct7AHLLtqv69pg7oD2lE4mzmUgvw649K3UiWKXN9KSubRB+NhWt5dWHiXsP6mQ dUQw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="wyX/r8P/"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-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 l16si16166821pgt.568.2019.08.13.01.36.09; Tue, 13 Aug 2019 01:36:09 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-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="wyX/r8P/"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-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 S1728281AbfHMIgI (ORCPT + 28 others); Tue, 13 Aug 2019 04:36:08 -0400 Received: from mail-wr1-f66.google.com ([209.85.221.66]:41568 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728239AbfHMIgD (ORCPT ); Tue, 13 Aug 2019 04:36:03 -0400 Received: by mail-wr1-f66.google.com with SMTP id j16so4685984wrr.8 for ; Tue, 13 Aug 2019 01:36:01 -0700 (PDT) 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=YGM7Gxwst0XYXuH0LX9D8gBnYmP3aL5yoOPWvgwMokU=; b=wyX/r8P/gv07+uMWjxpBdBUli9kBt4GcUNPLYGYa+6Vfj/NiWsmABPt2s2djdcUP98 U8HZod0DHojqK5tl1iXAgjdIAaQci1mKziTLAR1e0JpEsaQJPvkd+yc95JoQprOu1Pxg 2zv9UWYjKeF07/rG885DxydYSx8+UZWPMqsRE08viydbBKxOMK2BMP9Q9VB6gC83UpOX 93eXxYP19K+7EEt3CyEyNrnd3t89rbLT6thlutlFYRSycpIZsZ9pjaaJ20YKJV7RVXhb ZypO2hvIY0mRkbDTIEKmDL4F+tcNosVLQd1+PxS2KMHnPe/Do3CoJNLGFbkH2nt9STT1 kagQ== 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=YGM7Gxwst0XYXuH0LX9D8gBnYmP3aL5yoOPWvgwMokU=; b=s8mibhy0rM9R/d6xKn0RIRtc6BRoxaMTDpAAnSraRV/n/fKoxKeHbEtnmH15ZlWHWj jxy2WKz+poztI8MgVuZ2Ysp1Do3foxCpdoR3Luc9AEzrhXwTSKELcb8OUp5RrCjRl0y/ H21isY47OZwvkrnm090hc9WeELuwjMoKdz9+neYN+caRM5QjvHmX50yADkAlIT25P9El JFwQx4Pvsalg5l2qosA+D9z5Og4wWmnJbrn5ldv5/am/ARuCGpzPWyV5RY27Qo0xwhnl PeWAEuAheqjZhGAoQq93Vs+T1eiPyIPUHFjagej5lAOjNgul5plk1YjF2msmE6bghyWu W3TQ== X-Gm-Message-State: APjAAAXQ4IgfGL9z86LqQpXp3QOIHonXQKrfkD2VcgW+BzuIkX3FIxO1 29T4Zxj8jjLMvzEp9Ae+UWqW0w== X-Received: by 2002:adf:f991:: with SMTP id f17mr17289708wrr.233.1565685360431; Tue, 13 Aug 2019 01:36:00 -0700 (PDT) Received: from srini-hackbox.lan (cpc89974-aztw32-2-0-cust43.18-1.cable.virginm.net. [86.30.250.44]) by smtp.gmail.com with ESMTPSA id o11sm8651822wrw.19.2019.08.13.01.35.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 13 Aug 2019 01:35:59 -0700 (PDT) From: Srinivas Kandagatla To: vkoul@kernel.org, broonie@kernel.org Cc: bgoswami@codeaurora.org, plai@codeaurora.org, pierre-louis.bossart@linux.intel.com, robh+dt@kernel.org, devicetree@vger.kernel.org, lgirdwood@gmail.com, alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org, spapothi@codeaurora.org, Srinivas Kandagatla Subject: [PATCH v2 5/5] soundwire: qcom: add support for SoundWire controller Date: Tue, 13 Aug 2019 09:35:50 +0100 Message-Id: <20190813083550.5877-6-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190813083550.5877-1-srinivas.kandagatla@linaro.org> References: <20190813083550.5877-1-srinivas.kandagatla@linaro.org> MIME-Version: 1.0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Qualcomm SoundWire Master controller is present in most Qualcomm SoCs either integrated as part of WCD audio codecs via slimbus or as part of SOC I/O. This patchset adds support to a very basic controller which has been tested with WCD934x SoundWire controller connected to WSA881x smart speaker amplifiers. Signed-off-by: Srinivas Kandagatla --- drivers/soundwire/Kconfig | 9 + drivers/soundwire/Makefile | 4 + drivers/soundwire/qcom.c | 919 +++++++++++++++++++++++++++++++++++++ 3 files changed, 932 insertions(+) create mode 100644 drivers/soundwire/qcom.c -- 2.21.0 diff --git a/drivers/soundwire/Kconfig b/drivers/soundwire/Kconfig index f518273cfbe3..69f3b0e36b3d 100644 --- a/drivers/soundwire/Kconfig +++ b/drivers/soundwire/Kconfig @@ -30,4 +30,13 @@ config SOUNDWIRE_INTEL enable this config option to get the SoundWire support for that device. +config SOUNDWIRE_QCOM + tristate "Qualcomm SoundWire Master driver" + depends on SLIMBUS + depends on SND_SOC + help + SoundWire Qualcomm Master driver. + If you have an Qualcomm platform which has a SoundWire Master then + enable this config option to get the SoundWire support for that + device endif diff --git a/drivers/soundwire/Makefile b/drivers/soundwire/Makefile index 45b7e5001653..e2028a1df6d5 100644 --- a/drivers/soundwire/Makefile +++ b/drivers/soundwire/Makefile @@ -17,3 +17,7 @@ obj-$(CONFIG_SOUNDWIRE_INTEL) += soundwire-intel.o soundwire-intel-init-objs := intel_init.o obj-$(CONFIG_SOUNDWIRE_INTEL) += soundwire-intel-init.o + +#Qualcomm driver +soundwire-qcom-objs := qcom.o +obj-$(CONFIG_SOUNDWIRE_QCOM) += soundwire-qcom.o diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c new file mode 100644 index 000000000000..5634912e113c --- /dev/null +++ b/drivers/soundwire/qcom.c @@ -0,0 +1,919 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019, Linaro Limited + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bus.h" + +#define SWRM_COMP_HW_VERSION 0x00 +#define SWRM_COMP_CFG_ADDR 0x04 +#define SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_MSK BIT(1) +#define SWRM_COMP_CFG_ENABLE_MSK BIT(0) +#define SWRM_COMP_PARAMS 0x100 +#define SWRM_COMP_PARAMS_DOUT_PORTS_MASK GENMASK(4, 0) +#define SWRM_COMP_PARAMS_DIN_PORTS_MASK GENMASK(9, 5) +#define SWRM_INTERRUPT_STATUS 0x200 +#define SWRM_INTERRUPT_STATUS_RMSK GENMASK(16, 0) +#define SWRM_INTERRUPT_STATUS_NEW_SLAVE_ATTACHED BIT(1) +#define SWRM_INTERRUPT_STATUS_CHANGE_ENUM_SLAVE_STATUS BIT(2) +#define SWRM_INTERRUPT_STATUS_CMD_ERROR BIT(7) +#define SWRM_INTERRUPT_STATUS_SPECIAL_CMD_ID_FINISHED BIT(10) +#define SWRM_INTERRUPT_MASK_ADDR 0x204 +#define SWRM_INTERRUPT_CLEAR 0x208 +#define SWRM_CMD_FIFO_WR_CMD 0x300 +#define SWRM_CMD_FIFO_RD_CMD 0x304 +#define SWRM_CMD_FIFO_CMD 0x308 +#define SWRM_CMD_FIFO_STATUS 0x30C +#define SWRM_CMD_FIFO_CFG_ADDR 0x314 +#define SWRM_RD_WR_CMD_RETRIES 0x7 +#define SWRM_CMD_FIFO_RD_FIFO_ADDR 0x318 +#define SWRM_ENUMERATOR_CFG_ADDR 0x500 +#define SWRM_MCP_FRAME_CTRL_BANK_ADDR(m) (0x101C + 0x40 * (m)) +#define SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT 3 +#define SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK GENMASK(2, 0) +#define SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK GENMASK(7, 3) +#define SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT 0 +#define SWRM_MCP_CFG_ADDR 0x1048 +#define SWRM_MCP_CFG_MAX_NUM_OF_CMD_NO_PINGS_BMSK GENMASK(21, 17) +#define SWRM_MCP_CFG_MAX_NUM_OF_CMD_NO_PINGS_SHFT 0x11 +#define SWRM_DEF_CMD_NO_PINGS 0x1f +#define SWRM_MCP_STATUS 0x104C +#define SWRM_MCP_STATUS_BANK_NUM_MASK BIT(0) +#define SWRM_MCP_SLV_STATUS 0x1090 +#define SWRM_MCP_SLV_STATUS_MASK GENMASK(1, 0) +#define SWRM_DP_PORT_CTRL_BANK(n, m) (0x1124 + 0x100 * (n - 1) + 0x40 * m) +#define SWRM_DP_PORT_CTRL_EN_CHAN_SHFT 0x18 +#define SWRM_DP_PORT_CTRL_OFFSET2_SHFT 0x10 +#define SWRM_DP_PORT_CTRL_OFFSET1_SHFT 0x08 +#define SWRM_AHB_BRIDGE_WR_DATA_0 0xc85 +#define SWRM_AHB_BRIDGE_WR_ADDR_0 0xc89 +#define SWRM_AHB_BRIDGE_RD_ADDR_0 0xc8d +#define SWRM_AHB_BRIDGE_RD_DATA_0 0xc91 + +#define SWRM_REG_VAL_PACK(data, dev, id, reg) \ + ((reg) | ((id) << 16) | ((dev) << 20) | ((data) << 24)) + +#define SWRM_MAX_ROW_VAL 0 /* Rows = 48 */ +#define SWRM_DEFAULT_ROWS 48 +#define SWRM_MIN_COL_VAL 0 /* Cols = 2 */ +#define SWRM_DEFAULT_COL 16 +#define SWRM_MAX_COL_VAL 7 +#define SWRM_SPECIAL_CMD_ID 0xF +#define MAX_FREQ_NUM 1 +#define TIMEOUT_MS (2 * HZ) +#define QCOM_SWRM_MAX_RD_LEN 0xf +#define QCOM_SDW_MAX_PORTS 14 +#define DEFAULT_CLK_FREQ 9600000 +#define SWRM_MAX_DAIS 0xF + +struct qcom_swrm_port_config { + u8 si; + u8 off1; + u8 off2; +}; + +struct qcom_swrm_ctrl { + struct sdw_bus bus; + struct device *dev; + struct regmap *regmap; + struct completion *comp; + struct work_struct slave_work; + /* read/write lock */ + spinlock_t comp_lock; + /* Port alloc/free lock */ + struct mutex port_lock; + struct clk *hclk; + void __iomem *base; + u8 wr_cmd_id; + u8 rd_cmd_id; + int irq; + unsigned int version; + int num_din_ports; + int num_dout_ports; + unsigned long dout_port_mask; + unsigned long din_port_mask; + struct qcom_swrm_port_config pconfig[QCOM_SDW_MAX_PORTS]; + struct sdw_stream_runtime *sruntime[SWRM_MAX_DAIS]; + enum sdw_slave_status status[SDW_MAX_DEVICES]; + int (*reg_read)(struct qcom_swrm_ctrl *ctrl, int reg, u32 *val); + int (*reg_write)(struct qcom_swrm_ctrl *ctrl, int reg, int val); +}; + +#define to_qcom_sdw(b) container_of(b, struct qcom_swrm_ctrl, bus) + +static int qcom_swrm_abh_reg_read(struct qcom_swrm_ctrl *ctrl, int reg, + u32 *val) +{ + struct regmap *wcd_regmap = ctrl->regmap; + int ret; + + /* pg register + offset */ + ret = regmap_bulk_write(wcd_regmap, SWRM_AHB_BRIDGE_RD_ADDR_0, + (u8 *)®, 4); + if (ret < 0) + return SDW_CMD_FAIL; + + ret = regmap_bulk_read(wcd_regmap, SWRM_AHB_BRIDGE_RD_DATA_0, + val, 4); + if (ret < 0) + return SDW_CMD_FAIL; + + return SDW_CMD_OK; +} + +static int qcom_swrm_mmio_reg_read(struct qcom_swrm_ctrl *ctrl, int reg, + u32 *val) +{ + *val = readl_relaxed(ctrl->base + reg); + + return 0; +} + +static int qcom_swrm_mmio_reg_write(struct qcom_swrm_ctrl *ctrl, + int reg, int val) +{ + writel_relaxed(val, ctrl->base + reg); + + return 0; +} + +static int qcom_swrm_ahb_reg_write(struct qcom_swrm_ctrl *ctrl, + int reg, int val) +{ + struct regmap *wcd_regmap = ctrl->regmap; + int ret; + /* pg register + offset */ + ret = regmap_bulk_write(wcd_regmap, SWRM_AHB_BRIDGE_WR_DATA_0, + (u8 *)&val, 4); + if (ret) + return SDW_CMD_FAIL; + + /* write address register */ + ret = regmap_bulk_write(wcd_regmap, SWRM_AHB_BRIDGE_WR_ADDR_0, + (u8 *)®, 4); + if (ret) + return SDW_CMD_FAIL; + + return SDW_CMD_OK; +} + +static int qcom_swrm_cmd_fifo_wr_cmd(struct qcom_swrm_ctrl *ctrl, u8 cmd_data, + u8 dev_addr, u16 reg_addr) +{ + DECLARE_COMPLETION_ONSTACK(comp); + unsigned long flags; + u32 val; + int ret; + + spin_lock_irqsave(&ctrl->comp_lock, flags); + ctrl->comp = ∁ + spin_unlock_irqrestore(&ctrl->comp_lock, flags); + val = SWRM_REG_VAL_PACK(cmd_data, dev_addr, + SWRM_SPECIAL_CMD_ID, reg_addr); + ret = ctrl->reg_write(ctrl, SWRM_CMD_FIFO_WR_CMD, val); + if (ret) + goto err; + + ret = wait_for_completion_timeout(ctrl->comp, + msecs_to_jiffies(TIMEOUT_MS)); + + if (!ret) + ret = SDW_CMD_IGNORED; + else + ret = SDW_CMD_OK; +err: + spin_lock_irqsave(&ctrl->comp_lock, flags); + ctrl->comp = NULL; + spin_unlock_irqrestore(&ctrl->comp_lock, flags); + + return ret; +} + +static int qcom_swrm_cmd_fifo_rd_cmd(struct qcom_swrm_ctrl *ctrl, + u8 dev_addr, u16 reg_addr, + u32 len, u8 *rval) +{ + int i, ret; + u32 val; + DECLARE_COMPLETION_ONSTACK(comp); + unsigned long flags; + + spin_lock_irqsave(&ctrl->comp_lock, flags); + ctrl->comp = ∁ + spin_unlock_irqrestore(&ctrl->comp_lock, flags); + + val = SWRM_REG_VAL_PACK(len, dev_addr, SWRM_SPECIAL_CMD_ID, reg_addr); + ret = ctrl->reg_write(ctrl, SWRM_CMD_FIFO_RD_CMD, val); + if (ret) + goto err; + + ret = wait_for_completion_timeout(ctrl->comp, + msecs_to_jiffies(TIMEOUT_MS)); + + if (!ret) { + ret = SDW_CMD_IGNORED; + goto err; + } else { + ret = SDW_CMD_OK; + } + + for (i = 0; i < len; i++) { + ret = ctrl->reg_read(ctrl, SWRM_CMD_FIFO_RD_FIFO_ADDR, &val); + if (ret) + return ret; + + rval[i] = val & 0xFF; + } + +err: + spin_lock_irqsave(&ctrl->comp_lock, flags); + ctrl->comp = NULL; + spin_unlock_irqrestore(&ctrl->comp_lock, flags); + + return ret; +} + +static void qcom_swrm_get_device_status(struct qcom_swrm_ctrl *ctrl) +{ + u32 val; + int i; + + ctrl->reg_read(ctrl, SWRM_MCP_SLV_STATUS, &val); + + for (i = 0; i < SDW_MAX_DEVICES; i++) { + u32 s; + + s = (val >> (i * 2)); + s &= SWRM_MCP_SLV_STATUS_MASK; + ctrl->status[i] = s; + } +} + +static irqreturn_t qcom_swrm_irq_handler(int irq, void *dev_id) +{ + struct qcom_swrm_ctrl *ctrl = dev_id; + u32 sts, value; + unsigned long flags; + + ctrl->reg_read(ctrl, SWRM_INTERRUPT_STATUS, &sts); + + if (sts & SWRM_INTERRUPT_STATUS_CMD_ERROR) { + ctrl->reg_read(ctrl, SWRM_CMD_FIFO_STATUS, &value); + dev_err_ratelimited(ctrl->dev, + "CMD error, fifo status 0x%x\n", + value); + ctrl->reg_write(ctrl, SWRM_CMD_FIFO_CMD, 0x1); + } + + if ((sts & SWRM_INTERRUPT_STATUS_NEW_SLAVE_ATTACHED) || + sts & SWRM_INTERRUPT_STATUS_CHANGE_ENUM_SLAVE_STATUS) + schedule_work(&ctrl->slave_work); + + ctrl->reg_write(ctrl, SWRM_INTERRUPT_CLEAR, sts); + + if (sts & SWRM_INTERRUPT_STATUS_SPECIAL_CMD_ID_FINISHED) { + spin_lock_irqsave(&ctrl->comp_lock, flags); + if (ctrl->comp) + complete(ctrl->comp); + spin_unlock_irqrestore(&ctrl->comp_lock, flags); + } + + return IRQ_HANDLED; +} +static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl) +{ + u32 val; + + /* Clear Rows and Cols */ + val = (SWRM_MAX_ROW_VAL << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT | + SWRM_MIN_COL_VAL << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT); + + ctrl->reg_write(ctrl, SWRM_MCP_FRAME_CTRL_BANK_ADDR(0), val); + + /* Disable Auto enumeration */ + ctrl->reg_write(ctrl, SWRM_ENUMERATOR_CFG_ADDR, 0); + + /* Mask soundwire interrupts */ + ctrl->reg_write(ctrl, SWRM_INTERRUPT_MASK_ADDR, + SWRM_INTERRUPT_STATUS_RMSK); + + /* Configure No pings */ + ctrl->reg_read(ctrl, SWRM_MCP_CFG_ADDR, &val); + val &= ~SWRM_MCP_CFG_MAX_NUM_OF_CMD_NO_PINGS_BMSK; + val |= (SWRM_DEF_CMD_NO_PINGS << + SWRM_MCP_CFG_MAX_NUM_OF_CMD_NO_PINGS_SHFT); + ctrl->reg_write(ctrl, SWRM_MCP_CFG_ADDR, val); + + /* Configure number of retries of a read/write cmd */ + ctrl->reg_write(ctrl, SWRM_CMD_FIFO_CFG_ADDR, SWRM_RD_WR_CMD_RETRIES); + + /* Set IRQ to PULSE */ + ctrl->reg_write(ctrl, SWRM_COMP_CFG_ADDR, + SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_MSK | + SWRM_COMP_CFG_ENABLE_MSK); + return 0; +} + +static enum sdw_command_response qcom_swrm_xfer_msg(struct sdw_bus *bus, + struct sdw_msg *msg) +{ + struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus); + int ret, i, len; + + if (msg->flags == SDW_MSG_FLAG_READ) { + for (i = 0; i < msg->len;) { + if ((msg->len - i) < QCOM_SWRM_MAX_RD_LEN) + len = msg->len - i; + else + len = QCOM_SWRM_MAX_RD_LEN; + + ret = qcom_swrm_cmd_fifo_rd_cmd(ctrl, msg->dev_num, + msg->addr + i, len, + &msg->buf[i]); + if (ret) + return ret; + + i = i + len; + } + } else if (msg->flags == SDW_MSG_FLAG_WRITE) { + for (i = 0; i < msg->len; i++) { + ret = qcom_swrm_cmd_fifo_wr_cmd(ctrl, msg->buf[i], + msg->dev_num, + msg->addr + i); + if (ret) + return SDW_CMD_IGNORED; + } + } + + return SDW_CMD_OK; +} + +static int qcom_swrm_pre_bank_switch(struct sdw_bus *bus) +{ + u32 reg = SWRM_MCP_FRAME_CTRL_BANK_ADDR(bus->params.next_bank); + struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus); + u32 val; + int ret; + + ret = ctrl->reg_read(ctrl, reg, &val); + if (ret) + return ret; + + val &= ~SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK; + val &= ~SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK; + + val |= (SWRM_MAX_ROW_VAL << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT | + SWRM_MAX_COL_VAL << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT); + + return ctrl->reg_write(ctrl, reg, val); +} + +static int qcom_swrm_port_params(struct sdw_bus *bus, + struct sdw_port_params *p_params, + unsigned int bank) +{ + /* TBD */ + return 0; +} + +static int qcom_swrm_transport_params(struct sdw_bus *bus, + struct sdw_transport_params *params, + enum sdw_reg_bank bank) +{ + struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus); + u32 value; + + value = params->offset1 << SWRM_DP_PORT_CTRL_OFFSET1_SHFT; + value |= params->offset2 << SWRM_DP_PORT_CTRL_OFFSET2_SHFT; + value |= params->sample_interval - 1; + + return ctrl->reg_write(ctrl, + SWRM_DP_PORT_CTRL_BANK((params->port_num), bank), + value); +} + +static int qcom_swrm_port_enable(struct sdw_bus *bus, + struct sdw_enable_ch *enable_ch, + unsigned int bank) +{ + u32 reg = SWRM_DP_PORT_CTRL_BANK(enable_ch->port_num, bank); + struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus); + u32 val; + int ret; + + ret = ctrl->reg_read(ctrl, reg, &val); + if (ret) + return ret; + + if (enable_ch->enable) + val |= (enable_ch->ch_mask << SWRM_DP_PORT_CTRL_EN_CHAN_SHFT); + else + val &= ~(enable_ch->ch_mask << SWRM_DP_PORT_CTRL_EN_CHAN_SHFT); + + return ctrl->reg_write(ctrl, reg, val); +} + +static struct sdw_master_port_ops qcom_swrm_port_ops = { + .dpn_set_port_params = qcom_swrm_port_params, + .dpn_set_port_transport_params = qcom_swrm_transport_params, + .dpn_port_enable_ch = qcom_swrm_port_enable, +}; + +static struct sdw_master_ops qcom_swrm_ops = { + .xfer_msg = qcom_swrm_xfer_msg, + .pre_bank_switch = qcom_swrm_pre_bank_switch, +}; + +static int qcom_swrm_compute_params(struct sdw_bus *bus) +{ + struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus); + struct sdw_master_runtime *m_rt; + struct sdw_slave_runtime *s_rt; + struct sdw_port_runtime *p_rt; + struct qcom_swrm_port_config *pcfg; + int i = 0; + + list_for_each_entry(m_rt, &bus->m_rt_list, bus_node) { + list_for_each_entry(p_rt, &m_rt->port_list, port_node) { + pcfg = &ctrl->pconfig[p_rt->num - 1]; + p_rt->transport_params.port_num = p_rt->num; + p_rt->transport_params.sample_interval = pcfg->si + 1; + p_rt->transport_params.offset1 = pcfg->off1; + p_rt->transport_params.offset2 = pcfg->off2; + } + + list_for_each_entry(s_rt, &m_rt->slave_rt_list, m_rt_node) { + list_for_each_entry(p_rt, &s_rt->port_list, port_node) { + pcfg = &ctrl->pconfig[i]; + p_rt->transport_params.port_num = p_rt->num; + p_rt->transport_params.sample_interval = + pcfg->si + 1; + p_rt->transport_params.offset1 = pcfg->off1; + p_rt->transport_params.offset2 = pcfg->off2; + i++; + } + } + } + + return 0; +} + +static u32 qcom_swrm_freq_tbl[MAX_FREQ_NUM] = { + DEFAULT_CLK_FREQ, +}; + +static void qcom_swrm_slave_wq(struct work_struct *work) +{ + struct qcom_swrm_ctrl *ctrl = + container_of(work, struct qcom_swrm_ctrl, slave_work); + + qcom_swrm_get_device_status(ctrl); + sdw_handle_slave_status(&ctrl->bus, ctrl->status); +} + +static int qcom_swrm_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dai->dev); + + if (!ctrl->sruntime[dai->id]) + return -EINVAL; + + return sdw_enable_stream(ctrl->sruntime[dai->id]); +} + +static void qcom_swrm_stream_free_ports(struct qcom_swrm_ctrl *ctrl, + struct sdw_stream_runtime *stream) +{ + struct sdw_master_runtime *m_rt; + struct sdw_port_runtime *p_rt; + unsigned long *port_mask; + + mutex_lock(&ctrl->port_lock); + + list_for_each_entry(m_rt, &stream->master_list, stream_node) { + if (m_rt->direction == SDW_DATA_DIR_RX) + port_mask = &ctrl->dout_port_mask; + else + port_mask = &ctrl->din_port_mask; + + list_for_each_entry(p_rt, &m_rt->port_list, port_node) + clear_bit(p_rt->num - 1, port_mask); + } + + mutex_unlock(&ctrl->port_lock); +} + +static int qcom_swrm_stream_alloc_ports(struct qcom_swrm_ctrl *ctrl, + struct sdw_stream_runtime *stream, + struct snd_pcm_hw_params *params, + int direction) +{ + struct sdw_port_config pconfig[QCOM_SDW_MAX_PORTS]; + struct sdw_stream_config sconfig; + struct sdw_master_runtime *m_rt; + struct sdw_slave_runtime *s_rt; + struct sdw_port_runtime *p_rt; + unsigned long *port_mask; + int i, maxport, pn, nports = 0, ret = 0; + + mutex_lock(&ctrl->port_lock); + list_for_each_entry(m_rt, &stream->master_list, stream_node) { + if (m_rt->direction == SDW_DATA_DIR_RX) { + maxport = ctrl->num_dout_ports; + port_mask = &ctrl->dout_port_mask; + } else { + maxport = ctrl->num_din_ports; + port_mask = &ctrl->din_port_mask; + } + + list_for_each_entry(s_rt, &m_rt->slave_rt_list, m_rt_node) { + list_for_each_entry(p_rt, &s_rt->port_list, port_node) { + /* Port numbers start from 1 - 14*/ + pn = find_first_zero_bit(port_mask, maxport); + if (pn > (maxport - 1)) { + dev_err(ctrl->dev, "All ports busy\n"); + ret = -EBUSY; + goto err; + } + set_bit(pn, port_mask); + pconfig[nports].num = pn + 1; + pconfig[nports].ch_mask = p_rt->ch_mask; + nports++; + } + } + } + + if (direction == SNDRV_PCM_STREAM_CAPTURE) + sconfig.direction = SDW_DATA_DIR_TX; + else + sconfig.direction = SDW_DATA_DIR_RX; + + sconfig.ch_count = 1; + sconfig.frame_rate = params_rate(params); + sconfig.type = stream->type; + sconfig.bps = 1; + sdw_stream_add_master(&ctrl->bus, &sconfig, pconfig, + nports, stream); +err: + if (ret) { + for (i = 0; i < nports; i++) + clear_bit(pconfig[i].num - 1, port_mask); + } + + mutex_unlock(&ctrl->port_lock); + + return ret; +} + +static int qcom_swrm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dai->dev); + struct sdw_stream_runtime *sruntime = ctrl->sruntime[dai->id]; + int ret; + + ret = qcom_swrm_stream_alloc_ports(ctrl, sruntime, params, + substream->stream); + if (ret) + return ret; + + ret = sdw_prepare_stream(sruntime); + if (ret) + qcom_swrm_stream_free_ports(ctrl, sruntime); + + return ret; +} + +static int qcom_swrm_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dai->dev); + struct sdw_stream_runtime *sruntime = ctrl->sruntime[dai->id]; + + qcom_swrm_stream_free_ports(ctrl, sruntime); + sdw_stream_remove_master(&ctrl->bus, sruntime); + sdw_deprepare_stream(sruntime); + sdw_disable_stream(sruntime); + + return 0; +} + +static void *qcom_pdm_get_sdw_stream(struct snd_soc_dai *dai, + int direction) +{ + struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dai->dev); + + return ctrl->sruntime[dai->id]; +} + +static int qcom_swrm_startup(struct snd_pcm_substream *stream, + struct snd_soc_dai *dai) +{ + struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dai->dev); + struct sdw_stream_runtime *sruntime; + + sruntime = sdw_alloc_stream(dai->name); + if (!sruntime) + return -ENOMEM; + + ctrl->sruntime[dai->id] = sruntime; + + return 0; +} + +static void qcom_swrm_shutdown(struct snd_pcm_substream *stream, + struct snd_soc_dai *dai) +{ + struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dai->dev); + + sdw_release_stream(ctrl->sruntime[dai->id]); + ctrl->sruntime[dai->id] = NULL; +} + +static const struct snd_soc_dai_ops qcom_swrm_pdm_dai_ops = { + .hw_params = qcom_swrm_hw_params, + .prepare = qcom_swrm_prepare, + .hw_free = qcom_swrm_hw_free, + .startup = qcom_swrm_startup, + .shutdown = qcom_swrm_shutdown, + .get_sdw_stream = qcom_pdm_get_sdw_stream, +}; + +static const struct snd_soc_component_driver qcom_swrm_dai_component = { + .name = "soundwire", +}; + +static int qcom_swrm_register_dais(struct qcom_swrm_ctrl *ctrl) +{ + int num_dais = ctrl->num_dout_ports + ctrl->num_din_ports; + struct snd_soc_dai_driver *dais; + struct snd_soc_pcm_stream *stream; + struct device *dev = ctrl->dev; + int i; + + /* PDM dais are only tested for now */ + dais = devm_kcalloc(dev, num_dais, sizeof(*dais), GFP_KERNEL); + if (!dais) + return -ENOMEM; + + for (i = 0; i < num_dais; i++) { + dais[i].name = devm_kasprintf(dev, GFP_KERNEL, "SDW Pin%d", i); + if (!dais[i].name) + return -ENOMEM; + + if (i < ctrl->num_dout_ports) { + stream = &dais[i].playback; + stream->stream_name = devm_kasprintf(dev, GFP_KERNEL, + "SDW Tx%d", i); + } else { + stream = &dais[i].capture; + stream->stream_name = devm_kasprintf(dev, GFP_KERNEL, + "SDW Rx%d", i); + } + + if (!stream->stream_name) + return -ENOMEM; + + stream->channels_min = 1; + stream->channels_max = 1; + stream->rates = SNDRV_PCM_RATE_48000; + stream->formats = SNDRV_PCM_FMTBIT_S16_LE; + + dais[i].ops = &qcom_swrm_pdm_dai_ops; + dais[i].id = i; + } + + return devm_snd_soc_register_component(dev, &qcom_swrm_dai_component, + dais, num_dais); +} + +static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl) +{ + struct device_node *np = ctrl->dev->of_node; + u8 off1[QCOM_SDW_MAX_PORTS]; + u8 off2[QCOM_SDW_MAX_PORTS]; + u8 si[QCOM_SDW_MAX_PORTS]; + int i, ret, nports, val; + + ret = ctrl->reg_read(ctrl, SWRM_COMP_PARAMS, &val); + if (ret) + return ret; + + ctrl->num_dout_ports = val & SWRM_COMP_PARAMS_DOUT_PORTS_MASK; + ctrl->num_din_ports = (val & SWRM_COMP_PARAMS_DIN_PORTS_MASK) >> 5; + + ret = of_property_read_u32(np, "qcom,din-ports", &val); + if (ret) + return ret; + + if (val > ctrl->num_din_ports) + return -EINVAL; + + ctrl->num_din_ports = val; + + ret = of_property_read_u32(np, "qcom,dout-ports", &val); + if (ret) + return ret; + + if (val > ctrl->num_dout_ports) + return -EINVAL; + + ctrl->num_dout_ports = val; + + nports = ctrl->num_dout_ports + ctrl->num_din_ports; + + ret = of_property_read_u8_array(np, "qcom,ports-offset1", + off1, nports); + if (ret) + return ret; + + ret = of_property_read_u8_array(np, "qcom,ports-offset2", + off2, nports); + if (ret) + return ret; + + ret = of_property_read_u8_array(np, "qcom,ports-sinterval-low", + si, nports); + if (ret) + return ret; + + for (i = 0; i < nports; i++) { + ctrl->pconfig[i].si = si[i]; + ctrl->pconfig[i].off1 = off1[i]; + ctrl->pconfig[i].off2 = off2[i]; + } + + return 0; +} + +static int qcom_swrm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct sdw_master_prop *prop; + struct sdw_bus_params *params; + struct qcom_swrm_ctrl *ctrl; + struct resource *res; + int ret; + u32 val; + + ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); + if (!ctrl) + return -ENOMEM; + + if (dev->parent->bus == &slimbus_bus) { + ctrl->reg_read = qcom_swrm_abh_reg_read; + ctrl->reg_write = qcom_swrm_ahb_reg_write; + ctrl->regmap = dev_get_regmap(dev->parent, NULL); + if (!ctrl->regmap) + return -EINVAL; + } else { + ctrl->reg_read = qcom_swrm_mmio_reg_read; + ctrl->reg_write = qcom_swrm_mmio_reg_write; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + ctrl->base = devm_ioremap_resource(dev, res); + if (IS_ERR(ctrl->base)) + return PTR_ERR(ctrl->base); + } + + ctrl->irq = of_irq_get(dev->of_node, 0); + if (ctrl->irq < 0) + return ctrl->irq; + + ctrl->hclk = devm_clk_get(dev, "iface"); + if (IS_ERR(ctrl->hclk)) + return PTR_ERR(ctrl->hclk); + + clk_prepare_enable(ctrl->hclk); + + ctrl->dev = dev; + dev_set_drvdata(&pdev->dev, ctrl); + spin_lock_init(&ctrl->comp_lock); + mutex_init(&ctrl->port_lock); + INIT_WORK(&ctrl->slave_work, qcom_swrm_slave_wq); + + ctrl->bus.dev = dev; + ctrl->bus.ops = &qcom_swrm_ops; + ctrl->bus.port_ops = &qcom_swrm_port_ops; + ctrl->bus.compute_params = &qcom_swrm_compute_params; + + ret = qcom_swrm_get_port_config(ctrl); + if (ret) + return ret; + + params = &ctrl->bus.params; + params->max_dr_freq = DEFAULT_CLK_FREQ; + params->curr_dr_freq = DEFAULT_CLK_FREQ; + params->col = SWRM_DEFAULT_COL; + params->row = SWRM_DEFAULT_ROWS; + ctrl->reg_read(ctrl, SWRM_MCP_STATUS, &val); + params->curr_bank = val & SWRM_MCP_STATUS_BANK_NUM_MASK; + params->next_bank = !params->curr_bank; + + prop = &ctrl->bus.prop; + prop->max_clk_freq = DEFAULT_CLK_FREQ; + prop->num_clk_gears = 0; + prop->num_clk_freq = MAX_FREQ_NUM; + prop->clk_freq = &qcom_swrm_freq_tbl[0]; + prop->default_col = SWRM_DEFAULT_COL; + prop->default_row = SWRM_DEFAULT_ROWS; + + ctrl->reg_read(ctrl, SWRM_COMP_HW_VERSION, &ctrl->version); + + ret = devm_request_threaded_irq(dev, ctrl->irq, NULL, + qcom_swrm_irq_handler, + IRQF_TRIGGER_RISING, + "soundwire", ctrl); + if (ret) { + dev_err(dev, "Failed to request soundwire irq\n"); + goto err; + } + + ret = sdw_add_bus_master(&ctrl->bus); + if (ret) { + dev_err(dev, "Failed to register Soundwire controller (%d)\n", + ret); + goto err; + } + + qcom_swrm_init(ctrl); + ret = qcom_swrm_register_dais(ctrl); + if (ret) + goto err; + + dev_info(dev, "Qualcomm Soundwire controller v%x.%x.%x Registered\n", + (ctrl->version >> 24) & 0xff, (ctrl->version >> 16) & 0xff, + ctrl->version & 0xffff); + + return 0; +err: + clk_disable_unprepare(ctrl->hclk); + return ret; +} + +static int qcom_swrm_remove(struct platform_device *pdev) +{ + struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(&pdev->dev); + + sdw_delete_bus_master(&ctrl->bus); + clk_disable_unprepare(ctrl->hclk); + + return 0; +} + +static int qcom_swrm_runtime_suspend(struct device *device) +{ + /* TBD */ + return 0; +} + +static int qcom_swrm_runtime_resume(struct device *device) +{ + /* TBD */ + return 0; +} + +static const struct dev_pm_ops qcom_swrm_dev_pm_ops = { + SET_RUNTIME_PM_OPS(qcom_swrm_runtime_suspend, + qcom_swrm_runtime_resume, + NULL + ) +}; + +static const struct of_device_id qcom_swrm_of_match[] = { + { .compatible = "qcom,soundwire-v1.3.0",}, + { .compatible = "qcom,soundwire-v1.5.0",}, + { .compatible = "qcom,soundwire-v1.6.0",}, + {/* sentinel */}, +}; + +MODULE_DEVICE_TABLE(of, qcom_swrm_of_match); + +static struct platform_driver qcom_swrm_driver = { + .probe = &qcom_swrm_probe, + .remove = &qcom_swrm_remove, + .driver = { + .name = "qcom-soundwire", + .of_match_table = qcom_swrm_of_match, + .pm = &qcom_swrm_dev_pm_ops, + } +}; +module_platform_driver(qcom_swrm_driver); + +MODULE_DESCRIPTION("Qualcomm soundwire driver"); +MODULE_LICENSE("GPL v2");