From patchwork Fri Dec 20 13:11:33 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Pargmann X-Patchwork-Id: 3388431 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id E28B39F314 for ; Fri, 20 Dec 2013 13:16:27 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id A66F2206F6 for ; Fri, 20 Dec 2013 13:16:26 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 534A1206F1 for ; Fri, 20 Dec 2013 13:16:25 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VtzuG-0000bJ-Qh; Fri, 20 Dec 2013 13:14:21 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Vtztl-0002E8-Sk; Fri, 20 Dec 2013 13:13:49 +0000 Received: from metis.ext.pengutronix.de ([2001:6f8:1178:4:290:27ff:fe1d:cc33]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Vtzsl-00026f-4p for linux-arm-kernel@lists.infradead.org; Fri, 20 Dec 2013 13:12:49 +0000 Received: from dude.hi.pengutronix.de ([2001:6f8:1178:2:21e:67ff:fe11:9c5c]) by metis.ext.pengutronix.de with esmtp (Exim 4.72) (envelope-from ) id 1Vtzrw-0006XF-Fx; Fri, 20 Dec 2013 14:11:56 +0100 Received: from mpa by dude.hi.pengutronix.de with local (Exim 4.82) (envelope-from ) id 1Vtzrs-0004es-UM; Fri, 20 Dec 2013 14:11:52 +0100 From: Markus Pargmann To: Mark Brown , Liam Girdwood , Timur Tabi Subject: [PATCH v4 6/9] ASoC: fsl-ssi: Add configuration helper functions Date: Fri, 20 Dec 2013 14:11:33 +0100 Message-Id: <1387545096-2334-7-git-send-email-mpa@pengutronix.de> X-Mailer: git-send-email 1.8.5.1 In-Reply-To: <1387545096-2334-1-git-send-email-mpa@pengutronix.de> References: <1387545096-2334-1-git-send-email-mpa@pengutronix.de> X-SA-Exim-Connect-IP: 2001:6f8:1178:2:21e:67ff:fe11:9c5c X-SA-Exim-Mail-From: mpa@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-arm-kernel@lists.infradead.org X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20131220_081247_592148_197408E5 X-CRM114-Status: GOOD ( 20.24 ) X-Spam-Score: -2.4 (--) Cc: alsa-devel@alsa-project.org, Nicolin Chen , kernel@pengutronix.de, Markus Pargmann , Shawn Guo , Fabio Estevam , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.7 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds a struct 'fsl_ssi_rxtx_reg_val' which holds register values necessary to enable rx/tx. Based on those preset register values, the added configuration functions will cleanly enable/disable different parts of the SSI IP while supporting online/offline configuration. Different operating modes can be setup directly as different register values in fsl_ssi_reg_val. These functions and structs will help to cleanup and simplify the trigger function to support many different IP versions (online/offline configuration) and different operating modes. Signed-off-by: Markus Pargmann --- sound/soc/fsl/fsl_ssi.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 2f25525..70bb466 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -131,6 +131,18 @@ enum fsl_ssi_type { FSL_SSI_MX51, }; +struct fsl_ssi_reg_val { + u32 sier; + u32 srcr; + u32 stcr; + u32 scr; +}; + +struct fsl_ssi_rxtx_reg_val { + struct fsl_ssi_reg_val rx; + struct fsl_ssi_reg_val tx; +}; + /** * fsl_ssi_private: per-SSI private data * @@ -169,6 +181,8 @@ struct fsl_ssi_private { struct imx_dma_data filter_data_tx; struct imx_dma_data filter_data_rx; struct imx_pcm_fiq_params fiq_params; + /* Register values for rx/tx configuration */ + struct fsl_ssi_rxtx_reg_val rxtx_reg_val; struct { unsigned int rfrc; @@ -462,6 +476,114 @@ static void fsl_ssi_debugfs_remove(struct fsl_ssi_private *ssi_private) #endif /* IS_ENABLED(CONFIG_DEBUG_FS) */ +/* + * Enable/Disable all rx/tx config flags at once. + */ +static void fsl_ssi_rxtx_config(struct fsl_ssi_private *ssi_private, + bool enable) +{ + struct ccsr_ssi __iomem *ssi = ssi_private->ssi; + struct fsl_ssi_rxtx_reg_val *vals = &ssi_private->rxtx_reg_val; + + if (enable) { + write_ssi_mask(&ssi->sier, 0, vals->rx.sier | vals->tx.sier); + write_ssi_mask(&ssi->srcr, 0, vals->rx.srcr | vals->tx.srcr); + write_ssi_mask(&ssi->stcr, 0, vals->rx.stcr | vals->tx.stcr); + } else { + write_ssi_mask(&ssi->srcr, vals->rx.srcr | vals->tx.srcr, 0); + write_ssi_mask(&ssi->stcr, vals->rx.stcr | vals->tx.stcr, 0); + write_ssi_mask(&ssi->sier, vals->rx.sier | vals->tx.sier, 0); + } +} + +/* + * Enable/Disable a ssi configuration. You have to pass either + * ssi_private->rxtx_reg_val.rx or tx as vals parameter. + */ +static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable, + struct fsl_ssi_reg_val *vals) +{ + struct ccsr_ssi __iomem *ssi = ssi_private->ssi; + struct fsl_ssi_reg_val *avals; + u32 scr_val = read_ssi(&ssi->scr); + int nr_active_streams = !!(scr_val & CCSR_SSI_SCR_TE) + + !!(scr_val & CCSR_SSI_SCR_RE); + + /* Find the other direction values rx or tx which we do not want to + * modify */ + if (&ssi_private->rxtx_reg_val.rx == vals) + avals = &ssi_private->rxtx_reg_val.tx; + else + avals = &ssi_private->rxtx_reg_val.rx; + + /* If vals should be disabled, start with disabling the unit */ + if (!enable) { + u32 scr = vals->scr & (vals->scr ^ avals->scr); + write_ssi_mask(&ssi->scr, scr, 0); + } + + /* + * We are running on a SoC which does not support online SSI + * reconfiguration, so we have to enable all necessary flags at once + * even if we do not use them later (capture and playback configuration) + */ + if (ssi_private->offline_config) { + if ((enable && !nr_active_streams) || + (!enable && nr_active_streams == 1)) + fsl_ssi_rxtx_config(ssi_private, enable); + + goto config_done; + } + + /* + * Configure single direction units while the SSI unit is running + * (online configuration) + */ + if (enable) { + write_ssi_mask(&ssi->sier, 0, vals->sier); + write_ssi_mask(&ssi->srcr, 0, vals->srcr); + write_ssi_mask(&ssi->stcr, 0, vals->stcr); + } else { + u32 sier; + u32 srcr; + u32 stcr; + + /* + * Disabling the necessary flags for one of rx/tx while the + * other stream is active is a little bit more difficult. We + * have to disable only those flags that differ between both + * streams (rx XOR tx) and that are set in the stream that is + * disabled now. Otherwise we could alter flags of the other + * stream + */ + + /* These assignments are simply vals without bits set in avals*/ + sier = vals->sier & (vals->sier ^ avals->sier); + srcr = vals->srcr & (vals->srcr ^ avals->srcr); + stcr = vals->stcr & (vals->stcr ^ avals->stcr); + + write_ssi_mask(&ssi->srcr, srcr, 0); + write_ssi_mask(&ssi->stcr, stcr, 0); + write_ssi_mask(&ssi->sier, sier, 0); + } + +config_done: + /* Enabling of subunits is done after configuration */ + if (enable) + write_ssi_mask(&ssi->scr, 0, vals->scr); +} + + +static void fsl_ssi_rx_config(struct fsl_ssi_private *ssi_private, bool enable) +{ + fsl_ssi_config(ssi_private, enable, &ssi_private->rxtx_reg_val.rx); +} + +static void fsl_ssi_tx_config(struct fsl_ssi_private *ssi_private, bool enable) +{ + fsl_ssi_config(ssi_private, enable, &ssi_private->rxtx_reg_val.tx); +} + static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private) { struct ccsr_ssi __iomem *ssi = ssi_private->ssi;