From patchwork Fri May 26 12:28:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Fitzgerald X-Patchwork-Id: 99479 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp435028vqr; Fri, 26 May 2023 05:32:46 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5wj9hQUtK4oQ+l/YJxHPssN3mI0UnUdCoGYI8Ooga2Jd2qKnA44hIEjp8Ai5lqj8ej1IMK X-Received: by 2002:a05:6a00:1995:b0:64d:123d:cc74 with SMTP id d21-20020a056a00199500b0064d123dcc74mr3631376pfl.4.1685104365982; Fri, 26 May 2023 05:32:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685104365; cv=none; d=google.com; s=arc-20160816; b=CaaDvVoUZ8+wD4z2fHpzKWlOggOa//c0KL+4MwiondVRFdAYcJfPrPhRxLcF8cxszi DLiRnAbljaEpK+Y0rl9egG9fSoz9aCnEtedXNgRyEKMrLpEbxBtmZ7Grups+vg0LO6UI nO1J9idt+zcVfBoyE+brOQyaQr2sZketaDX5tseE5iP7v0PZTHKTCcxsiDG6gRHrwc3B Y7LlCUdWtM1U3Or0SFYKWVi7Bs4MQLwMIVcyfVGRZ7MxZ8iVjuZ0ogXLlIckTXW54OEY r1kMDA2fQgt6f3OlMvwgNzF0J0fa1yWho1AjK5eYe2FFenJsIpeoOZAlgxxrHgtxGPpT k+NQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=vhdBi80tQTrbC9pnuMymFLkYdlzd+ymyPzVzH7zmeI8=; b=nnPsfCOuNprBwO2QBP+vlcINdTa6v7cQWmu3nL9hM75J2Jxpqj9tCYS2K4JEeOLpXJ 7dhmYAXAjSugrktOYwqjlUjpoK8hvCCic1Gsgkd4unG/JpXVrTsa6ZXbWeW55KRuUibc 6AAdUN16jeE96/maeiLut7aww16L9QRnddRijXxUrGdhxj2YQuDKLn8pFh9Sq4Owzbt0 uIwzWo7c3IiQ9d1kxGQSBqJnVRHHYAtt43cobMeGjbD13XRzJIlF5QG7eYtmw9TM0UXr qzIwPXoRf/jcX0aQtmqEbKkZ7iPdUwrFSDjEHX0x3FIup//jDQLKpe03owVL49ma6D/W rx1A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=EISV7JI+; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id t127-20020a637885000000b00524ca1b89f0si586598pgc.596.2023.05.26.05.32.33; Fri, 26 May 2023 05:32:45 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=EISV7JI+; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243604AbjEZM3y (ORCPT + 99 others); Fri, 26 May 2023 08:29:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59258 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243466AbjEZM3X (ORCPT ); Fri, 26 May 2023 08:29:23 -0400 Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 92A911B1 for ; Fri, 26 May 2023 05:29:16 -0700 (PDT) Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 34QC2vwT003125; Fri, 26 May 2023 07:28:57 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=vhdBi80tQTrbC9pnuMymFLkYdlzd+ymyPzVzH7zmeI8=; b=EISV7JI+7XXswEfuOLpSwV/IJJQg0PeNxmEHQjeSedWTzFyfkVdm127qsHgFlkr8eCZo 59MDnUOtM7ioHgT7btepLdHgilISgkbt4hZ812bGl2iEUj0AF8ALE02RPFyjp7gnT7t7 b7GqsK0OBKIks7dwJGUEcYGCG6beRZMIzGEhZYM4bBKoZXSwkoVbxNdjrJtKmHbEwiRm hljHXnr+HND0z9xAsDFqWSz2I5YHHDrR6eA9J3SEuzNvrNF1kBNydH9/A0DKcLO+x10O LcOVRlXuNk5SI/d7N6V2KYHdO/9303R26Q/NFlcVWPlmb9owzixVd7JUh4PNlFhlx08B Yw== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 3qsde8k66w-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 26 May 2023 07:28:57 -0500 Received: from ediex01.ad.cirrus.com (198.61.84.80) by ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Fri, 26 May 2023 07:28:54 -0500 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Fri, 26 May 2023 07:28:54 -0500 Received: from EDIN4L06LR3.ad.cirrus.com (EDIN4L06LR3.ad.cirrus.com [198.61.65.166]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id BCDB3B38; Fri, 26 May 2023 12:28:54 +0000 (UTC) From: Richard Fitzgerald To: , , CC: , , , Simon Trimmer , Richard Fitzgerald Subject: [PATCH v3 01/12] ASoC: cs35l56: Move shared data into a common data structure Date: Fri, 26 May 2023 13:28:41 +0100 Message-ID: <20230526122852.4552-2-rf@opensource.cirrus.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230526122852.4552-1-rf@opensource.cirrus.com> References: <20230526122852.4552-1-rf@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: QUNgCjzPW_dBkrC8WsY0aK45lv-HKTut X-Proofpoint-GUID: QUNgCjzPW_dBkrC8WsY0aK45lv-HKTut X-Proofpoint-Spam-Reason: safe X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1766959995420316784?= X-GMAIL-MSGID: =?utf-8?q?1766959995420316784?= From: Simon Trimmer The ASoC and HDA drivers have structures that contain some of the same information - instead of maintaining two locations for this data the drivers should share a common data structure as this will enable common utility functions to be created. The first step is to move the location of these members in the ASoC driver. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Acked-by: Mark Brown --- This is identical to V1 except that the 1-line fix for cs35l56_sdw_interrupt() has been squashed in. So I've included Mark's ack that was conditional on that squash. --- include/sound/cs35l56.h | 15 +- sound/soc/codecs/cs35l56-i2c.c | 14 +- sound/soc/codecs/cs35l56-sdw.c | 68 ++--- sound/soc/codecs/cs35l56-shared.c | 6 +- sound/soc/codecs/cs35l56-spi.c | 10 +- sound/soc/codecs/cs35l56.c | 404 +++++++++++++++--------------- sound/soc/codecs/cs35l56.h | 13 +- 7 files changed, 270 insertions(+), 260 deletions(-) diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h index 1f9713d7ca76..3a029c6621c9 100644 --- a/include/sound/cs35l56.h +++ b/include/sound/cs35l56.h @@ -252,6 +252,19 @@ #define CS35L56_NUM_BULK_SUPPLIES 3 #define CS35L56_NUM_DSP_REGIONS 5 +struct cs35l56_base { + struct device *dev; + struct regmap *regmap; + int irq; + struct mutex irq_lock; + u8 rev; + bool init_done; + bool fw_patched; + bool secured; + bool can_hibernate; + struct gpio_desc *reset_gpio; +}; + extern struct regmap_config cs35l56_regmap_i2c; extern struct regmap_config cs35l56_regmap_spi; extern struct regmap_config cs35l56_regmap_sdw; @@ -260,7 +273,7 @@ extern const struct cs_dsp_region cs35l56_dsp1_regions[CS35L56_NUM_DSP_REGIONS]; extern const char * const cs35l56_tx_input_texts[CS35L56_NUM_INPUT_SRC]; extern const unsigned int cs35l56_tx_input_values[CS35L56_NUM_INPUT_SRC]; -void cs35l56_reread_firmware_registers(struct device *dev, struct regmap *regmap); +void cs35l56_reread_firmware_registers(struct cs35l56_base *cs35l56_base); int cs35l56_get_bclk_freq_id(unsigned int freq); void cs35l56_fill_supply_names(struct regulator_bulk_data *data); diff --git a/sound/soc/codecs/cs35l56-i2c.c b/sound/soc/codecs/cs35l56-i2c.c index 295caad26224..1f430829214b 100644 --- a/sound/soc/codecs/cs35l56-i2c.c +++ b/sound/soc/codecs/cs35l56-i2c.c @@ -26,14 +26,14 @@ static int cs35l56_i2c_probe(struct i2c_client *client) if (!cs35l56) return -ENOMEM; - cs35l56->dev = dev; - cs35l56->can_hibernate = true; + cs35l56->base.dev = dev; + cs35l56->base.can_hibernate = true; i2c_set_clientdata(client, cs35l56); - cs35l56->regmap = devm_regmap_init_i2c(client, regmap_config); - if (IS_ERR(cs35l56->regmap)) { - ret = PTR_ERR(cs35l56->regmap); - return dev_err_probe(cs35l56->dev, ret, "Failed to allocate register map\n"); + cs35l56->base.regmap = devm_regmap_init_i2c(client, regmap_config); + if (IS_ERR(cs35l56->base.regmap)) { + ret = PTR_ERR(cs35l56->base.regmap); + return dev_err_probe(cs35l56->base.dev, ret, "Failed to allocate register map\n"); } ret = cs35l56_common_probe(cs35l56); @@ -42,7 +42,7 @@ static int cs35l56_i2c_probe(struct i2c_client *client) ret = cs35l56_init(cs35l56); if (ret == 0) - ret = cs35l56_irq_request(cs35l56, client->irq); + ret = cs35l56_irq_request(&cs35l56->base, client->irq); if (ret < 0) cs35l56_remove(cs35l56); diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c index 2cde78605ba9..98be005b8787 100644 --- a/sound/soc/codecs/cs35l56-sdw.c +++ b/sound/soc/codecs/cs35l56-sdw.c @@ -166,13 +166,13 @@ static void cs35l56_sdw_init(struct sdw_slave *peripheral) struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); int ret; - pm_runtime_get_noresume(cs35l56->dev); + pm_runtime_get_noresume(cs35l56->base.dev); - regcache_cache_only(cs35l56->regmap, false); + regcache_cache_only(cs35l56->base.regmap, false); ret = cs35l56_init(cs35l56); if (ret < 0) { - regcache_cache_only(cs35l56->regmap, true); + regcache_cache_only(cs35l56->base.regmap, true); goto out; } @@ -180,15 +180,15 @@ static void cs35l56_sdw_init(struct sdw_slave *peripheral) * cs35l56_init can return with !init_done if it triggered * a soft reset. */ - if (cs35l56->init_done) { + if (cs35l56->base.init_done) { /* Enable SoundWire interrupts */ sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, CS35L56_SDW_INT_MASK_CODEC_IRQ); } out: - pm_runtime_mark_last_busy(cs35l56->dev); - pm_runtime_put_autosuspend(cs35l56->dev); + pm_runtime_mark_last_busy(cs35l56->base.dev); + pm_runtime_put_autosuspend(cs35l56->base.dev); } static int cs35l56_sdw_interrupt(struct sdw_slave *peripheral, @@ -198,7 +198,7 @@ static int cs35l56_sdw_interrupt(struct sdw_slave *peripheral, /* SoundWire core holds our pm_runtime when calling this function. */ - dev_dbg(cs35l56->dev, "int control_port=%#x\n", status->control_port); + dev_dbg(cs35l56->base.dev, "int control_port=%#x\n", status->control_port); if ((status->control_port & SDW_SCP_INT1_IMPL_DEF) == 0) return 0; @@ -207,7 +207,7 @@ static int cs35l56_sdw_interrupt(struct sdw_slave *peripheral, * Prevent bus manager suspending and possibly issuing a * bus-reset before the queued work has run. */ - pm_runtime_get_noresume(cs35l56->dev); + pm_runtime_get_noresume(cs35l56->base.dev); /* * Mask and clear until it has been handled. The read of GEN_INT_STAT_1 @@ -230,14 +230,14 @@ static void cs35l56_sdw_irq_work(struct work_struct *work) struct cs35l56_private, sdw_irq_work); - cs35l56_irq(-1, cs35l56); + cs35l56_irq(-1, &cs35l56->base); /* unmask interrupts */ if (!cs35l56->sdw_irq_no_unmask) sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, CS35L56_SDW_INT_MASK_CODEC_IRQ); - pm_runtime_put_autosuspend(cs35l56->dev); + pm_runtime_put_autosuspend(cs35l56->base.dev); } static int cs35l56_sdw_read_prop(struct sdw_slave *peripheral) @@ -246,7 +246,7 @@ static int cs35l56_sdw_read_prop(struct sdw_slave *peripheral) struct sdw_slave_prop *prop = &peripheral->prop; struct sdw_dpn_prop *ports; - ports = devm_kcalloc(cs35l56->dev, 2, sizeof(*ports), GFP_KERNEL); + ports = devm_kcalloc(cs35l56->base.dev, 2, sizeof(*ports), GFP_KERNEL); if (!ports) return -ENOMEM; @@ -279,17 +279,17 @@ static int cs35l56_sdw_update_status(struct sdw_slave *peripheral, switch (status) { case SDW_SLAVE_ATTACHED: - dev_dbg(cs35l56->dev, "%s: ATTACHED\n", __func__); + dev_dbg(cs35l56->base.dev, "%s: ATTACHED\n", __func__); if (cs35l56->sdw_attached) break; - if (!cs35l56->init_done || cs35l56->soft_resetting) + if (!cs35l56->base.init_done || cs35l56->soft_resetting) cs35l56_sdw_init(peripheral); cs35l56->sdw_attached = true; break; case SDW_SLAVE_UNATTACHED: - dev_dbg(cs35l56->dev, "%s: UNATTACHED\n", __func__); + dev_dbg(cs35l56->base.dev, "%s: UNATTACHED\n", __func__); cs35l56->sdw_attached = false; break; default: @@ -305,7 +305,7 @@ static int cs35l56_a1_kick_divider(struct cs35l56_private *cs35l56, unsigned int curr_scale_reg, next_scale_reg; int curr_scale, next_scale, ret; - if (!cs35l56->init_done) + if (!cs35l56->base.init_done) return 0; if (peripheral->bus->params.curr_bank) { @@ -324,13 +324,13 @@ static int cs35l56_a1_kick_divider(struct cs35l56_private *cs35l56, */ curr_scale = sdw_read_no_pm(peripheral, curr_scale_reg); if (curr_scale < 0) { - dev_err(cs35l56->dev, "Failed to read current clock scale: %d\n", curr_scale); + dev_err(cs35l56->base.dev, "Failed to read current clock scale: %d\n", curr_scale); return curr_scale; } next_scale = sdw_read_no_pm(peripheral, next_scale_reg); if (next_scale < 0) { - dev_err(cs35l56->dev, "Failed to read next clock scale: %d\n", next_scale); + dev_err(cs35l56->base.dev, "Failed to read next clock scale: %d\n", next_scale); return next_scale; } @@ -338,7 +338,8 @@ static int cs35l56_a1_kick_divider(struct cs35l56_private *cs35l56, next_scale = cs35l56->old_sdw_clock_scale; ret = sdw_write_no_pm(peripheral, next_scale_reg, next_scale); if (ret < 0) { - dev_err(cs35l56->dev, "Failed to modify current clock scale: %d\n", ret); + dev_err(cs35l56->base.dev, "Failed to modify current clock scale: %d\n", + ret); return ret; } } @@ -346,11 +347,11 @@ static int cs35l56_a1_kick_divider(struct cs35l56_private *cs35l56, cs35l56->old_sdw_clock_scale = curr_scale; ret = sdw_write_no_pm(peripheral, curr_scale_reg, CS35L56_SDW_INVALID_BUS_SCALE); if (ret < 0) { - dev_err(cs35l56->dev, "Failed to modify current clock scale: %d\n", ret); + dev_err(cs35l56->base.dev, "Failed to modify current clock scale: %d\n", ret); return ret; } - dev_dbg(cs35l56->dev, "Next bus scale: %#x\n", next_scale); + dev_dbg(cs35l56->base.dev, "Next bus scale: %#x\n", next_scale); return 0; } @@ -362,9 +363,10 @@ static int cs35l56_sdw_bus_config(struct sdw_slave *peripheral, int sclk; sclk = params->curr_dr_freq / 2; - dev_dbg(cs35l56->dev, "%s: sclk=%u c=%u r=%u\n", __func__, sclk, params->col, params->row); + dev_dbg(cs35l56->base.dev, "%s: sclk=%u c=%u r=%u\n", + __func__, sclk, params->col, params->row); - if (cs35l56->rev < 0xb0) + if (cs35l56->base.rev < 0xb0) return cs35l56_a1_kick_divider(cs35l56, peripheral); return 0; @@ -376,7 +378,7 @@ static int __maybe_unused cs35l56_sdw_clk_stop(struct sdw_slave *peripheral, { struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); - dev_dbg(cs35l56->dev, "%s: mode:%d type:%d\n", __func__, mode, type); + dev_dbg(cs35l56->base.dev, "%s: mode:%d type:%d\n", __func__, mode, type); return 0; } @@ -397,10 +399,10 @@ static int __maybe_unused cs35l56_sdw_handle_unattach(struct cs35l56_private *cs if (peripheral->unattach_request) { /* Cannot access registers until bus is re-initialized. */ - dev_dbg(cs35l56->dev, "Wait for initialization_complete\n"); + dev_dbg(cs35l56->base.dev, "Wait for initialization_complete\n"); if (!wait_for_completion_timeout(&peripheral->initialization_complete, msecs_to_jiffies(5000))) { - dev_err(cs35l56->dev, "initialization_complete timed out\n"); + dev_err(cs35l56->base.dev, "initialization_complete timed out\n"); return -ETIMEDOUT; } @@ -419,7 +421,7 @@ static int __maybe_unused cs35l56_sdw_runtime_suspend(struct device *dev) { struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); - if (!cs35l56->init_done) + if (!cs35l56->base.init_done) return 0; return cs35l56_runtime_suspend(dev); @@ -432,7 +434,7 @@ static int __maybe_unused cs35l56_sdw_runtime_resume(struct device *dev) dev_dbg(dev, "Runtime resume\n"); - if (!cs35l56->init_done) + if (!cs35l56->base.init_done) return 0; ret = cs35l56_sdw_handle_unattach(cs35l56); @@ -454,7 +456,7 @@ static int __maybe_unused cs35l56_sdw_system_suspend(struct device *dev) { struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); - if (!cs35l56->init_done) + if (!cs35l56->base.init_done) return 0; /* @@ -493,21 +495,21 @@ static int cs35l56_sdw_probe(struct sdw_slave *peripheral, const struct sdw_devi if (!cs35l56) return -ENOMEM; - cs35l56->dev = dev; + cs35l56->base.dev = dev; cs35l56->sdw_peripheral = peripheral; INIT_WORK(&cs35l56->sdw_irq_work, cs35l56_sdw_irq_work); dev_set_drvdata(dev, cs35l56); - cs35l56->regmap = devm_regmap_init(dev, &cs35l56_regmap_bus_sdw, + cs35l56->base.regmap = devm_regmap_init(dev, &cs35l56_regmap_bus_sdw, peripheral, &cs35l56_regmap_sdw); - if (IS_ERR(cs35l56->regmap)) { - ret = PTR_ERR(cs35l56->regmap); + if (IS_ERR(cs35l56->base.regmap)) { + ret = PTR_ERR(cs35l56->base.regmap); return dev_err_probe(dev, ret, "Failed to allocate register map\n"); } /* Start in cache-only until device is enumerated */ - regcache_cache_only(cs35l56->regmap, true); + regcache_cache_only(cs35l56->base.regmap, true); ret = cs35l56_common_probe(cs35l56); if (ret != 0) diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index 60da8c75b7b9..0cbaf8c7b05a 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -187,14 +187,14 @@ static const u32 cs35l56_firmware_registers[] = { CS35L56_MAIN_POSTURE_NUMBER, }; -void cs35l56_reread_firmware_registers(struct device *dev, struct regmap *regmap) +void cs35l56_reread_firmware_registers(struct cs35l56_base *cs35l56_base) { int i; unsigned int val; for (i = 0; i < ARRAY_SIZE(cs35l56_firmware_registers); i++) { - regmap_read(regmap, cs35l56_firmware_registers[i], &val); - dev_dbg(dev, "%s: %d: %#x: %#x\n", __func__, + regmap_read(cs35l56_base->regmap, cs35l56_firmware_registers[i], &val); + dev_dbg(cs35l56_base->dev, "%s: %d: %#x: %#x\n", __func__, i, cs35l56_firmware_registers[i], val); } } diff --git a/sound/soc/codecs/cs35l56-spi.c b/sound/soc/codecs/cs35l56-spi.c index 996aab10500e..2057fce435be 100644 --- a/sound/soc/codecs/cs35l56-spi.c +++ b/sound/soc/codecs/cs35l56-spi.c @@ -25,13 +25,13 @@ static int cs35l56_spi_probe(struct spi_device *spi) return -ENOMEM; spi_set_drvdata(spi, cs35l56); - cs35l56->regmap = devm_regmap_init_spi(spi, regmap_config); - if (IS_ERR(cs35l56->regmap)) { - ret = PTR_ERR(cs35l56->regmap); + cs35l56->base.regmap = devm_regmap_init_spi(spi, regmap_config); + if (IS_ERR(cs35l56->base.regmap)) { + ret = PTR_ERR(cs35l56->base.regmap); return dev_err_probe(&spi->dev, ret, "Failed to allocate register map\n"); } - cs35l56->dev = &spi->dev; + cs35l56->base.dev = &spi->dev; ret = cs35l56_common_probe(cs35l56); if (ret != 0) @@ -39,7 +39,7 @@ static int cs35l56_spi_probe(struct spi_device *spi) ret = cs35l56_init(cs35l56); if (ret == 0) - ret = cs35l56_irq_request(cs35l56, spi->irq); + ret = cs35l56_irq_request(&cs35l56->base, spi->irq); if (ret < 0) cs35l56_remove(cs35l56); diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 3c07bd1e959e..4d41c4b040a4 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -34,17 +34,17 @@ static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); -static int cs35l56_mbox_send(struct cs35l56_private *cs35l56, unsigned int command) +static int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command) { unsigned int val; int ret; - regmap_write(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, command); - ret = regmap_read_poll_timeout(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, + regmap_write(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, command); + ret = regmap_read_poll_timeout(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, val, (val == 0), CS35L56_MBOX_POLL_US, CS35L56_MBOX_TIMEOUT_US); if (ret) { - dev_warn(cs35l56->dev, "MBOX command %#x failed: %d\n", command, ret); + dev_warn(cs35l56_base->dev, "MBOX command %#x failed: %d\n", command, ret); return ret; } @@ -174,25 +174,25 @@ static int cs35l56_play_event(struct snd_soc_dapm_widget *w, unsigned int val; int ret; - dev_dbg(cs35l56->dev, "play: %d\n", event); + dev_dbg(cs35l56->base.dev, "play: %d\n", event); switch (event) { case SND_SOC_DAPM_PRE_PMU: /* Don't wait for ACK, we check in POST_PMU that it completed */ - return regmap_write(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, + return regmap_write(cs35l56->base.regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_AUDIO_PLAY); case SND_SOC_DAPM_POST_PMU: /* Wait for firmware to enter PS0 power state */ - ret = regmap_read_poll_timeout(cs35l56->regmap, + ret = regmap_read_poll_timeout(cs35l56->base.regmap, CS35L56_TRANSDUCER_ACTUAL_PS, val, (val == CS35L56_PS0), CS35L56_PS0_POLL_US, CS35L56_PS0_TIMEOUT_US); if (ret) - dev_err(cs35l56->dev, "PS0 wait failed: %d\n", ret); + dev_err(cs35l56->base.dev, "PS0 wait failed: %d\n", ret); return ret; case SND_SOC_DAPM_POST_PMD: - return cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_AUDIO_PAUSE); + return cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_PAUSE); default: return 0; } @@ -310,14 +310,14 @@ static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); - dev_dbg(cs35l56->dev, "%s: %d\n", __func__, event); + dev_dbg(cs35l56->base.dev, "%s: %d\n", __func__, event); return wm_adsp_event(w, kcontrol, event); } irqreturn_t cs35l56_irq(int irq, void *data) { - struct cs35l56_private *cs35l56 = data; + struct cs35l56_base *cs35l56_base = data; unsigned int status1 = 0, status8 = 0, status20 = 0; unsigned int mask1, mask8, mask20; unsigned int val; @@ -325,77 +325,77 @@ irqreturn_t cs35l56_irq(int irq, void *data) irqreturn_t ret = IRQ_NONE; - if (!cs35l56->init_done) + if (!cs35l56_base->init_done) return IRQ_NONE; - mutex_lock(&cs35l56->irq_lock); + mutex_lock(&cs35l56_base->irq_lock); - rv = pm_runtime_resume_and_get(cs35l56->dev); + rv = pm_runtime_resume_and_get(cs35l56_base->dev); if (rv < 0) { - dev_err(cs35l56->dev, "irq: failed to get pm_runtime: %d\n", rv); + dev_err(cs35l56_base->dev, "irq: failed to get pm_runtime: %d\n", rv); goto err_unlock; } - regmap_read(cs35l56->regmap, CS35L56_IRQ1_STATUS, &val); + regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_STATUS, &val); if ((val & CS35L56_IRQ1_STS_MASK) == 0) { - dev_dbg(cs35l56->dev, "Spurious IRQ: no pending interrupt\n"); + dev_dbg(cs35l56_base->dev, "Spurious IRQ: no pending interrupt\n"); goto err; } /* Ack interrupts */ - regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_1, &status1); - regmap_read(cs35l56->regmap, CS35L56_IRQ1_MASK_1, &mask1); + regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_1, &status1); + regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_1, &mask1); status1 &= ~mask1; - regmap_write(cs35l56->regmap, CS35L56_IRQ1_EINT_1, status1); + regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_EINT_1, status1); - regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_8, &status8); - regmap_read(cs35l56->regmap, CS35L56_IRQ1_MASK_8, &mask8); + regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_8, &status8); + regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_8, &mask8); status8 &= ~mask8; - regmap_write(cs35l56->regmap, CS35L56_IRQ1_EINT_8, status8); + regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_EINT_8, status8); - regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_20, &status20); - regmap_read(cs35l56->regmap, CS35L56_IRQ1_MASK_20, &mask20); + regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_20, &status20); + regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, &mask20); status20 &= ~mask20; /* We don't want EINT20 but they default to unmasked: force mask */ - regmap_write(cs35l56->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff); + regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff); - dev_dbg(cs35l56->dev, "%s: %#x %#x\n", __func__, status1, status8); + dev_dbg(cs35l56_base->dev, "%s: %#x %#x\n", __func__, status1, status8); /* Check to see if unmasked bits are active */ if (!status1 && !status8 && !status20) goto err; if (status1 & CS35L56_AMP_SHORT_ERR_EINT1_MASK) - dev_crit(cs35l56->dev, "Amp short error\n"); + dev_crit(cs35l56_base->dev, "Amp short error\n"); if (status8 & CS35L56_TEMP_ERR_EINT1_MASK) - dev_crit(cs35l56->dev, "Overtemp error\n"); + dev_crit(cs35l56_base->dev, "Overtemp error\n"); ret = IRQ_HANDLED; err: - pm_runtime_put(cs35l56->dev); + pm_runtime_put(cs35l56_base->dev); err_unlock: - mutex_unlock(&cs35l56->irq_lock); + mutex_unlock(&cs35l56_base->irq_lock); return ret; } EXPORT_SYMBOL_NS_GPL(cs35l56_irq, SND_SOC_CS35L56_CORE); -int cs35l56_irq_request(struct cs35l56_private *cs35l56, int irq) +int cs35l56_irq_request(struct cs35l56_base *cs35l56_base, int irq) { int ret; if (!irq) return 0; - ret = devm_request_threaded_irq(cs35l56->dev, irq, NULL, cs35l56_irq, + ret = devm_request_threaded_irq(cs35l56_base->dev, irq, NULL, cs35l56_irq, IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW, - "cs35l56", cs35l56); + "cs35l56", cs35l56_base); if (!ret) - cs35l56->irq = irq; + cs35l56_base->irq = irq; else - dev_err(cs35l56->dev, "Failed to get IRQ: %d\n", ret); + dev_err(cs35l56_base->dev, "Failed to get IRQ: %d\n", ret); return ret; } @@ -406,13 +406,13 @@ static int cs35l56_asp_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int f struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(codec_dai->component); unsigned int val; - dev_dbg(cs35l56->dev, "%s: %#x\n", __func__, fmt); + dev_dbg(cs35l56->base.dev, "%s: %#x\n", __func__, fmt); switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { case SND_SOC_DAIFMT_CBC_CFC: break; default: - dev_err(cs35l56->dev, "Unsupported clock source mode\n"); + dev_err(cs35l56->base.dev, "Unsupported clock source mode\n"); return -EINVAL; } @@ -426,7 +426,7 @@ static int cs35l56_asp_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int f cs35l56->tdm_mode = false; break; default: - dev_err(cs35l56->dev, "Unsupported DAI format\n"); + dev_err(cs35l56->base.dev, "Unsupported DAI format\n"); return -EINVAL; } @@ -443,18 +443,18 @@ static int cs35l56_asp_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int f case SND_SOC_DAIFMT_NB_NF: break; default: - dev_err(cs35l56->dev, "Invalid clock invert\n"); + dev_err(cs35l56->base.dev, "Invalid clock invert\n"); return -EINVAL; } - regmap_update_bits(cs35l56->regmap, + regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_CONTROL2, CS35L56_ASP_FMT_MASK | CS35L56_ASP_BCLK_INV_MASK | CS35L56_ASP_FSYNC_INV_MASK, val); /* Hi-Z DOUT in unused slots and when all TX are disabled */ - regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL3, + regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_CONTROL3, CS35L56_ASP1_DOUT_HIZ_CTRL_MASK, CS35L56_ASP_UNUSED_HIZ_OFF_HIZ); @@ -485,7 +485,7 @@ static void cs35l56_set_asp_slot_positions(struct cs35l56_private *cs35l56, channel_shift += 8; } - regmap_write(cs35l56->regmap, reg, reg_val); + regmap_write(cs35l56->base.regmap, reg, reg_val); } static int cs35l56_asp_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, @@ -494,20 +494,20 @@ static int cs35l56_asp_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); if ((slots == 0) || (slot_width == 0)) { - dev_dbg(cs35l56->dev, "tdm config cleared\n"); + dev_dbg(cs35l56->base.dev, "tdm config cleared\n"); cs35l56->asp_slot_width = 0; cs35l56->asp_slot_count = 0; return 0; } if (slot_width > (CS35L56_ASP_RX_WIDTH_MASK >> CS35L56_ASP_RX_WIDTH_SHIFT)) { - dev_err(cs35l56->dev, "tdm invalid slot width %d\n", slot_width); + dev_err(cs35l56->base.dev, "tdm invalid slot width %d\n", slot_width); return -EINVAL; } /* More than 32 slots would give an unsupportable BCLK frequency */ if (slots > 32) { - dev_err(cs35l56->dev, "tdm invalid slot count %d\n", slots); + dev_err(cs35l56->base.dev, "tdm invalid slot count %d\n", slots); return -EINVAL; } @@ -524,7 +524,7 @@ static int cs35l56_asp_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx cs35l56_set_asp_slot_positions(cs35l56, CS35L56_ASP1_FRAME_CONTROL1, rx_mask); cs35l56_set_asp_slot_positions(cs35l56, CS35L56_ASP1_FRAME_CONTROL5, tx_mask); - dev_dbg(cs35l56->dev, "tdm slot width: %u count: %u tx_mask: %#x rx_mask: %#x\n", + dev_dbg(cs35l56->base.dev, "tdm slot width: %u count: %u tx_mask: %#x rx_mask: %#x\n", cs35l56->asp_slot_width, cs35l56->asp_slot_count, tx_mask, rx_mask); return 0; @@ -544,7 +544,8 @@ static int cs35l56_asp_dai_hw_params(struct snd_pcm_substream *substream, else asp_width = asp_wl; - dev_dbg(cs35l56->dev, "%s: wl=%d, width=%d, rate=%d", __func__, asp_wl, asp_width, rate); + dev_dbg(cs35l56->base.dev, "%s: wl=%d, width=%d, rate=%d", + __func__, asp_wl, asp_width, rate); if (!cs35l56->sysclk_set) { unsigned int slots = cs35l56->asp_slot_count; @@ -562,26 +563,26 @@ static int cs35l56_asp_dai_hw_params(struct snd_pcm_substream *substream, bclk_freq = asp_width * slots * rate; freq_id = cs35l56_get_bclk_freq_id(bclk_freq); if (freq_id < 0) { - dev_err(cs35l56->dev, "%s: Invalid BCLK %u\n", __func__, bclk_freq); + dev_err(cs35l56->base.dev, "%s: Invalid BCLK %u\n", __func__, bclk_freq); return -EINVAL; } - regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL1, + regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_CONTROL1, CS35L56_ASP_BCLK_FREQ_MASK, freq_id << CS35L56_ASP_BCLK_FREQ_SHIFT); } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL2, + regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_CONTROL2, CS35L56_ASP_RX_WIDTH_MASK, asp_width << CS35L56_ASP_RX_WIDTH_SHIFT); - regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_DATA_CONTROL5, + regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_DATA_CONTROL5, CS35L56_ASP_RX_WL_MASK, asp_wl); } else { - regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL2, + regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_CONTROL2, CS35L56_ASP_TX_WIDTH_MASK, asp_width << CS35L56_ASP_TX_WIDTH_SHIFT); - regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_DATA_CONTROL1, + regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_DATA_CONTROL1, CS35L56_ASP_TX_WL_MASK, asp_wl); } @@ -603,7 +604,7 @@ static int cs35l56_asp_dai_set_sysclk(struct snd_soc_dai *dai, if (freq_id < 0) return freq_id; - regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL1, + regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_CONTROL1, CS35L56_ASP_BCLK_FREQ_MASK, freq_id << CS35L56_ASP_BCLK_FREQ_SHIFT); cs35l56->sysclk_set = true; @@ -646,9 +647,9 @@ static int cs35l56_sdw_dai_hw_params(struct snd_pcm_substream *substream, struct sdw_port_config pconfig; int ret; - dev_dbg(cs35l56->dev, "%s: rate %d\n", __func__, params_rate(params)); + dev_dbg(cs35l56->base.dev, "%s: rate %d\n", __func__, params_rate(params)); - if (!cs35l56->init_done) + if (!cs35l56->base.init_done) return -ENODEV; if (!sdw_stream) @@ -764,30 +765,30 @@ static struct snd_soc_dai_driver cs35l56_dai[] = { } }; -static int cs35l56_wait_for_firmware_boot(struct cs35l56_private *cs35l56) +static int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base) { unsigned int reg; unsigned int val; int ret; - if (cs35l56->rev < CS35L56_REVID_B0) + if (cs35l56_base->rev < CS35L56_REVID_B0) reg = CS35L56_DSP1_HALO_STATE_A1; else reg = CS35L56_DSP1_HALO_STATE; - ret = regmap_read_poll_timeout(cs35l56->regmap, reg, + ret = regmap_read_poll_timeout(cs35l56_base->regmap, reg, val, (val < 0xFFFF) && (val >= CS35L56_HALO_STATE_BOOT_DONE), CS35L56_HALO_STATE_POLL_US, CS35L56_HALO_STATE_TIMEOUT_US); if ((ret < 0) && (ret != -ETIMEDOUT)) { - dev_err(cs35l56->dev, "Failed to read HALO_STATE: %d\n", ret); + dev_err(cs35l56_base->dev, "Failed to read HALO_STATE: %d\n", ret); return ret; } if ((ret == -ETIMEDOUT) || (val != CS35L56_HALO_STATE_BOOT_DONE)) { - dev_err(cs35l56->dev, "Firmware boot fail: HALO_STATE=%#x\n", val); + dev_err(cs35l56_base->dev, "Firmware boot fail: HALO_STATE=%#x\n", val); return -EIO; } @@ -812,8 +813,8 @@ static void cs35l56_system_reset(struct cs35l56_private *cs35l56) * Must enter cache-only first so there can't be any more register * accesses other than the controlled system reset sequence below. */ - regcache_cache_only(cs35l56->regmap, true); - regmap_multi_reg_write_bypassed(cs35l56->regmap, + regcache_cache_only(cs35l56->base.regmap, true); + regmap_multi_reg_write_bypassed(cs35l56->base.regmap, cs35l56_system_reset_seq, ARRAY_SIZE(cs35l56_system_reset_seq)); @@ -822,7 +823,7 @@ static void cs35l56_system_reset(struct cs35l56_private *cs35l56) return; usleep_range(CS35L56_CONTROL_PORT_READY_US, CS35L56_CONTROL_PORT_READY_US + 400); - regcache_cache_only(cs35l56->regmap, false); + regcache_cache_only(cs35l56->base.regmap, false); } static void cs35l56_secure_patch(struct cs35l56_private *cs35l56) @@ -832,9 +833,9 @@ static void cs35l56_secure_patch(struct cs35l56_private *cs35l56) /* Use wm_adsp to load and apply the firmware patch and coefficient files */ ret = wm_adsp_power_up(&cs35l56->dsp); if (ret) - dev_dbg(cs35l56->dev, "%s: wm_adsp_power_up ret %d\n", __func__, ret); + dev_dbg(cs35l56->base.dev, "%s: wm_adsp_power_up ret %d\n", __func__, ret); else - cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_AUDIO_REINIT); + cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_REINIT); } static void cs35l56_patch(struct cs35l56_private *cs35l56) @@ -857,31 +858,31 @@ static void cs35l56_patch(struct cs35l56_private *cs35l56) flush_work(&cs35l56->sdw_irq_work); } - ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_SHUTDOWN); + ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_SHUTDOWN); if (ret) goto err; - if (cs35l56->rev < CS35L56_REVID_B0) + if (cs35l56->base.rev < CS35L56_REVID_B0) reg = CS35L56_DSP1_PM_CUR_STATE_A1; else reg = CS35L56_DSP1_PM_CUR_STATE; - ret = regmap_read_poll_timeout(cs35l56->regmap, reg, + ret = regmap_read_poll_timeout(cs35l56->base.regmap, reg, val, (val == CS35L56_HALO_STATE_SHUTDOWN), CS35L56_HALO_STATE_POLL_US, CS35L56_HALO_STATE_TIMEOUT_US); if (ret < 0) - dev_err(cs35l56->dev, "Failed to poll PM_CUR_STATE to 1 is %d (ret %d)\n", + dev_err(cs35l56->base.dev, "Failed to poll PM_CUR_STATE to 1 is %d (ret %d)\n", val, ret); /* Use wm_adsp to load and apply the firmware patch and coefficient files */ ret = wm_adsp_power_up(&cs35l56->dsp); if (ret) { - dev_dbg(cs35l56->dev, "%s: wm_adsp_power_up ret %d\n", __func__, ret); + dev_dbg(cs35l56->base.dev, "%s: wm_adsp_power_up ret %d\n", __func__, ret); goto err; } - mutex_lock(&cs35l56->irq_lock); + mutex_lock(&cs35l56->base.irq_lock); init_completion(&cs35l56->init_completion); @@ -895,18 +896,20 @@ static void cs35l56_patch(struct cs35l56_private *cs35l56) */ if (!wait_for_completion_timeout(&cs35l56->init_completion, msecs_to_jiffies(5000))) { - dev_err(cs35l56->dev, "%s: init_completion timed out (SDW)\n", __func__); + dev_err(cs35l56->base.dev, "%s: init_completion timed out (SDW)\n", + __func__); goto err_unlock; } } else if (cs35l56_init(cs35l56)) { goto err_unlock; } - regmap_clear_bits(cs35l56->regmap, CS35L56_PROTECTION_STATUS, CS35L56_FIRMWARE_MISSING); - cs35l56->fw_patched = true; + regmap_clear_bits(cs35l56->base.regmap, CS35L56_PROTECTION_STATUS, + CS35L56_FIRMWARE_MISSING); + cs35l56->base.fw_patched = true; err_unlock: - mutex_unlock(&cs35l56->irq_lock); + mutex_unlock(&cs35l56->base.irq_lock); err: /* Re-enable SoundWire interrupts */ if (cs35l56->sdw_peripheral) { @@ -922,10 +925,10 @@ static void cs35l56_dsp_work(struct work_struct *work) struct cs35l56_private, dsp_work); - if (!cs35l56->init_done) + if (!cs35l56->base.init_done) return; - pm_runtime_get_sync(cs35l56->dev); + pm_runtime_get_sync(cs35l56->base.dev); /* * When the device is running in secure mode the firmware files can @@ -933,13 +936,13 @@ static void cs35l56_dsp_work(struct work_struct *work) * shutdown the firmware to apply them and can use the lower cost * reinit sequence instead. */ - if (cs35l56->secured) + if (cs35l56->base.secured) cs35l56_secure_patch(cs35l56); else cs35l56_patch(cs35l56); - pm_runtime_mark_last_busy(cs35l56->dev); - pm_runtime_put_autosuspend(cs35l56->dev); + pm_runtime_mark_last_busy(cs35l56->base.dev); + pm_runtime_put_autosuspend(cs35l56->base.dev); } static int cs35l56_component_probe(struct snd_soc_component *component) @@ -951,16 +954,16 @@ static int cs35l56_component_probe(struct snd_soc_component *component) if (!wait_for_completion_timeout(&cs35l56->init_completion, msecs_to_jiffies(5000))) { - dev_err(cs35l56->dev, "%s: init_completion timed out\n", __func__); + dev_err(cs35l56->base.dev, "%s: init_completion timed out\n", __func__); return -ENODEV; } cs35l56->component = component; wm_adsp2_component_probe(&cs35l56->dsp, component); - debugfs_create_bool("init_done", 0444, debugfs_root, &cs35l56->init_done); - debugfs_create_bool("can_hibernate", 0444, debugfs_root, &cs35l56->can_hibernate); - debugfs_create_bool("fw_patched", 0444, debugfs_root, &cs35l56->fw_patched); + debugfs_create_bool("init_done", 0444, debugfs_root, &cs35l56->base.init_done); + debugfs_create_bool("can_hibernate", 0444, debugfs_root, &cs35l56->base.can_hibernate); + debugfs_create_bool("fw_patched", 0444, debugfs_root, &cs35l56->base.fw_patched); queue_work(cs35l56->dsp_wq, &cs35l56->dsp_work); @@ -1027,23 +1030,23 @@ int cs35l56_runtime_suspend(struct device *dev) unsigned int val; int ret; - if (!cs35l56->init_done) + if (!cs35l56->base.init_done) return 0; /* Firmware must have entered a power-save state */ - ret = regmap_read_poll_timeout(cs35l56->regmap, + ret = regmap_read_poll_timeout(cs35l56->base.regmap, CS35L56_TRANSDUCER_ACTUAL_PS, val, (val >= CS35L56_PS3), CS35L56_PS3_POLL_US, CS35L56_PS3_TIMEOUT_US); if (ret) - dev_warn(cs35l56->dev, "PS3 wait failed: %d\n", ret); + dev_warn(cs35l56->base.dev, "PS3 wait failed: %d\n", ret); /* Clear BOOT_DONE so it can be used to detect a reboot */ - regmap_write(cs35l56->regmap, CS35L56_IRQ1_EINT_4, CS35L56_OTP_BOOT_DONE_MASK); + regmap_write(cs35l56->base.regmap, CS35L56_IRQ1_EINT_4, CS35L56_OTP_BOOT_DONE_MASK); - if (!cs35l56->can_hibernate) { - regcache_cache_only(cs35l56->regmap, true); + if (!cs35l56->base.can_hibernate) { + regcache_cache_only(cs35l56->base.regmap, true); dev_dbg(dev, "Suspended: no hibernate"); return 0; @@ -1053,15 +1056,15 @@ int cs35l56_runtime_suspend(struct device *dev) * Enable auto-hibernate. If it is woken by some other wake source * it will automatically return to hibernate. */ - cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE); + cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE); /* * Must enter cache-only first so there can't be any more register * accesses other than the controlled hibernate sequence below. */ - regcache_cache_only(cs35l56->regmap, true); + regcache_cache_only(cs35l56->base.regmap, true); - regmap_multi_reg_write_bypassed(cs35l56->regmap, + regmap_multi_reg_write_bypassed(cs35l56->base.regmap, cs35l56_hibernate_seq, ARRAY_SIZE(cs35l56_hibernate_seq)); @@ -1075,7 +1078,7 @@ static int __maybe_unused cs35l56_runtime_resume_i2c_spi(struct device *dev) { struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); - if (!cs35l56->init_done) + if (!cs35l56->base.init_done) return 0; return cs35l56_runtime_resume_common(cs35l56); @@ -1086,7 +1089,7 @@ int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56) unsigned int val; int ret; - if (!cs35l56->can_hibernate) + if (!cs35l56->base.can_hibernate) goto out_sync; if (!cs35l56->sdw_peripheral) { @@ -1094,7 +1097,7 @@ int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56) * Dummy transaction to trigger I2C/SPI auto-wake. This will NAK on I2C. * Must be done before releasing cache-only. */ - regmap_multi_reg_write_bypassed(cs35l56->regmap, + regmap_multi_reg_write_bypassed(cs35l56->base.regmap, cs35l56_hibernate_wake_seq, ARRAY_SIZE(cs35l56_hibernate_wake_seq)); @@ -1103,36 +1106,36 @@ int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56) } out_sync: - regcache_cache_only(cs35l56->regmap, false); + regcache_cache_only(cs35l56->base.regmap, false); - ret = cs35l56_wait_for_firmware_boot(cs35l56); + ret = cs35l56_wait_for_firmware_boot(&cs35l56->base); if (ret) { - dev_err(cs35l56->dev, "Hibernate wake failed: %d\n", ret); + dev_err(cs35l56->base.dev, "Hibernate wake failed: %d\n", ret); goto err; } - ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE); + ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE); if (ret) goto err; /* BOOT_DONE will be 1 if the amp reset */ - regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_4, &val); + regmap_read(cs35l56->base.regmap, CS35L56_IRQ1_EINT_4, &val); if (val & CS35L56_OTP_BOOT_DONE_MASK) { - dev_dbg(cs35l56->dev, "Registers reset in suspend\n"); - regcache_mark_dirty(cs35l56->regmap); + dev_dbg(cs35l56->base.dev, "Registers reset in suspend\n"); + regcache_mark_dirty(cs35l56->base.regmap); } - regcache_sync(cs35l56->regmap); + regcache_sync(cs35l56->base.regmap); - dev_dbg(cs35l56->dev, "Resumed"); + dev_dbg(cs35l56->base.dev, "Resumed"); return 0; err: - regmap_write(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, + regmap_write(cs35l56->base.regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_HIBERNATE_NOW); - regcache_cache_only(cs35l56->regmap, true); + regcache_cache_only(cs35l56->base.regmap, true); return ret; } @@ -1144,14 +1147,14 @@ static int cs35l56_is_fw_reload_needed(struct cs35l56_private *cs35l56) int ret; /* Nothing to re-patch if we haven't done any patching yet. */ - if (!cs35l56->fw_patched) + if (!cs35l56->base.fw_patched) return false; /* * If we have control of RESET we will have asserted it so the firmware * will need re-patching. */ - if (cs35l56->reset_gpio) + if (cs35l56->base.reset_gpio) return true; /* @@ -1159,22 +1162,22 @@ static int cs35l56_is_fw_reload_needed(struct cs35l56_private *cs35l56) * can't be used here to test for memory retention. * Assume that tuning must be re-loaded. */ - if (cs35l56->secured) + if (cs35l56->base.secured) return true; - ret = pm_runtime_resume_and_get(cs35l56->dev); + ret = pm_runtime_resume_and_get(cs35l56->base.dev); if (ret) { - dev_err(cs35l56->dev, "Failed to runtime_get: %d\n", ret); + dev_err(cs35l56->base.dev, "Failed to runtime_get: %d\n", ret); return ret; } - ret = regmap_read(cs35l56->regmap, CS35L56_PROTECTION_STATUS, &val); + ret = regmap_read(cs35l56->base.regmap, CS35L56_PROTECTION_STATUS, &val); if (ret) - dev_err(cs35l56->dev, "Failed to read PROTECTION_STATUS: %d\n", ret); + dev_err(cs35l56->base.dev, "Failed to read PROTECTION_STATUS: %d\n", ret); else ret = !!(val & CS35L56_FIRMWARE_MISSING); - pm_runtime_put_autosuspend(cs35l56->dev); + pm_runtime_put_autosuspend(cs35l56->base.dev); return ret; } @@ -1194,8 +1197,8 @@ int cs35l56_system_suspend(struct device *dev) * clear it. Prevent this race by temporarily disabling the parent irq * until we reach _no_irq. */ - if (cs35l56->irq) - disable_irq(cs35l56->irq); + if (cs35l56->base.irq) + disable_irq(cs35l56->base.irq); return pm_runtime_force_suspend(dev); } @@ -1212,8 +1215,8 @@ int cs35l56_system_suspend_late(struct device *dev) * RESET is usually shared by all amps so it must not be asserted until * all driver instances have done their suspend() stage. */ - if (cs35l56->reset_gpio) { - gpiod_set_value_cansleep(cs35l56->reset_gpio, 0); + if (cs35l56->base.reset_gpio) { + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0); cs35l56_wait_min_reset_pulse(); } @@ -1230,8 +1233,8 @@ int cs35l56_system_suspend_no_irq(struct device *dev) dev_dbg(dev, "system_suspend_no_irq\n"); /* Handlers are now disabled so the parent IRQ can safely be re-enabled. */ - if (cs35l56->irq) - enable_irq(cs35l56->irq); + if (cs35l56->base.irq) + enable_irq(cs35l56->base.irq); return 0; } @@ -1250,8 +1253,8 @@ int cs35l56_system_resume_no_irq(struct device *dev) * clear it, until it has fully resumed. Prevent this race by temporarily * disabling the parent irq until we complete resume(). */ - if (cs35l56->irq) - disable_irq(cs35l56->irq); + if (cs35l56->base.irq) + disable_irq(cs35l56->base.irq); return 0; } @@ -1265,8 +1268,8 @@ int cs35l56_system_resume_early(struct device *dev) dev_dbg(dev, "system_resume_early\n"); /* Ensure a spec-compliant RESET pulse. */ - if (cs35l56->reset_gpio) { - gpiod_set_value_cansleep(cs35l56->reset_gpio, 0); + if (cs35l56->base.reset_gpio) { + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0); cs35l56_wait_min_reset_pulse(); } @@ -1278,7 +1281,7 @@ int cs35l56_system_resume_early(struct device *dev) } /* Release shared RESET before drivers start resume(). */ - gpiod_set_value_cansleep(cs35l56->reset_gpio, 1); + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 1); return 0; } @@ -1293,8 +1296,8 @@ int cs35l56_system_resume(struct device *dev) /* Undo pm_runtime_force_suspend() before re-enabling the irq */ ret = pm_runtime_force_resume(dev); - if (cs35l56->irq) - enable_irq(cs35l56->irq); + if (cs35l56->base.irq) + enable_irq(cs35l56->base.irq); if (ret) return ret; @@ -1304,11 +1307,11 @@ int cs35l56_system_resume(struct device *dev) return 0; ret = cs35l56_is_fw_reload_needed(cs35l56); - dev_dbg(cs35l56->dev, "fw_reload_needed: %d\n", ret); + dev_dbg(cs35l56->base.dev, "fw_reload_needed: %d\n", ret); if (ret < 1) return ret; - cs35l56->fw_patched = false; + cs35l56->base.fw_patched = false; queue_work(cs35l56->dsp_wq, &cs35l56->dsp_work); /* @@ -1337,8 +1340,8 @@ static int cs35l56_dsp_init(struct cs35l56_private *cs35l56) dsp->cs_dsp.type = WMFW_HALO; dsp->cs_dsp.rev = 0; dsp->fw = 12; - dsp->cs_dsp.dev = cs35l56->dev; - dsp->cs_dsp.regmap = cs35l56->regmap; + dsp->cs_dsp.dev = cs35l56->base.dev; + dsp->cs_dsp.regmap = cs35l56->base.regmap; dsp->cs_dsp.base = CS35L56_DSP1_CORE_BASE; dsp->cs_dsp.base_sysinfo = CS35L56_DSP1_SYS_INFO_ID; dsp->cs_dsp.mem = cs35l56_dsp1_regions; @@ -1346,11 +1349,11 @@ static int cs35l56_dsp_init(struct cs35l56_private *cs35l56) dsp->cs_dsp.no_core_startstop = true; dsp->wmfw_optional = true; - dev_dbg(cs35l56->dev, "DSP system name: '%s'\n", dsp->system_name); + dev_dbg(cs35l56->base.dev, "DSP system name: '%s'\n", dsp->system_name); ret = wm_halo_init(dsp); if (ret != 0) { - dev_err(cs35l56->dev, "wm_halo_init failed\n"); + dev_err(cs35l56->base.dev, "wm_halo_init failed\n"); return ret; } @@ -1359,7 +1362,7 @@ static int cs35l56_dsp_init(struct cs35l56_private *cs35l56) static int cs35l56_acpi_get_name(struct cs35l56_private *cs35l56) { - acpi_handle handle = ACPI_HANDLE(cs35l56->dev); + acpi_handle handle = ACPI_HANDLE(cs35l56->base.dev); const char *sub; /* If there is no ACPI_HANDLE, there is no ACPI for this system, return 0 */ @@ -1376,7 +1379,7 @@ static int cs35l56_acpi_get_name(struct cs35l56_private *cs35l56) } cs35l56->dsp.system_name = sub; - dev_dbg(cs35l56->dev, "Subsystem ID: %s\n", cs35l56->dsp.system_name); + dev_dbg(cs35l56->base.dev, "Subsystem ID: %s\n", cs35l56->dsp.system_name); return 0; } @@ -1386,38 +1389,39 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) int ret; init_completion(&cs35l56->init_completion); - mutex_init(&cs35l56->irq_lock); + mutex_init(&cs35l56->base.irq_lock); - dev_set_drvdata(cs35l56->dev, cs35l56); + dev_set_drvdata(cs35l56->base.dev, cs35l56); cs35l56_fill_supply_names(cs35l56->supplies); - ret = devm_regulator_bulk_get(cs35l56->dev, ARRAY_SIZE(cs35l56->supplies), + ret = devm_regulator_bulk_get(cs35l56->base.dev, ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); if (ret != 0) - return dev_err_probe(cs35l56->dev, ret, "Failed to request supplies\n"); + return dev_err_probe(cs35l56->base.dev, ret, "Failed to request supplies\n"); /* Reset could be controlled by the BIOS or shared by multiple amps */ - cs35l56->reset_gpio = devm_gpiod_get_optional(cs35l56->dev, "reset", GPIOD_OUT_LOW); - if (IS_ERR(cs35l56->reset_gpio)) { - ret = PTR_ERR(cs35l56->reset_gpio); + cs35l56->base.reset_gpio = devm_gpiod_get_optional(cs35l56->base.dev, "reset", + GPIOD_OUT_LOW); + if (IS_ERR(cs35l56->base.reset_gpio)) { + ret = PTR_ERR(cs35l56->base.reset_gpio); /* * If RESET is shared the first amp to probe will grab the reset * line and reset all the amps */ if (ret != -EBUSY) - return dev_err_probe(cs35l56->dev, ret, "Failed to get reset GPIO\n"); + return dev_err_probe(cs35l56->base.dev, ret, "Failed to get reset GPIO\n"); - dev_info(cs35l56->dev, "Reset GPIO busy, assume shared reset\n"); - cs35l56->reset_gpio = NULL; + dev_info(cs35l56->base.dev, "Reset GPIO busy, assume shared reset\n"); + cs35l56->base.reset_gpio = NULL; } ret = regulator_bulk_enable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); if (ret != 0) - return dev_err_probe(cs35l56->dev, ret, "Failed to enable supplies\n"); + return dev_err_probe(cs35l56->base.dev, ret, "Failed to enable supplies\n"); - if (cs35l56->reset_gpio) { + if (cs35l56->base.reset_gpio) { cs35l56_wait_min_reset_pulse(); - gpiod_set_value_cansleep(cs35l56->reset_gpio, 1); + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 1); } ret = cs35l56_acpi_get_name(cs35l56); @@ -1426,22 +1430,22 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) ret = cs35l56_dsp_init(cs35l56); if (ret < 0) { - dev_err_probe(cs35l56->dev, ret, "DSP init failed\n"); + dev_err_probe(cs35l56->base.dev, ret, "DSP init failed\n"); goto err; } - ret = devm_snd_soc_register_component(cs35l56->dev, + ret = devm_snd_soc_register_component(cs35l56->base.dev, &soc_component_dev_cs35l56, cs35l56_dai, ARRAY_SIZE(cs35l56_dai)); if (ret < 0) { - dev_err_probe(cs35l56->dev, ret, "Register codec failed\n"); + dev_err_probe(cs35l56->base.dev, ret, "Register codec failed\n"); goto err; } return 0; err: - gpiod_set_value_cansleep(cs35l56->reset_gpio, 0); + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0); regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); return ret; @@ -1460,20 +1464,20 @@ int cs35l56_init(struct cs35l56_private *cs35l56) if (cs35l56->soft_resetting) goto post_soft_reset; - if (cs35l56->init_done) + if (cs35l56->base.init_done) return 0; - pm_runtime_set_autosuspend_delay(cs35l56->dev, 100); - pm_runtime_use_autosuspend(cs35l56->dev); - pm_runtime_set_active(cs35l56->dev); - pm_runtime_enable(cs35l56->dev); + pm_runtime_set_autosuspend_delay(cs35l56->base.dev, 100); + pm_runtime_use_autosuspend(cs35l56->base.dev); + pm_runtime_set_active(cs35l56->base.dev); + pm_runtime_enable(cs35l56->base.dev); /* * If the system is not using a reset_gpio then issue a * dummy read to force a wakeup. */ - if (!cs35l56->reset_gpio) - regmap_read(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, &devid); + if (!cs35l56->base.reset_gpio) + regmap_read(cs35l56->base.regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, &devid); /* Wait for control port to be ready (datasheet tIRS). */ usleep_range(CS35L56_CONTROL_PORT_READY_US, @@ -1484,20 +1488,20 @@ int cs35l56_init(struct cs35l56_private *cs35l56) * devices so the REVID needs to be determined before waiting for the * firmware to boot. */ - ret = regmap_read(cs35l56->regmap, CS35L56_REVID, &revid); + ret = regmap_read(cs35l56->base.regmap, CS35L56_REVID, &revid); if (ret < 0) { - dev_err(cs35l56->dev, "Get Revision ID failed\n"); + dev_err(cs35l56->base.dev, "Get Revision ID failed\n"); return ret; } - cs35l56->rev = revid & (CS35L56_AREVID_MASK | CS35L56_MTLREVID_MASK); + cs35l56->base.rev = revid & (CS35L56_AREVID_MASK | CS35L56_MTLREVID_MASK); - ret = cs35l56_wait_for_firmware_boot(cs35l56); + ret = cs35l56_wait_for_firmware_boot(&cs35l56->base); if (ret) return ret; - ret = regmap_read(cs35l56->regmap, CS35L56_DEVID, &devid); + ret = regmap_read(cs35l56->base.regmap, CS35L56_DEVID, &devid); if (ret < 0) { - dev_err(cs35l56->dev, "Get Device ID failed\n"); + dev_err(cs35l56->base.dev, "Get Device ID failed\n"); return ret; } devid &= CS35L56_DEVID_MASK; @@ -1506,50 +1510,50 @@ int cs35l56_init(struct cs35l56_private *cs35l56) case 0x35A56: break; default: - dev_err(cs35l56->dev, "Unknown device %x\n", devid); + dev_err(cs35l56->base.dev, "Unknown device %x\n", devid); return ret; } - ret = regmap_read(cs35l56->regmap, CS35L56_DSP_RESTRICT_STS1, &secured); + ret = regmap_read(cs35l56->base.regmap, CS35L56_DSP_RESTRICT_STS1, &secured); if (ret) { - dev_err(cs35l56->dev, "Get Secure status failed\n"); + dev_err(cs35l56->base.dev, "Get Secure status failed\n"); return ret; } /* When any bus is restricted treat the device as secured */ if (secured & CS35L56_RESTRICTED_MASK) - cs35l56->secured = true; + cs35l56->base.secured = true; - ret = regmap_read(cs35l56->regmap, CS35L56_OTPID, &otpid); + ret = regmap_read(cs35l56->base.regmap, CS35L56_OTPID, &otpid); if (ret < 0) { - dev_err(cs35l56->dev, "Get OTP ID failed\n"); + dev_err(cs35l56->base.dev, "Get OTP ID failed\n"); return ret; } - dev_info(cs35l56->dev, "Cirrus Logic CS35L56%s Rev %02X OTP%d\n", - cs35l56->secured ? "s" : "", cs35l56->rev, otpid); + dev_info(cs35l56->base.dev, "Cirrus Logic CS35L56%s Rev %02X OTP%d\n", + cs35l56->base.secured ? "s" : "", cs35l56->base.rev, otpid); /* Populate the DSP information with the revision and security state */ - cs35l56->dsp.part = devm_kasprintf(cs35l56->dev, GFP_KERNEL, "cs35l56%s-%02x", - cs35l56->secured ? "s" : "", cs35l56->rev); + cs35l56->dsp.part = devm_kasprintf(cs35l56->base.dev, GFP_KERNEL, "cs35l56%s-%02x", + cs35l56->base.secured ? "s" : "", cs35l56->base.rev); if (!cs35l56->dsp.part) return -ENOMEM; /* Wake source and *_BLOCKED interrupts default to unmasked, so mask them */ - regmap_write(cs35l56->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff); - regmap_update_bits(cs35l56->regmap, CS35L56_IRQ1_MASK_1, + regmap_write(cs35l56->base.regmap, CS35L56_IRQ1_MASK_20, 0xffffffff); + regmap_update_bits(cs35l56->base.regmap, CS35L56_IRQ1_MASK_1, CS35L56_AMP_SHORT_ERR_EINT1_MASK, 0); - regmap_update_bits(cs35l56->regmap, CS35L56_IRQ1_MASK_8, + regmap_update_bits(cs35l56->base.regmap, CS35L56_IRQ1_MASK_8, CS35L56_TEMP_ERR_EINT1_MASK, 0); - if (!cs35l56->reset_gpio) { - dev_dbg(cs35l56->dev, "No reset gpio: using soft reset\n"); + if (!cs35l56->base.reset_gpio) { + dev_dbg(cs35l56->base.dev, "No reset gpio: using soft reset\n"); cs35l56_system_reset(cs35l56); if (cs35l56->sdw_peripheral) { /* Keep alive while we wait for re-enumeration */ - pm_runtime_get_noresume(cs35l56->dev); + pm_runtime_get_noresume(cs35l56->base.dev); return 0; } } @@ -1559,29 +1563,29 @@ int cs35l56_init(struct cs35l56_private *cs35l56) cs35l56->soft_resetting = false; /* Done re-enumerating after one-time init so release the keep-alive */ - if (cs35l56->sdw_peripheral && !cs35l56->init_done) - pm_runtime_put_noidle(cs35l56->dev); + if (cs35l56->sdw_peripheral && !cs35l56->base.init_done) + pm_runtime_put_noidle(cs35l56->base.dev); - regcache_mark_dirty(cs35l56->regmap); - ret = cs35l56_wait_for_firmware_boot(cs35l56); + regcache_mark_dirty(cs35l56->base.regmap); + ret = cs35l56_wait_for_firmware_boot(&cs35l56->base); if (ret) return ret; - dev_dbg(cs35l56->dev, "Firmware rebooted after soft reset\n"); + dev_dbg(cs35l56->base.dev, "Firmware rebooted after soft reset\n"); } /* Disable auto-hibernate so that runtime_pm has control */ - ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE); + ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE); if (ret) return ret; /* Populate soft registers in the regmap cache */ - cs35l56_reread_firmware_registers(cs35l56->dev, cs35l56->regmap); + cs35l56_reread_firmware_registers(&cs35l56->base); /* Registers could be dirty after soft reset or SoundWire enumeration */ - regcache_sync(cs35l56->regmap); + regcache_sync(cs35l56->base.regmap); - cs35l56->init_done = true; + cs35l56->base.init_done = true; complete(&cs35l56->init_completion); return 0; @@ -1590,26 +1594,26 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_init, SND_SOC_CS35L56_CORE); void cs35l56_remove(struct cs35l56_private *cs35l56) { - cs35l56->init_done = false; + cs35l56->base.init_done = false; /* * WAKE IRQs unmask if CS35L56 hibernates so free the handler to * prevent it racing with remove(). */ - if (cs35l56->irq) - devm_free_irq(cs35l56->dev, cs35l56->irq, cs35l56); + if (cs35l56->base.irq) + devm_free_irq(cs35l56->base.dev, cs35l56->base.irq, cs35l56); flush_workqueue(cs35l56->dsp_wq); destroy_workqueue(cs35l56->dsp_wq); - pm_runtime_suspend(cs35l56->dev); - pm_runtime_disable(cs35l56->dev); + pm_runtime_suspend(cs35l56->base.dev); + pm_runtime_disable(cs35l56->base.dev); - regcache_cache_only(cs35l56->regmap, true); + regcache_cache_only(cs35l56->base.regmap, true); kfree(cs35l56->dsp.system_name); - gpiod_set_value_cansleep(cs35l56->reset_gpio, 0); + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0); regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); } EXPORT_SYMBOL_NS_GPL(cs35l56_remove, SND_SOC_CS35L56_CORE); diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h index 1f7894662fcb..f39f8fa9e37e 100644 --- a/sound/soc/codecs/cs35l56.h +++ b/sound/soc/codecs/cs35l56.h @@ -32,26 +32,17 @@ struct sdw_slave; struct cs35l56_private { struct wm_adsp dsp; /* must be first member */ + struct cs35l56_base base; struct work_struct dsp_work; struct workqueue_struct *dsp_wq; - struct mutex irq_lock; struct snd_soc_component *component; - struct device *dev; - struct regmap *regmap; struct regulator_bulk_data supplies[CS35L56_NUM_BULK_SUPPLIES]; - int irq; struct sdw_slave *sdw_peripheral; - u8 rev; struct work_struct sdw_irq_work; - bool secured; bool sdw_irq_no_unmask; bool soft_resetting; - bool init_done; bool sdw_attached; - bool fw_patched; - bool can_hibernate; struct completion init_completion; - struct gpio_desc *reset_gpio; u32 rx_mask; u32 tx_mask; @@ -73,7 +64,7 @@ int cs35l56_system_resume_no_irq(struct device *dev); int cs35l56_system_resume_early(struct device *dev); int cs35l56_system_resume(struct device *dev); irqreturn_t cs35l56_irq(int irq, void *data); -int cs35l56_irq_request(struct cs35l56_private *cs35l56, int irq); +int cs35l56_irq_request(struct cs35l56_base *cs35l56_base, int irq); int cs35l56_common_probe(struct cs35l56_private *cs35l56); int cs35l56_init(struct cs35l56_private *cs35l56); void cs35l56_remove(struct cs35l56_private *cs35l56); From patchwork Fri May 26 12:28:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Fitzgerald X-Patchwork-Id: 99470 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp433986vqr; Fri, 26 May 2023 05:31:23 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ7qKw3VyWD7es5f0qopfHrXHLuSrPQ+dWJIeadC9YMOc7VOO9C1B2KIze3Bct4v8RSVhsbQ X-Received: by 2002:a17:90a:db07:b0:256:281d:9b20 with SMTP id g7-20020a17090adb0700b00256281d9b20mr1953940pjv.16.1685104283492; Fri, 26 May 2023 05:31:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685104283; cv=none; d=google.com; s=arc-20160816; b=NQpMopgVXS6gNePKNMJUPdc+OM0X0r6yNLWdbtSxYAY4bbxLQsbR8FXmkbPpsKU/KP K9phsmJ5rqjwGxp9tkOVLjRIYHhkHl7DCIISTelzjT0fEwC85rZbyOVnAu6mGNVc5f6c x4aGzD4LV5RHpJa4QGHkNA/+vkx7Byz6joEKqmkepWn/dWW1AZ16EUbK6rzvbxjwAy7y k9ysMpRWr15Xgl+PkeQp8wKfHw2VVofwM0x/XxsFsix++MnOOc6N2kK2LQOE1d6Gk7Nf G/FD0wTmqGk9Xss648sVeA4b+P/61uYJc8R5kuBf8zdGdOuwgm8SniX209bSSefgfjVr DVaA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=gjvF9y3c82RzHTgs5t2qAQVubD+R1HPBW6x2ID+7JwQ=; b=ZzaIw5U9X/0Iu/wpcJyAb0bYgFr3Axe7boMErUQsCK48HzmDfQjFj8f/NPRMtjMBmQ wYSgLBuELhsp7HfrPmNPRdgSGd7Y+InkxohAIW/i6XXk1bbCoq9rkuD7tvq8kpsIxn0M sRvIqSpKykXwKYOldcu4otOk6NE+nFVQIecTHVwmWN9a9rRaxI6L4aBQWnB/9cN4Tfo8 XgjfLzO8XPz9+2t8F0AdJLkt+vp+PBHfpZL7Vj6HMStTjszal/G/ECR49kTk6ZJSW0ET /cw0tfWr3oiUEtXFBs4rQHmacXnIa4zWDEjZ11+w62t3OXEnGoKrK7P1STYWWEQBxdrM 7c6w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=eqt5WJIJ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id i192-20020a636dc9000000b00536e63cbd99si3640508pgc.20.2023.05.26.05.31.10; Fri, 26 May 2023 05:31:23 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=eqt5WJIJ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243424AbjEZM3S (ORCPT + 99 others); Fri, 26 May 2023 08:29:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59178 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229766AbjEZM3R (ORCPT ); Fri, 26 May 2023 08:29:17 -0400 Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AB50A194 for ; Fri, 26 May 2023 05:29:12 -0700 (PDT) Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 34QC7FGt007721; Fri, 26 May 2023 07:28:57 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=gjvF9y3c82RzHTgs5t2qAQVubD+R1HPBW6x2ID+7JwQ=; b=eqt5WJIJjV6uOmIoS+tpPbLNSegqSGlhzqoB2ID8kU7U/H7n8NYpUPeoVocqolQbiVZa uYHMWUFxG3s8lVLXNBw3URyJwM5UK0cnecJ0WMu7oZTIGb3W/qX7HNzIQJI4A9rzfpKu 9aHmhcjmxLeryHB26muVTkxV6kUFBoR1JsG/SMJ1TPvL4N5uNFlP3YmeRBLxYZRs6gnX kZLSe/k+hGKpZddU5TW1g5Pr+Io/Ag4gOkSvHHJ0h4Hk0UJWxgZ6z5dP32Cpl2Bu0duK bxDRaN3UXzFS7wwkH59yEXEc6OQ4Crpd8Ii2/lLzT7/EvAEK7Rk3ai4fscenzMsuSl+s vQ== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 3qsde8k66v-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 26 May 2023 07:28:57 -0500 Received: from ediex02.ad.cirrus.com (198.61.84.81) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Fri, 26 May 2023 07:28:55 -0500 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by anon-ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Fri, 26 May 2023 07:28:55 -0500 Received: from EDIN4L06LR3.ad.cirrus.com (EDIN4L06LR3.ad.cirrus.com [198.61.65.166]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 3A52611A8; Fri, 26 May 2023 12:28:55 +0000 (UTC) From: Richard Fitzgerald To: , , CC: , , , Simon Trimmer , Richard Fitzgerald Subject: [PATCH v3 02/12] ASoC: cs35l56: Make cs35l56_system_reset() code more generic Date: Fri, 26 May 2023 13:28:42 +0100 Message-ID: <20230526122852.4552-3-rf@opensource.cirrus.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230526122852.4552-1-rf@opensource.cirrus.com> References: <20230526122852.4552-1-rf@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: qIVzziWqmjJFw00D4UuMtyws15xD_hoS X-Proofpoint-GUID: qIVzziWqmjJFw00D4UuMtyws15xD_hoS X-Proofpoint-Spam-Reason: safe X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1766959908969123503?= X-GMAIL-MSGID: =?utf-8?q?1766959908969123503?= From: Simon Trimmer The function can be more easily reused in HDA if the tracking of whether a soft reset is being performed and whether the device is connected to a SoundWire bus is moved out of the function. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Acked-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 4d41c4b040a4..76cc9110d4e0 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -805,10 +805,8 @@ static const struct reg_sequence cs35l56_system_reset_seq[] = { REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET), }; -static void cs35l56_system_reset(struct cs35l56_private *cs35l56) +static void cs35l56_system_reset(struct cs35l56_private *cs35l56, bool is_soundwire) { - cs35l56->soft_resetting = true; - /* * Must enter cache-only first so there can't be any more register * accesses other than the controlled system reset sequence below. @@ -819,7 +817,7 @@ static void cs35l56_system_reset(struct cs35l56_private *cs35l56) ARRAY_SIZE(cs35l56_system_reset_seq)); /* On SoundWire the registers won't be accessible until it re-enumerates. */ - if (cs35l56->sdw_peripheral) + if (is_soundwire) return; usleep_range(CS35L56_CONTROL_PORT_READY_US, CS35L56_CONTROL_PORT_READY_US + 400); @@ -886,7 +884,8 @@ static void cs35l56_patch(struct cs35l56_private *cs35l56) init_completion(&cs35l56->init_completion); - cs35l56_system_reset(cs35l56); + cs35l56->soft_resetting = true; + cs35l56_system_reset(cs35l56, !!cs35l56->sdw_peripheral); if (cs35l56->sdw_peripheral) { /* @@ -1550,7 +1549,8 @@ int cs35l56_init(struct cs35l56_private *cs35l56) if (!cs35l56->base.reset_gpio) { dev_dbg(cs35l56->base.dev, "No reset gpio: using soft reset\n"); - cs35l56_system_reset(cs35l56); + cs35l56->soft_resetting = true; + cs35l56_system_reset(cs35l56, !!cs35l56->sdw_peripheral); if (cs35l56->sdw_peripheral) { /* Keep alive while we wait for re-enumeration */ pm_runtime_get_noresume(cs35l56->base.dev); From patchwork Fri May 26 12:28:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Fitzgerald X-Patchwork-Id: 99473 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp434416vqr; Fri, 26 May 2023 05:31:55 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4aB6+YcdEdANnCffNOuylv2D9VAAzgI2Mx2w8rQPQkttJujqqeNBjm+okQnYiWHOPjn2f4 X-Received: by 2002:a17:903:41d0:b0:1b0:e0a:b7ab with SMTP id u16-20020a17090341d000b001b00e0ab7abmr2446399ple.31.1685104315063; Fri, 26 May 2023 05:31:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685104315; cv=none; d=google.com; s=arc-20160816; b=HYtVu/MVkFZwh1Io8mCEISC/Xp1eUiwBKjRRwddgDH5FMa3yHJAfgm4OMXVnZJQ+yP 8e3IDbkzjfSD/yLQw0+R53QATeIpRyrArlalaOCFyjDqweh53GO2CRFhUQ1FhAdqRvyy lPgAdn5FeHAydv8AQcfWNU+BnYIHaVMA+hUvK4Mb6I959q9EwmTvrW6GL+oDlNYwnDAG Ngw2DPUfAl5Ap18JYoQdx358WJegtlcbagg4r5dqXCAi85APh4hG4S8oZkYIKR+tvqvn m9zo6h0PIyiMV+nyCpq+5gpjmf3zWD9k1kzgCZO0Obcv0mEkyEcUTWCAs2y7TEmrk1Ht tzVQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=5JHSTn8HhfaguMfczWYlhmKIp98Y8mr035TZOnR3y5A=; b=fjkd97cjj20WDfpFiFFmH7XwgENbTnJuY+UQ06LAlXI24vM2RIXRtxD8ZMoeEFSWNb gxRQYuoOd5O0K4vU6mwpRSn3AWKT7TTg+YXPAKRQ9pPoAG5gpftOYq8HUsjqjjZ+Yfnu wWAv2ptzmcW/Gl87fZljUtWGa5YMwE8w/N7DUoC2X0gX5tdHMesp+R2A24jcc7f7Kk9A B8k0sa5mhyJ5Q8nS1vbJJ14h43/0/IKADdEGJqTg/nF9w95OO/deW/V2L/CNJ9gAd2bL w81eNrmZW5DXhiq5G/xdWfRD/tFuDvcwXdvF3i0fjW9pOQyTlUY3jBTq28SnRA6zdjkb VY9Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=aj7zSqK2; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id w8-20020a1709027b8800b001ae4c3bbb0dsi3697891pll.145.2023.05.26.05.31.41; Fri, 26 May 2023 05:31:55 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=aj7zSqK2; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243486AbjEZM3a (ORCPT + 99 others); Fri, 26 May 2023 08:29:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59198 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237222AbjEZM3R (ORCPT ); Fri, 26 May 2023 08:29:17 -0400 Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 828AB19A for ; Fri, 26 May 2023 05:29:13 -0700 (PDT) Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 34QC7FGv007721; Fri, 26 May 2023 07:28:58 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=5JHSTn8HhfaguMfczWYlhmKIp98Y8mr035TZOnR3y5A=; b=aj7zSqK2VMXMOFi4565HXyXLtqyJeSYAbJNOTRIiBfCfI40S+iD1Ee2xufWSRud5xwBp 2K07S6sk0196F6eNbnQdvnJTPRcAOSPgPGNQPa3dSqn0nxkfm5yNn4m7FCvKKxb3EImN x49hShQWtym8b7E7yPjm3pEZITzE+yYgcRvGU2O74xdtuAgyyMtCgHe1Xc87VM449NAM EJesPy0VHSYEVFLmcdzkXY+/XOvei+maxVVlxxNlAXcW3J3qvi72Z90UeKz+qlRFP8YZ 0i5ew1oj+FyfSxMf7G41FvisrDwwFfjzzVMJvhAEADNgBTLMIfgYj7FetOcSDp4lodgy gQ== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 3qsde8k66v-3 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 26 May 2023 07:28:58 -0500 Received: from ediex01.ad.cirrus.com (198.61.84.80) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Fri, 26 May 2023 07:28:55 -0500 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Fri, 26 May 2023 07:28:55 -0500 Received: from EDIN4L06LR3.ad.cirrus.com (EDIN4L06LR3.ad.cirrus.com [198.61.65.166]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 9A511B38; Fri, 26 May 2023 12:28:55 +0000 (UTC) From: Richard Fitzgerald To: , , CC: , , , Simon Trimmer , Richard Fitzgerald Subject: [PATCH v3 03/12] ASoC: cs35l56: Convert utility functions to use common data structure Date: Fri, 26 May 2023 13:28:43 +0100 Message-ID: <20230526122852.4552-4-rf@opensource.cirrus.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230526122852.4552-1-rf@opensource.cirrus.com> References: <20230526122852.4552-1-rf@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: pAr_NR0Hv0XjjnS91RPvrFF4Ap5yTNoX X-Proofpoint-GUID: pAr_NR0Hv0XjjnS91RPvrFF4Ap5yTNoX X-Proofpoint-Spam-Reason: safe X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1766959942081826838?= X-GMAIL-MSGID: =?utf-8?q?1766959942081826838?= From: Simon Trimmer Use the new cs35l56_base struct for utility functions. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Acked-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 76cc9110d4e0..48e856583477 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -805,14 +805,14 @@ static const struct reg_sequence cs35l56_system_reset_seq[] = { REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET), }; -static void cs35l56_system_reset(struct cs35l56_private *cs35l56, bool is_soundwire) +static void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire) { /* * Must enter cache-only first so there can't be any more register * accesses other than the controlled system reset sequence below. */ - regcache_cache_only(cs35l56->base.regmap, true); - regmap_multi_reg_write_bypassed(cs35l56->base.regmap, + regcache_cache_only(cs35l56_base->regmap, true); + regmap_multi_reg_write_bypassed(cs35l56_base->regmap, cs35l56_system_reset_seq, ARRAY_SIZE(cs35l56_system_reset_seq)); @@ -821,7 +821,7 @@ static void cs35l56_system_reset(struct cs35l56_private *cs35l56, bool is_soundw return; usleep_range(CS35L56_CONTROL_PORT_READY_US, CS35L56_CONTROL_PORT_READY_US + 400); - regcache_cache_only(cs35l56->base.regmap, false); + regcache_cache_only(cs35l56_base->regmap, false); } static void cs35l56_secure_patch(struct cs35l56_private *cs35l56) @@ -885,7 +885,7 @@ static void cs35l56_patch(struct cs35l56_private *cs35l56) init_completion(&cs35l56->init_completion); cs35l56->soft_resetting = true; - cs35l56_system_reset(cs35l56, !!cs35l56->sdw_peripheral); + cs35l56_system_reset(&cs35l56->base, !!cs35l56->sdw_peripheral); if (cs35l56->sdw_peripheral) { /* @@ -1140,20 +1140,20 @@ int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56) } EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_resume_common, SND_SOC_CS35L56_CORE); -static int cs35l56_is_fw_reload_needed(struct cs35l56_private *cs35l56) +static int cs35l56_is_fw_reload_needed(struct cs35l56_base *cs35l56_base) { unsigned int val; int ret; /* Nothing to re-patch if we haven't done any patching yet. */ - if (!cs35l56->base.fw_patched) + if (!cs35l56_base->fw_patched) return false; /* * If we have control of RESET we will have asserted it so the firmware * will need re-patching. */ - if (cs35l56->base.reset_gpio) + if (cs35l56_base->reset_gpio) return true; /* @@ -1161,22 +1161,22 @@ static int cs35l56_is_fw_reload_needed(struct cs35l56_private *cs35l56) * can't be used here to test for memory retention. * Assume that tuning must be re-loaded. */ - if (cs35l56->base.secured) + if (cs35l56_base->secured) return true; - ret = pm_runtime_resume_and_get(cs35l56->base.dev); + ret = pm_runtime_resume_and_get(cs35l56_base->dev); if (ret) { - dev_err(cs35l56->base.dev, "Failed to runtime_get: %d\n", ret); + dev_err(cs35l56_base->dev, "Failed to runtime_get: %d\n", ret); return ret; } - ret = regmap_read(cs35l56->base.regmap, CS35L56_PROTECTION_STATUS, &val); + ret = regmap_read(cs35l56_base->regmap, CS35L56_PROTECTION_STATUS, &val); if (ret) - dev_err(cs35l56->base.dev, "Failed to read PROTECTION_STATUS: %d\n", ret); + dev_err(cs35l56_base->dev, "Failed to read PROTECTION_STATUS: %d\n", ret); else ret = !!(val & CS35L56_FIRMWARE_MISSING); - pm_runtime_put_autosuspend(cs35l56->base.dev); + pm_runtime_put_autosuspend(cs35l56_base->dev); return ret; } @@ -1305,7 +1305,7 @@ int cs35l56_system_resume(struct device *dev) if (!cs35l56->component) return 0; - ret = cs35l56_is_fw_reload_needed(cs35l56); + ret = cs35l56_is_fw_reload_needed(&cs35l56->base); dev_dbg(cs35l56->base.dev, "fw_reload_needed: %d\n", ret); if (ret < 1) return ret; @@ -1550,7 +1550,7 @@ int cs35l56_init(struct cs35l56_private *cs35l56) if (!cs35l56->base.reset_gpio) { dev_dbg(cs35l56->base.dev, "No reset gpio: using soft reset\n"); cs35l56->soft_resetting = true; - cs35l56_system_reset(cs35l56, !!cs35l56->sdw_peripheral); + cs35l56_system_reset(&cs35l56->base, !!cs35l56->sdw_peripheral); if (cs35l56->sdw_peripheral) { /* Keep alive while we wait for re-enumeration */ pm_runtime_get_noresume(cs35l56->base.dev); From patchwork Fri May 26 12:28:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Fitzgerald X-Patchwork-Id: 99480 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp439081vqr; Fri, 26 May 2023 05:39:40 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5XsybSEEnOtf9hGUaRuVr7JrNA1dz0gNNqaPNQq5ynELVQkhe9M1Vn0gyrKJ/HGUqBgveO X-Received: by 2002:a05:6a00:2308:b0:640:e12a:3a20 with SMTP id h8-20020a056a00230800b00640e12a3a20mr3187391pfh.1.1685104780330; Fri, 26 May 2023 05:39:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685104780; cv=none; d=google.com; s=arc-20160816; b=uCCgqfBBErl4vMms0frf7PnjGpgbH1X5TMf4HhmmMnYo6b9wNU/H9SVApGvlL7SrDm cmcB0Se9NhHFhGHjjsINUWeD8W4byEfu/ZVoAV/biRPiEUR2VIysa7VDhx5FFkK3tU8Z pFRemq6IwVLG1EF55XAXcrSrQ7sDlY6/9CM1F6WenWKkLbtRyjYhMWH6uPqzqbw1lhSW 3y0ZVzI06283JgS3BsHWhTJRC9rTh0i0iBidcwzg5t4xS29XAOfEfg9KE/H0bJwSH/P4 mMDjaZX8DgmeMYfdPgW1w3+U3Oopmu1Xu/3yrLrC0Cmoce8BdUBO52RiE1mNCsdaOeHg RlLw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=ppg0+PZKB7EwgPPkxrUAWwZqi0ulP9/yIwPqN9AKEy0=; b=LdG9i2ZR7uDsfqSm9Q8972coXOI2krqjAuyzdav50Pi48acWYOoFV7WdM5yKz50J8n 18PnDVInWS9GjwQFvhOAFKG8dZ013vIHGHu2XlKouIv0Jg/djS8rgx4ZNdp/+o+uuMxr nSMOXKFNd1Zu2YVKIepKBbLI/fNx+pMBFDT4CopGrXrPa7EGBJPvZotFyYlcXHd0Xoey 5MbkRrhiVRBO61m2VN63FUr1Urz/03Dt+Z1vJ9s38vpyEclMXYqCHgH+dKP8SSEn3trP rDJ4YmjkOdJE+8Mu0nqJYZNcXNMZtrH0Xr1uXFCBFPqDu9Vvfs7eSMvXVMXztYQ1Ufdi /znA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=bTb4WyKu; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id y28-20020aa79afc000000b0064f4d57a5ffsi3839830pfp.388.2023.05.26.05.39.27; Fri, 26 May 2023 05:39:40 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=bTb4WyKu; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243461AbjEZM3p (ORCPT + 99 others); Fri, 26 May 2023 08:29:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59218 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243441AbjEZM3T (ORCPT ); Fri, 26 May 2023 08:29:19 -0400 Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B37BB1A7 for ; Fri, 26 May 2023 05:29:14 -0700 (PDT) Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 34QC2vwU003125; Fri, 26 May 2023 07:28:58 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=ppg0+PZKB7EwgPPkxrUAWwZqi0ulP9/yIwPqN9AKEy0=; b=bTb4WyKuUVfY7AS5ipEknuJCSwVKTJ/sEIeb4OW8GDOxngMEE91pTXubbNrh2wQkGnFL lAcWN2PZ+lYSMYZ+FPYB4ZrAhtEFU6cSifChshAZY7IqjRijLZrAQIoczW1BVYz1FWq6 aSw11qwPKsrAWkXBICVMN+eQDYRAP3w2hWhRiQOWiOwzlJ/i+h2J6ANoL8njhSdjy1EI C53YRIyMbWFJxVfzr1S6bM1SHdE8LczKvIUrN8kbFXeoVp86yODgpfhTZzL73YohYJsk pgw7b30B/E/HCGbGjXHnbIZp7xZpsFaf9GlHtZN+iitSKobvO5dMtAkkx99FnypizuDv Fw== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 3qsde8k66w-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 26 May 2023 07:28:58 -0500 Received: from ediex02.ad.cirrus.com (198.61.84.81) by ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Fri, 26 May 2023 07:28:56 -0500 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by anon-ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Fri, 26 May 2023 07:28:55 -0500 Received: from EDIN4L06LR3.ad.cirrus.com (EDIN4L06LR3.ad.cirrus.com [198.61.65.166]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 0622211A8; Fri, 26 May 2023 12:28:55 +0000 (UTC) From: Richard Fitzgerald To: , , CC: , , , Simon Trimmer , Richard Fitzgerald Subject: [PATCH v3 04/12] ASoC: cs35l56: Move utility functions to shared file Date: Fri, 26 May 2023 13:28:44 +0100 Message-ID: <20230526122852.4552-5-rf@opensource.cirrus.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230526122852.4552-1-rf@opensource.cirrus.com> References: <20230526122852.4552-1-rf@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: EUUCstQc_fL3vFlLQdjLIOnfrb2jw5s7 X-Proofpoint-GUID: EUUCstQc_fL3vFlLQdjLIOnfrb2jw5s7 X-Proofpoint-Spam-Reason: safe X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1766960430152368143?= X-GMAIL-MSGID: =?utf-8?q?1766960430152368143?= From: Simon Trimmer Move the cs35l56 utility functions into the shared file so they are available for use in HDA. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Acked-by: Mark Brown --- include/sound/cs35l56.h | 7 + sound/soc/codecs/cs35l56-shared.c | 208 ++++++++++++++++++++++++++++++ sound/soc/codecs/cs35l56.c | 203 ----------------------------- 3 files changed, 215 insertions(+), 203 deletions(-) diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h index 3a029c6621c9..4d270eb23473 100644 --- a/include/sound/cs35l56.h +++ b/include/sound/cs35l56.h @@ -274,6 +274,13 @@ extern const char * const cs35l56_tx_input_texts[CS35L56_NUM_INPUT_SRC]; extern const unsigned int cs35l56_tx_input_values[CS35L56_NUM_INPUT_SRC]; void cs35l56_reread_firmware_registers(struct cs35l56_base *cs35l56_base); +int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command); +int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base); +void cs35l56_wait_min_reset_pulse(void); +void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire); +int cs35l56_irq_request(struct cs35l56_base *cs35l56_base, int irq); +irqreturn_t cs35l56_irq(int irq, void *data); +int cs35l56_is_fw_reload_needed(struct cs35l56_base *cs35l56_base); int cs35l56_get_bclk_freq_id(unsigned int freq); void cs35l56_fill_supply_names(struct regulator_bulk_data *data); diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index 0cbaf8c7b05a..93cd898dbab6 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -200,6 +200,214 @@ void cs35l56_reread_firmware_registers(struct cs35l56_base *cs35l56_base) } EXPORT_SYMBOL_NS_GPL(cs35l56_reread_firmware_registers, SND_SOC_CS35L56_SHARED); +int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command) +{ + unsigned int val; + int ret; + + regmap_write(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, command); + ret = regmap_read_poll_timeout(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, + val, (val == 0), + CS35L56_MBOX_POLL_US, CS35L56_MBOX_TIMEOUT_US); + if (ret) { + dev_warn(cs35l56_base->dev, "MBOX command %#x failed: %d\n", command, ret); + return ret; + } + + return 0; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_mbox_send, SND_SOC_CS35L56_SHARED); + +int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base) +{ + unsigned int reg; + unsigned int val; + int ret; + + if (cs35l56_base->rev < CS35L56_REVID_B0) + reg = CS35L56_DSP1_HALO_STATE_A1; + else + reg = CS35L56_DSP1_HALO_STATE; + + ret = regmap_read_poll_timeout(cs35l56_base->regmap, reg, + val, + (val < 0xFFFF) && (val >= CS35L56_HALO_STATE_BOOT_DONE), + CS35L56_HALO_STATE_POLL_US, + CS35L56_HALO_STATE_TIMEOUT_US); + + if ((ret < 0) && (ret != -ETIMEDOUT)) { + dev_err(cs35l56_base->dev, "Failed to read HALO_STATE: %d\n", ret); + return ret; + } + + if ((ret == -ETIMEDOUT) || (val != CS35L56_HALO_STATE_BOOT_DONE)) { + dev_err(cs35l56_base->dev, "Firmware boot fail: HALO_STATE=%#x\n", val); + return -EIO; + } + + return 0; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_wait_for_firmware_boot, SND_SOC_CS35L56_SHARED); + +void cs35l56_wait_min_reset_pulse(void) +{ + /* Satisfy minimum reset pulse width spec */ + usleep_range(CS35L56_RESET_PULSE_MIN_US, 2 * CS35L56_RESET_PULSE_MIN_US); +} +EXPORT_SYMBOL_NS_GPL(cs35l56_wait_min_reset_pulse, SND_SOC_CS35L56_SHARED); + +static const struct reg_sequence cs35l56_system_reset_seq[] = { + REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET), +}; + +void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire) +{ + /* + * Must enter cache-only first so there can't be any more register + * accesses other than the controlled system reset sequence below. + */ + regcache_cache_only(cs35l56_base->regmap, true); + regmap_multi_reg_write_bypassed(cs35l56_base->regmap, + cs35l56_system_reset_seq, + ARRAY_SIZE(cs35l56_system_reset_seq)); + + /* On SoundWire the registers won't be accessible until it re-enumerates. */ + if (is_soundwire) + return; + + usleep_range(CS35L56_CONTROL_PORT_READY_US, CS35L56_CONTROL_PORT_READY_US + 400); + regcache_cache_only(cs35l56_base->regmap, false); +} +EXPORT_SYMBOL_NS_GPL(cs35l56_system_reset, SND_SOC_CS35L56_SHARED); + +int cs35l56_irq_request(struct cs35l56_base *cs35l56_base, int irq) +{ + int ret; + + if (!irq) + return 0; + + ret = devm_request_threaded_irq(cs35l56_base->dev, irq, NULL, cs35l56_irq, + IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW, + "cs35l56", cs35l56_base); + if (!ret) + cs35l56_base->irq = irq; + else + dev_err(cs35l56_base->dev, "Failed to get IRQ: %d\n", ret); + + return ret; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_irq_request, SND_SOC_CS35L56_SHARED); + +irqreturn_t cs35l56_irq(int irq, void *data) +{ + struct cs35l56_base *cs35l56_base = data; + unsigned int status1 = 0, status8 = 0, status20 = 0; + unsigned int mask1, mask8, mask20; + unsigned int val; + int rv; + + irqreturn_t ret = IRQ_NONE; + + if (!cs35l56_base->init_done) + return IRQ_NONE; + + mutex_lock(&cs35l56_base->irq_lock); + + rv = pm_runtime_resume_and_get(cs35l56_base->dev); + if (rv < 0) { + dev_err(cs35l56_base->dev, "irq: failed to get pm_runtime: %d\n", rv); + goto err_unlock; + } + + regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_STATUS, &val); + if ((val & CS35L56_IRQ1_STS_MASK) == 0) { + dev_dbg(cs35l56_base->dev, "Spurious IRQ: no pending interrupt\n"); + goto err; + } + + /* Ack interrupts */ + regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_1, &status1); + regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_1, &mask1); + status1 &= ~mask1; + regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_EINT_1, status1); + + regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_8, &status8); + regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_8, &mask8); + status8 &= ~mask8; + regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_EINT_8, status8); + + regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_20, &status20); + regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, &mask20); + status20 &= ~mask20; + /* We don't want EINT20 but they default to unmasked: force mask */ + regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff); + + dev_dbg(cs35l56_base->dev, "%s: %#x %#x\n", __func__, status1, status8); + + /* Check to see if unmasked bits are active */ + if (!status1 && !status8 && !status20) + goto err; + + if (status1 & CS35L56_AMP_SHORT_ERR_EINT1_MASK) + dev_crit(cs35l56_base->dev, "Amp short error\n"); + + if (status8 & CS35L56_TEMP_ERR_EINT1_MASK) + dev_crit(cs35l56_base->dev, "Overtemp error\n"); + + ret = IRQ_HANDLED; + +err: + pm_runtime_put(cs35l56_base->dev); +err_unlock: + mutex_unlock(&cs35l56_base->irq_lock); + + return ret; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_irq, SND_SOC_CS35L56_SHARED); + +int cs35l56_is_fw_reload_needed(struct cs35l56_base *cs35l56_base) +{ + unsigned int val; + int ret; + + /* Nothing to re-patch if we haven't done any patching yet. */ + if (!cs35l56_base->fw_patched) + return false; + + /* + * If we have control of RESET we will have asserted it so the firmware + * will need re-patching. + */ + if (cs35l56_base->reset_gpio) + return true; + + /* + * In secure mode FIRMWARE_MISSING is cleared by the BIOS loader so + * can't be used here to test for memory retention. + * Assume that tuning must be re-loaded. + */ + if (cs35l56_base->secured) + return true; + + ret = pm_runtime_resume_and_get(cs35l56_base->dev); + if (ret) { + dev_err(cs35l56_base->dev, "Failed to runtime_get: %d\n", ret); + return ret; + } + + ret = regmap_read(cs35l56_base->regmap, CS35L56_PROTECTION_STATUS, &val); + if (ret) + dev_err(cs35l56_base->dev, "Failed to read PROTECTION_STATUS: %d\n", ret); + else + ret = !!(val & CS35L56_FIRMWARE_MISSING); + + pm_runtime_put_autosuspend(cs35l56_base->dev); + + return ret; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_is_fw_reload_needed, SND_SOC_CS35L56_SHARED); + const struct cs_dsp_region cs35l56_dsp1_regions[] = { { .type = WMFW_HALO_PM_PACKED, .base = CS35L56_DSP1_PMEM_0 }, { .type = WMFW_HALO_XM_PACKED, .base = CS35L56_DSP1_XMEM_PACKED_0 }, diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 48e856583477..c1c7b7e408c3 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -34,23 +34,6 @@ static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); -static int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command) -{ - unsigned int val; - int ret; - - regmap_write(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, command); - ret = regmap_read_poll_timeout(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, - val, (val == 0), - CS35L56_MBOX_POLL_US, CS35L56_MBOX_TIMEOUT_US); - if (ret) { - dev_warn(cs35l56_base->dev, "MBOX command %#x failed: %d\n", command, ret); - return ret; - } - - return 0; -} - static void cs35l56_wait_dsp_ready(struct cs35l56_private *cs35l56) { /* Wait for patching to complete */ @@ -315,92 +298,6 @@ static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w, return wm_adsp_event(w, kcontrol, event); } -irqreturn_t cs35l56_irq(int irq, void *data) -{ - struct cs35l56_base *cs35l56_base = data; - unsigned int status1 = 0, status8 = 0, status20 = 0; - unsigned int mask1, mask8, mask20; - unsigned int val; - int rv; - - irqreturn_t ret = IRQ_NONE; - - if (!cs35l56_base->init_done) - return IRQ_NONE; - - mutex_lock(&cs35l56_base->irq_lock); - - rv = pm_runtime_resume_and_get(cs35l56_base->dev); - if (rv < 0) { - dev_err(cs35l56_base->dev, "irq: failed to get pm_runtime: %d\n", rv); - goto err_unlock; - } - - regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_STATUS, &val); - if ((val & CS35L56_IRQ1_STS_MASK) == 0) { - dev_dbg(cs35l56_base->dev, "Spurious IRQ: no pending interrupt\n"); - goto err; - } - - /* Ack interrupts */ - regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_1, &status1); - regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_1, &mask1); - status1 &= ~mask1; - regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_EINT_1, status1); - - regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_8, &status8); - regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_8, &mask8); - status8 &= ~mask8; - regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_EINT_8, status8); - - regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_20, &status20); - regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, &mask20); - status20 &= ~mask20; - /* We don't want EINT20 but they default to unmasked: force mask */ - regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff); - - dev_dbg(cs35l56_base->dev, "%s: %#x %#x\n", __func__, status1, status8); - - /* Check to see if unmasked bits are active */ - if (!status1 && !status8 && !status20) - goto err; - - if (status1 & CS35L56_AMP_SHORT_ERR_EINT1_MASK) - dev_crit(cs35l56_base->dev, "Amp short error\n"); - - if (status8 & CS35L56_TEMP_ERR_EINT1_MASK) - dev_crit(cs35l56_base->dev, "Overtemp error\n"); - - ret = IRQ_HANDLED; - -err: - pm_runtime_put(cs35l56_base->dev); -err_unlock: - mutex_unlock(&cs35l56_base->irq_lock); - - return ret; -} -EXPORT_SYMBOL_NS_GPL(cs35l56_irq, SND_SOC_CS35L56_CORE); - -int cs35l56_irq_request(struct cs35l56_base *cs35l56_base, int irq) -{ - int ret; - - if (!irq) - return 0; - - ret = devm_request_threaded_irq(cs35l56_base->dev, irq, NULL, cs35l56_irq, - IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW, - "cs35l56", cs35l56_base); - if (!ret) - cs35l56_base->irq = irq; - else - dev_err(cs35l56_base->dev, "Failed to get IRQ: %d\n", ret); - - return ret; -} -EXPORT_SYMBOL_NS_GPL(cs35l56_irq_request, SND_SOC_CS35L56_CORE); - static int cs35l56_asp_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(codec_dai->component); @@ -765,65 +662,6 @@ static struct snd_soc_dai_driver cs35l56_dai[] = { } }; -static int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base) -{ - unsigned int reg; - unsigned int val; - int ret; - - if (cs35l56_base->rev < CS35L56_REVID_B0) - reg = CS35L56_DSP1_HALO_STATE_A1; - else - reg = CS35L56_DSP1_HALO_STATE; - - ret = regmap_read_poll_timeout(cs35l56_base->regmap, reg, - val, - (val < 0xFFFF) && (val >= CS35L56_HALO_STATE_BOOT_DONE), - CS35L56_HALO_STATE_POLL_US, - CS35L56_HALO_STATE_TIMEOUT_US); - - if ((ret < 0) && (ret != -ETIMEDOUT)) { - dev_err(cs35l56_base->dev, "Failed to read HALO_STATE: %d\n", ret); - return ret; - } - - if ((ret == -ETIMEDOUT) || (val != CS35L56_HALO_STATE_BOOT_DONE)) { - dev_err(cs35l56_base->dev, "Firmware boot fail: HALO_STATE=%#x\n", val); - return -EIO; - } - - return 0; -} - -static inline void cs35l56_wait_min_reset_pulse(void) -{ - /* Satisfy minimum reset pulse width spec */ - usleep_range(CS35L56_RESET_PULSE_MIN_US, 2 * CS35L56_RESET_PULSE_MIN_US); -} - -static const struct reg_sequence cs35l56_system_reset_seq[] = { - REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET), -}; - -static void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire) -{ - /* - * Must enter cache-only first so there can't be any more register - * accesses other than the controlled system reset sequence below. - */ - regcache_cache_only(cs35l56_base->regmap, true); - regmap_multi_reg_write_bypassed(cs35l56_base->regmap, - cs35l56_system_reset_seq, - ARRAY_SIZE(cs35l56_system_reset_seq)); - - /* On SoundWire the registers won't be accessible until it re-enumerates. */ - if (is_soundwire) - return; - - usleep_range(CS35L56_CONTROL_PORT_READY_US, CS35L56_CONTROL_PORT_READY_US + 400); - regcache_cache_only(cs35l56_base->regmap, false); -} - static void cs35l56_secure_patch(struct cs35l56_private *cs35l56) { int ret; @@ -1140,47 +978,6 @@ int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56) } EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_resume_common, SND_SOC_CS35L56_CORE); -static int cs35l56_is_fw_reload_needed(struct cs35l56_base *cs35l56_base) -{ - unsigned int val; - int ret; - - /* Nothing to re-patch if we haven't done any patching yet. */ - if (!cs35l56_base->fw_patched) - return false; - - /* - * If we have control of RESET we will have asserted it so the firmware - * will need re-patching. - */ - if (cs35l56_base->reset_gpio) - return true; - - /* - * In secure mode FIRMWARE_MISSING is cleared by the BIOS loader so - * can't be used here to test for memory retention. - * Assume that tuning must be re-loaded. - */ - if (cs35l56_base->secured) - return true; - - ret = pm_runtime_resume_and_get(cs35l56_base->dev); - if (ret) { - dev_err(cs35l56_base->dev, "Failed to runtime_get: %d\n", ret); - return ret; - } - - ret = regmap_read(cs35l56_base->regmap, CS35L56_PROTECTION_STATUS, &val); - if (ret) - dev_err(cs35l56_base->dev, "Failed to read PROTECTION_STATUS: %d\n", ret); - else - ret = !!(val & CS35L56_FIRMWARE_MISSING); - - pm_runtime_put_autosuspend(cs35l56_base->dev); - - return ret; -} - int cs35l56_system_suspend(struct device *dev) { struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); From patchwork Fri May 26 12:28:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Fitzgerald X-Patchwork-Id: 99477 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp434855vqr; Fri, 26 May 2023 05:32:30 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4grI6rIZqCv9ICnB96tL92tHJbjwbiSntGwlZT0/vN9unKjNFSqot2uZslfvVMVwgZcaOq X-Received: by 2002:a17:90b:1244:b0:253:510e:130a with SMTP id gx4-20020a17090b124400b00253510e130amr1970362pjb.19.1685104350550; Fri, 26 May 2023 05:32:30 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685104350; cv=none; d=google.com; s=arc-20160816; b=mQaCdoB0pPxrVX3ivERmxK64FZs7BToRE57jAB/IKmMvTurkm18CKHqH91wbzxjrdA Z+kO/GD+qjI5Nb+4qBHfuG6LJzFjGpJre4jAvKxo//DV9wD652gQLva5jPrIK/CeUIJm t10hTm0MwScrxIvPtkHjxhzhDilTqvtcGOCiGs5+duUsKW3UkGuUMxb9tMGWhotcz4h0 3YNwYdEfQ8RvSAjQH1V3rzUXKIbXaZ+rTT8oZFrZmcwNYb+3ByOEBEm5i9e7GKCDH0CY EnogY8ZGHnMx3jOL0UYUWu56xwT+bK85VsxhPyPWXvRih+hzndbeAVeQq2T7py/hmT++ 3upQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=Pp/FxknvJU5rjQkHvgUZ0XH4fzvFFYwJcRUhKcKT6dw=; b=JU3hfD5YPh82era/e8Bf/6mPNbeJRRPHneszPoMDb4apIZWgxaSCBrfeh3hPLsDfxX YaKMNwaVWO0AWKkvKRphM5Yi7KvXn1Br2a3Kt8ktSveWZjRz+UP7ulPq/L+sg+ohNrQk BrdBI0SudNToFO2Rkd+Oj3HgEAkXiYROw/3GK9ZhYJPLbrLa2b+IQyWqmlrxet4x2rx3 o4TAuL9aRFE9KytY/XpEYR0YRfJOvvkrNYAVjGdr1s8MHvL4ZJEjtH+oxsLufTDzPanB QX7J+0Q3jokvbhCpwIJJc7sP/a3A2Hb8P+cWZ0BaPsq1I8iF1sINLqqc6yp2l7Tqg6qg tM7g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=iViiYU+u; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id u10-20020a17090abb0a00b002508889985fsi1917645pjr.95.2023.05.26.05.32.17; Fri, 26 May 2023 05:32:30 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=iViiYU+u; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243539AbjEZM3m (ORCPT + 99 others); Fri, 26 May 2023 08:29:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59214 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243434AbjEZM3T (ORCPT ); Fri, 26 May 2023 08:29:19 -0400 Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0CF891A8 for ; Fri, 26 May 2023 05:29:14 -0700 (PDT) Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 34QC7FGw007721; Fri, 26 May 2023 07:28:59 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=Pp/FxknvJU5rjQkHvgUZ0XH4fzvFFYwJcRUhKcKT6dw=; b=iViiYU+uOglyUhaliUlpF/mIC0GB3rVo6Urv+X3paIcIjaJOAyPMKak1ZnYKxI13qJle HoBzLS10FaIjlUWA4nOj+V/1oJuRvJ0BJRN7ex2UAhNAO0DiTsyUNEs+MBOPD7d+kAuW x5kJBST1TQ4CE8fawHvZwpUtPxXpTDAlGThMDX1c4zrCm0/kRc2BZC3IXrs+0mQpBv+6 8OdC4RG19JC21N95MbYW8OVa54PC7Ep4bgg1X59kncVB5x1v2QNB7YwqOOVoKB4y0lsP t0GD4wbGCoAERwFMvzb5H+A3sDwwf8lY7osYx9rrt2J0jsbQdVZfrcv9h1TFRPf3a50K qQ== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 3qsde8k66v-4 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 26 May 2023 07:28:59 -0500 Received: from ediex01.ad.cirrus.com (198.61.84.80) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Fri, 26 May 2023 07:28:56 -0500 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Fri, 26 May 2023 07:28:56 -0500 Received: from EDIN4L06LR3.ad.cirrus.com (EDIN4L06LR3.ad.cirrus.com [198.61.65.166]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 6A54315B6; Fri, 26 May 2023 12:28:56 +0000 (UTC) From: Richard Fitzgerald To: , , CC: , , , Richard Fitzgerald Subject: [PATCH v3 05/12] ASoC: cs35l56: Move runtime suspend/resume to shared library Date: Fri, 26 May 2023 13:28:45 +0100 Message-ID: <20230526122852.4552-6-rf@opensource.cirrus.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230526122852.4552-1-rf@opensource.cirrus.com> References: <20230526122852.4552-1-rf@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: CQyOM-SOj9MYLj_of7QU8tEvgMATg9ND X-Proofpoint-GUID: CQyOM-SOj9MYLj_of7QU8tEvgMATg9ND X-Proofpoint-Spam-Reason: safe X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1766959979660274323?= X-GMAIL-MSGID: =?utf-8?q?1766959979660274323?= The majority of runtime_suspend and runtime_resume handling doesn't have anything specific to the ASoC driver, so can be shared by the HDA driver. Move this code into the shared library. Signed-off-by: Richard Fitzgerald Acked-by: Mark Brown --- include/sound/cs35l56.h | 2 + sound/soc/codecs/cs35l56-sdw.c | 4 +- sound/soc/codecs/cs35l56-shared.c | 118 +++++++++++++++++++++++++++++ sound/soc/codecs/cs35l56.c | 120 +----------------------------- sound/soc/codecs/cs35l56.h | 2 - 5 files changed, 126 insertions(+), 120 deletions(-) diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h index 4d270eb23473..4a885c2321c1 100644 --- a/include/sound/cs35l56.h +++ b/include/sound/cs35l56.h @@ -281,6 +281,8 @@ void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire); int cs35l56_irq_request(struct cs35l56_base *cs35l56_base, int irq); irqreturn_t cs35l56_irq(int irq, void *data); int cs35l56_is_fw_reload_needed(struct cs35l56_base *cs35l56_base); +int cs35l56_runtime_suspend_common(struct cs35l56_base *cs35l56_base); +int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_soundwire); int cs35l56_get_bclk_freq_id(unsigned int freq); void cs35l56_fill_supply_names(struct regulator_bulk_data *data); diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c index 98be005b8787..b433266b7844 100644 --- a/sound/soc/codecs/cs35l56-sdw.c +++ b/sound/soc/codecs/cs35l56-sdw.c @@ -424,7 +424,7 @@ static int __maybe_unused cs35l56_sdw_runtime_suspend(struct device *dev) if (!cs35l56->base.init_done) return 0; - return cs35l56_runtime_suspend(dev); + return cs35l56_runtime_suspend_common(&cs35l56->base); } static int __maybe_unused cs35l56_sdw_runtime_resume(struct device *dev) @@ -441,7 +441,7 @@ static int __maybe_unused cs35l56_sdw_runtime_resume(struct device *dev) if (ret < 0) return ret; - ret = cs35l56_runtime_resume_common(cs35l56); + ret = cs35l56_runtime_resume_common(&cs35l56->base, true); if (ret) return ret; diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index 93cd898dbab6..194fa08e1cc2 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -408,6 +408,124 @@ int cs35l56_is_fw_reload_needed(struct cs35l56_base *cs35l56_base) } EXPORT_SYMBOL_NS_GPL(cs35l56_is_fw_reload_needed, SND_SOC_CS35L56_SHARED); +static const struct reg_sequence cs35l56_hibernate_seq[] = { + /* This must be the last register access */ + REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_HIBERNATE_NOW), +}; + +static const struct reg_sequence cs35l56_hibernate_wake_seq[] = { + REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_WAKEUP), +}; + +int cs35l56_runtime_suspend_common(struct cs35l56_base *cs35l56_base) +{ + unsigned int val; + int ret; + + if (!cs35l56_base->init_done) + return 0; + + /* Firmware must have entered a power-save state */ + ret = regmap_read_poll_timeout(cs35l56_base->regmap, + CS35L56_TRANSDUCER_ACTUAL_PS, + val, (val >= CS35L56_PS3), + CS35L56_PS3_POLL_US, + CS35L56_PS3_TIMEOUT_US); + if (ret) + dev_warn(cs35l56_base->dev, "PS3 wait failed: %d\n", ret); + + /* Clear BOOT_DONE so it can be used to detect a reboot */ + regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_EINT_4, CS35L56_OTP_BOOT_DONE_MASK); + + if (!cs35l56_base->can_hibernate) { + regcache_cache_only(cs35l56_base->regmap, true); + dev_dbg(cs35l56_base->dev, "Suspended: no hibernate"); + + return 0; + } + + /* + * Enable auto-hibernate. If it is woken by some other wake source + * it will automatically return to hibernate. + */ + cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE); + + /* + * Must enter cache-only first so there can't be any more register + * accesses other than the controlled hibernate sequence below. + */ + regcache_cache_only(cs35l56_base->regmap, true); + + regmap_multi_reg_write_bypassed(cs35l56_base->regmap, + cs35l56_hibernate_seq, + ARRAY_SIZE(cs35l56_hibernate_seq)); + + dev_dbg(cs35l56_base->dev, "Suspended: hibernate"); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_suspend_common, SND_SOC_CS35L56_SHARED); + +int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_soundwire) +{ + unsigned int val; + int ret; + + if (!cs35l56_base->init_done) + return 0; + + if (!cs35l56_base->can_hibernate) + goto out_sync; + + if (!is_soundwire) { + /* + * Dummy transaction to trigger I2C/SPI auto-wake. This will NAK on I2C. + * Must be done before releasing cache-only. + */ + regmap_multi_reg_write_bypassed(cs35l56_base->regmap, + cs35l56_hibernate_wake_seq, + ARRAY_SIZE(cs35l56_hibernate_wake_seq)); + + usleep_range(CS35L56_CONTROL_PORT_READY_US, + CS35L56_CONTROL_PORT_READY_US + 400); + } + +out_sync: + regcache_cache_only(cs35l56_base->regmap, false); + + ret = cs35l56_wait_for_firmware_boot(cs35l56_base); + if (ret) { + dev_err(cs35l56_base->dev, "Hibernate wake failed: %d\n", ret); + goto err; + } + + ret = cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE); + if (ret) + goto err; + + /* BOOT_DONE will be 1 if the amp reset */ + regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_4, &val); + if (val & CS35L56_OTP_BOOT_DONE_MASK) { + dev_dbg(cs35l56_base->dev, "Registers reset in suspend\n"); + regcache_mark_dirty(cs35l56_base->regmap); + } + + regcache_sync(cs35l56_base->regmap); + + dev_dbg(cs35l56_base->dev, "Resumed"); + + return 0; + +err: + regmap_write(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, + CS35L56_MBOX_CMD_HIBERNATE_NOW); + + regcache_cache_only(cs35l56_base->regmap, true); + + return ret; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_resume_common, SND_SOC_CS35L56_SHARED); + const struct cs_dsp_region cs35l56_dsp1_regions[] = { { .type = WMFW_HALO_PM_PACKED, .base = CS35L56_DSP1_PMEM_0 }, { .type = WMFW_HALO_XM_PACKED, .base = CS35L56_DSP1_XMEM_PACKED_0 }, diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index c1c7b7e408c3..ce8142249f05 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -852,132 +852,20 @@ static const struct snd_soc_component_driver soc_component_dev_cs35l56 = { .suspend_bias_off = 1, /* see cs35l56_system_resume() */ }; -static const struct reg_sequence cs35l56_hibernate_seq[] = { - /* This must be the last register access */ - REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_HIBERNATE_NOW), -}; - -static const struct reg_sequence cs35l56_hibernate_wake_seq[] = { - REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_WAKEUP), -}; - -int cs35l56_runtime_suspend(struct device *dev) +static int __maybe_unused cs35l56_runtime_suspend_i2c_spi(struct device *dev) { struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); - unsigned int val; - int ret; - if (!cs35l56->base.init_done) - return 0; - - /* Firmware must have entered a power-save state */ - ret = regmap_read_poll_timeout(cs35l56->base.regmap, - CS35L56_TRANSDUCER_ACTUAL_PS, - val, (val >= CS35L56_PS3), - CS35L56_PS3_POLL_US, - CS35L56_PS3_TIMEOUT_US); - if (ret) - dev_warn(cs35l56->base.dev, "PS3 wait failed: %d\n", ret); - - /* Clear BOOT_DONE so it can be used to detect a reboot */ - regmap_write(cs35l56->base.regmap, CS35L56_IRQ1_EINT_4, CS35L56_OTP_BOOT_DONE_MASK); - - if (!cs35l56->base.can_hibernate) { - regcache_cache_only(cs35l56->base.regmap, true); - dev_dbg(dev, "Suspended: no hibernate"); - - return 0; - } - - /* - * Enable auto-hibernate. If it is woken by some other wake source - * it will automatically return to hibernate. - */ - cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE); - - /* - * Must enter cache-only first so there can't be any more register - * accesses other than the controlled hibernate sequence below. - */ - regcache_cache_only(cs35l56->base.regmap, true); - - regmap_multi_reg_write_bypassed(cs35l56->base.regmap, - cs35l56_hibernate_seq, - ARRAY_SIZE(cs35l56_hibernate_seq)); - - dev_dbg(dev, "Suspended: hibernate"); - - return 0; + return cs35l56_runtime_suspend_common(&cs35l56->base); } -EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_suspend, SND_SOC_CS35L56_CORE); static int __maybe_unused cs35l56_runtime_resume_i2c_spi(struct device *dev) { struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); - if (!cs35l56->base.init_done) - return 0; - - return cs35l56_runtime_resume_common(cs35l56); + return cs35l56_runtime_resume_common(&cs35l56->base, false); } -int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56) -{ - unsigned int val; - int ret; - - if (!cs35l56->base.can_hibernate) - goto out_sync; - - if (!cs35l56->sdw_peripheral) { - /* - * Dummy transaction to trigger I2C/SPI auto-wake. This will NAK on I2C. - * Must be done before releasing cache-only. - */ - regmap_multi_reg_write_bypassed(cs35l56->base.regmap, - cs35l56_hibernate_wake_seq, - ARRAY_SIZE(cs35l56_hibernate_wake_seq)); - - usleep_range(CS35L56_CONTROL_PORT_READY_US, - CS35L56_CONTROL_PORT_READY_US + 400); - } - -out_sync: - regcache_cache_only(cs35l56->base.regmap, false); - - ret = cs35l56_wait_for_firmware_boot(&cs35l56->base); - if (ret) { - dev_err(cs35l56->base.dev, "Hibernate wake failed: %d\n", ret); - goto err; - } - - ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE); - if (ret) - goto err; - - /* BOOT_DONE will be 1 if the amp reset */ - regmap_read(cs35l56->base.regmap, CS35L56_IRQ1_EINT_4, &val); - if (val & CS35L56_OTP_BOOT_DONE_MASK) { - dev_dbg(cs35l56->base.dev, "Registers reset in suspend\n"); - regcache_mark_dirty(cs35l56->base.regmap); - } - - regcache_sync(cs35l56->base.regmap); - - dev_dbg(cs35l56->base.dev, "Resumed"); - - return 0; - -err: - regmap_write(cs35l56->base.regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, - CS35L56_MBOX_CMD_HIBERNATE_NOW); - - regcache_cache_only(cs35l56->base.regmap, true); - - return ret; -} -EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_resume_common, SND_SOC_CS35L56_CORE); - int cs35l56_system_suspend(struct device *dev) { struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); @@ -1416,7 +1304,7 @@ void cs35l56_remove(struct cs35l56_private *cs35l56) EXPORT_SYMBOL_NS_GPL(cs35l56_remove, SND_SOC_CS35L56_CORE); const struct dev_pm_ops cs35l56_pm_ops_i2c_spi = { - SET_RUNTIME_PM_OPS(cs35l56_runtime_suspend, cs35l56_runtime_resume_i2c_spi, NULL) + SET_RUNTIME_PM_OPS(cs35l56_runtime_suspend_i2c_spi, cs35l56_runtime_resume_i2c_spi, NULL) SYSTEM_SLEEP_PM_OPS(cs35l56_system_suspend, cs35l56_system_resume) LATE_SYSTEM_SLEEP_PM_OPS(cs35l56_system_suspend_late, cs35l56_system_resume_early) NOIRQ_SYSTEM_SLEEP_PM_OPS(cs35l56_system_suspend_no_irq, cs35l56_system_resume_no_irq) diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h index f39f8fa9e37e..8159c3e217d9 100644 --- a/sound/soc/codecs/cs35l56.h +++ b/sound/soc/codecs/cs35l56.h @@ -55,8 +55,6 @@ struct cs35l56_private { extern const struct dev_pm_ops cs35l56_pm_ops_i2c_spi; -int cs35l56_runtime_suspend(struct device *dev); -int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56); int cs35l56_system_suspend(struct device *dev); int cs35l56_system_suspend_late(struct device *dev); int cs35l56_system_suspend_no_irq(struct device *dev); From patchwork Fri May 26 12:28:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Fitzgerald X-Patchwork-Id: 99475 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp434648vqr; Fri, 26 May 2023 05:32:15 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4lEKggtN0DVHRJTZrljKmgBY3Z8sPzZJZPmMl7hV9lDcFmc63Sltl/DeRyLPND2ShSuJhy X-Received: by 2002:a05:6a20:1442:b0:10b:97c8:2e16 with SMTP id a2-20020a056a20144200b0010b97c82e16mr2594599pzi.29.1685104335318; Fri, 26 May 2023 05:32:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685104335; cv=none; d=google.com; s=arc-20160816; b=niayuak0dlKWZchA9xK4gzl4GPhlLOp1nOahcp6hC3VAxfBFsrn/F4nJysUhT5EVq6 a8Jg+uBAnAWSkCyphfpwoIyI+5VZ+vExJFQqtFIQIwGzRsbDmzCohQWi6OmzZQwI91dJ JuYUGfjSIo7zh4mFzLDwvTwT4eNu7tqdZuCGD0DptaUuYXPFOYTM4k+YWaelrQUYvlFh u3G8HkETewgXg4cqF99TBIEkJuSZ/bNEhs7dU6q4eATGR3Ttlu5l6SvDGOy3oMNgj4yJ ZW/2bauM8EF9tJFSj6bHoez3tixiUhpA7CZLsoeZWeHlo3cKQGuurWzX6uWOTGYKumBq EDig== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=CXq9mbKlLBRisrpUyaThKs1+eOHnWJtaVQ0ZDo/2FOQ=; b=XBnUN6ZCbf9+9TGAgpcebmvxnJUVm+rYTqK47x0dMYrtwM6OmAhsUD3LZ++uudt5EO AzE333+Vr6vkn1kapALxumA5WMoILgzQF363K2vnPiOhv0E/SaqfJKn6o+ema6uzhBIe mziVXztLKp1KTFLISe+CfcLKqoqXp/5uyLCJdcPnDfT5wufgeZSrQb6pnOC4OU7ibOcE axHCDfPDxmQhWLqwREGMXDorxWCJGktdmkxR087qqlTjNuFygjN7hvbVBS4zZhpjWynf SrM/E9pTgTHwV9z5q+0GXd5XwFgRSEy1NtrfS3bZHhuej7Km8W/fiwMltt3sxkpWXmrM 3Pbg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b="RgwaUL//"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id a3-20020aa78e83000000b0063b88c406c4si2774227pfr.171.2023.05.26.05.32.03; Fri, 26 May 2023 05:32:15 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b="RgwaUL//"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230361AbjEZM3g (ORCPT + 99 others); Fri, 26 May 2023 08:29:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59210 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243354AbjEZM3S (ORCPT ); Fri, 26 May 2023 08:29:18 -0400 Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 50D7E19D for ; Fri, 26 May 2023 05:29:14 -0700 (PDT) Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 34QC2vwV003125; Fri, 26 May 2023 07:28:59 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=CXq9mbKlLBRisrpUyaThKs1+eOHnWJtaVQ0ZDo/2FOQ=; b=RgwaUL//bwxgf1BlB3Q/W8Mb23+/323+Xyxj3hbZT0bUBVx4946B2JLA4Wcu/KZMJCao 1bWrbC0QDWslpoasSBeVFPxMKMmAzk6yqsDOsNIEg2+Lmr3jzYrJd7wOFopcHH160Osg unYj81tGDXerLG1hpG17H7vg+h7Zr0sVc582o10NTmEFgONPZ+kxM1elKl7M4Ikmtv+Q JFBe7Lbm2qEdgolQOg3P5DmhTbPx5wFyhawCrWLocTVSTHDsD+a1gokoOm+L7L9WY1+W HFAwYESVVqNoy1vvrbEnJPoOQlh3MREYAARWhGGQVDnhADoMryN6A/BWeU6j60c4sHPk 3A== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 3qsde8k66w-3 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 26 May 2023 07:28:59 -0500 Received: from ediex01.ad.cirrus.com (198.61.84.80) by ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Fri, 26 May 2023 07:28:56 -0500 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Fri, 26 May 2023 07:28:56 -0500 Received: from EDIN4L06LR3.ad.cirrus.com (EDIN4L06LR3.ad.cirrus.com [198.61.65.166]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id BE3D711A8; Fri, 26 May 2023 12:28:56 +0000 (UTC) From: Richard Fitzgerald To: , , CC: , , , Richard Fitzgerald Subject: [PATCH v3 06/12] ASoC: cs35l56: Move cs_dsp init into shared library Date: Fri, 26 May 2023 13:28:46 +0100 Message-ID: <20230526122852.4552-7-rf@opensource.cirrus.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230526122852.4552-1-rf@opensource.cirrus.com> References: <20230526122852.4552-1-rf@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: -5uoPgngUNFtAR9g4A-opnvCgiOIovCL X-Proofpoint-GUID: -5uoPgngUNFtAR9g4A-opnvCgiOIovCL X-Proofpoint-Spam-Reason: safe X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1766959963207783081?= X-GMAIL-MSGID: =?utf-8?q?1766959963207783081?= Move the code that initialized the struct cs_dsp members into the shared library so that the HDA driver can use it. Signed-off-by: Richard Fitzgerald Acked-by: Mark Brown --- include/sound/cs35l56.h | 2 +- sound/soc/codecs/cs35l56-shared.c | 18 ++++++++++++++++-- sound/soc/codecs/cs35l56.c | 11 +---------- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h index 4a885c2321c1..e97c7ccfc051 100644 --- a/include/sound/cs35l56.h +++ b/include/sound/cs35l56.h @@ -269,7 +269,6 @@ extern struct regmap_config cs35l56_regmap_i2c; extern struct regmap_config cs35l56_regmap_spi; extern struct regmap_config cs35l56_regmap_sdw; -extern const struct cs_dsp_region cs35l56_dsp1_regions[CS35L56_NUM_DSP_REGIONS]; extern const char * const cs35l56_tx_input_texts[CS35L56_NUM_INPUT_SRC]; extern const unsigned int cs35l56_tx_input_values[CS35L56_NUM_INPUT_SRC]; @@ -283,6 +282,7 @@ irqreturn_t cs35l56_irq(int irq, void *data); int cs35l56_is_fw_reload_needed(struct cs35l56_base *cs35l56_base); int cs35l56_runtime_suspend_common(struct cs35l56_base *cs35l56_base); int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_soundwire); +void cs35l56_init_cs_dsp(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_dsp); int cs35l56_get_bclk_freq_id(unsigned int freq); void cs35l56_fill_supply_names(struct regulator_bulk_data *data); diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index 194fa08e1cc2..82e5edef1b3f 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -526,14 +526,28 @@ int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_sou } EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_resume_common, SND_SOC_CS35L56_SHARED); -const struct cs_dsp_region cs35l56_dsp1_regions[] = { +static const struct cs_dsp_region cs35l56_dsp1_regions[] = { { .type = WMFW_HALO_PM_PACKED, .base = CS35L56_DSP1_PMEM_0 }, { .type = WMFW_HALO_XM_PACKED, .base = CS35L56_DSP1_XMEM_PACKED_0 }, { .type = WMFW_HALO_YM_PACKED, .base = CS35L56_DSP1_YMEM_PACKED_0 }, { .type = WMFW_ADSP2_XM, .base = CS35L56_DSP1_XMEM_UNPACKED24_0 }, { .type = WMFW_ADSP2_YM, .base = CS35L56_DSP1_YMEM_UNPACKED24_0 }, }; -EXPORT_SYMBOL_NS_GPL(cs35l56_dsp1_regions, SND_SOC_CS35L56_SHARED); + +void cs35l56_init_cs_dsp(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_dsp) +{ + cs_dsp->num = 1; + cs_dsp->type = WMFW_HALO; + cs_dsp->rev = 0; + cs_dsp->dev = cs35l56_base->dev; + cs_dsp->regmap = cs35l56_base->regmap; + cs_dsp->base = CS35L56_DSP1_CORE_BASE; + cs_dsp->base_sysinfo = CS35L56_DSP1_SYS_INFO_ID; + cs_dsp->mem = cs35l56_dsp1_regions; + cs_dsp->num_mems = ARRAY_SIZE(cs35l56_dsp1_regions); + cs_dsp->no_core_startstop = true; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_init_cs_dsp, SND_SOC_CS35L56_SHARED); static const u32 cs35l56_bclk_valid_for_pll_freq_table[] = { [0x0C] = 128000, diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index ce8142249f05..8b9b5822d515 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -1019,18 +1019,9 @@ static int cs35l56_dsp_init(struct cs35l56_private *cs35l56) INIT_WORK(&cs35l56->dsp_work, cs35l56_dsp_work); dsp = &cs35l56->dsp; + cs35l56_init_cs_dsp(&cs35l56->base, &dsp->cs_dsp); dsp->part = "cs35l56"; - dsp->cs_dsp.num = 1; - dsp->cs_dsp.type = WMFW_HALO; - dsp->cs_dsp.rev = 0; dsp->fw = 12; - dsp->cs_dsp.dev = cs35l56->base.dev; - dsp->cs_dsp.regmap = cs35l56->base.regmap; - dsp->cs_dsp.base = CS35L56_DSP1_CORE_BASE; - dsp->cs_dsp.base_sysinfo = CS35L56_DSP1_SYS_INFO_ID; - dsp->cs_dsp.mem = cs35l56_dsp1_regions; - dsp->cs_dsp.num_mems = ARRAY_SIZE(cs35l56_dsp1_regions); - dsp->cs_dsp.no_core_startstop = true; dsp->wmfw_optional = true; dev_dbg(cs35l56->base.dev, "DSP system name: '%s'\n", dsp->system_name); From patchwork Fri May 26 12:28:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Fitzgerald X-Patchwork-Id: 99478 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp434936vqr; Fri, 26 May 2023 05:32:37 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5JhbTEAnLkvVvU+5eqQZYDnaH29e9Q5XGNuvk6rmEsttKyh8fMGVNUg+/ggxNMFWz8x6OT X-Received: by 2002:a05:6a20:734f:b0:10f:c81d:f18a with SMTP id v15-20020a056a20734f00b0010fc81df18amr1456121pzc.49.1685104357412; Fri, 26 May 2023 05:32:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685104357; cv=none; d=google.com; s=arc-20160816; b=onXZGUlY+yCtCSKvTRFBFtnLEhNDPSNTYa24mG0geDsMB9Avu8Ue5zQfIdncBN44df SU5WIeTePDnDuDH8kd6hXG/ttguexB+CnLdHnELn0t1vF08OSO/96OzVWboV+Wu6kMsE RfDCSF9/etVlayEh7wY0Tt2OK6Dqi1jKbxFTcoUnsZV9KNdRACJy3kUcSMJJzliDzFH7 R4a3rwHbgXYW+aPWwZogGV7IznpJntIVLFSwLEpD8OeBpzlozWerYP5hcLNssKUqIsZR oaRriyTSQam92ABniwR/b4koXIqmEn0eQlI8h+EAB4rHJxDUNFZ0OD8oWqw4kbZBnauw OHbA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=WNpNSqwCWkeBgvDE9x0bIc8fdAFnPwg9OFgmJ92nuHM=; b=Ak19VniWL51iTrLb5c3yNLXn9h2prYdCMrH5nWRwnFM0nW58UOLWWO2HtHc9OoxGZc 0+2gY9hfWWPuijw/VnjIftGqWH/2LSqbpj/LqNo442HCBwsJgU2nmb9+4igYkj/cD/y4 CqEeDV2L7P2/wU55laEk6btniLL4b+iT2uhhviwrhd8Q4N3BUeaq0cUQ0I5HVh38O1Ad QNCWRCxVo5h/3TPKM4c7rr4KsecqKxpxmUoGlFsvN+s3ew3TfXC9SYbom0Ur+3rrx1T6 dKcim6RvdssCASXPsqLZEPTtJXpouyVqb4TSULkVO8pfilz6xwGvH6OGpzhOKOzW4dZb ccRQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=fP5jaK2C; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id i192-20020a636dc9000000b00536e63cbd99si3640508pgc.20.2023.05.26.05.32.25; Fri, 26 May 2023 05:32:37 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=fP5jaK2C; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243561AbjEZM3r (ORCPT + 99 others); Fri, 26 May 2023 08:29:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59216 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243346AbjEZM3T (ORCPT ); Fri, 26 May 2023 08:29:19 -0400 Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5F7561AC for ; Fri, 26 May 2023 05:29:15 -0700 (PDT) Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 34QC7FGx007721; Fri, 26 May 2023 07:29:00 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=WNpNSqwCWkeBgvDE9x0bIc8fdAFnPwg9OFgmJ92nuHM=; b=fP5jaK2CBdggXPMYUBEpaRE3LYLCVUIfPhSpzYG004lv8BZjDJ7yIPYkDE6PYKt3Ba8Z mT7eXHOGzzNgQBbBMxaeXLAI/lCvNthjkvkHPjqFuKrEXr0AXF+Le6DIGj20cXepT5VO K6+59TtMfoeAaFhhRBNrxDKSr4v53f5H82yTi83rimO4owmJ/k9MlESFKeJEl2fxjIEw 4jMXLiohtcKIWkAg8dnq4qYnhpqOw9LFDv4Tv9NYbIUXCNDxCxZ61Ovpp4qshv8UP/sk pD3naSSndtK6ciNIg7tmAYGsxApCYr7noXSTV3NfuEoXaJtRgJuOAQgHBprk7+8uoFuD Yw== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 3qsde8k66v-5 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 26 May 2023 07:29:00 -0500 Received: from ediex02.ad.cirrus.com (198.61.84.81) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Fri, 26 May 2023 07:28:57 -0500 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by anon-ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Fri, 26 May 2023 07:28:57 -0500 Received: from EDIN4L06LR3.ad.cirrus.com (EDIN4L06LR3.ad.cirrus.com [198.61.65.166]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 24DE8B38; Fri, 26 May 2023 12:28:57 +0000 (UTC) From: Richard Fitzgerald To: , , CC: , , , Richard Fitzgerald Subject: [PATCH v3 07/12] ASoC: cs35l56: Move part of cs35l56_init() to shared library Date: Fri, 26 May 2023 13:28:47 +0100 Message-ID: <20230526122852.4552-8-rf@opensource.cirrus.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230526122852.4552-1-rf@opensource.cirrus.com> References: <20230526122852.4552-1-rf@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: bMluVOYX02W7pBtylERTNH8q2EHaYEJH X-Proofpoint-GUID: bMluVOYX02W7pBtylERTNH8q2EHaYEJH X-Proofpoint-Spam-Reason: safe X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1766959986809838361?= X-GMAIL-MSGID: =?utf-8?q?1766959986809838361?= Part of the initialization code in cs35l56_init() can be re-used by the HDA driver so move it into a new function in the shared library. Signed-off-by: Richard Fitzgerald Acked-by: Mark Brown --- include/sound/cs35l56.h | 1 + sound/soc/codecs/cs35l56-shared.c | 79 +++++++++++++++++++++++++++++++ sound/soc/codecs/cs35l56.c | 71 +-------------------------- 3 files changed, 82 insertions(+), 69 deletions(-) diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h index e97c7ccfc051..489a61f84325 100644 --- a/include/sound/cs35l56.h +++ b/include/sound/cs35l56.h @@ -283,6 +283,7 @@ int cs35l56_is_fw_reload_needed(struct cs35l56_base *cs35l56_base); int cs35l56_runtime_suspend_common(struct cs35l56_base *cs35l56_base); int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_soundwire); void cs35l56_init_cs_dsp(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_dsp); +int cs35l56_hw_init(struct cs35l56_base *cs35l56_base); int cs35l56_get_bclk_freq_id(unsigned int freq); void cs35l56_fill_supply_names(struct regulator_bulk_data *data); diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index 82e5edef1b3f..e3b935bd9037 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -549,6 +549,85 @@ void cs35l56_init_cs_dsp(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_ds } EXPORT_SYMBOL_NS_GPL(cs35l56_init_cs_dsp, SND_SOC_CS35L56_SHARED); +int cs35l56_hw_init(struct cs35l56_base *cs35l56_base) +{ + int ret; + unsigned int devid, revid, otpid, secured; + + /* + * If the system is not using a reset_gpio then issue a + * dummy read to force a wakeup. + */ + if (!cs35l56_base->reset_gpio) + regmap_read(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, &devid); + + /* Wait for control port to be ready (datasheet tIRS). */ + usleep_range(CS35L56_CONTROL_PORT_READY_US, + CS35L56_CONTROL_PORT_READY_US + 400); + + /* + * The HALO_STATE register is in different locations on Ax and B0 + * devices so the REVID needs to be determined before waiting for the + * firmware to boot. + */ + ret = regmap_read(cs35l56_base->regmap, CS35L56_REVID, &revid); + if (ret < 0) { + dev_err(cs35l56_base->dev, "Get Revision ID failed\n"); + return ret; + } + cs35l56_base->rev = revid & (CS35L56_AREVID_MASK | CS35L56_MTLREVID_MASK); + + ret = cs35l56_wait_for_firmware_boot(cs35l56_base); + if (ret) + return ret; + + ret = regmap_read(cs35l56_base->regmap, CS35L56_DEVID, &devid); + if (ret < 0) { + dev_err(cs35l56_base->dev, "Get Device ID failed\n"); + return ret; + } + devid &= CS35L56_DEVID_MASK; + + switch (devid) { + case 0x35A56: + break; + default: + dev_err(cs35l56_base->dev, "Unknown device %x\n", devid); + return ret; + } + + ret = regmap_read(cs35l56_base->regmap, CS35L56_DSP_RESTRICT_STS1, &secured); + if (ret) { + dev_err(cs35l56_base->dev, "Get Secure status failed\n"); + return ret; + } + + /* When any bus is restricted treat the device as secured */ + if (secured & CS35L56_RESTRICTED_MASK) + cs35l56_base->secured = true; + + ret = regmap_read(cs35l56_base->regmap, CS35L56_OTPID, &otpid); + if (ret < 0) { + dev_err(cs35l56_base->dev, "Get OTP ID failed\n"); + return ret; + } + + dev_info(cs35l56_base->dev, "Cirrus Logic CS35L56%s Rev %02X OTP%d\n", + cs35l56_base->secured ? "s" : "", cs35l56_base->rev, otpid); + + /* Wake source and *_BLOCKED interrupts default to unmasked, so mask them */ + regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff); + regmap_update_bits(cs35l56_base->regmap, CS35L56_IRQ1_MASK_1, + CS35L56_AMP_SHORT_ERR_EINT1_MASK, + 0); + regmap_update_bits(cs35l56_base->regmap, CS35L56_IRQ1_MASK_8, + CS35L56_TEMP_ERR_EINT1_MASK, + 0); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_hw_init, SND_SOC_CS35L56_SHARED); + static const u32 cs35l56_bclk_valid_for_pll_freq_table[] = { [0x0C] = 128000, [0x0F] = 256000, diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 8b9b5822d515..f472bde6d21a 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -1130,7 +1130,6 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_common_probe, SND_SOC_CS35L56_CORE); int cs35l56_init(struct cs35l56_private *cs35l56) { int ret; - unsigned int devid, revid, otpid, secured; /* * Check whether the actions associated with soft reset or one time @@ -1147,66 +1146,9 @@ int cs35l56_init(struct cs35l56_private *cs35l56) pm_runtime_set_active(cs35l56->base.dev); pm_runtime_enable(cs35l56->base.dev); - /* - * If the system is not using a reset_gpio then issue a - * dummy read to force a wakeup. - */ - if (!cs35l56->base.reset_gpio) - regmap_read(cs35l56->base.regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, &devid); - - /* Wait for control port to be ready (datasheet tIRS). */ - usleep_range(CS35L56_CONTROL_PORT_READY_US, - CS35L56_CONTROL_PORT_READY_US + 400); - - /* - * The HALO_STATE register is in different locations on Ax and B0 - * devices so the REVID needs to be determined before waiting for the - * firmware to boot. - */ - ret = regmap_read(cs35l56->base.regmap, CS35L56_REVID, &revid); - if (ret < 0) { - dev_err(cs35l56->base.dev, "Get Revision ID failed\n"); + ret = cs35l56_hw_init(&cs35l56->base); + if (ret < 0) return ret; - } - cs35l56->base.rev = revid & (CS35L56_AREVID_MASK | CS35L56_MTLREVID_MASK); - - ret = cs35l56_wait_for_firmware_boot(&cs35l56->base); - if (ret) - return ret; - - ret = regmap_read(cs35l56->base.regmap, CS35L56_DEVID, &devid); - if (ret < 0) { - dev_err(cs35l56->base.dev, "Get Device ID failed\n"); - return ret; - } - devid &= CS35L56_DEVID_MASK; - - switch (devid) { - case 0x35A56: - break; - default: - dev_err(cs35l56->base.dev, "Unknown device %x\n", devid); - return ret; - } - - ret = regmap_read(cs35l56->base.regmap, CS35L56_DSP_RESTRICT_STS1, &secured); - if (ret) { - dev_err(cs35l56->base.dev, "Get Secure status failed\n"); - return ret; - } - - /* When any bus is restricted treat the device as secured */ - if (secured & CS35L56_RESTRICTED_MASK) - cs35l56->base.secured = true; - - ret = regmap_read(cs35l56->base.regmap, CS35L56_OTPID, &otpid); - if (ret < 0) { - dev_err(cs35l56->base.dev, "Get OTP ID failed\n"); - return ret; - } - - dev_info(cs35l56->base.dev, "Cirrus Logic CS35L56%s Rev %02X OTP%d\n", - cs35l56->base.secured ? "s" : "", cs35l56->base.rev, otpid); /* Populate the DSP information with the revision and security state */ cs35l56->dsp.part = devm_kasprintf(cs35l56->base.dev, GFP_KERNEL, "cs35l56%s-%02x", @@ -1214,15 +1156,6 @@ int cs35l56_init(struct cs35l56_private *cs35l56) if (!cs35l56->dsp.part) return -ENOMEM; - /* Wake source and *_BLOCKED interrupts default to unmasked, so mask them */ - regmap_write(cs35l56->base.regmap, CS35L56_IRQ1_MASK_20, 0xffffffff); - regmap_update_bits(cs35l56->base.regmap, CS35L56_IRQ1_MASK_1, - CS35L56_AMP_SHORT_ERR_EINT1_MASK, - 0); - regmap_update_bits(cs35l56->base.regmap, CS35L56_IRQ1_MASK_8, - CS35L56_TEMP_ERR_EINT1_MASK, - 0); - if (!cs35l56->base.reset_gpio) { dev_dbg(cs35l56->base.dev, "No reset gpio: using soft reset\n"); cs35l56->soft_resetting = true; From patchwork Fri May 26 12:28:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Fitzgerald X-Patchwork-Id: 99471 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp434178vqr; Fri, 26 May 2023 05:31:40 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ7z9VCDJY3qBopvsjJ8Ep2v++L5F5DeCEcR5Y7l5dIVlu+sOq9u0GhYuwkePJ6YSIJVrCfW X-Received: by 2002:a05:6a00:891:b0:643:2559:80f3 with SMTP id q17-20020a056a00089100b00643255980f3mr3577450pfj.2.1685104300085; Fri, 26 May 2023 05:31:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685104300; cv=none; d=google.com; s=arc-20160816; b=CMItQS+rVqMA7AV7e48PPrrQ2las7I7JW4zI/Oz+MYoSjIKWlylDexQmesBpw5mXPO kETVaNAjUPAMbhSdBFzxHBNDtHUcryz3BdjhZCvk7i15jU6VMCtVuQpQUQruDfm3OY7K wX5c8uRb8veqxi6lLiHELqM025x59wU8/whANKe9C/SgWXZd/iKMOR/185Keio6yqviu apSKqPF0IF6Zft2T5gn+zEWLuCVdgeOdD/+M6GxFT6q6zpBaniNHHaY076Ntq9MODqZN FvYQFpPc1ngPpIXRcoHQK6ikCrmi7APugTh/Am7s5kEKl2VFMENB5kyfh5Fas3RDwPAl zZIw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=ZtRVanoa2UL9fx2mOjgnx7Kor2SKPiAisybX4sOubCs=; b=CujKaRQ9aFgbF1aPQzdAmAvFpec4BXK6JgY1+EsUsuDHJfeG3Dtx7DaQxLEl6beCGg OjunBLuwGDOyv9OvoFYtW7xKyHRQ3jINavD43y/Ha03fEDdg80MoWsvz1Izm1S+uA+gf xBCd4VxV4i1yj+SEOaswYoD9mrR1EZDeXgWTBnQfzDH/3Nzw6Y08sXodj/fcdWK/AOCp 3vE6LscJRX9ypALVUBo34r0eZNIJWlDkqKjPRtYDlHnet3kRoNt2kew5msGrFlvB6X7W aov79UkPpEMKG1h1YdoUdKtupMHdUYShhPCjDnOkZ9/xGBEVRTXnSknwlPCnz2Y4AXWF 6pVg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b="ScP5U/Ci"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id r12-20020aa7962c000000b0064d72c6eab6si1929062pfg.274.2023.05.26.05.31.28; Fri, 26 May 2023 05:31:40 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b="ScP5U/Ci"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243472AbjEZM3Z (ORCPT + 99 others); Fri, 26 May 2023 08:29:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59184 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237116AbjEZM3R (ORCPT ); Fri, 26 May 2023 08:29:17 -0400 Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DD124195 for ; Fri, 26 May 2023 05:29:12 -0700 (PDT) Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 34QC2vwW003125; Fri, 26 May 2023 07:29:00 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=ZtRVanoa2UL9fx2mOjgnx7Kor2SKPiAisybX4sOubCs=; b=ScP5U/Cib/hhvm9EHNfZK1/HworEvV2+pz1qPf+pPjFyNKZIUpgbJkvk4jr6FnRuYmOq KpkZoP71HCnvxZDydMzvQvrdT3ANYHhc+bZkR+jL84NIoTn88WCrVomqJ1nNbjCMcnjO vVR3EyQX9fZeQkOHWBLsfFmg/G70/LVSmAqqLfT3AjCIuFOHikZT+B5YF8zuzGSfX5F1 Z5ETz/hCjO7hbvtjJKKsoUG/hkXkro0ywGBz9iO+2rNMdO4aT0MXn83QuhEPehE8RxAD yZvP6dyH3cPjarPWbOjf13ITNLnxx1f35GlfFA3X0vl0EYSlqhEG1ysSecgmP1vTiqUN iw== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 3qsde8k66w-4 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 26 May 2023 07:29:00 -0500 Received: from ediex01.ad.cirrus.com (198.61.84.80) by ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Fri, 26 May 2023 07:28:57 -0500 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Fri, 26 May 2023 07:28:57 -0500 Received: from EDIN4L06LR3.ad.cirrus.com (EDIN4L06LR3.ad.cirrus.com [198.61.65.166]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 7B61B15B4; Fri, 26 May 2023 12:28:57 +0000 (UTC) From: Richard Fitzgerald To: , , CC: , , , Simon Trimmer , Richard Fitzgerald Subject: [PATCH v3 08/12] ASoC: cs35l56: Make common function for control port wait Date: Fri, 26 May 2023 13:28:48 +0100 Message-ID: <20230526122852.4552-9-rf@opensource.cirrus.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230526122852.4552-1-rf@opensource.cirrus.com> References: <20230526122852.4552-1-rf@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: 6vqy0MMJIYXBSUWycPiXZhcRCKeYIfYf X-Proofpoint-GUID: 6vqy0MMJIYXBSUWycPiXZhcRCKeYIfYf X-Proofpoint-Spam-Reason: safe X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1766959926572171794?= X-GMAIL-MSGID: =?utf-8?q?1766959926572171794?= From: Simon Trimmer Move the waits for CS35L56_CONTROL_PORT_READY_US into a common function, and also allow a wider range of allowed wait times. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Acked-by: Mark Brown --- include/sound/cs35l56.h | 1 + sound/soc/codecs/cs35l56-shared.c | 16 ++++++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h index 489a61f84325..ae9e8f55962a 100644 --- a/include/sound/cs35l56.h +++ b/include/sound/cs35l56.h @@ -275,6 +275,7 @@ extern const unsigned int cs35l56_tx_input_values[CS35L56_NUM_INPUT_SRC]; void cs35l56_reread_firmware_registers(struct cs35l56_base *cs35l56_base); int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command); int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base); +void cs35l56_wait_control_port_ready(void); void cs35l56_wait_min_reset_pulse(void); void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire); int cs35l56_irq_request(struct cs35l56_base *cs35l56_base, int irq); diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index e3b935bd9037..7e02d023338c 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -249,6 +249,13 @@ int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base) } EXPORT_SYMBOL_NS_GPL(cs35l56_wait_for_firmware_boot, SND_SOC_CS35L56_SHARED); +void cs35l56_wait_control_port_ready(void) +{ + /* Wait for control port to be ready (datasheet tIRS). */ + usleep_range(CS35L56_CONTROL_PORT_READY_US, 2 * CS35L56_CONTROL_PORT_READY_US); +} +EXPORT_SYMBOL_NS_GPL(cs35l56_wait_control_port_ready, SND_SOC_CS35L56_SHARED); + void cs35l56_wait_min_reset_pulse(void) { /* Satisfy minimum reset pulse width spec */ @@ -275,7 +282,7 @@ void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire) if (is_soundwire) return; - usleep_range(CS35L56_CONTROL_PORT_READY_US, CS35L56_CONTROL_PORT_READY_US + 400); + cs35l56_wait_control_port_ready(); regcache_cache_only(cs35l56_base->regmap, false); } EXPORT_SYMBOL_NS_GPL(cs35l56_system_reset, SND_SOC_CS35L56_SHARED); @@ -486,8 +493,7 @@ int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_sou cs35l56_hibernate_wake_seq, ARRAY_SIZE(cs35l56_hibernate_wake_seq)); - usleep_range(CS35L56_CONTROL_PORT_READY_US, - CS35L56_CONTROL_PORT_READY_US + 400); + cs35l56_wait_control_port_ready(); } out_sync: @@ -561,9 +567,7 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base) if (!cs35l56_base->reset_gpio) regmap_read(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, &devid); - /* Wait for control port to be ready (datasheet tIRS). */ - usleep_range(CS35L56_CONTROL_PORT_READY_US, - CS35L56_CONTROL_PORT_READY_US + 400); + cs35l56_wait_control_port_ready(); /* * The HALO_STATE register is in different locations on Ax and B0 From patchwork Fri May 26 12:28:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Fitzgerald X-Patchwork-Id: 99476 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp434735vqr; Fri, 26 May 2023 05:32:21 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ7bG9B4f2gY7m7tc0OFHLCKAneVEPJeboLSJIuHTdlbamqgecYsLodz9pBOPYD/qWTxqRhZ X-Received: by 2002:a05:6a20:548a:b0:10f:fea:1997 with SMTP id i10-20020a056a20548a00b0010f0fea1997mr2510197pzk.5.1685104341361; Fri, 26 May 2023 05:32:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685104341; cv=none; d=google.com; s=arc-20160816; b=o0POO211KOrHuCG2bTPfS6HRNhcv+dKhw7gA18DiJ33GWUfOo1WgN6aFZeuG5AGR11 KUAm2xmiR/vq9RCW6rk9+ac7fQIJH1cIP/nRBTu62ccMt88pX3iZg3vHd+Wi4rd4EXkQ VtZAJHBT6VzcnwBQMmOpk07KV3NqTP7FzfvXQO6jyV8d/ZXYQWoNBG7YiOMTINBkc3Wt PjoLMBCHiRNT923MMUud6YhxDaisnYjpb1IDM43IiobMxYB5pIIgrntGj90NLp5oGrTL 8q3Agi25JctDFw0mtY1Z+QaK/RbMVXuvkC57BZ3qeiK5lBBHV0lQN4rGQP0rI5t4cqog mxnA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=bFYPw6wLCSpL41YWCAF1soDlcwsIVO5BLl0PUe5WOmc=; b=rjQv7AZkKg47FVzssxZSEuI/Dl2ITW8fqsWMi/LNFKxVY5IYIajizkJB1kHcHVqhrT s9w7Xu7FGor6YtqS8c2UAlmG3pxo4TFe4wILwM5cQ1lPHR5XdxoAvPzwI9t7qxtLeGsq 2Se19ieN4l0BMeZpFL5kDh4hDiXzAytlIz4CAvAefljwoqgMAlLWkvb3or8b/noyr9Ov EQK3a1P66Q98V7u4FoPWYuOj6OeVCWrWQbwug0suAEvrbpwVR25UscLpakCrZCs/rgpB UFaCIa3TxZzqTuaT3Kpp2izoWl6j3euZ9hIOfYYq1QmLxXFf2wWyD1GZKPj2mkjkPALe KW6w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=SqaypTwr; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id bu26-20020a63295a000000b00534dbd0d219si380812pgb.301.2023.05.26.05.32.08; Fri, 26 May 2023 05:32:21 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=SqaypTwr; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243528AbjEZM3i (ORCPT + 99 others); Fri, 26 May 2023 08:29:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59212 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243407AbjEZM3S (ORCPT ); Fri, 26 May 2023 08:29:18 -0400 Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AC9521A2 for ; Fri, 26 May 2023 05:29:14 -0700 (PDT) Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 34QC2vwX003125; Fri, 26 May 2023 07:29:01 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=bFYPw6wLCSpL41YWCAF1soDlcwsIVO5BLl0PUe5WOmc=; b=SqaypTwrxLH7UjzdyQn7NBU9izss7LhWFXEgbuyNY13WRyXOlPbwMEJZQIj4f0I/J7Id Az/DB9nYvWEKOFaPa8Gu9DGFF/9nvIliM0PiYUU8Dj9UvHWS0hJP3o6YytT7EK+ujxkJ QzaoU7PGsxY5YVoNkLnvaDdGXoz7ScbOLlCzQCGrER9KYUtGnB9277zLuRlztcm9EOxO 4begONxRHnAcTp7UDhU8lAOSNTxShPXepse5WABxE+MWQP7wXgQSXfqoBuGLCbW0iEXW BB6nzjCJndpo48npIBTGgg8nBAzJqOJaRyWgOe0fG+moFC2p9in9rYFBbWeBGH5Xy/DS Lw== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 3qsde8k66w-5 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 26 May 2023 07:29:00 -0500 Received: from ediex01.ad.cirrus.com (198.61.84.80) by ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Fri, 26 May 2023 07:28:57 -0500 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Fri, 26 May 2023 07:28:57 -0500 Received: from EDIN4L06LR3.ad.cirrus.com (EDIN4L06LR3.ad.cirrus.com [198.61.65.166]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id DB69BB38; Fri, 26 May 2023 12:28:57 +0000 (UTC) From: Richard Fitzgerald To: , , CC: , , , Simon Trimmer , Richard Fitzgerald Subject: [PATCH v3 09/12] ASoC: cs35l56: Make a common function to shutdown the DSP Date: Fri, 26 May 2023 13:28:49 +0100 Message-ID: <20230526122852.4552-10-rf@opensource.cirrus.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230526122852.4552-1-rf@opensource.cirrus.com> References: <20230526122852.4552-1-rf@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: OLakzikK8_v39V_hT5T3t97ZqPvBDzNU X-Proofpoint-GUID: OLakzikK8_v39V_hT5T3t97ZqPvBDzNU X-Proofpoint-Spam-Reason: safe X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1766959969490298985?= X-GMAIL-MSGID: =?utf-8?q?1766959969490298985?= From: Simon Trimmer Move issuing of a CS35L56_MBOX_CMD_SHUTDOWN command and then waiting for the DSP to reach CS35L56_HALO_STATE_SHUTDOWN in the register appropriate for the hardware revision into a common function. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Acked-by: Mark Brown --- include/sound/cs35l56.h | 1 + sound/soc/codecs/cs35l56-shared.c | 26 ++++++++++++++++++++++++++ sound/soc/codecs/cs35l56.c | 17 +---------------- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h index ae9e8f55962a..5b32aa7468cb 100644 --- a/include/sound/cs35l56.h +++ b/include/sound/cs35l56.h @@ -274,6 +274,7 @@ extern const unsigned int cs35l56_tx_input_values[CS35L56_NUM_INPUT_SRC]; void cs35l56_reread_firmware_registers(struct cs35l56_base *cs35l56_base); int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command); +int cs35l56_firmware_shutdown(struct cs35l56_base *cs35l56_base); int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base); void cs35l56_wait_control_port_ready(void); void cs35l56_wait_min_reset_pulse(void); diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index 7e02d023338c..95ef71c7b8f1 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -218,6 +218,32 @@ int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command) } EXPORT_SYMBOL_NS_GPL(cs35l56_mbox_send, SND_SOC_CS35L56_SHARED); +int cs35l56_firmware_shutdown(struct cs35l56_base *cs35l56_base) +{ + int ret; + unsigned int reg; + unsigned int val; + + ret = cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_SHUTDOWN); + if (ret) + return ret; + + if (cs35l56_base->rev < CS35L56_REVID_B0) + reg = CS35L56_DSP1_PM_CUR_STATE_A1; + else + reg = CS35L56_DSP1_PM_CUR_STATE; + + ret = regmap_read_poll_timeout(cs35l56_base->regmap, reg, + val, (val == CS35L56_HALO_STATE_SHUTDOWN), + CS35L56_HALO_STATE_POLL_US, + CS35L56_HALO_STATE_TIMEOUT_US); + if (ret < 0) + dev_err(cs35l56_base->dev, "Failed to poll PM_CUR_STATE to 1 is %d (ret %d)\n", + val, ret); + return ret; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_firmware_shutdown, SND_SOC_CS35L56_SHARED); + int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base) { unsigned int reg; diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index f472bde6d21a..dbe9134ae09a 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -676,8 +676,6 @@ static void cs35l56_secure_patch(struct cs35l56_private *cs35l56) static void cs35l56_patch(struct cs35l56_private *cs35l56) { - unsigned int reg; - unsigned int val; int ret; /* @@ -694,23 +692,10 @@ static void cs35l56_patch(struct cs35l56_private *cs35l56) flush_work(&cs35l56->sdw_irq_work); } - ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_SHUTDOWN); + ret = cs35l56_firmware_shutdown(&cs35l56->base); if (ret) goto err; - if (cs35l56->base.rev < CS35L56_REVID_B0) - reg = CS35L56_DSP1_PM_CUR_STATE_A1; - else - reg = CS35L56_DSP1_PM_CUR_STATE; - - ret = regmap_read_poll_timeout(cs35l56->base.regmap, reg, - val, (val == CS35L56_HALO_STATE_SHUTDOWN), - CS35L56_HALO_STATE_POLL_US, - CS35L56_HALO_STATE_TIMEOUT_US); - if (ret < 0) - dev_err(cs35l56->base.dev, "Failed to poll PM_CUR_STATE to 1 is %d (ret %d)\n", - val, ret); - /* Use wm_adsp to load and apply the firmware patch and coefficient files */ ret = wm_adsp_power_up(&cs35l56->dsp); if (ret) { From patchwork Fri May 26 12:28:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Fitzgerald X-Patchwork-Id: 99472 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp434229vqr; Fri, 26 May 2023 05:31:43 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ7mFPj/uwTfJDegcxpphRVDQMVaJT3VoLG4+n43QI2mq0Y6n6dQrHAYu66usYil2TcEQQkb X-Received: by 2002:a17:90b:182:b0:256:1441:95b5 with SMTP id t2-20020a17090b018200b00256144195b5mr1951164pjs.29.1685104303115; Fri, 26 May 2023 05:31:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685104303; cv=none; d=google.com; s=arc-20160816; b=DXUwf3Csj6XgaETqgxiVv2Di4hjMwZcZwLXPeZcCjewSyKiUGxj8KET/oteepcXXZl TomAPGatC1gUMU8aJISXw4T7mrp6WG49L7FpIGwnx2rXRU2NO3YE14aeRaKAoNZ/1qDh LTyHyAEgpdPLCtMft4Hlg/xjKfMC0AfR8odg7LkP2XHJULSdQMZ7XcEJmnYB2ebBgQ0q gCMkJEN61UBMCcWyF+9CcUdjEUdp3ziBq/ttM7mw9OYnlCZq45SL3j2WwJBuiQRYqNYP JeIht/9Mvm6qSRaolS2zUa/19nF/MRs+SkU3sBt+E9yQqFgSRanj1V9R+/XlxpcwwNoy 5owQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=KBIQkBTpPs9dMkt+aC+6iuTHRtDG89mSTGRvAWzKXRU=; b=jqzke0uYzHSy4X7WIx472Mk2jVRICqPNQr36KtwBxA7xMMacHM63Nxv4VtdZ/Yhq6g vjWdeT0ZBEsjK2HviXQbAZKaVKaL+po3vCZFEl1vuBO+rkpATXLgzcxGlU7M5xGjhqA7 CecFWNpjQU9OdeAaxyOPsHyOx6FJJQt+Bh49GWuwmDTCniNbrCHgpCmMd8Zf2KZr75FC CAo9kh3dPUZCzaTFBqVQ06famfmucX/h83kPyJ/qqpkrwHncKdLigY8yimCXQOeDYrml aEg7qUdNdl+5u9scC2/ltTzLe7SEQdYqdf9xxNthmdrLi0iHFl1i0slgFHb0R9B0A9Vx Hh/Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=P7nHmpfD; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id p9-20020a17090a930900b0024e29c5c06dsi3879320pjo.12.2023.05.26.05.31.30; Fri, 26 May 2023 05:31:43 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=P7nHmpfD; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242987AbjEZM31 (ORCPT + 99 others); Fri, 26 May 2023 08:29:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59200 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237193AbjEZM3R (ORCPT ); Fri, 26 May 2023 08:29:17 -0400 Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 15D6B19C for ; Fri, 26 May 2023 05:29:14 -0700 (PDT) Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 34QC2vwY003125; Fri, 26 May 2023 07:29:01 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=KBIQkBTpPs9dMkt+aC+6iuTHRtDG89mSTGRvAWzKXRU=; b=P7nHmpfDqv2Ea24kGpV0uFyEYACFsNZxoV5CjyxxEDKKj14TX841TEYJqqfg9aZ6QjtF riC7MXIRs7qq9SbUiQyF7rZYbNGIfre6ypIo66MfPhBUwGOxNRvokKQuVWFyjIeVNe/r FhMsYcyTdevMbPRrpGU/4DtKDvc3lO3oWnSAFqV3BBlravLtwGrcBAZYcpJjqoX9z+e7 m5YWNgL5ejzsEQJAa2oidNp6kYZSw7x/GBDXXXAFvyu8aN2GvN4zvK+wJ4C456CUQ/nw c2PteC0XAPwndzL5DcZkOHfawXnF35wocmUw2v7TIjI6JJWIM3BHHhy1ecBCfPAuGhdG yQ== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 3qsde8k66w-6 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 26 May 2023 07:29:01 -0500 Received: from ediex02.ad.cirrus.com (198.61.84.81) by ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Fri, 26 May 2023 07:28:58 -0500 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by anon-ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Fri, 26 May 2023 07:28:58 -0500 Received: from EDIN4L06LR3.ad.cirrus.com (EDIN4L06LR3.ad.cirrus.com [198.61.65.166]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 5D0C211A8; Fri, 26 May 2023 12:28:58 +0000 (UTC) From: Richard Fitzgerald To: , , CC: , , , Richard Fitzgerald Subject: [PATCH v3 10/12] ALSA: hda: Fix missing header dependencies Date: Fri, 26 May 2023 13:28:50 +0100 Message-ID: <20230526122852.4552-11-rf@opensource.cirrus.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230526122852.4552-1-rf@opensource.cirrus.com> References: <20230526122852.4552-1-rf@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: siU6mYtNbsCJcDIrUgRljH4Oii1Key1i X-Proofpoint-GUID: siU6mYtNbsCJcDIrUgRljH4Oii1Key1i X-Proofpoint-Spam-Reason: safe X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1766959929660588273?= X-GMAIL-MSGID: =?utf-8?q?1766959929660588273?= Add #includes of dependencies into hda_auto_parser.h and hda_generic.h hda_auto_parser.h uses definitions in hda_local.h. hda_generic.h uses definitions in hda_local.h and hda_auto_parser.h. It also references struct hda_jack_callback, but only as a pointer. This has been forward-declared so hda_jack.h only needs to be included in source that actually uses it. Signed-off-by: Richard Fitzgerald --- sound/pci/hda/hda_auto_parser.h | 2 ++ sound/pci/hda/hda_generic.h | 3 +++ 2 files changed, 5 insertions(+) diff --git a/sound/pci/hda/hda_auto_parser.h b/sound/pci/hda/hda_auto_parser.h index df63d66af1ab..579b11beac71 100644 --- a/sound/pci/hda/hda_auto_parser.h +++ b/sound/pci/hda/hda_auto_parser.h @@ -8,6 +8,8 @@ #ifndef __SOUND_HDA_AUTO_PARSER_H #define __SOUND_HDA_AUTO_PARSER_H +#include "hda_local.h" + /* * Helper for automatic pin configuration */ diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h index 34eba40cc6e6..a8eea8367629 100644 --- a/sound/pci/hda/hda_generic.h +++ b/sound/pci/hda/hda_generic.h @@ -9,6 +9,9 @@ #define __SOUND_HDA_GENERIC_H #include +#include "hda_auto_parser.h" + +struct hda_jack_callback; /* table entry for multi-io paths */ struct hda_multi_io { From patchwork Fri May 26 12:28:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Fitzgerald X-Patchwork-Id: 99474 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp434555vqr; Fri, 26 May 2023 05:32:07 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5u3xvw2Sr+zIE382VrtJevgTcGs3Ts0ct9al4qJcn+4CKQ8StwQKQu/OWK0cAYOcYiAjpv X-Received: by 2002:a17:902:ef8a:b0:1ac:7ae7:3fe1 with SMTP id iz10-20020a170902ef8a00b001ac7ae73fe1mr2169144plb.20.1685104327085; Fri, 26 May 2023 05:32:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685104327; cv=none; d=google.com; s=arc-20160816; b=qeVpuir6yvl+XIgwa+UtUDgxPA5voSc2047yw2AUEGEMvkK9xgM/gyFX5rofHb3IH+ YXZBCrc13G5fu3fC5pEP6BzAcukooR4e9XUaL4cqervxbgtsznoyW1JFp9ZEnM98UPMY p3LMMSGbgMYPMOGPkUlAkyBa+1vyKLHXcLoPpBlJo9jTl1sO4g+/irkHf0b44MJdAJmH GQ49kyrOYPOmTZ5i2evAEevrWYE6IHM8EV/rDzUQjB2m3tRkOp5Ew5NLW7m13IWpzcHs WK40zWEpnQr7Azc66WafzdlwYJowCzUlb9PNToYZeO7qZgPC1jKrRxE6NtWLpRijqqKb HIWQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=2PmIs0Q08Dk6L0sS+J7nSOBP8MhP2M6e7/lxtiv4sR0=; b=A3gRZN92vom0RFXskAacMwQA+ycY5rp9Wq3iFKbymewTMlbKqnpsiU0icgui6wJKQB PQRUpiDhLE1CPcz4hrqaxcid8c7SWXGzzTejhFJmPK/VxAROULOB+IA6rXxrvmPHlGSa zzGh39L87tv/go9PHqvSxBk0wPKFpSAfFdctNjnvenEtjwZamODC9kfUJdvhe8+spVYY J/bFuaLazutLsKVFqujS13XDEa5607y6IdCg2z2IeCyJ7JVvc/uMnnHCRYJBzVGQpsyJ qu34xhIy303Y5k0GIwvSs5XsQj/AKYe3s35b1XRu4T9NWNn5/DPEaiapzWzRzV9TG9wt 2ORA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=R+FA9P0D; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id o8-20020a170902778800b001ac82e60516si3273988pll.323.2023.05.26.05.31.53; Fri, 26 May 2023 05:32:07 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=R+FA9P0D; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243491AbjEZM3d (ORCPT + 99 others); Fri, 26 May 2023 08:29:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59204 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243254AbjEZM3S (ORCPT ); Fri, 26 May 2023 08:29:18 -0400 Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AFD0F1A4 for ; Fri, 26 May 2023 05:29:14 -0700 (PDT) Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 34QC2vwZ003125; Fri, 26 May 2023 07:29:02 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=2PmIs0Q08Dk6L0sS+J7nSOBP8MhP2M6e7/lxtiv4sR0=; b=R+FA9P0DKpB9jO33MUHjJHqlRa0t+UOezjLVmA0MTYfAJJtTEvS8j/uaa69Cpu8s3WSx sEYQCrq2vhxltTvP9p1g61pLoDCotyhgmr/Fqea4Q4eY5MSpQeD1Zams006NWOXS2uop 6UUkhttrfK09r9xg9AtGmmzjiVrsGYPIul14SCsun+obZ90Waop/Xrnm2PLgwdMOL42U Gwf/TQcVkUIKMboc0IiYBiu1ldeJo7CBoYJZ7foWQsgih8Ld+fL1/76wl413yaPCO5N9 VzUUEhQU6XCkMOODFxcu+EKzcKUDCKxdHaG6nMwd1EUPfiQUTgu1h62CkxWR9IqK8tM7 LA== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 3qsde8k66w-7 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 26 May 2023 07:29:02 -0500 Received: from ediex01.ad.cirrus.com (198.61.84.80) by ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Fri, 26 May 2023 07:28:58 -0500 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Fri, 26 May 2023 07:28:58 -0500 Received: from EDIN4L06LR3.ad.cirrus.com (EDIN4L06LR3.ad.cirrus.com [198.61.65.166]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id B899015B6; Fri, 26 May 2023 12:28:58 +0000 (UTC) From: Richard Fitzgerald To: , , CC: , , , Simon Trimmer , Richard Fitzgerald Subject: [PATCH v3 11/12] ALSA: hda: Add mute_hook to hda_component Date: Fri, 26 May 2023 13:28:51 +0100 Message-ID: <20230526122852.4552-12-rf@opensource.cirrus.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230526122852.4552-1-rf@opensource.cirrus.com> References: <20230526122852.4552-1-rf@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: gkYvOMf1T7frH69dtQQp3Lc0qNdVJXul X-Proofpoint-GUID: gkYvOMf1T7frH69dtQQp3Lc0qNdVJXul X-Proofpoint-Spam-Reason: safe X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1766959954915114128?= X-GMAIL-MSGID: =?utf-8?q?1766959954915114128?= From: Simon Trimmer Add a hook into hda_component to allow the amplifier mute to be controlled by the owning HDA codec driver. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald --- sound/pci/hda/hda_component.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/hda_component.h b/sound/pci/hda/hda_component.h index 534e845b9cd1..2a2dfed3aed4 100644 --- a/sound/pci/hda/hda_component.h +++ b/sound/pci/hda/hda_component.h @@ -16,4 +16,5 @@ struct hda_component { char name[HDA_MAX_NAME_SIZE]; struct hda_codec *codec; void (*playback_hook)(struct device *dev, int action); + void (*mute_hook)(struct device *dev, bool mute); }; From patchwork Fri May 26 12:28:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Fitzgerald X-Patchwork-Id: 99481 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp443522vqr; Fri, 26 May 2023 05:47:30 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4c8AmS8Z6ZEp3j/5lqoLBl4d3vXP1ydm7jSnzmguVYNSYaJAplxaNjvQ2HOj6NdejLWjuW X-Received: by 2002:a05:6a00:158a:b0:645:cfb0:2779 with SMTP id u10-20020a056a00158a00b00645cfb02779mr3295393pfk.26.1685105249980; Fri, 26 May 2023 05:47:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685105249; cv=none; d=google.com; s=arc-20160816; b=vOO+51gWSyIQm04rreAr/H0LPtigUrqtfTcasODddde1HjfCkz24y5Tmo/gdYQSB4K ZIeMPQte3sDauLdEXWdgfDp/p1NWq1i4HEdNOlEhIuIOjK0BNqlh+HUFdncDSofIupuY 1NBNiaFgIP7e8kFa06OOAzdSnr9UCHRGOfSMY8ooSDx9O8oQ1nzD+fMWV/QPL0Pm1JsO pKcUCJMhKI+XO065b3u3a0UzTHDQa+KyQiq7+REDHvF0B9dhMNAApezXc/bOuMIBhNnU TO+RoQunLOacHtkLwZFUG4Syk2xerOWFZVSm72l5xXQGTqbV+hmqN3xjl3Pt1InIlN5m gegA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=uPWmiyWDa6rCdPxjKyZvDj5RXjnFYAxPTgL3bLh3NtU=; b=bid+3NV0XEbfNA0yzhVG89PaH3ilQku4RapOh4bQ0JyvOo0EUszsRoO5kXzVe7ZeIj UEcZUMwLI7qvxYYB4/FsYr3AasQxZZEHdOj4X3dP9lbq0tYrjb5ube1fwyCA8ZJ1R/Yx 8XOfk9rHQz9h1dUUKi00I5SpdSy/BfvuYnCncR11Bzwv44KgqWI9L0akQUWZI05ufUyJ Qj+yw28kR+tLtImwvf9J106czBrOPLKdVbbSKnMaZIIv7JJqZ94DFPfk6rJ+fzTmRvO0 yWOJIGs9t3gWNKrHuXU56G6HxBH5QcaPI33cHVPtZYQ0NwgcDz57Ry3OzYy8CIPZv4xS cBlA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=RKUUd9G+; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id q15-20020aa7842f000000b00646479e5702si3968297pfn.381.2023.05.26.05.46.50; Fri, 26 May 2023 05:47:29 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=RKUUd9G+; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243446AbjEZM3U (ORCPT + 99 others); Fri, 26 May 2023 08:29:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59174 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230292AbjEZM3Q (ORCPT ); Fri, 26 May 2023 08:29:16 -0400 Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 92AEA116 for ; Fri, 26 May 2023 05:29:12 -0700 (PDT) Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 34QC7FH0007721; Fri, 26 May 2023 07:29:01 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=uPWmiyWDa6rCdPxjKyZvDj5RXjnFYAxPTgL3bLh3NtU=; b=RKUUd9G+IDojpu9FTp/Gb4HcDZVInjwu4TrMiq6ODQCCImVi/hNZQ7XHOJOzGvaASFTa pH2LsGYd2Ae8qu3YUyz/9zIYIk5PU5n9XmhlPAY9MU81czCZslj6UeaHVIvOAOP3jVci k4WHpZPlpUdpBizaopt0RSOsdgo2TBahO3E1sBrxvKdh5ptoOVMKMdl5Llsu3aVjRmZu B1/uIcZ8BdhJdqkWguGttUv4y0dQp+0lkcYgpGrg9yCcfwWNCGleHUYNaLGuPnZIj+Z7 XOVsLKlSDW95sb9tKh2PSKeFi9czRmnl1sjI+g2ouHUTNleSIWlNxY1niz04sN6rqfcD Ng== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 3qsde8k66v-6 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 26 May 2023 07:29:01 -0500 Received: from ediex02.ad.cirrus.com (198.61.84.81) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Fri, 26 May 2023 07:28:59 -0500 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by anon-ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Fri, 26 May 2023 07:28:59 -0500 Received: from EDIN4L06LR3.ad.cirrus.com (EDIN4L06LR3.ad.cirrus.com [198.61.65.166]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 2FC0B11A8; Fri, 26 May 2023 12:28:59 +0000 (UTC) From: Richard Fitzgerald To: , , CC: , , , Simon Trimmer , Richard Fitzgerald Subject: [PATCH v3 12/12] ALSA: hda/cs35l56: Add driver for Cirrus Logic CS35L56 amplifier Date: Fri, 26 May 2023 13:28:52 +0100 Message-ID: <20230526122852.4552-13-rf@opensource.cirrus.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230526122852.4552-1-rf@opensource.cirrus.com> References: <20230526122852.4552-1-rf@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: v-AmDbrPwaC90u6gsiUXKa8W2g5hTk34 X-Proofpoint-GUID: v-AmDbrPwaC90u6gsiUXKa8W2g5hTk34 X-Proofpoint-Spam-Reason: safe X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1766960922589410719?= X-GMAIL-MSGID: =?utf-8?q?1766960922589410719?= From: Simon Trimmer Add a driver for the Cirrus Logic CS35L56 amplifier. This uses the same component binding API as the CS35L41 driver. This is not a standalone HDA device; it provides control of the CS35L56 for systems that use a combination of an HDA codec and CS35L56 amplifiers with audio routed through the HDA codec. The CS35L56 combines a high-performance mono audio amplifier, Class-H tracking inductive boost converter, Halo Core(TM) DSP and a DC-DC boost converter supporting Class-H tracking. Control interfaces are I2C or SPI through the standard Linux I2C or SPI bus framework. Most chip functionality is controlled by on-board ROM firmware that is always running. Firmware patches can be applied by the driver in the form of a .wmfw file (firmware patch) and/or a .bin file (system tuning). Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald --- sound/pci/hda/Kconfig | 31 + sound/pci/hda/Makefile | 6 + sound/pci/hda/cs35l56_hda.c | 990 ++++++++++++++++++++++++++++++++ sound/pci/hda/cs35l56_hda.h | 48 ++ sound/pci/hda/cs35l56_hda_i2c.c | 69 +++ sound/pci/hda/cs35l56_hda_spi.c | 68 +++ 6 files changed, 1212 insertions(+) create mode 100644 sound/pci/hda/cs35l56_hda.c create mode 100644 sound/pci/hda/cs35l56_hda.h create mode 100644 sound/pci/hda/cs35l56_hda_i2c.c create mode 100644 sound/pci/hda/cs35l56_hda_spi.c diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 886255a03e8b..0f2e941ce646 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig @@ -130,6 +130,37 @@ config SND_HDA_SCODEC_CS35L41_SPI comment "Set to Y if you want auto-loading the side codec driver" depends on SND_HDA=y && SND_HDA_SCODEC_CS35L41_SPI=m +config SND_HDA_SCODEC_CS35L56 + tristate + +config SND_HDA_SCODEC_CS35L56_I2C + tristate "Build CS35L56 HD-audio side codec support for I2C Bus" + depends on I2C + depends on ACPI || COMPILE_TEST + depends on SND_SOC + select CS_DSP + select SND_HDA_GENERIC + select SND_SOC_CS35L56_SHARED + select SND_HDA_SCODEC_CS35L56 + select SND_HDA_CS_DSP_CONTROLS + help + Say Y or M here to include CS35L56 amplifier support with + I2C control. + +config SND_HDA_SCODEC_CS35L56_SPI + tristate "Build CS35L56 HD-audio codec support for SPI Bus" + depends on SPI_MASTER + depends on ACPI || COMPILE_TEST + depends on SND_SOC + select CS_DSP + select SND_HDA_GENERIC + select SND_SOC_CS35L56_SHARED + select SND_HDA_SCODEC_CS35L56 + select SND_HDA_CS_DSP_CONTROLS + help + Say Y or M here to include CS35L56 amplifier support with + SPI control. + config SND_HDA_CODEC_REALTEK tristate "Build Realtek HD-audio codec support" select SND_HDA_GENERIC diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index 00d306104484..c6e6509e7b8e 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile @@ -31,6 +31,9 @@ snd-hda-codec-hdmi-objs := patch_hdmi.o hda_eld.o snd-hda-scodec-cs35l41-objs := cs35l41_hda.o snd-hda-scodec-cs35l41-i2c-objs := cs35l41_hda_i2c.o snd-hda-scodec-cs35l41-spi-objs := cs35l41_hda_spi.o +snd-hda-scodec-cs35l56-objs := cs35l56_hda.o +snd-hda-scodec-cs35l56-i2c-objs := cs35l56_hda_i2c.o +snd-hda-scodec-cs35l56-spi-objs := cs35l56_hda_spi.o snd-hda-cs-dsp-ctls-objs := hda_cs_dsp_ctl.o # common driver @@ -55,6 +58,9 @@ obj-$(CONFIG_SND_HDA_CODEC_HDMI) += snd-hda-codec-hdmi.o obj-$(CONFIG_SND_HDA_SCODEC_CS35L41) += snd-hda-scodec-cs35l41.o obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_I2C) += snd-hda-scodec-cs35l41-i2c.o obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_SPI) += snd-hda-scodec-cs35l41-spi.o +obj-$(CONFIG_SND_HDA_SCODEC_CS35L56) += snd-hda-scodec-cs35l56.o +obj-$(CONFIG_SND_HDA_SCODEC_CS35L56_I2C) += snd-hda-scodec-cs35l56-i2c.o +obj-$(CONFIG_SND_HDA_SCODEC_CS35L56_SPI) += snd-hda-scodec-cs35l56-spi.o obj-$(CONFIG_SND_HDA_CS_DSP_CONTROLS) += snd-hda-cs-dsp-ctls.o # this must be the last entry after codec drivers; diff --git a/sound/pci/hda/cs35l56_hda.c b/sound/pci/hda/cs35l56_hda.c new file mode 100644 index 000000000000..96f8a30e5745 --- /dev/null +++ b/sound/pci/hda/cs35l56_hda.c @@ -0,0 +1,990 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// HDA audio driver for Cirrus Logic CS35L56 smart amp +// +// Copyright (C) 2023 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cs35l56_hda.h" +#include "hda_component.h" +#include "hda_cs_dsp_ctl.h" +#include "hda_generic.h" + + /* + * The cs35l56_hda_dai_config[] reg sequence configures the device as + * ASP1_BCLK_FREQ = 3.072 MHz + * ASP1_RX_WIDTH = 32 cycles per slot, ASP1_TX_WIDTH = 32 cycles per slot, ASP1_FMT = I2S + * ASP1_DOUT_HIZ_CONTROL = Hi-Z during unused timeslots + * ASP1_RX_WL = 24 bits per sample + * ASP1_TX_WL = 24 bits per sample + * ASP1_RXn_EN 1..3 and ASP1_TXn_EN 1..4 disabled + */ +static const struct reg_sequence cs35l56_hda_dai_config[] = { + { CS35L56_ASP1_CONTROL1, 0x00000021 }, + { CS35L56_ASP1_CONTROL2, 0x20200200 }, + { CS35L56_ASP1_CONTROL3, 0x00000003 }, + { CS35L56_ASP1_DATA_CONTROL5, 0x00000018 }, + { CS35L56_ASP1_DATA_CONTROL1, 0x00000018 }, + { CS35L56_ASP1_ENABLES1, 0x00000000 }, +}; + +static void cs35l56_hda_play(struct cs35l56_hda *cs35l56) +{ + unsigned int val; + int ret; + + pm_runtime_get_sync(cs35l56->base.dev); + ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_PLAY); + if (ret == 0) { + /* Wait for firmware to enter PS0 power state */ + ret = regmap_read_poll_timeout(cs35l56->base.regmap, + CS35L56_TRANSDUCER_ACTUAL_PS, + val, (val == CS35L56_PS0), + CS35L56_PS0_POLL_US, + CS35L56_PS0_TIMEOUT_US); + if (ret) + dev_warn(cs35l56->base.dev, "PS0 wait failed: %d\n", ret); + } + regmap_set_bits(cs35l56->base.regmap, CS35L56_ASP1_ENABLES1, + BIT(CS35L56_ASP_RX1_EN_SHIFT) | BIT(CS35L56_ASP_RX2_EN_SHIFT) | + cs35l56->asp_tx_mask); + cs35l56->playing = true; +} + +static void cs35l56_hda_pause(struct cs35l56_hda *cs35l56) +{ + cs35l56->playing = false; + cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_PAUSE); + regmap_clear_bits(cs35l56->base.regmap, CS35L56_ASP1_ENABLES1, + BIT(CS35L56_ASP_RX1_EN_SHIFT) | BIT(CS35L56_ASP_RX2_EN_SHIFT) | + BIT(CS35L56_ASP_TX1_EN_SHIFT) | BIT(CS35L56_ASP_TX2_EN_SHIFT) | + BIT(CS35L56_ASP_TX3_EN_SHIFT) | BIT(CS35L56_ASP_TX4_EN_SHIFT)); + + pm_runtime_mark_last_busy(cs35l56->base.dev); + pm_runtime_put_autosuspend(cs35l56->base.dev); +} + +static void cs35l56_hda_playback_hook(struct device *dev, int action) +{ + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); + + dev_dbg(cs35l56->base.dev, "%s()%d: action: %d\n", __func__, __LINE__, action); + + switch (action) { + case HDA_GEN_PCM_ACT_PREPARE: + if (cs35l56->playing) + break; + + /* If we're suspended: flag that resume should start playback */ + if (cs35l56->suspended) { + cs35l56->playing = true; + break; + } + + cs35l56_hda_play(cs35l56); + break; + case HDA_GEN_PCM_ACT_CLEANUP: + if (!cs35l56->playing) + break; + + cs35l56_hda_pause(cs35l56); + break; + default: + break; + } +} + +static void cs35l56_hda_mute_hook(struct device *dev, bool mute) +{ + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); + unsigned int val; + + if (mute) + val = CS35L56_MAIN_RENDER_USER_MUTE_MASK; + else + val = 0; + + regmap_write(cs35l56->base.regmap, CS35L56_MAIN_RENDER_USER_MUTE, val); +} + +static int __maybe_unused cs35l56_hda_runtime_suspend(struct device *dev) +{ + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); + + if (cs35l56->cs_dsp.booted) + cs_dsp_stop(&cs35l56->cs_dsp); + + return cs35l56_runtime_suspend_common(&cs35l56->base); +} + +static int __maybe_unused cs35l56_hda_runtime_resume(struct device *dev) +{ + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); + int ret; + + ret = cs35l56_runtime_resume_common(&cs35l56->base, false); + if (ret < 0) + return ret; + + if (cs35l56->cs_dsp.booted) { + ret = cs_dsp_run(&cs35l56->cs_dsp); + if (ret) { + dev_dbg(cs35l56->base.dev, "%s: cs_dsp_run ret %d\n", __func__, ret); + goto err; + } + } + + return 0; + +err: + cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE); + regmap_write(cs35l56->base.regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, + CS35L56_MBOX_CMD_HIBERNATE_NOW); + + regcache_cache_only(cs35l56->base.regmap, true); + + return ret; +} + +static int cs35l56_hda_mixer_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + uinfo->value.enumerated.items = CS35L56_NUM_INPUT_SRC; + if (uinfo->value.enumerated.item >= CS35L56_NUM_INPUT_SRC) + uinfo->value.enumerated.item = CS35L56_NUM_INPUT_SRC - 1; + strcpy(uinfo->value.enumerated.name, cs35l56_tx_input_texts[uinfo->value.enumerated.item]); + + return 0; +} + +static int cs35l56_hda_mixer_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data; + unsigned int reg_val; + int i; + + regmap_read(cs35l56->base.regmap, kcontrol->private_value, ®_val); + reg_val &= CS35L56_ASP_TXn_SRC_MASK; + + for (i = 0; i < CS35L56_NUM_INPUT_SRC; ++i) { + if (cs35l56_tx_input_values[i] == reg_val) { + ucontrol->value.enumerated.item[0] = i; + break; + } + } + + return 0; +} + +static int cs35l56_hda_mixer_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data; + unsigned int item = ucontrol->value.enumerated.item[0]; + bool changed; + + if (item >= CS35L56_NUM_INPUT_SRC) + return -EINVAL; + + regmap_update_bits_check(cs35l56->base.regmap, kcontrol->private_value, + CS35L56_INPUT_MASK, cs35l56_tx_input_values[item], + &changed); + + return changed; +} + +static int cs35l56_hda_posture_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = CS35L56_MAIN_POSTURE_MIN; + uinfo->value.integer.max = CS35L56_MAIN_POSTURE_MAX; + return 0; +} + +static int cs35l56_hda_posture_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data; + unsigned int pos; + int ret; + + ret = regmap_read(cs35l56->base.regmap, CS35L56_MAIN_POSTURE_NUMBER, &pos); + if (ret) + return ret; + + ucontrol->value.integer.value[0] = pos; + + return ret; +} + +static int cs35l56_hda_posture_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data; + unsigned long pos = ucontrol->value.integer.value[0]; + bool changed; + int ret; + + if ((pos < CS35L56_MAIN_POSTURE_MIN) || + (pos > CS35L56_MAIN_POSTURE_MAX)) + return -EINVAL; + + ret = regmap_update_bits_check(cs35l56->base.regmap, + CS35L56_MAIN_POSTURE_NUMBER, + CS35L56_MAIN_POSTURE_MASK, + pos, &changed); + if (ret) + return ret; + + return changed; +} + +static const struct { + const char *name; + unsigned int reg; +} cs35l56_hda_mixer_controls[] = { + { "ASP1 TX1 Source", CS35L56_ASP1TX1_INPUT }, + { "ASP1 TX2 Source", CS35L56_ASP1TX2_INPUT }, + { "ASP1 TX3 Source", CS35L56_ASP1TX3_INPUT }, + { "ASP1 TX4 Source", CS35L56_ASP1TX4_INPUT }, +}; + +static const DECLARE_TLV_DB_SCALE(cs35l56_hda_vol_tlv, -10000, 25, 0); + +static int cs35l56_hda_vol_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.step = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = CS35L56_MAIN_RENDER_USER_VOLUME_MAX - + CS35L56_MAIN_RENDER_USER_VOLUME_MIN; + + return 0; +} + +static int cs35l56_hda_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data; + unsigned int raw_vol; + int vol; + int ret; + + ret = regmap_read(cs35l56->base.regmap, CS35L56_MAIN_RENDER_USER_VOLUME, &raw_vol); + + if (ret) + return ret; + + vol = (s16)(raw_vol & 0xFFFF); + vol >>= CS35L56_MAIN_RENDER_USER_VOLUME_SHIFT; + + if (vol & BIT(CS35L56_MAIN_RENDER_USER_VOLUME_SIGNBIT)) + vol |= ~((int)(BIT(CS35L56_MAIN_RENDER_USER_VOLUME_SIGNBIT) - 1)); + + ucontrol->value.integer.value[0] = vol - CS35L56_MAIN_RENDER_USER_VOLUME_MIN; + + return 0; +} + +static int cs35l56_hda_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data; + long vol = ucontrol->value.integer.value[0]; + unsigned int raw_vol; + bool changed; + int ret; + + if ((vol < 0) || (vol > (CS35L56_MAIN_RENDER_USER_VOLUME_MAX - + CS35L56_MAIN_RENDER_USER_VOLUME_MIN))) + return -EINVAL; + + raw_vol = (vol + CS35L56_MAIN_RENDER_USER_VOLUME_MIN) << + CS35L56_MAIN_RENDER_USER_VOLUME_SHIFT; + + ret = regmap_update_bits_check(cs35l56->base.regmap, + CS35L56_MAIN_RENDER_USER_VOLUME, + CS35L56_MAIN_RENDER_USER_VOLUME_MASK, + raw_vol, &changed); + if (ret) + return ret; + + return changed; +} + +static void cs35l56_hda_create_controls(struct cs35l56_hda *cs35l56) +{ + struct snd_kcontrol_new ctl_template = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = cs35l56_hda_posture_info, + .get = cs35l56_hda_posture_get, + .put = cs35l56_hda_posture_put, + }; + char name[64]; + int i; + + snprintf(name, sizeof(name), "%s Posture Number", cs35l56->amp_name); + ctl_template.name = name; + cs35l56->posture_ctl = snd_ctl_new1(&ctl_template, cs35l56); + if (snd_ctl_add(cs35l56->codec->card, cs35l56->posture_ctl)) + dev_err(cs35l56->base.dev, "Failed to add KControl: %s\n", ctl_template.name); + + /* Mixer controls */ + ctl_template.info = cs35l56_hda_mixer_info; + ctl_template.get = cs35l56_hda_mixer_get; + ctl_template.put = cs35l56_hda_mixer_put; + + BUILD_BUG_ON(ARRAY_SIZE(cs35l56->mixer_ctl) != ARRAY_SIZE(cs35l56_hda_mixer_controls)); + + for (i = 0; i < ARRAY_SIZE(cs35l56_hda_mixer_controls); ++i) { + snprintf(name, sizeof(name), "%s %s", cs35l56->amp_name, + cs35l56_hda_mixer_controls[i].name); + ctl_template.private_value = cs35l56_hda_mixer_controls[i].reg; + cs35l56->mixer_ctl[i] = snd_ctl_new1(&ctl_template, cs35l56); + if (snd_ctl_add(cs35l56->codec->card, cs35l56->mixer_ctl[i])) { + dev_err(cs35l56->base.dev, "Failed to add KControl: %s\n", + ctl_template.name); + } + } + + ctl_template.info = cs35l56_hda_vol_info; + ctl_template.get = cs35l56_hda_vol_get; + ctl_template.put = cs35l56_hda_vol_put; + ctl_template.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ); + ctl_template.tlv.p = cs35l56_hda_vol_tlv; + snprintf(name, sizeof(name), "%s Speaker Playback Volume", cs35l56->amp_name); + ctl_template.name = name; + cs35l56->volume_ctl = snd_ctl_new1(&ctl_template, cs35l56); + if (snd_ctl_add(cs35l56->codec->card, cs35l56->volume_ctl)) + dev_err(cs35l56->base.dev, "Failed to add KControl: %s\n", ctl_template.name); +} + +static void cs35l56_hda_remove_controls(struct cs35l56_hda *cs35l56) +{ + int i; + + for (i = ARRAY_SIZE(cs35l56->mixer_ctl) - 1; i >= 0; i--) + snd_ctl_remove(cs35l56->codec->card, cs35l56->mixer_ctl[i]); + + snd_ctl_remove(cs35l56->codec->card, cs35l56->posture_ctl); + snd_ctl_remove(cs35l56->codec->card, cs35l56->volume_ctl); +} + +static const struct cs_dsp_client_ops cs35l56_hda_client_ops = { + .control_remove = hda_cs_dsp_control_remove, +}; + +static int cs35l56_hda_request_firmware_file(struct cs35l56_hda *cs35l56, + const struct firmware **firmware, char **filename, + const char *dir, const char *system_name, + const char *amp_name, + const char *filetype) +{ + char *s, c; + int ret = 0; + + if (system_name && amp_name) + *filename = kasprintf(GFP_KERNEL, "%scs35l56%s-%02x-dsp1-misc-%s-%s.%s", dir, + cs35l56->base.secured ? "s" : "", cs35l56->base.rev, + system_name, amp_name, filetype); + else if (system_name) + *filename = kasprintf(GFP_KERNEL, "%scs35l56%s-%02x-dsp1-misc-%s.%s", dir, + cs35l56->base.secured ? "s" : "", cs35l56->base.rev, + system_name, filetype); + else + *filename = kasprintf(GFP_KERNEL, "%scs35l56%s-%02x-dsp1-misc.%s", dir, + cs35l56->base.secured ? "s" : "", cs35l56->base.rev, + filetype); + + if (!*filename) + return -ENOMEM; + + /* + * Make sure that filename is lower-case and any non alpha-numeric + * characters except full stop and forward slash are replaced with + * hyphens. + */ + s = *filename; + while (*s) { + c = *s; + if (isalnum(c)) + *s = tolower(c); + else if (c != '.' && c != '/') + *s = '-'; + s++; + } + + ret = firmware_request_nowarn(firmware, *filename, cs35l56->base.dev); + if (ret) { + dev_dbg(cs35l56->base.dev, "Failed to request '%s'\n", *filename); + kfree(*filename); + *filename = NULL; + } else { + dev_dbg(cs35l56->base.dev, "Found '%s'\n", *filename); + } + + return ret; +} + +static const char cirrus_dir[] = "cirrus/"; +static int cs35l56_hda_request_firmware_files(struct cs35l56_hda *cs35l56, + const struct firmware **wmfw_firmware, + char **wmfw_filename, + const struct firmware **coeff_firmware, + char **coeff_filename) +{ + const char *system_name = cs35l56->system_name; + const char *amp_name = cs35l56->amp_name; + int ret; + + if (system_name && amp_name) { + if (!cs35l56_hda_request_firmware_file(cs35l56, wmfw_firmware, wmfw_filename, + cirrus_dir, system_name, amp_name, "wmfw")) { + cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename, + cirrus_dir, system_name, amp_name, "bin"); + return 0; + } + } + + if (system_name) { + if (!cs35l56_hda_request_firmware_file(cs35l56, wmfw_firmware, wmfw_filename, + cirrus_dir, system_name, NULL, "wmfw")) { + if (amp_name) + cs35l56_hda_request_firmware_file(cs35l56, + coeff_firmware, coeff_filename, + cirrus_dir, system_name, + amp_name, "bin"); + if (!*coeff_firmware) + cs35l56_hda_request_firmware_file(cs35l56, + coeff_firmware, coeff_filename, + cirrus_dir, system_name, + NULL, "bin"); + return 0; + } + } + + ret = cs35l56_hda_request_firmware_file(cs35l56, wmfw_firmware, wmfw_filename, + cirrus_dir, NULL, NULL, "wmfw"); + if (!ret) { + cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename, + cirrus_dir, NULL, NULL, "bin"); + return 0; + } + + /* When a firmware file is not found must still search for the coeff files */ + if (system_name) { + if (amp_name) + cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename, + cirrus_dir, system_name, amp_name, "bin"); + if (!*coeff_firmware) + cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename, + cirrus_dir, system_name, NULL, "bin"); + } + + if (!*coeff_firmware) + cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename, + cirrus_dir, NULL, NULL, "bin"); + + return 0; +} + +static void cs35l56_hda_add_dsp_controls(struct cs35l56_hda *cs35l56) +{ + struct hda_cs_dsp_ctl_info info; + + info.device_name = cs35l56->amp_name; + info.fw_type = HDA_CS_DSP_FW_MISC; + info.card = cs35l56->codec->card; + + hda_cs_dsp_add_controls(&cs35l56->cs_dsp, &info); +} + +static int cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56) +{ + const struct firmware *coeff_firmware = NULL; + const struct firmware *wmfw_firmware = NULL; + char *coeff_filename = NULL; + char *wmfw_filename = NULL; + int ret = 0; + + mutex_lock(&cs35l56->base.irq_lock); + pm_runtime_get_sync(cs35l56->base.dev); + + /* + * When the device is running in secure mode the firmware files can + * only contain insecure tunings and therefore we do not need to + * shutdown the firmware to apply them and can use the lower cost + * reinit sequence instead. + */ + if (!cs35l56->base.secured) { + ret = cs35l56_firmware_shutdown(&cs35l56->base); + if (ret) + goto err; + } + + cs35l56_hda_request_firmware_files(cs35l56, &wmfw_firmware, &wmfw_filename, + &coeff_firmware, &coeff_filename); + + ret = cs_dsp_power_up(&cs35l56->cs_dsp, wmfw_firmware, wmfw_filename, + coeff_firmware, coeff_filename, "misc"); + if (ret) { + dev_dbg(cs35l56->base.dev, "%s: cs_dsp_power_up ret %d\n", __func__, ret); + goto err; + } + + if (wmfw_filename) + dev_dbg(cs35l56->base.dev, "Loaded WMFW Firmware: %s\n", wmfw_filename); + + if (coeff_filename) + dev_dbg(cs35l56->base.dev, "Loaded Coefficients: %s\n", coeff_filename); + + ret = cs_dsp_run(&cs35l56->cs_dsp); + if (ret) { + dev_dbg(cs35l56->base.dev, "%s: cs_dsp_run ret %d\n", __func__, ret); + goto err; + } + + if (cs35l56->base.secured) { + ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_REINIT); + if (ret) + goto err; + } else { + /* Reset the device and wait for it to boot */ + cs35l56_system_reset(&cs35l56->base, false); + ret = cs35l56_wait_for_firmware_boot(&cs35l56->base); + if (ret) + goto err; + } + + /* Disable auto-hibernate so that runtime_pm has control */ + ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE); + if (ret) + goto err; + + /* Re-read the values from the device after a firmware/cofficient download */ + cs35l56_reread_firmware_registers(&cs35l56->base); + + regcache_mark_dirty(cs35l56->base.regmap); + regcache_sync(cs35l56->base.regmap); + + regmap_clear_bits(cs35l56->base.regmap, CS35L56_PROTECTION_STATUS, + CS35L56_FIRMWARE_MISSING); + cs35l56->base.fw_patched = true; +err: + pm_runtime_put(cs35l56->base.dev); + mutex_unlock(&cs35l56->base.irq_lock); + + return ret; +} + +static int cs35l56_hda_bind(struct device *dev, struct device *master, void *master_data) +{ + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); + struct hda_component *comps = master_data; + int ret; + + if (!comps || cs35l56->index < 0 || cs35l56->index >= HDA_MAX_COMPONENTS) + return -EINVAL; + + comps = &comps[cs35l56->index]; + if (comps->dev) + return -EBUSY; + + comps->dev = dev; + cs35l56->codec = comps->codec; + strscpy(comps->name, dev_name(dev), sizeof(comps->name)); + comps->playback_hook = cs35l56_hda_playback_hook; + comps->mute_hook = cs35l56_hda_mute_hook; + + ret = cs35l56_hda_fw_load(cs35l56); + if (ret) + return ret; + + cs35l56_hda_create_controls(cs35l56); + cs35l56_hda_add_dsp_controls(cs35l56); + +#if IS_ENABLED(CONFIG_SND_DEBUG) + cs35l56->debugfs_root = debugfs_create_dir(dev_name(cs35l56->base.dev), sound_debugfs_root); + cs_dsp_init_debugfs(&cs35l56->cs_dsp, cs35l56->debugfs_root); +#endif + + dev_dbg(cs35l56->base.dev, "Bound\n"); + + return 0; +} + +static void cs35l56_hda_unbind(struct device *dev, struct device *master, void *master_data) +{ + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); + struct hda_component *comps = master_data; + + cs35l56_hda_remove_controls(cs35l56); + +#if IS_ENABLED(CONFIG_SND_DEBUG) + cs_dsp_cleanup_debugfs(&cs35l56->cs_dsp); + debugfs_remove_recursive(cs35l56->debugfs_root); +#endif + + cs_dsp_remove(&cs35l56->cs_dsp); + + if (comps[cs35l56->index].dev == dev) + memset(&comps[cs35l56->index], 0, sizeof(*comps)); + + dev_dbg(cs35l56->base.dev, "Unbound\n"); +} + +static const struct component_ops cs35l56_hda_comp_ops = { + .bind = cs35l56_hda_bind, + .unbind = cs35l56_hda_unbind, +}; + +static int cs35l56_hda_system_suspend(struct device *dev) +{ + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); + + if (cs35l56->playing) + cs35l56_hda_pause(cs35l56); + + cs35l56->suspended = true; + + /* + * The interrupt line is normally shared, but after we start suspending + * we can't check if our device is the source of an interrupt, and can't + * clear it. Prevent this race by temporarily disabling the parent irq + * until we reach _no_irq. + */ + if (cs35l56->base.irq) + disable_irq(cs35l56->base.irq); + + return pm_runtime_force_suspend(dev); +} + +static int cs35l56_hda_system_suspend_late(struct device *dev) +{ + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); + + /* + * RESET is usually shared by all amps so it must not be asserted until + * all driver instances have done their suspend() stage. + */ + if (cs35l56->base.reset_gpio) { + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0); + cs35l56_wait_min_reset_pulse(); + } + + return 0; +} + +static int cs35l56_hda_system_suspend_no_irq(struct device *dev) +{ + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); + + /* Handlers are now disabled so the parent IRQ can safely be re-enabled. */ + if (cs35l56->base.irq) + enable_irq(cs35l56->base.irq); + + return 0; +} + +static int cs35l56_hda_system_resume_no_irq(struct device *dev) +{ + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); + + /* + * WAKE interrupts unmask if the CS35L56 hibernates, which can cause + * spurious interrupts, and the interrupt line is normally shared. + * We can't check if our device is the source of an interrupt, and can't + * clear it, until it has fully resumed. Prevent this race by temporarily + * disabling the parent irq until we complete resume(). + */ + if (cs35l56->base.irq) + disable_irq(cs35l56->base.irq); + + return 0; +} + +static int cs35l56_hda_system_resume_early(struct device *dev) +{ + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); + + /* Ensure a spec-compliant RESET pulse. */ + if (cs35l56->base.reset_gpio) { + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0); + cs35l56_wait_min_reset_pulse(); + + /* Release shared RESET before drivers start resume(). */ + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 1); + cs35l56_wait_control_port_ready(); + } + + return 0; +} + +static int cs35l56_hda_system_resume(struct device *dev) +{ + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); + int ret; + + /* Undo pm_runtime_force_suspend() before re-enabling the irq */ + ret = pm_runtime_force_resume(dev); + if (cs35l56->base.irq) + enable_irq(cs35l56->base.irq); + + if (ret) + return ret; + + cs35l56->suspended = false; + + ret = cs35l56_is_fw_reload_needed(&cs35l56->base); + dev_dbg(cs35l56->base.dev, "fw_reload_needed: %d\n", ret); + if (ret > 0) { + ret = cs35l56_hda_fw_load(cs35l56); + if (ret) + return ret; + } + + if (cs35l56->playing) + cs35l56_hda_play(cs35l56); + + return 0; +} + +static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int id) +{ + u32 values[HDA_MAX_COMPONENTS]; + struct acpi_device *adev; + const char *property, *sub; + size_t nval; + int i, ret; + + /* + * ACPI_COMPANION isn't available when this driver was instantiated by + * the serial-multi-instantiate driver, so lookup the node by HID + */ + if (!ACPI_COMPANION(cs35l56->base.dev)) { + adev = acpi_dev_get_first_match_dev("CSC3556", NULL, -1); + if (!adev) { + dev_err(cs35l56->base.dev, "Failed to find an ACPI device for %s\n", + dev_name(cs35l56->base.dev)); + return -ENODEV; + } + ACPI_COMPANION_SET(cs35l56->base.dev, adev); + } + + property = "cirrus,dev-index"; + ret = device_property_count_u32(cs35l56->base.dev, property); + if (ret <= 0) + goto err; + + if (ret > ARRAY_SIZE(values)) { + ret = -EINVAL; + goto err; + } + nval = ret; + + ret = device_property_read_u32_array(cs35l56->base.dev, property, values, nval); + if (ret) + goto err; + + cs35l56->index = -1; + for (i = 0; i < nval; i++) { + if (values[i] == id) { + cs35l56->index = i; + break; + } + } + if (cs35l56->index == -1) { + dev_err(cs35l56->base.dev, "No index found in %s\n", property); + ret = -ENODEV; + goto err; + } + + sub = acpi_get_subsystem_id(ACPI_HANDLE(cs35l56->base.dev)); + + if (IS_ERR(sub)) { + /* If no ACPI SUB, return 0 and fallback to legacy firmware path, otherwise fail */ + if (PTR_ERR(sub) == -ENODATA) + return 0; + else + return PTR_ERR(sub); + } + + cs35l56->system_name = sub; + + cs35l56->base.reset_gpio = devm_gpiod_get_index_optional(cs35l56->base.dev, + "reset", + cs35l56->index, + GPIOD_OUT_LOW); + if (IS_ERR(cs35l56->base.reset_gpio)) { + ret = PTR_ERR(cs35l56->base.reset_gpio); + + /* + * If RESET is shared the first amp to probe will grab the reset + * line and reset all the amps + */ + if (ret != -EBUSY) + return dev_err_probe(cs35l56->base.dev, ret, "Failed to get reset GPIO\n"); + + dev_info(cs35l56->base.dev, "Reset GPIO busy, assume shared reset\n"); + cs35l56->base.reset_gpio = NULL; + } + + return 0; + +err: + dev_err(cs35l56->base.dev, "Failed property %s: %d\n", property, ret); + + return ret; +} + +int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int id) +{ + int ret; + + mutex_init(&cs35l56->base.irq_lock); + dev_set_drvdata(cs35l56->base.dev, cs35l56); + + ret = cs35l56_hda_read_acpi(cs35l56, id); + if (ret) { + dev_err_probe(cs35l56->base.dev, ret, "Platform not supported\n"); + goto err; + } + + cs35l56->amp_name = devm_kasprintf(cs35l56->base.dev, GFP_KERNEL, "AMP%d", + cs35l56->index + 1); + if (!cs35l56->amp_name) { + ret = -ENOMEM; + goto err; + } + + cs35l56_init_cs_dsp(&cs35l56->base, &cs35l56->cs_dsp); + cs35l56->cs_dsp.client_ops = &cs35l56_hda_client_ops; + + if (cs35l56->base.reset_gpio) { + dev_dbg(cs35l56->base.dev, "Hard reset\n"); + + /* + * The GPIOD_OUT_LOW to *_gpiod_get_*() will be ignored if the + * ACPI defines a different default state. So explicitly set low. + */ + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0); + cs35l56_wait_min_reset_pulse(); + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 1); + } + + ret = cs35l56_hw_init(&cs35l56->base); + if (ret < 0) + goto err; + + /* Reset the device and wait for it to boot */ + cs35l56_system_reset(&cs35l56->base, false); + ret = cs35l56_wait_for_firmware_boot(&cs35l56->base); + if (ret) + goto err; + + regcache_mark_dirty(cs35l56->base.regmap); + regcache_sync(cs35l56->base.regmap); + + /* Disable auto-hibernate so that runtime_pm has control */ + ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE); + if (ret) + goto err; + + ret = cs_dsp_halo_init(&cs35l56->cs_dsp); + if (ret) { + dev_err_probe(cs35l56->base.dev, ret, "cs_dsp_halo_init failed\n"); + goto err; + } + + dev_dbg(cs35l56->base.dev, "DSP system name: '%s', amp name: '%s'\n", + cs35l56->system_name, cs35l56->amp_name); + + /* Populate soft registers in the regmap cache */ + cs35l56_reread_firmware_registers(&cs35l56->base); + + regmap_multi_reg_write(cs35l56->base.regmap, cs35l56_hda_dai_config, + ARRAY_SIZE(cs35l56_hda_dai_config)); + + /* + * By default only enable one ASP1TXn, where n=amplifier index, + * This prevents multiple amps trying to drive the same slot. + */ + cs35l56->asp_tx_mask = BIT(cs35l56->index); + + pm_runtime_set_autosuspend_delay(cs35l56->base.dev, 3000); + pm_runtime_use_autosuspend(cs35l56->base.dev); + pm_runtime_set_active(cs35l56->base.dev); + pm_runtime_mark_last_busy(cs35l56->base.dev); + pm_runtime_enable(cs35l56->base.dev); + + ret = component_add(cs35l56->base.dev, &cs35l56_hda_comp_ops); + if (ret) { + dev_err(cs35l56->base.dev, "Register component failed: %d\n", ret); + goto pm_err; + } + + cs35l56->base.init_done = true; + + return 0; + +pm_err: + pm_runtime_disable(cs35l56->base.dev); +err: + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0); + + return ret; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_hda_common_probe, SND_HDA_SCODEC_CS35L56); + +void cs35l56_hda_remove(struct device *dev) +{ + struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); + + pm_runtime_get_sync(cs35l56->base.dev); + pm_runtime_disable(cs35l56->base.dev); + + component_del(cs35l56->base.dev, &cs35l56_hda_comp_ops); + + kfree(cs35l56->system_name); + pm_runtime_put_noidle(cs35l56->base.dev); + + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0); +} +EXPORT_SYMBOL_NS_GPL(cs35l56_hda_remove, SND_HDA_SCODEC_CS35L56); + +const struct dev_pm_ops cs35l56_hda_pm_ops = { + SET_RUNTIME_PM_OPS(cs35l56_hda_runtime_suspend, cs35l56_hda_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(cs35l56_hda_system_suspend, cs35l56_hda_system_resume) + LATE_SYSTEM_SLEEP_PM_OPS(cs35l56_hda_system_suspend_late, + cs35l56_hda_system_resume_early) + NOIRQ_SYSTEM_SLEEP_PM_OPS(cs35l56_hda_system_suspend_no_irq, + cs35l56_hda_system_resume_no_irq) +}; +EXPORT_SYMBOL_NS_GPL(cs35l56_hda_pm_ops, SND_HDA_SCODEC_CS35L56); + +MODULE_DESCRIPTION("CS35L56 HDA Driver"); +MODULE_IMPORT_NS(SND_HDA_CS_DSP_CONTROLS); +MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED); +MODULE_AUTHOR("Richard Fitzgerald "); +MODULE_AUTHOR("Simon Trimmer "); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(FW_CS_DSP); diff --git a/sound/pci/hda/cs35l56_hda.h b/sound/pci/hda/cs35l56_hda.h new file mode 100644 index 000000000000..6e5bc5397db5 --- /dev/null +++ b/sound/pci/hda/cs35l56_hda.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * HDA audio driver for Cirrus Logic CS35L56 smart amp + * + * Copyright (C) 2023 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#ifndef __CS35L56_HDA_H__ +#define __CS35L56_HDA_H__ + +#include +#include +#include +#include +#include +#include + +struct dentry; + +struct cs35l56_hda { + struct cs35l56_base base; + struct hda_codec *codec; + + int index; + const char *system_name; + const char *amp_name; + + struct cs_dsp cs_dsp; + bool playing; + bool suspended; + u8 asp_tx_mask; + + struct snd_kcontrol *posture_ctl; + struct snd_kcontrol *volume_ctl; + struct snd_kcontrol *mixer_ctl[4]; + +#if IS_ENABLED(CONFIG_SND_DEBUG) + struct dentry *debugfs_root; +#endif +}; + +extern const struct dev_pm_ops cs35l56_hda_pm_ops; + +int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int id); +void cs35l56_hda_remove(struct device *dev); + +#endif /*__CS35L56_HDA_H__*/ diff --git a/sound/pci/hda/cs35l56_hda_i2c.c b/sound/pci/hda/cs35l56_hda_i2c.c new file mode 100644 index 000000000000..83e4acdd89ac --- /dev/null +++ b/sound/pci/hda/cs35l56_hda_i2c.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// CS35L56 HDA audio driver I2C binding +// +// Copyright (C) 2023 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. + +#include +#include +#include + +#include "cs35l56_hda.h" + +static int cs35l56_hda_i2c_probe(struct i2c_client *clt) +{ + struct cs35l56_hda *cs35l56; + int ret; + + cs35l56 = devm_kzalloc(&clt->dev, sizeof(*cs35l56), GFP_KERNEL); + if (!cs35l56) + return -ENOMEM; + + cs35l56->base.dev = &clt->dev; + cs35l56->base.can_hibernate = true; + cs35l56->base.regmap = devm_regmap_init_i2c(clt, &cs35l56_regmap_i2c); + if (IS_ERR(cs35l56->base.regmap)) { + ret = PTR_ERR(cs35l56->base.regmap); + dev_err(cs35l56->base.dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + ret = cs35l56_hda_common_probe(cs35l56, clt->addr); + if (ret) + return ret; + ret = cs35l56_irq_request(&cs35l56->base, clt->irq); + if (ret < 0) + cs35l56_hda_remove(cs35l56->base.dev); + + return ret; +} + +static void cs35l56_hda_i2c_remove(struct i2c_client *clt) +{ + cs35l56_hda_remove(&clt->dev); +} + +static const struct i2c_device_id cs35l56_hda_i2c_id[] = { + { "cs35l56-hda", 0 }, + {} +}; + +static struct i2c_driver cs35l56_hda_i2c_driver = { + .driver = { + .name = "cs35l56-hda", + .pm = &cs35l56_hda_pm_ops, + }, + .id_table = cs35l56_hda_i2c_id, + .probe = cs35l56_hda_i2c_probe, + .remove = cs35l56_hda_i2c_remove, +}; +module_i2c_driver(cs35l56_hda_i2c_driver); + +MODULE_DESCRIPTION("HDA CS35L56 I2C driver"); +MODULE_IMPORT_NS(SND_HDA_SCODEC_CS35L56); +MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED); +MODULE_AUTHOR("Richard Fitzgerald "); +MODULE_AUTHOR("Simon Trimmer "); +MODULE_LICENSE("GPL"); diff --git a/sound/pci/hda/cs35l56_hda_spi.c b/sound/pci/hda/cs35l56_hda_spi.c new file mode 100644 index 000000000000..756aec342eab --- /dev/null +++ b/sound/pci/hda/cs35l56_hda_spi.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// CS35L56 HDA audio driver SPI binding +// +// Copyright (C) 2023 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. + +#include +#include +#include + +#include "cs35l56_hda.h" + +static int cs35l56_hda_spi_probe(struct spi_device *spi) +{ + struct cs35l56_hda *cs35l56; + int ret; + + cs35l56 = devm_kzalloc(&spi->dev, sizeof(*cs35l56), GFP_KERNEL); + if (!cs35l56) + return -ENOMEM; + + cs35l56->base.dev = &spi->dev; + cs35l56->base.regmap = devm_regmap_init_spi(spi, &cs35l56_regmap_spi); + if (IS_ERR(cs35l56->base.regmap)) { + ret = PTR_ERR(cs35l56->base.regmap); + dev_err(cs35l56->base.dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + ret = cs35l56_hda_common_probe(cs35l56, spi->chip_select); + if (ret) + return ret; + ret = cs35l56_irq_request(&cs35l56->base, spi->irq); + if (ret < 0) + cs35l56_hda_remove(cs35l56->base.dev); + + return ret; +} + +static void cs35l56_hda_spi_remove(struct spi_device *spi) +{ + cs35l56_hda_remove(&spi->dev); +} + +static const struct spi_device_id cs35l56_hda_spi_id[] = { + { "cs35l56-hda", 0 }, + {} +}; + +static struct spi_driver cs35l56_hda_spi_driver = { + .driver = { + .name = "cs35l56-hda", + .pm = &cs35l56_hda_pm_ops, + }, + .id_table = cs35l56_hda_spi_id, + .probe = cs35l56_hda_spi_probe, + .remove = cs35l56_hda_spi_remove, +}; +module_spi_driver(cs35l56_hda_spi_driver); + +MODULE_DESCRIPTION("HDA CS35L56 SPI driver"); +MODULE_IMPORT_NS(SND_HDA_SCODEC_CS35L56); +MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED); +MODULE_AUTHOR("Richard Fitzgerald "); +MODULE_AUTHOR("Simon Trimmer "); +MODULE_LICENSE("GPL");