From patchwork Thu Sep 5 07:02:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Binbin Zhou X-Patchwork-Id: 13791794 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 7F5B6188A24; Thu, 5 Sep 2024 07:02:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725519771; cv=none; b=p0xLAepXK8MvCgz6QcrhDCMPTZYkQ8H8I5fDn6R+QJQRPd5ON2MzS4HJ7JUxSpjga1ExbrTcUrdeYOA3bbPS4RZXhyEmgUJmmuK4rp/2yDvDUhaRyG7OrhI9XN0SsxuPvrBCd31zR+P+pYZOGG/TfkTRHYUHMlc3/lWCoILdI04= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725519771; c=relaxed/simple; bh=lbf9ue3aAcGlXfxXdOu+9hB4qTEZWT5b/au2Tydd/jo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sRc9KWBYIV2G92HvfqASbnRZ2d+sXPSQ98FAK8o17EnSr7g0bwOENCy4DdEU7PKHY7ohkBTBkKi5qcKpZFiSLhXJjUPoN0UEsM+S3u5tyOWgKUDesuvdqlNxb+VxWMt8eUBv/rnRUtMJYxE/A3DGrGRGjMCSfGnWzTrnuIgY4gg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn; spf=pass smtp.mailfrom=loongson.cn; arc=none smtp.client-ip=114.242.206.163 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=loongson.cn Received: from loongson.cn (unknown [223.64.68.71]) by gateway (Coremail) with SMTP id _____8Cxd+mWV9lmkRkrAA--.16477S3; Thu, 05 Sep 2024 15:02:46 +0800 (CST) Received: from localhost.localdomain (unknown [223.64.68.71]) by front1 (Coremail) with SMTP id qMiowMAxXNyJV9lm38IEAA--.21058S3; Thu, 05 Sep 2024 15:02:44 +0800 (CST) From: Binbin Zhou To: Binbin Zhou , Huacai Chen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai Cc: Huacai Chen , devicetree@vger.kernel.org, linux-sound@vger.kernel.org, Xuerui Wang , loongarch@lists.linux.dev, Binbin Zhou Subject: [PATCH v1 01/10] ASoC: dt-bindings: Add Everest ES8323 Codec Date: Thu, 5 Sep 2024 15:02:14 +0800 Message-ID: X-Mailer: git-send-email 2.43.5 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: qMiowMAxXNyJV9lm38IEAA--.21058S3 X-CM-SenderInfo: p2kr3uplqex0o6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBj93XoW7Cw4xZF1Dury5Gw15Ar4rtFc_yoW8XFWUpF s3Cr95trySgF17A39xJFy8Cr1rJ395AF4YqFnrtwn3t3s8Xa4Fqws0krn8Z3ZrAFyxKay3 XFW7uw1rK3W8AabCm3ZEXasCq-sJn29KB7ZKAUJUUUUx529EdanIXcx71UUUUU7KY7ZEXa sCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU 0xBIdaVrnRJUUUBIb4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2 IYs7xG6rWj6s0DM7CIcVAFz4kK6r1Y6r17M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Xr0_Ar1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Gr0_Cr1l84ACjcxK6I8E87Iv67AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVCY1x0267AK xVW8Jr0_Cr1UM2kKe7AKxVWUAVWUtwAS0I0E0xvYzxvE52x082IY62kv0487Mc804VCY07 AIYIkI8VC2zVCFFI0UMc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWU tVWrXwAv7VC2z280aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7V AKI48JMxkF7I0En4kS14v26r126r1DMxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY 6r1j6r4UMxCIbckI1I0E14v26r126r1DMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7 xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUtVW8ZwCIc40Y0x0EwIxGrwCI42IY6xII jxv20xvE14v26r4j6ryUMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8JVWxJwCI42IY6xAIw2 0EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x02 67AKxVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7IU8_gA5UUUUU== Add Everest Semiconductor ES8316 low power audio CODEC binding with DT schema format using json-schema. Signed-off-by: Binbin Zhou --- .../bindings/sound/everest,es8323.yaml | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/everest,es8323.yaml diff --git a/Documentation/devicetree/bindings/sound/everest,es8323.yaml b/Documentation/devicetree/bindings/sound/everest,es8323.yaml new file mode 100644 index 000000000000..0450d0f49d03 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/everest,es8323.yaml @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/everest,es8323.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Everest ES8323 audio CODECs + +maintainers: + - Binbin Zhou + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: everest,es8323 + + reg: + maxItems: 1 + + clocks: + description: clock for master clock (MCLK) + maxItems: 1 + + clock-names: + const: mclk + + '#sound-dai-cells': + const: 0 + +required: + - compatible + - reg + - '#sound-dai-cells' + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + codec@10 { + compatible = "everest,es8323"; + reg = <0x10>; + #sound-dai-cells = <0>; + }; + }; From patchwork Thu Sep 5 07:02:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Binbin Zhou X-Patchwork-Id: 13791796 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B93B81925B2; Thu, 5 Sep 2024 07:02:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725519775; cv=none; b=KFxz7TmHmqRQmgda6scKoCn8YASSNdYejO94Mu3RTCuHQ+2CHnXM77dDWDdoHu40Iq+1DPh70+3SybQpklwzHCTg4aTJaTEvWWchAZK0tttvkZmrALJ6wkqVV2ryCOsv97MC1qdnJOQt/b3KomV4TpwmhtQn2+jjpFwXkKntYFc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725519775; c=relaxed/simple; bh=o5+iCJYkWJegFBJz0AhQ29i514liklJW0LsD+ebg29Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=a1TY00Z6DmM5D7Mt1U6t0jW5RU0ENmuc/dBIzPjUNv1Jtuho1oZ9xGm/Ca3rX2j9YpjPt5uEzNGTg47RU/7pUruJAVv0mlJnjE4tiuzJx/DvzIJgstbcIctX2l9fOle8uOo6aCQNwAd9PWngeUp06bjc/eJaWzM4tEpli943Azw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn; spf=pass smtp.mailfrom=loongson.cn; arc=none smtp.client-ip=114.242.206.163 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=loongson.cn Received: from loongson.cn (unknown [223.64.68.71]) by gateway (Coremail) with SMTP id _____8DxOJqaV9lmphkrAA--.45895S3; Thu, 05 Sep 2024 15:02:50 +0800 (CST) Received: from localhost.localdomain (unknown [223.64.68.71]) by front1 (Coremail) with SMTP id qMiowMAxXNyJV9lm38IEAA--.21058S4; Thu, 05 Sep 2024 15:02:46 +0800 (CST) From: Binbin Zhou To: Binbin Zhou , Huacai Chen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai Cc: Huacai Chen , devicetree@vger.kernel.org, linux-sound@vger.kernel.org, Xuerui Wang , loongarch@lists.linux.dev, Binbin Zhou Subject: [PATCH v1 02/10] ASoC: codecs: Add support for ES8323 Date: Thu, 5 Sep 2024 15:02:15 +0800 Message-ID: X-Mailer: git-send-email 2.43.5 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: qMiowMAxXNyJV9lm38IEAA--.21058S4 X-CM-SenderInfo: p2kr3uplqex0o6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBj9fXoWfXF4rZF1furWUCw4UJr13trc_yoW5tF18to WSq34rtw17JryxXry5Jr1fGFyj9r15WF1fJFs8AanYvr17Aa45Kw4jqw15Ga43XFyFv340 qryDJ3s5Jwsakrsrl-sFpf9Il3svdjkaLaAFLSUrUUUU0b8apTn2vfkv8UJUUUU8wcxFpf 9Il3svdxBIdaVrn0xqx4xG64xvF2IEw4CE5I8CrVC2j2Jv73VFW2AGmfu7bjvjm3AaLaJ3 UjIYCTnIWjp_UUUYC7kC6x804xWl14x267AKxVWUJVW8JwAFc2x0x2IEx4CE42xK8VAvwI 8IcIk0rVWrJVCq3wAFIxvE14AKwVWUXVWUAwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xG Y2AK021l84ACjcxK6xIIjxv20xvE14v26ryj6F1UM28EF7xvwVC0I7IYx2IY6xkF7I0E14 v26r4j6F4UM28EF7xvwVC2z280aVAFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIEc7CjxVAF wI0_Gr1j6F4UJwAaw2AFwI0_JF0_Jw1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqjxCEc2 xF0cIa020Ex4CE44I27wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2Ix0cI8IcVAFwI0_ Jw0_WrylYx0Ex4A2jsIE14v26r4j6F4UMcvjeVCFs4IE7xkEbVWUJVW8JwACjcxG0xvY0x 0EwIxGrwCY1x0262kKe7AKxVWUAVWUtwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkE bVWUJVW8JwCFI7km07C267AKxVWUAVWUtwC20s026c02F40E14v26r1j6r18MI8I3I0E74 80Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw0_GFylIxkGc2Ij64vIr41lIxAIcVC0 I7IYx2IY67AKxVW8JVW5JwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr0_Cr1lIxAIcVCF04 k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F4UMIIF0xvEx4A2jsIEc7Cj xVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x07jz5lbUUUUU= Add a codec driver for the Everest ES8323. It supports two separate audio outputs and two separate audio inputs. Signed-off-by: Binbin Zhou --- sound/soc/codecs/Kconfig | 5 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/es8323.c | 849 ++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/es8323.h | 77 ++++ 4 files changed, 933 insertions(+) create mode 100644 sound/soc/codecs/es8323.c create mode 100644 sound/soc/codecs/es8323.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index b5e6d0a986c8..85270aa43512 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -112,6 +112,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_DA9055 imply SND_SOC_DMIC imply SND_SOC_ES8316 + imply SND_SOC_ES8323 imply SND_SOC_ES8326 imply SND_SOC_ES8328_SPI imply SND_SOC_ES8328_I2C @@ -1142,6 +1143,10 @@ config SND_SOC_ES8316 tristate "Everest Semi ES8316 CODEC" depends on I2C +config SND_SOC_ES8323 + tristate "Everest Semi ES8323 CODEC" + depends on I2C + config SND_SOC_ES8326 tristate "Everest Semi ES8326 CODEC" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 622e360f0086..00ff3fdf0133 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -125,6 +125,7 @@ snd-soc-es7241-y := es7241.o snd-soc-es83xx-dsm-common-y := es83xx-dsm-common.o snd-soc-es8311-y := es8311.o snd-soc-es8316-y := es8316.o +snd-soc-es8323-y := es8323.o snd-soc-es8326-y := es8326.o snd-soc-es8328-y := es8328.o snd-soc-es8328-i2c-y := es8328-i2c.o @@ -531,6 +532,7 @@ obj-$(CONFIG_SND_SOC_ES7241) += snd-soc-es7241.o obj-$(CONFIG_SND_SOC_ES83XX_DSM_COMMON) += snd-soc-es83xx-dsm-common.o obj-$(CONFIG_SND_SOC_ES8311) += snd-soc-es8311.o obj-$(CONFIG_SND_SOC_ES8316) += snd-soc-es8316.o +obj-$(CONFIG_SND_SOC_ES8323) += snd-soc-es8323.o obj-$(CONFIG_SND_SOC_ES8326) += snd-soc-es8326.o obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o diff --git a/sound/soc/codecs/es8323.c b/sound/soc/codecs/es8323.c new file mode 100644 index 000000000000..596eba3214ea --- /dev/null +++ b/sound/soc/codecs/es8323.c @@ -0,0 +1,847 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * es8323.c -- es8323 ALSA SoC audio driver + * + * Copyright Rockchip Electronics Co. Ltd. + * Copyright Everest Semiconductor Co.,Ltd + * + * Author: Mark Brown + * Jianqun Xu + * Nickey Yang + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "es8323.h" + +#define ES8323_CODEC_SET_SPK 1 +#define ES8323_CODEC_SET_HP 2 + +#define ES8323_DEF_VOL 0x1b + +/* + * es8323 register cache + * We can't read the es8323 register space when we + * are using 2 wire for device control, so we cache them instead. + */ +static u16 es8323_reg[] = { + 0x06, 0x1C, 0xC3, 0xFC, /* 0 */ + 0xC0, 0x00, 0x00, 0x7C, /* 4 */ + 0x80, 0x00, 0x00, 0x06, /* 8 */ + 0x00, 0x06, 0x30, 0x30, /* 12 */ + 0xC0, 0xC0, 0x38, 0xB0, /* 16 */ + 0x32, 0x06, 0x00, 0x00, /* 20 */ + 0x06, 0x30, 0xC0, 0xC0, /* 24 */ + 0x08, 0x06, 0x1F, 0xF7, /* 28 */ + 0xFD, 0xFF, 0x1F, 0xF7, /* 32 */ + 0xFD, 0xFF, 0x00, 0x38, /* 36 */ + 0x38, 0x38, 0x38, 0x38, /* 40 */ + 0x38, 0x00, 0x00, 0x00, /* 44 */ + 0x00, 0x00, 0x00, 0x00, /* 48 */ + 0x00, 0x00, 0x00, 0x00, /* 52 */ +}; + +/* codec private data */ +struct es8323_priv { + unsigned int sysclk; + struct clk *mclk; + struct snd_pcm_hw_constraint_list *sysclk_constraints; + struct snd_soc_component *component; + struct i2c_client *i2c; + int spk_ctl_gpio; + bool hp_inserted; + bool spk_gpio_level; +}; + +static const char *const es8323_line_texts[] = { + "Line 1", "Line 2", "PGA" +}; + +static const unsigned int es8323_line_values[] = { + 0, 1, 3 +}; + +static const char *const es8323_pga_sell[] = { "Line 1L", "Line 2L", "NC", "DifferentialL" }; +static const char *const es8323_pga_selr[] = { "Line 1R", "Line 2R", "NC", "DifferentialR" }; +static const char *const es8323_lin_sell[] = { "Line 1L", "Line 2L", "NC", "MicL" }; +static const char *const es8323_lin_selr[] = { "Line 1R", "Line 2R", "NC", "MicR" }; + +static const char *const stereo_3d_txt[] = { "No 3D ", "Level 1", "Level 2", "Level 3", + "Level 4", "Level 5", "Level 6", "Level 7" }; +static const char *const ng_type_txt[] = { "Constant PGA Gain", "Mute ADC Output" }; +static const char *const deemph_txt[] = { "None", "32Khz", "44.1Khz", "48Khz" }; +static const char *const adcpol_txt[] = { "Normal", "L Invert", "R Invert", "L + R Invert" }; + +static const char *const es8323_mono_mux[] = { "Stereo", "Mono (Left)", "Mono (Right)" }; +static const char *const es8323_diff_sel[] = { "Line 1", "Line 2" }; + +static SOC_ENUM_SINGLE_DECL(es8323_left_dac_enum, ES8323_ADCCONTROL2, 6, es8323_pga_sell); +static SOC_ENUM_SINGLE_DECL(es8323_right_dac_enum, ES8323_ADCCONTROL2, 4, es8323_pga_selr); +static SOC_ENUM_SINGLE_DECL(es8323_diff_enum, ES8323_ADCCONTROL3, 7, es8323_diff_sel); +static SOC_ENUM_SINGLE_DECL(es8323_llin_enum, ES8323_DACCONTROL16, 3, es8323_lin_sell); +static SOC_ENUM_SINGLE_DECL(es8323_rlin_enum, ES8323_DACCONTROL16, 0, es8323_lin_selr); +static SOC_ENUM_SINGLE_DECL(es8323_mono_enum, ES8323_ADCCONTROL3, 3, es8323_mono_mux); + +static const struct soc_enum es8323_enum[] = { + SOC_VALUE_ENUM_SINGLE(ES8323_DACCONTROL16, 3, 7, ARRAY_SIZE(es8323_line_texts), + es8323_line_texts, es8323_line_values), /* LLINE */ + SOC_VALUE_ENUM_SINGLE(ES8323_DACCONTROL16, 0, 7, ARRAY_SIZE(es8323_line_texts), + es8323_line_texts, es8323_line_values), /* RLINE */ + SOC_VALUE_ENUM_SINGLE(ES8323_ADCCONTROL2, 6, 3, ARRAY_SIZE(es8323_pga_sell), + es8323_line_texts, es8323_line_values), /* Left PGA Mux */ + SOC_VALUE_ENUM_SINGLE(ES8323_ADCCONTROL2, 4, 3, ARRAY_SIZE(es8323_pga_sell), + es8323_line_texts, es8323_line_values), /* Right PGA Mux */ + SOC_ENUM_SINGLE(ES8323_DACCONTROL7, 2, 8, stereo_3d_txt), /* stereo-3d */ + SOC_ENUM_SINGLE(ES8323_ADCCONTROL14, 1, 2, ng_type_txt), /* noise gate type */ + SOC_ENUM_SINGLE(ES8323_DACCONTROL6, 6, 4, deemph_txt), /* Playback De-emphasis */ + SOC_ENUM_SINGLE(ES8323_ADCCONTROL6, 6, 4, adcpol_txt), + SOC_ENUM_SINGLE(ES8323_ADCCONTROL3, 3, 3, es8323_mono_mux), + SOC_ENUM_SINGLE(ES8323_ADCCONTROL3, 7, 2, es8323_diff_sel), +}; + +static const DECLARE_TLV_DB_SCALE(pga_tlv, 0, 300, 0); +static const DECLARE_TLV_DB_SCALE(adc_tlv, -9600, 50, 1); +static const DECLARE_TLV_DB_SCALE(dac_tlv, -9600, 50, 1); +static const DECLARE_TLV_DB_SCALE(out_tlv, -4500, 150, 0); +static const DECLARE_TLV_DB_SCALE(bypass_tlv, 0, 300, 0); +static const DECLARE_TLV_DB_SCALE(bypass_tlv2, -15, 300, 0); + +static const struct snd_kcontrol_new es8323_snd_controls[] = { + SOC_ENUM("3D Mode", es8323_enum[4]), + SOC_ENUM("ALC Capture Function", es8323_enum[5]), + SOC_SINGLE("ALC Capture ZC Switch", ES8323_ADCCONTROL13, 6, 1, 0), + SOC_SINGLE("ALC Capture Decay Time", ES8323_ADCCONTROL12, 4, 15, 0), + SOC_SINGLE("ALC Capture Attack Time", ES8323_ADCCONTROL12, 0, 15, 0), + SOC_SINGLE("ALC Capture NG Threshold", ES8323_ADCCONTROL14, 3, 31, 0), + SOC_ENUM("ALC Capture NG Type", es8323_enum[6]), + SOC_SINGLE("ALC Capture NG Switch", ES8323_ADCCONTROL14, 0, 1, 0), + SOC_SINGLE("ZC Timeout Switch", ES8323_ADCCONTROL13, 6, 1, 0), + SOC_DOUBLE_R_TLV("Capture Digital Volume", ES8323_LADC_VOL, + ES8323_RADC_VOL, 0, 192, 1, adc_tlv), + SOC_SINGLE("Capture Mute", ES8323_ADC_MUTE, 2, 1, 0), + SOC_SINGLE_TLV("Left Channel Capture Volume", ES8323_ADCCONTROL1, 4, 8, + 0, bypass_tlv), + SOC_SINGLE_TLV("Right Channel Capture Volume", ES8323_ADCCONTROL1, 0, + 8, 0, bypass_tlv), + SOC_ENUM("Playback De-emphasis", es8323_enum[7]), + SOC_ENUM("Capture Polarity", es8323_enum[8]), + SOC_DOUBLE_R_TLV("PCM Volume", ES8323_LDAC_VOL, ES8323_RDAC_VOL, + 0, 192, 1, dac_tlv), + SOC_SINGLE_TLV("Left Mixer Left Bypass Volume", ES8323_DACCONTROL17, 3, + 7, 1, bypass_tlv2), + SOC_SINGLE_TLV("Right Mixer Right Bypass Volume", ES8323_DACCONTROL20, + 3, 7, 1, bypass_tlv2), + SOC_DOUBLE_R_TLV("Output 1 Playback Volume", ES8323_LOUT1_VOL, + ES8323_ROUT1_VOL, 0, 33, 0, out_tlv), + SOC_DOUBLE_R_TLV("Output 2 Playback Volume", ES8323_LOUT2_VOL, + ES8323_ROUT2_VOL, 0, 33, 0, out_tlv), +}; + +static const struct snd_kcontrol_new es8323_left_dac_mux_controls = + SOC_DAPM_ENUM("Route", es8323_left_dac_enum); + +static const struct snd_kcontrol_new es8323_right_dac_mux_controls = + SOC_DAPM_ENUM("Route", es8323_right_dac_enum); + +static const struct snd_kcontrol_new es8323_left_line_controls = + SOC_DAPM_ENUM("LLIN Mux", es8323_llin_enum); + +static const struct snd_kcontrol_new es8323_right_line_controls = + SOC_DAPM_ENUM("RLIN Mux", es8323_rlin_enum); + +/* Differential Mux */ +static const struct snd_kcontrol_new es8323_diffmux_controls = + SOC_DAPM_ENUM("Route2", es8323_diff_enum); + +/* Mono ADC Mux */ +static const struct snd_kcontrol_new es8323_monomux_controls = + SOC_DAPM_ENUM("Mono Mux", es8323_mono_enum); + +/* Right PGA Mux */ +static const struct snd_kcontrol_new es8323_right_pga_controls = + SOC_DAPM_ENUM("Route", es8323_enum[3]); + +/* Left Mixer */ +static const struct snd_kcontrol_new es8323_left_mixer_controls[] = { + SOC_DAPM_SINGLE("Left Playback Switch", SND_SOC_NOPM, 7, 1, 1), + SOC_DAPM_SINGLE("Left Bypass Switch", ES8323_DACCONTROL17, 6, 1, 0), +}; + +/* Right Mixer */ +static const struct snd_kcontrol_new es8323_right_mixer_controls[] = { + SOC_DAPM_SINGLE("Right Playback Switch", SND_SOC_NOPM, 6, 1, 1), + SOC_DAPM_SINGLE("Right Bypass Switch", ES8323_DACCONTROL20, 6, 1, 0), +}; + +static const struct snd_soc_dapm_widget es8323_dapm_widgets[] = { + SND_SOC_DAPM_INPUT("LINPUT1"), + SND_SOC_DAPM_INPUT("LINPUT2"), + SND_SOC_DAPM_INPUT("RINPUT1"), + SND_SOC_DAPM_INPUT("RINPUT2"), + + SND_SOC_DAPM_MUX("Left PGA Mux", SND_SOC_NOPM, 0, 0, + &es8323_left_dac_mux_controls), + SND_SOC_DAPM_MUX("Right PGA Mux", SND_SOC_NOPM, 0, 0, + &es8323_right_dac_mux_controls), + SND_SOC_DAPM_MICBIAS("Mic Bias", SND_SOC_NOPM, 3, 1), + + SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0, + &es8323_diffmux_controls), + + SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0, + &es8323_monomux_controls), + SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0, + &es8323_monomux_controls), + SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0, + &es8323_left_line_controls), + SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0, + &es8323_right_line_controls), + SND_SOC_DAPM_ADC("Right ADC", "Right Capture", SND_SOC_NOPM, 4, 1), + SND_SOC_DAPM_ADC("Left ADC", "Left Capture", SND_SOC_NOPM, 5, 1), + /* gModify.Cmmt Implement when suspend/startup */ + SND_SOC_DAPM_DAC("Right DAC", "Right Playback", SND_SOC_NOPM, 6, 1), + SND_SOC_DAPM_DAC("Left DAC", "Left Playback", SND_SOC_NOPM, 7, 1), + SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0, + &es8323_left_mixer_controls[0], + ARRAY_SIZE(es8323_left_mixer_controls)), + SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0, + &es8323_right_mixer_controls[0], + ARRAY_SIZE(es8323_right_mixer_controls)), + + SND_SOC_DAPM_PGA("Right ADC Power", SND_SOC_NOPM, 6, 1, NULL, 0), + SND_SOC_DAPM_PGA("Left ADC Power", SND_SOC_NOPM, 7, 1, NULL, 0), + SND_SOC_DAPM_PGA("Right Out 2", SND_SOC_NOPM, 2, 0, NULL, 0), + SND_SOC_DAPM_PGA("Left Out 2", SND_SOC_NOPM, 3, 0, NULL, 0), + SND_SOC_DAPM_PGA("Right Out 1", SND_SOC_NOPM, 4, 0, NULL, 0), + SND_SOC_DAPM_PGA("Left Out 1", SND_SOC_NOPM, 5, 0, NULL, 0), + SND_SOC_DAPM_PGA("LAMP", ES8323_ADCCONTROL1, 4, 0, NULL, 0), + SND_SOC_DAPM_PGA("RAMP", ES8323_ADCCONTROL1, 0, 0, NULL, 0), + + SND_SOC_DAPM_OUTPUT("LOUT1"), + SND_SOC_DAPM_OUTPUT("ROUT1"), + SND_SOC_DAPM_OUTPUT("LOUT2"), + SND_SOC_DAPM_OUTPUT("ROUT2"), + SND_SOC_DAPM_OUTPUT("VREF"), +}; + +static const struct snd_soc_dapm_route audio_map[] = { + /*12.22*/ + {"Left PGA Mux", "Line 1L", "LINPUT1"}, + {"Left PGA Mux", "Line 2L", "LINPUT2"}, + {"Left PGA Mux", "DifferentialL", "Differential Mux"}, + + {"Right PGA Mux", "Line 1R", "RINPUT1"}, + {"Right PGA Mux", "Line 2R", "RINPUT2"}, + {"Right PGA Mux", "DifferentialR", "Differential Mux"}, + + {"Differential Mux", "Line 1", "LINPUT1"}, + {"Differential Mux", "Line 1", "RINPUT1"}, + {"Differential Mux", "Line 2", "LINPUT2"}, + {"Differential Mux", "Line 2", "RINPUT2"}, + + {"Left ADC Mux", "Stereo", "Right PGA Mux"}, + {"Left ADC Mux", "Stereo", "Left PGA Mux"}, + {"Left ADC Mux", "Mono (Left)", "Left PGA Mux"}, + + {"Right ADC Mux", "Stereo", "Left PGA Mux"}, + {"Right ADC Mux", "Stereo", "Right PGA Mux"}, + {"Right ADC Mux", "Mono (Right)", "Right PGA Mux"}, + + {"Left ADC Power", NULL, "Left ADC Mux"}, + {"Right ADC Power", NULL, "Right ADC Mux"}, + {"Left ADC", NULL, "Left ADC Power"}, + {"Right ADC", NULL, "Right ADC Power"}, + + {"Left Line Mux", "Line 1L", "LINPUT1"}, + {"Left Line Mux", "Line 2L", "LINPUT2"}, + {"Left Line Mux", "MicL", "Left PGA Mux"}, + + {"Right Line Mux", "Line 1R", "RINPUT1"}, + {"Right Line Mux", "Line 2R", "RINPUT2"}, + {"Right Line Mux", "MicR", "Right PGA Mux"}, + + {"Left Mixer", "Left Playback Switch", "Left DAC"}, + {"Left Mixer", "Left Bypass Switch", "Left Line Mux"}, + + {"Right Mixer", "Right Playback Switch", "Right DAC"}, + {"Right Mixer", "Right Bypass Switch", "Right Line Mux"}, + + {"Left Out 1", NULL, "Left Mixer"}, + {"LOUT1", NULL, "Left Out 1"}, + {"Right Out 1", NULL, "Right Mixer"}, + {"ROUT1", NULL, "Right Out 1"}, + + {"Left Out 2", NULL, "Left Mixer"}, + {"LOUT2", NULL, "Left Out 2"}, + {"Right Out 2", NULL, "Right Mixer"}, + {"ROUT2", NULL, "Right Out 2"}, +}; + +struct coeff_div { + u32 mclk; + u32 rate; + u16 fs; + u8 sr:4; + u8 usb:1; +}; + +/* codec hifi mclk clock divider coefficients */ +static const struct coeff_div es8323_coeff_div[] = { + /* 8k */ + {12288000, 8000, 1536, 0xa, 0x0}, + {11289600, 8000, 1408, 0x9, 0x0}, + {18432000, 8000, 2304, 0xc, 0x0}, + {16934400, 8000, 2112, 0xb, 0x0}, + {12000000, 8000, 1500, 0xb, 0x1}, + + /* 11.025k */ + {11289600, 11025, 1024, 0x7, 0x0}, + {16934400, 11025, 1536, 0xa, 0x0}, + {12000000, 11025, 1088, 0x9, 0x1}, + + /* 16k */ + {12288000, 16000, 768, 0x6, 0x0}, + {18432000, 16000, 1152, 0x8, 0x0}, + {12000000, 16000, 750, 0x7, 0x1}, + + /* 22.05k */ + {11289600, 22050, 512, 0x4, 0x0}, + {16934400, 22050, 768, 0x6, 0x0}, + {12000000, 22050, 544, 0x6, 0x1}, + + /* 32k */ + {12288000, 32000, 384, 0x3, 0x0}, + {18432000, 32000, 576, 0x5, 0x0}, + {12000000, 32000, 375, 0x4, 0x1}, + + /* 44.1k */ + {11289600, 44100, 256, 0x2, 0x0}, + {16934400, 44100, 384, 0x3, 0x0}, + {12000000, 44100, 272, 0x3, 0x1}, + + /* 48k */ + {12288000, 48000, 256, 0x2, 0x0}, + {18432000, 48000, 384, 0x3, 0x0}, + {12000000, 48000, 250, 0x2, 0x1}, + + /* 88.2k */ + {11289600, 88200, 128, 0x0, 0x0}, + {16934400, 88200, 192, 0x1, 0x0}, + {12000000, 88200, 136, 0x1, 0x1}, + + /* 96k */ + {12288000, 96000, 128, 0x0, 0x0}, + {18432000, 96000, 192, 0x1, 0x0}, + {12000000, 96000, 125, 0x0, 0x1}, +}; + +/* The set of rates we can generate from the above for each SYSCLK */ + +static unsigned int rates_12288[] = { + 8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000, +}; + +static struct snd_pcm_hw_constraint_list constraints_12288 = { + .count = ARRAY_SIZE(rates_12288), + .list = rates_12288, +}; + +static unsigned int rates_112896[] = { + 8000, 11025, 22050, 44100, +}; + +static struct snd_pcm_hw_constraint_list constraints_112896 = { + .count = ARRAY_SIZE(rates_112896), + .list = rates_112896, +}; + +static unsigned int rates_12[] = { + 8000, 11025, 12000, 16000, 22050, 24000, + 32000, 44100, 48000, 48000, 88235, 96000, +}; + +static struct snd_pcm_hw_constraint_list constraints_12 = { + .count = ARRAY_SIZE(rates_12), + .list = rates_12, +}; + +static inline int get_coeff(int mclk, int rate) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(es8323_coeff_div); i++) { + if (es8323_coeff_div[i].rate == rate && + es8323_coeff_div[i].mclk == mclk) + return i; + } + + return -EINVAL; +} + +static void es8323_set_gpio(int gpio, bool level, int spk_ctl_gpio) +{ + if (!(gpio & ES8323_CODEC_SET_SPK) || spk_ctl_gpio == -1) + return; + + gpio_set_value(spk_ctl_gpio, level); +} + +static int es8323_write(struct snd_soc_component *component, + unsigned int reg, unsigned int value) +{ + int ret; + u8 data[2]; + struct es8323_priv *es8323 = snd_soc_component_get_drvdata(component); + + data[0] = reg; + data[1] = value & 0x00ff; + + if (reg < ARRAY_SIZE(es8323_reg)) + es8323_reg[reg] = value; + + ret = i2c_master_send(es8323->i2c, data, 2); + if (ret == 2) + return 0; + + return (ret < 0) ? ret : -EIO; +} + +static unsigned int es8323_read_reg_cache(struct snd_soc_component *component, + unsigned int reg) +{ + if (reg >= ARRAY_SIZE(es8323_reg)) + return -1; + + return es8323_reg[reg]; +} + +static void es8323_reset(struct snd_soc_component *component) +{ + snd_soc_component_write(component, ES8323_CONTROL1, 0x80); + snd_soc_component_write(component, ES8323_CONTROL1, 0x00); +} + +/* + * Note that this should be called from init rather than from hw_params. + */ +static int es8323_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_component *component = codec_dai->component; + struct es8323_priv *es8323 = snd_soc_component_get_drvdata(component); + + switch (freq) { + case 11289600: + case 18432000: + case 22579200: + case 36864000: + es8323->sysclk_constraints = &constraints_112896; + es8323->sysclk = freq; + break; + case 12288000: + case 16934400: + case 24576000: + case 33868800: + es8323->sysclk_constraints = &constraints_12288; + es8323->sysclk = freq; + break; + case 12000000: + case 24000000: + es8323->sysclk_constraints = &constraints_12; + es8323->sysclk = freq; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int es8323_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) +{ + struct snd_soc_component *component = codec_dai->component; + u8 iface = snd_soc_component_read(component, ES8323_MASTERMODE); + u8 adciface = snd_soc_component_read(component, ES8323_ADC_IFACE); + u8 daciface = snd_soc_component_read(component, ES8323_DAC_IFACE); + + /* set master/slave audio interface */ + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: /* MASTER MODE */ + iface |= 0x80; + break; + case SND_SOC_DAIFMT_CBS_CFS: /* SLAVE MODE */ + iface &= 0x7F; + break; + default: + return -EINVAL; + } + + /* interface format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + adciface &= 0xFC; + daciface &= 0xF9; + break; + case SND_SOC_DAIFMT_RIGHT_J: + case SND_SOC_DAIFMT_LEFT_J: + case SND_SOC_DAIFMT_DSP_A: + case SND_SOC_DAIFMT_DSP_B: + break; + default: + return -EINVAL; + } + + /* clock inversion */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + iface &= 0xDF; + adciface &= 0xDF; + daciface &= 0xBF; + break; + case SND_SOC_DAIFMT_IB_IF: + iface |= 0x20; + adciface |= 0x20; + daciface |= 0x40; + break; + case SND_SOC_DAIFMT_IB_NF: + iface |= 0x20; + adciface &= 0xDF; + daciface &= 0xBF; + break; + case SND_SOC_DAIFMT_NB_IF: + iface &= 0xDF; + adciface |= 0x20; + daciface |= 0x40; + break; + default: + return -EINVAL; + } + + snd_soc_component_write(component, ES8323_MASTERMODE, iface); + snd_soc_component_write(component, ES8323_ADC_IFACE, adciface); + snd_soc_component_write(component, ES8323_DAC_IFACE, daciface); + + return 0; +} + +static int es8323_pcm_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct es8323_priv *es8323 = snd_soc_component_get_drvdata(component); + + if (es8323->sysclk) { + snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + es8323->sysclk_constraints); + } + + return 0; +} + +static int es8323_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct es8323_priv *es8323 = snd_soc_component_get_drvdata(component); + u16 srate = snd_soc_component_read(component, ES8323_MASTERMODE) & 0x80; + u16 adciface = snd_soc_component_read(component, ES8323_ADC_IFACE) & 0xE3; + u16 daciface = snd_soc_component_read(component, ES8323_DAC_IFACE) & 0xC7; + int coeff; + + coeff = get_coeff(es8323->sysclk, params_rate(params)); + if (coeff < 0) { + coeff = get_coeff(es8323->sysclk / 2, params_rate(params)); + srate |= 0x40; + } + + if (coeff < 0) { + dev_err(component->dev, + "Unable to configure sample rate %dHz with %dHz MCLK\n", + params_rate(params), es8323->sysclk); + return coeff; + } + + /* bit size */ + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + adciface |= 0x000C; + daciface |= 0x0018; + break; + case SNDRV_PCM_FORMAT_S20_3LE: + adciface |= 0x0004; + daciface |= 0x0008; + break; + case SNDRV_PCM_FORMAT_S24_LE: + break; + case SNDRV_PCM_FORMAT_S32_LE: + adciface |= 0x0010; + daciface |= 0x0020; + break; + } + + /* set iface & srate */ + snd_soc_component_write(component, ES8323_DAC_IFACE, daciface); + snd_soc_component_write(component, ES8323_ADC_IFACE, adciface); + + snd_soc_component_write(component, ES8323_MASTERMODE, srate); + snd_soc_component_write(component, ES8323_ADCCONTROL5, + es8323_coeff_div[coeff].sr | + (es8323_coeff_div[coeff].usb) << 4); + snd_soc_component_write(component, ES8323_DACCONTROL2, + es8323_coeff_div[coeff].sr | + (es8323_coeff_div[coeff].usb) << 4); + + /* open dac output here */ + snd_soc_component_write(component, ES8323_DACPOWER, 0x3c); + + return 0; +} + +static int es8323_mute(struct snd_soc_dai *dai, int mute, int stream) +{ + struct snd_soc_component *component = dai->component; + struct es8323_priv *es8323 = snd_soc_component_get_drvdata(component); + + if (mute) { + es8323_set_gpio(ES8323_CODEC_SET_SPK, + !es8323->spk_gpio_level, es8323->spk_ctl_gpio); + usleep_range(2000, 3000); + snd_soc_component_write(component, ES8323_DAC_MUTE, 0x06); + } else { + snd_soc_component_write(component, ES8323_DAC_MUTE, 0x02); + usleep_range(2000, 3000); + if (!es8323->hp_inserted) + es8323_set_gpio(ES8323_CODEC_SET_SPK, + es8323->spk_gpio_level, es8323->spk_ctl_gpio); + usleep_range(2000, 3000); + } + + return 0; +} + +#define ES8323_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ + SNDRV_PCM_FMTBIT_S24_LE) + +static const struct snd_soc_dai_ops es8323_ops = { + .startup = es8323_pcm_startup, + .hw_params = es8323_pcm_hw_params, + .set_fmt = es8323_set_dai_fmt, + .set_sysclk = es8323_set_dai_sysclk, + .mute_stream = es8323_mute, +}; + +static struct snd_soc_dai_driver es8323_dai = { + .name = "ES8323 HiFi", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = ES8323_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = ES8323_FORMATS, + }, + .ops = &es8323_ops, + .symmetric_rate = 1, +}; + +static int es8323_suspend(struct snd_soc_component *component) +{ + snd_soc_component_write(component, ES8323_DAC_MUTE, 0x06); + snd_soc_component_write(component, ES8323_LOUT1_VOL, 0x00); + snd_soc_component_write(component, ES8323_ROUT1_VOL, 0x00); + snd_soc_component_write(component, ES8323_LOUT2_VOL, 0x00); + snd_soc_component_write(component, ES8323_ROUT2_VOL, 0x00); + snd_soc_component_write(component, ES8323_DACCONTROL17, 0x38); + snd_soc_component_write(component, ES8323_DACCONTROL20, 0x38); + snd_soc_component_write(component, ES8323_DACPOWER, 0x00); + snd_soc_component_write(component, ES8323_DACPOWER, 0xc0); + snd_soc_component_write(component, ES8323_ADCPOWER, 0xff); + snd_soc_component_write(component, ES8323_CHIPPOWER, 0xf3); + snd_soc_component_write(component, ES8323_DACCONTROL21, 0x9c); + snd_soc_component_write(component, ES8323_CONTROL1, 0x06); + snd_soc_component_write(component, ES8323_CONTROL2, 0x58); + usleep_range(18000, 20000); + + return 0; +} + +static void es8323_init_component_regs(struct snd_soc_component *component) +{ + snd_soc_component_write(component, ES8323_CONTROL2, 0x60); + snd_soc_component_write(component, ES8323_CHIPPOWER, 0xF3); + snd_soc_component_write(component, ES8323_CHIPPOWER, 0xF0); + snd_soc_component_write(component, ES8323_DACCONTROL21, 0x80); + snd_soc_component_write(component, ES8323_CONTROL1, 0x36); + snd_soc_component_write(component, ES8323_MASTERMODE, 0x00); + snd_soc_component_write(component, ES8323_DACPOWER, 0x00); + snd_soc_component_write(component, ES8323_CHIPLOPOW2, 0xC3); + snd_soc_component_write(component, ES8323_DAC_MUTE, 0x02); + snd_soc_component_write(component, ES8323_ADCCONTROL1, 0x88); + snd_soc_component_write(component, ES8323_ADCCONTROL2, 0xF0); + snd_soc_component_write(component, ES8323_ADCCONTROL3, 0x02); + snd_soc_component_write(component, ES8323_ADCCONTROL4, 0x0C); + snd_soc_component_write(component, ES8323_ADCCONTROL5, 0x02); + snd_soc_component_write(component, ES8323_LADC_VOL, 0x00); + snd_soc_component_write(component, ES8323_RADC_VOL, 0x00); + snd_soc_component_write(component, ES8323_ADCCONTROL10, 0xea); + snd_soc_component_write(component, ES8323_ADCCONTROL11, 0xa2); + snd_soc_component_write(component, ES8323_ADCCONTROL12, 0x32); + snd_soc_component_write(component, ES8323_DACCONTROL1, 0x18); + snd_soc_component_write(component, ES8323_DACCONTROL2, 0x02); + snd_soc_component_write(component, ES8323_LDAC_VOL, 0x00); + snd_soc_component_write(component, ES8323_RDAC_VOL, 0x00); + snd_soc_component_write(component, ES8323_DACCONTROL17, 0xB8); + snd_soc_component_write(component, ES8323_DACCONTROL20, 0xB8); + usleep_range(18000, 20000); + snd_soc_component_write(component, ES8323_LOUT1_VOL, 0x1e); + snd_soc_component_write(component, ES8323_ROUT1_VOL, 0x1e); + snd_soc_component_write(component, ES8323_LOUT2_VOL, 0x1e); + snd_soc_component_write(component, ES8323_ROUT2_VOL, 0x1e); + snd_soc_component_write(component, ES8323_ADCPOWER, 0x09); + snd_soc_component_write(component, ES8323_CHIPPOWER, 0x00); + usleep_range(18000, 20000); +} + +static int es8323_resume(struct snd_soc_component *component) +{ + es8323_init_component_regs(component); + /* open dac output */ + snd_soc_component_write(component, ES8323_DACPOWER, 0x3c); + + return 0; +} + +static void es8323_remove(struct snd_soc_component *component) +{ + snd_soc_component_write(component, ES8323_CONTROL2, 0x58); + snd_soc_component_write(component, ES8323_CONTROL1, 0x32); + snd_soc_component_write(component, ES8323_CHIPPOWER, 0xf3); + snd_soc_component_write(component, ES8323_DACPOWER, 0xc0); + mdelay(50); + snd_soc_component_write(component, ES8323_LOUT2_VOL, 0x00); + snd_soc_component_write(component, ES8323_ROUT2_VOL, 0x00); + mdelay(50); + snd_soc_component_write(component, ES8323_CONTROL1, 0x30); + snd_soc_component_write(component, ES8323_CONTROL1, 0x34); +} + +static int es8323_probe(struct snd_soc_component *component) +{ + struct es8323_priv *es8323 = snd_soc_component_get_drvdata(component); + + es8323->mclk = devm_clk_get_optional_enabled(component->dev, "mclk"); + if (IS_ERR(es8323->mclk)) { + dev_err(component->dev, "mclk is missing or invalid\n"); + return PTR_ERR(es8323->mclk); + } + + es8323->component = component; + es8323_reset(component); + es8323_init_component_regs(component); + + return 0; +} + +static const struct snd_soc_component_driver soc_codec_dev_es8323 = { + .probe = es8323_probe, + .remove = es8323_remove, + .suspend = es8323_suspend, + .resume = es8323_resume, + .read = es8323_read_reg_cache, + .write = es8323_write, + .dapm_widgets = es8323_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(es8323_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), + .controls = es8323_snd_controls, + .num_controls = ARRAY_SIZE(es8323_snd_controls), +}; + +static int es8323_i2c_probe(struct i2c_client *i2c) +{ + struct es8323_priv *es8323; + struct i2c_adapter *adapter = to_i2c_adapter(i2c->dev.parent); + + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { + dev_warn(&adapter->dev, + "I2C-Adapter doesn't support I2C_FUNC_I2C\n"); + return -EIO; + } + + es8323 = devm_kzalloc(&i2c->dev, sizeof(*es8323), GFP_KERNEL); + if (IS_ERR(es8323)) + return -ENOMEM; + + i2c_set_clientdata(i2c, es8323); + es8323->i2c = i2c; + + return devm_snd_soc_register_component(&i2c->dev, + &soc_codec_dev_es8323, + &es8323_dai, 1); +} + +static void es8323_i2c_shutdown(struct i2c_client *client) +{ + struct es8323_priv *es8323 = i2c_get_clientdata(client); + struct snd_soc_component *component = es8323->component; + + es8323_set_gpio(ES8323_CODEC_SET_SPK, + !es8323->spk_gpio_level, es8323->spk_ctl_gpio); + + es8323_remove(component); +} + +static const struct i2c_device_id es8323_i2c_id[] = { + { "es8323", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, es8323_i2c_id); + +static const struct acpi_device_id es8323_acpi_match[] = { + { "ESSX8323", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, es8323_acpi_match); + +static const struct of_device_id es8323_of_match[] = { + { .compatible = "everest,es8323" }, + { } +}; +MODULE_DEVICE_TABLE(of, es8323_of_match); + +static struct i2c_driver es8323_i2c_driver = { + .driver = { + .name = "ES8323", + .acpi_match_table = es8323_acpi_match, + .of_match_table = es8323_of_match, + }, + .shutdown = es8323_i2c_shutdown, + .probe = es8323_i2c_probe, + .id_table = es8323_i2c_id, +}; +module_i2c_driver(es8323_i2c_driver); + +MODULE_DESCRIPTION("Everest Semi ES8323 ALSA SoC Codec Driver"); +MODULE_AUTHOR("Mark Brown "); +MODULE_AUTHOR("Binbin Zhou "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/es8323.h b/sound/soc/codecs/es8323.h new file mode 100644 index 000000000000..d379dcfc4fed --- /dev/null +++ b/sound/soc/codecs/es8323.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright Openedhand Ltd. + * + * Author: Richard Purdie + * + */ + +#ifndef _ES8323_H +#define _ES8323_H + +/* ES8323 register space */ + +/* Chip Control and Power Management */ +#define ES8323_CONTROL1 0x00 +#define ES8323_CONTROL2 0x01 +#define ES8323_CHIPPOWER 0x02 +#define ES8323_ADCPOWER 0x03 +#define ES8323_DACPOWER 0x04 +#define ES8323_CHIPLOPOW1 0x05 +#define ES8323_CHIPLOPOW2 0x06 +#define ES8323_ANAVOLMANAG 0x07 +#define ES8323_MASTERMODE 0x08 + +/* ADC Control */ +#define ES8323_ADCCONTROL1 0x09 +#define ES8323_ADCCONTROL2 0x0a +#define ES8323_ADCCONTROL3 0x0b +#define ES8323_ADCCONTROL4 0x0c +#define ES8323_ADCCONTROL5 0x0d +#define ES8323_ADCCONTROL6 0x0e +#define ES8323_ADC_MUTE 0x0f +#define ES8323_LADC_VOL 0x10 +#define ES8323_RADC_VOL 0x11 +#define ES8323_ADCCONTROL10 0x12 +#define ES8323_ADCCONTROL11 0x13 +#define ES8323_ADCCONTROL12 0x14 +#define ES8323_ADCCONTROL13 0x15 +#define ES8323_ADCCONTROL14 0x16 + +/* DAC Control */ +#define ES8323_DACCONTROL1 0x17 +#define ES8323_DACCONTROL2 0x18 +#define ES8323_DAC_MUTE 0x19 +#define ES8323_LDAC_VOL 0x1a +#define ES8323_RDAC_VOL 0x1b +#define ES8323_DACCONTROL6 0x1c +#define ES8323_DACCONTROL7 0x1d +#define ES8323_DACCONTROL8 0x1e +#define ES8323_DACCONTROL9 0x1f +#define ES8323_DACCONTROL10 0x20 +#define ES8323_DACCONTROL11 0x21 +#define ES8323_DACCONTROL12 0x22 +#define ES8323_DACCONTROL13 0x23 +#define ES8323_DACCONTROL14 0x24 +#define ES8323_DACCONTROL15 0x25 +#define ES8323_DACCONTROL16 0x26 +#define ES8323_DACCONTROL17 0x27 +#define ES8323_DACCONTROL18 0x28 +#define ES8323_DACCONTROL19 0x29 +#define ES8323_DACCONTROL20 0x2a +#define ES8323_DACCONTROL21 0x2b +#define ES8323_DACCONTROL22 0x2c +#define ES8323_DACCONTROL23 0x2d +#define ES8323_LOUT1_VOL 0x2e +#define ES8323_ROUT1_VOL 0x2f +#define ES8323_LOUT2_VOL 0x30 +#define ES8323_ROUT2_VOL 0x31 +#define ES8323_DACCONTROL28 0x32 +#define ES8323_DACCONTROL29 0x33 +#define ES8323_DACCONTROL30 0x34 + +#define ES8323_ADC_IFACE ES8323_ADCCONTROL4 +#define ES8323_ADC_SRATE ES8323_ADCCONTROL5 +#define ES8323_DAC_IFACE ES8323_DACCONTROL1 +#define ES8323_DAC_SRATE ES8323_DACCONTROL2 +#endif From patchwork Thu Sep 5 07:02:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Binbin Zhou X-Patchwork-Id: 13791795 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id AD7B61898E5; Thu, 5 Sep 2024 07:02:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725519774; cv=none; b=egvpAlNToCuS8Mxsc5pT/eiUUB2tFiTEK3Id0gSOME7DP9I6HuAJFCb2C27KMlHDcibKHFwkpoBjc9QrPLaVpob0i3+bStRdesu29tX9IMXqVz816mypFOHnFm8c/1GMaAUifm3cQO1q9J3lxSmbVwlguNEA+c4nye5OxqNK08A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725519774; c=relaxed/simple; bh=iY7g1O6xKW0kgAPxw2f8D/exeaIi8NrmuXfu4RzeJqU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YxhKneRVJugRk3iebIK5fL96YoB6UCUjTbvidHlc4NeoFAU5X9zX9NgT+dLCDYmuHDYRKYlWTkE5vtzjnpJucSq/MN+JZF/Ky2jNiKG8/NPpIsqs1BxY4OjfpyHFGnsX6D2MxV/tQkAk/OhRNnMAs5RNdnBACAuR7NUa4t3ILWk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn; spf=pass smtp.mailfrom=loongson.cn; arc=none smtp.client-ip=114.242.206.163 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=loongson.cn Received: from loongson.cn (unknown [223.64.68.71]) by gateway (Coremail) with SMTP id _____8CxuOmbV9lmsRkrAA--.18084S3; Thu, 05 Sep 2024 15:02:51 +0800 (CST) Received: from localhost.localdomain (unknown [223.64.68.71]) by front1 (Coremail) with SMTP id qMiowMAxXNyJV9lm38IEAA--.21058S5; Thu, 05 Sep 2024 15:02:49 +0800 (CST) From: Binbin Zhou To: Binbin Zhou , Huacai Chen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai Cc: Huacai Chen , devicetree@vger.kernel.org, linux-sound@vger.kernel.org, Xuerui Wang , loongarch@lists.linux.dev, Binbin Zhou Subject: [PATCH v1 03/10] ASoC: dt-bindings: Add NXP uda1342 Codec Date: Thu, 5 Sep 2024 15:02:16 +0800 Message-ID: <563dc4c3738d6c5e211bc0c4f0a0386adb44eb22.1725518229.git.zhoubinbin@loongson.cn> X-Mailer: git-send-email 2.43.5 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: qMiowMAxXNyJV9lm38IEAA--.21058S5 X-CM-SenderInfo: p2kr3uplqex0o6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBj93XoW7tF15ArW7Aw4rCw1ruw4rZwc_yoW8GrW8pF s7CF9xJrWFgF17A3y3GFyxur1rXw4kAFWjvr17t340yF95Ca4rtw4S9r15Zr17Ga48Gay3 uF9ruw13K3WkWwcCm3ZEXasCq-sJn29KB7ZKAUJUUUUx529EdanIXcx71UUUUU7KY7ZEXa sCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU 0xBIdaVrnRJUUUBab4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2 IYs7xG6rWj6s0DM7CIcVAFz4kK6r126r13M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Xr0_Ar1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Cr0_Gr1UM28EF7xvwVC2z280aVAFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIEc7CjxVAF wI0_Gr1j6F4UJwAaw2AFwI0_JF0_Jw1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqjxCEc2 xF0cIa020Ex4CE44I27wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2Ix0cI8IcVAFwI0_ Jw0_WrylYx0Ex4A2jsIE14v26r4j6F4UMcvjeVCFs4IE7xkEbVWUJVW8JwACjcxG0xvY0x 0EwIxGrwCY1x0262kKe7AKxVWUAVWUtwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkE bVWUJVW8JwCFI7km07C267AKxVWUAVWUtwC20s026c02F40E14v26r1j6r18MI8I3I0E74 80Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw0_GFylIxkGc2Ij64vIr41lIxAIcVC0 I7IYx2IY67AKxVW5JVW7JwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr0_Cr1lIxAIcVCF04 k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F4UMIIF0xvEx4A2jsIEc7Cj xVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x07jr6p9UUUUU= Add NXP uda1342 CODEC binding with DT schema format using json-schema. Signed-off-by: Binbin Zhou Reviewed-by: Krzysztof Kozlowski --- .../bindings/sound/nxp,uda1342.yaml | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/nxp,uda1342.yaml diff --git a/Documentation/devicetree/bindings/sound/nxp,uda1342.yaml b/Documentation/devicetree/bindings/sound/nxp,uda1342.yaml new file mode 100644 index 000000000000..71c6a5a2f5bc --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nxp,uda1342.yaml @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nxp,uda1342.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP uda1342 audio CODECs + +maintainers: + - Binbin Zhou + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: nxp,uda1342 + + reg: + maxItems: 1 + + '#sound-dai-cells': + const: 0 + +required: + - compatible + - reg + - '#sound-dai-cells' + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + codec@1a { + compatible = "nxp,uda1342"; + reg = <0x1a>; + #sound-dai-cells = <0>; + }; + }; From patchwork Thu Sep 5 07:02:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Binbin Zhou X-Patchwork-Id: 13791797 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id C3311193068; Thu, 5 Sep 2024 07:03:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725519790; cv=none; b=hZ7aHUhupTnTxHvAqALLkX1ae6f5IenvqyCKnaU9Ni+jP8qb1j6qT+mDDYM2jNK36nGVvNMJtJCEF5xn79yVvkWB/AfDT8jKsGxTub7E1ZUaze5uLqcfS4/jtFf87Qb+qQEt2E5Qs+eNWYnFWRiYBxRxR6mQkt63VRWv6HONcOw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725519790; c=relaxed/simple; bh=dXhA2ziw63DKd2N/UEJBZxw11Xyk26YoJf1e0TflXMY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aEMyhLjc4n2NbSI3ZpBS5ZDw9tHWVEWHAPMCR032F3gR570z+amPZQKw46FB47cGbt85HSrW7XT7/ZH8ke4qGHLKUNOvtvv8krvGzPKX0MKlR8oC1JIXrpfyr+2Xhw+xVqJuja/tMuTA+mLxyYfSITRx7C+0nOQiZZDM10z6tLA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn; spf=pass smtp.mailfrom=loongson.cn; arc=none smtp.client-ip=114.242.206.163 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=loongson.cn Received: from loongson.cn (unknown [223.64.68.71]) by gateway (Coremail) with SMTP id _____8DxOJqoV9lm6xkrAA--.45899S3; Thu, 05 Sep 2024 15:03:04 +0800 (CST) Received: from localhost.localdomain (unknown [223.64.68.71]) by front1 (Coremail) with SMTP id qMiowMBxbNyhV9lmDcMEAA--.21040S2; Thu, 05 Sep 2024 15:03:00 +0800 (CST) From: Binbin Zhou To: Binbin Zhou , Huacai Chen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai Cc: Huacai Chen , devicetree@vger.kernel.org, linux-sound@vger.kernel.org, Xuerui Wang , loongarch@lists.linux.dev, Binbin Zhou Subject: [PATCH v1 04/10] ASoC: codecs: Add uda1342 codec driver Date: Thu, 5 Sep 2024 15:02:53 +0800 Message-ID: <3fd0c3a04f5f3bd293168732db457f6854db706e.1725518229.git.zhoubinbin@loongson.cn> X-Mailer: git-send-email 2.43.5 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: qMiowMBxbNyhV9lmDcMEAA--.21040S2 X-CM-SenderInfo: p2kr3uplqex0o6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBj9fXoWfJFy8KFWfGryfJw1UXF1kWFX_yoW8Wr1xKo W3KFnYvr1rXryxZFW5X3WkWFW7ZF15Cay8J3WDZ3ykJ3yrJan8GrWDGr1Uua4aqFsYgFWj yFyIy3s3ArW2yr9rl-sFpf9Il3svdjkaLaAFLSUrUUUU0b8apTn2vfkv8UJUUUU8wcxFpf 9Il3svdxBIdaVrn0xqx4xG64xvF2IEw4CE5I8CrVC2j2Jv73VFW2AGmfu7bjvjm3AaLaJ3 UjIYCTnIWjp_UUUYu7kC6x804xWl14x267AKxVWUJVW8JwAFc2x0x2IEx4CE42xK8VAvwI 8IcIk0rVWrJVCq3wAFIxvE14AKwVWUXVWUAwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xG Y2AK021l84ACjcxK6xIIjxv20xvE14v26F1j6w1UM28EF7xvwVC0I7IYx2IY6xkF7I0E14 v26F4j6r4UJwA2z4x0Y4vEx4A2jsIE14v26r4UJVWxJr1l84ACjcxK6I8E87Iv6xkF7I0E 14v26r4UJVWxJr1ln4kS14v26r126r1DM2AIxVAIcxkEcVAq07x20xvEncxIr21l57IF6x kI12xvs2x26I8E6xACxx1l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v2 6rWY6Fy7McIj6I8E87Iv67AKxVW8JVWxJwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2 Ij64vIr41lc7CjxVAaw2AFwI0_JF0_Jw1l42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Y z7v_Jr0_Gr1l4IxYO2xFxVAFwI0_JF0_Jw1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x 8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r1q6r43MIIYrxkI7VAKI48JMIIF0xvE 2Ix0cI8IcVAFwI0_Xr0_Ar1lIxAIcVC0I7IYx2IY6xkF7I0E14v26F4j6r4UJwCI42IY6x AIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aVCY 1x0267AKxVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7IU0_WrPUUUUU== The UDA1342 is an NXP audio codec, support 2x Stereo audio ADC (4x PGA mic inputs), stereo audio DAC, with basic audio processing. Signed-off-by: Binbin Zhou --- sound/soc/codecs/Kconfig | 8 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/uda1342.c | 397 +++++++++++++++++++++++++++++++++++++ sound/soc/codecs/uda1342.h | 77 +++++++ 4 files changed, 484 insertions(+) create mode 100644 sound/soc/codecs/uda1342.c create mode 100644 sound/soc/codecs/uda1342.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 85270aa43512..347ac5e8eca7 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -281,6 +281,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_TWL4030 imply SND_SOC_TWL6040 imply SND_SOC_UDA1334 + imply SND_SOC_UDA1342 imply SND_SOC_UDA1380 imply SND_SOC_WCD9335 imply SND_SOC_WCD934X @@ -2118,6 +2119,13 @@ config SND_SOC_UDA1334 and has basic features such as de-emphasis (at 44.1 kHz sampling rate) and mute. +config SND_SOC_UDA1342 + tristate "NXP UDA1342 CODEC" + depends on I2C + help + The UDA1342 is an NXP audio codec, support 2x Stereo audio ADC (4x PGA mic inputs), + stereo audio DAC, with basic audio processing. + config SND_SOC_UDA1380 tristate depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 00ff3fdf0133..f5b1c8499d6c 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -319,6 +319,7 @@ snd-soc-ts3a227e-y := ts3a227e.o snd-soc-twl4030-y := twl4030.o snd-soc-twl6040-y := twl6040.o snd-soc-uda1334-y := uda1334.o +snd-soc-uda1342-y := uda1342.o snd-soc-uda1380-y := uda1380.o snd-soc-wcd-classh-y := wcd-clsh-v2.o snd-soc-wcd-mbhc-y := wcd-mbhc-v2.o @@ -723,6 +724,7 @@ obj-$(CONFIG_SND_SOC_TS3A227E) += snd-soc-ts3a227e.o obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o obj-$(CONFIG_SND_SOC_UDA1334) += snd-soc-uda1334.o +obj-$(CONFIG_SND_SOC_UDA1342) += snd-soc-uda1342.o obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o obj-$(CONFIG_SND_SOC_WCD_CLASSH) += snd-soc-wcd-classh.o obj-$(CONFIG_SND_SOC_WCD_MBHC) += snd-soc-wcd-mbhc.o diff --git a/sound/soc/codecs/uda1342.c b/sound/soc/codecs/uda1342.c new file mode 100644 index 000000000000..e26aa4148434 --- /dev/null +++ b/sound/soc/codecs/uda1342.c @@ -0,0 +1,397 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * uda1342.c -- UDA1342 ALSA SoC Codec driver + * + * Modifications by Christian Pellegrin + * + * Copyright 2007 Dension Audio Systems Ltd. + * Author: Zoltan Devai + * + * Based on the WM87xx drivers by Liam Girdwood and Richard Purdie + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "uda1342.h" + +#define UDA134X_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE) + +struct uda1342_priv { + int sysclk; + int dai_fmt; + + struct snd_pcm_substream *master_substream; + struct snd_pcm_substream *slave_substream; + + struct regmap *regmap; + struct i2c_client *i2c; +}; + +static const struct reg_default uda1342_reg_defaults[] = { + { 0x00, 0x1042 }, + { 0x01, 0x0000 }, + { 0x10, 0x0088 }, + { 0x11, 0x0000 }, + { 0x12, 0x0000 }, + { 0x20, 0x0080 }, + { 0x21, 0x0080 }, +}; + +static inline void uda1342_reset(struct uda1342_priv *uda1342) +{ + unsigned int mask = BIT(15); + + regmap_write(uda1342->regmap, 0x00, mask); +} + +static int uda1342_mute(struct snd_soc_dai *dai, int mute, int direction) +{ + struct snd_soc_component *component = dai->component; + struct uda1342_priv *uda1342 = snd_soc_component_get_drvdata(component); + unsigned int mask; + unsigned int val = 0; + + dev_info(&uda1342->i2c->dev, "mute: %d\n", mute); + + /* Master mute */ + mask = BIT(5); + val = mute ? mask : 0; + + return regmap_update_bits(uda1342->regmap, 0x10, mask, val); +} + +static int uda1342_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct uda1342_priv *uda1342 = snd_soc_component_get_drvdata(component); + struct snd_pcm_runtime *master_runtime; + + if (uda1342->master_substream) { + master_runtime = uda1342->master_substream->runtime; + + snd_pcm_hw_constraint_single(substream->runtime, + SNDRV_PCM_HW_PARAM_RATE, master_runtime->rate); + snd_pcm_hw_constraint_single(substream->runtime, + SNDRV_PCM_HW_PARAM_SAMPLE_BITS, + master_runtime->sample_bits); + + uda1342->slave_substream = substream; + } else { + uda1342->master_substream = substream; + } + + return 0; +} + +static void uda1342_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct uda1342_priv *uda1342 = snd_soc_component_get_drvdata(component); + + if (uda1342->master_substream == substream) + uda1342->master_substream = uda1342->slave_substream; + + uda1342->slave_substream = NULL; +} + +static int uda1342_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct uda1342_priv *uda1342 = snd_soc_component_get_drvdata(component); + struct device *dev = &uda1342->i2c->dev; + unsigned int hw_params = 0; + + if (substream == uda1342->slave_substream) { + dev_info(dev, "ignoring hw_params for slave substream\n"); + return 0; + } + + /* set SYSCLK / fs ratio */ + switch (uda1342->sysclk / params_rate(params)) { + case 512: + break; + case 384: + hw_params |= BIT(4); + break; + case 256: + hw_params |= BIT(5); + break; + default: + dev_err(dev, "unsupported frequency\n"); + return -EINVAL; + } + + /* set DAI format and word length */ + switch (uda1342->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + break; + case SND_SOC_DAIFMT_RIGHT_J: + switch (params_width(params)) { + case 16: + hw_params |= BIT(1); + break; + case 18: + hw_params |= BIT(2); + break; + case 20: + hw_params |= BIT(2) | BIT(1); + break; + default: + dev_err(dev, "unsupported format (right)\n"); + return -EINVAL; + } + break; + case SND_SOC_DAIFMT_LEFT_J: + hw_params |= BIT(3); + break; + default: + dev_err(dev, "unsupported format\n"); + return -EINVAL; + } + + return 0; +} + +static int uda1342_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_component *component = codec_dai->component; + struct uda1342_priv *uda1342 = snd_soc_component_get_drvdata(component); + struct device *dev = &uda1342->i2c->dev; + + /* + * Anything between 256fs*8Khz and 512fs*48Khz should be acceptable + * because the codec is slave. Of course limitations of the clock + * master (the IIS controller) apply. + * We'll error out on set_hw_params if it's not OK + */ + if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) { + uda1342->sysclk = freq; + return 0; + } + + dev_err(dev, "unsupported sysclk\n"); + + return -EINVAL; +} + +static int uda1342_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) +{ + struct snd_soc_component *component = codec_dai->component; + struct uda1342_priv *uda1342 = snd_soc_component_get_drvdata(component); + struct device *dev = &uda1342->i2c->dev; + + /* codec supports only full slave mode */ + if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) { + dev_err(dev, "unsupported slave mode.\n"); + return -EINVAL; + } + + /* + * We can't setup DAI format here as it depends on the word bit num, + * so let's just store the value for later + */ + uda1342->dai_fmt = fmt; + + return 0; +} + +static int uda1342_set_bias_level(struct snd_soc_component *component, + enum snd_soc_bias_level level) +{ + switch (level) { + case SND_SOC_BIAS_ON: + break; + case SND_SOC_BIAS_PREPARE: + break; + case SND_SOC_BIAS_STANDBY: + break; + case SND_SOC_BIAS_OFF: + break; + } + + return 0; +} + +static const char *const uda1342_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; +static const char *const uda1342_mixmode[] = {"Differential", "Analog1", "Analog2", "Both"}; + +static const struct soc_enum uda1342_mixer_enum[] = { + SOC_ENUM_SINGLE(0x10, 3, 0x04, uda1342_deemph), + SOC_ENUM_SINGLE(0x10, 0, 0x04, uda1342_mixmode), +}; + +static const struct snd_kcontrol_new uda1342_snd_controls[] = { + SOC_SINGLE("Master Playback Volume", 0x11, 0, 0x3F, 1), + SOC_SINGLE("Analog1 Volume", 0x12, 0, 0x1F, 1), +}; + +/* Common DAPM widgets */ +static const struct snd_soc_dapm_widget uda1342_dapm_widgets[] = { + SND_SOC_DAPM_INPUT("VINL1"), + SND_SOC_DAPM_INPUT("VINR1"), + SND_SOC_DAPM_INPUT("VINL2"), + SND_SOC_DAPM_INPUT("VINR2"), + + SND_SOC_DAPM_DAC("DAC", "Playback", 0, 1, 0), + SND_SOC_DAPM_ADC("ADC", "Capture", 0, 9, 0), + + SND_SOC_DAPM_OUTPUT("VOUTL"), + SND_SOC_DAPM_OUTPUT("VOUTR"), +}; + +static const struct snd_soc_dapm_route uda1342_dapm_routes[] = { + { "ADC", NULL, "VINL1" }, + { "ADC", NULL, "VINR1" }, + { "ADC", NULL, "VINL2" }, + { "ADC", NULL, "VINR2" }, + { "VOUTL", NULL, "DAC" }, + { "VOUTR", NULL, "DAC" }, +}; + +static const struct snd_soc_dai_ops uda1342_dai_ops = { + .startup = uda1342_startup, + .shutdown = uda1342_shutdown, + .hw_params = uda1342_hw_params, + .mute_stream = uda1342_mute, + .set_sysclk = uda1342_set_dai_sysclk, + .set_fmt = uda1342_set_dai_fmt, +}; + +static struct snd_soc_dai_driver uda1342_dai = { + .name = "uda1342-hifi", + /* playback capabilities */ + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = UDA134X_FORMATS, + }, + /* capture capabilities */ + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = UDA134X_FORMATS, + }, + /* pcm operations */ + .ops = &uda1342_dai_ops, +}; + +static int uda1342_soc_probe(struct snd_soc_component *component) +{ + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); + + snd_soc_add_component_controls(component, uda1342_snd_controls, + ARRAY_SIZE(uda1342_snd_controls)); + snd_soc_dapm_new_controls(dapm, uda1342_dapm_widgets, + ARRAY_SIZE(uda1342_dapm_widgets)); + snd_soc_dapm_add_routes(dapm, uda1342_dapm_routes, + ARRAY_SIZE(uda1342_dapm_routes)); + + return 0; +} + +static const struct snd_soc_component_driver soc_component_dev_uda1342 = { + .probe = uda1342_soc_probe, + .set_bias_level = uda1342_set_bias_level, + .suspend_bias_off = 1, + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, +}; + +static const struct regmap_config uda1342_regmap = { + .reg_bits = 8, + .val_bits = 16, + .max_register = 0x21, + .reg_defaults = uda1342_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(uda1342_reg_defaults), + .cache_type = REGCACHE_RBTREE, +}; + +static int uda1342_i2c_probe(struct i2c_client *i2c) +{ + struct uda1342_priv *uda1342; + int ret; + + uda1342 = devm_kzalloc(&i2c->dev, sizeof(*uda1342), GFP_KERNEL); + if (!uda1342) + return -ENOMEM; + + uda1342->regmap = devm_regmap_init_i2c(i2c, &uda1342_regmap); + if (IS_ERR(uda1342->regmap)) + return PTR_ERR(uda1342->regmap); + + i2c_set_clientdata(i2c, uda1342); + uda1342->i2c = i2c; + + return devm_snd_soc_register_component(&i2c->dev, + &soc_component_dev_uda1342, + &uda1342_dai, 1); +} + +static int uda1342_suspend(struct device *dev) +{ + struct uda1342_priv *uda1342 = dev_get_drvdata(dev); + + regcache_cache_only(uda1342->regmap, true); + + return 0; +} + +static int uda1342_resume(struct device *dev) +{ + struct uda1342_priv *uda1342 = dev_get_drvdata(dev); + + regcache_mark_dirty(uda1342->regmap); + regcache_sync(uda1342->regmap); + + return 0; +} + +static const struct dev_pm_ops uda1342_pm = { + SET_SYSTEM_SLEEP_PM_OPS(uda1342_suspend, uda1342_resume) +}; + +static const struct i2c_device_id uda1342_i2c_id[] = { + { "uda1342", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, uda1342_i2c_id); + +static const struct of_device_id uda1342_of_match[] = { + { .compatible = "nxp,uda1342" }, + { } +}; +MODULE_DEVICE_TABLE(of, uda1342_of_match); + +static struct i2c_driver uda1342_i2c_driver = { + .driver = { + .name = "uda1342", + .of_match_table = uda1342_of_match, + .pm = pm_sleep_ptr(&uda1342_pm), + }, + .probe = uda1342_i2c_probe, + .id_table = uda1342_i2c_id, +}; +module_i2c_driver(uda1342_i2c_driver); + +MODULE_DESCRIPTION("UDA1342 ALSA soc codec driver"); +MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/uda1342.h b/sound/soc/codecs/uda1342.h new file mode 100644 index 000000000000..1f4632643ddd --- /dev/null +++ b/sound/soc/codecs/uda1342.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Audio support for NXP UDA1342 + * + * Copyright (c) 2005 Giorgio Padrin + * Copyright (c) 2024 Loongson Technology Corporation Limited. + */ + +#ifndef _UDA1342_H +#define _UDA1342_H + +#define UDA1342_CLK 0x00 +#define UDA1342_IFACE 0x01 +#define UDA1342_PM 0x02 +#define UDA1342_AMIX 0x03 +#define UDA1342_HP 0x04 +#define UDA1342_MVOL 0x11 +#define UDA1342_MIXVOL 0x12 +#define UDA1342_MODE 0x12 +#define UDA1342_DEEMP 0x13 +#define UDA1342_MIXER 0x14 +#define UDA1342_INTSTAT 0x18 +#define UDA1342_DEC 0x20 +#define UDA1342_PGA 0x21 +#define UDA1342_ADC 0x22 +#define UDA1342_AGC 0x23 +#define UDA1342_DECSTAT 0x28 +#define UDA1342_RESET 0x7f + +#define UDA1342_CACHEREGNUM 0x24 + +/* Register flags */ +#define R00_EN_ADC 0x0800 +#define R00_EN_DEC 0x0400 +#define R00_EN_DAC 0x0200 +#define R00_EN_INT 0x0100 +#define R00_DAC_CLK 0x0010 +#define R01_SFORI_I2S 0x0000 +#define R01_SFORI_LSB16 0x0100 +#define R01_SFORI_LSB18 0x0200 +#define R01_SFORI_LSB20 0x0300 +#define R01_SFORI_MSB 0x0500 +#define R01_SFORI_MASK 0x0700 +#define R01_SFORO_I2S 0x0000 +#define R01_SFORO_LSB16 0x0001 +#define R01_SFORO_LSB18 0x0002 +#define R01_SFORO_LSB20 0x0003 +#define R01_SFORO_LSB24 0x0004 +#define R01_SFORO_MSB 0x0005 +#define R01_SFORO_MASK 0x0007 +#define R01_SEL_SOURCE 0x0040 +#define R01_SIM 0x0010 +#define R02_PON_PLL 0x8000 +#define R02_PON_HP 0x2000 +#define R02_PON_DAC 0x0400 +#define R02_PON_BIAS 0x0100 +#define R02_EN_AVC 0x0080 +#define R02_PON_AVC 0x0040 +#define R02_PON_LNA 0x0010 +#define R02_PON_PGAL 0x0008 +#define R02_PON_ADCL 0x0004 +#define R02_PON_PGAR 0x0002 +#define R02_PON_ADCR 0x0001 +#define R13_MTM 0x4000 +#define R14_SILENCE 0x0080 +#define R14_SDET_ON 0x0040 +#define R21_MT_ADC 0x8000 +#define R22_SEL_LNA 0x0008 +#define R22_SEL_MIC 0x0004 +#define R22_SKIP_DCFIL 0x0002 +#define R23_AGC_EN 0x0001 + +#define UDA1342_DAI_DUPLEX 0 /* playback and capture on single DAI */ +#define UDA1342_DAI_PLAYBACK 1 /* playback DAI */ +#define UDA1342_DAI_CAPTURE 2 /* capture DAI */ + +#endif /* _UDA1342_H */ From patchwork Thu Sep 5 07:02:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Binbin Zhou X-Patchwork-Id: 13791798 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 0578D1925B2; Thu, 5 Sep 2024 07:03:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725519793; cv=none; b=ZVD5QSlf+uzqHLHwHaxA8dJZ+QXk45xkR8VQ89L43odnDM0SPblilM1blPuuUzJdYQ17nFKhybNZvOqZPGfxX/Gu08Ct0ysWbb6DHvD4wAGwTl6AaslLQvIckv0ZbWSNz+VkLXzAvgwo+SzO7VpyA5B+hN83pSJIyUwReYQ745g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725519793; c=relaxed/simple; bh=3/CBZR6pzcmP47JzOTvZKGUcRW4mYPP9XpvPFsXbmdk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=m8lXoAOtSGxzG/XJIDqsextgNasUP9nMFGpg2n6oicBHQpjhMrifkNy25f9WpZLzOXBlY5vfzzJ3xdc/38P41YDlOJBEXcMRt0bvCpBXcxfVbXjKRqY6yFkKTyXz1XwLCCxCFKtyp5QZI7cIsw4iE0zpipVvrcwkdF09h7lSAFc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn; spf=pass smtp.mailfrom=loongson.cn; arc=none smtp.client-ip=114.242.206.163 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=loongson.cn Received: from loongson.cn (unknown [223.64.68.71]) by gateway (Coremail) with SMTP id _____8Dxh+mtV9lm+hkrAA--.16503S3; Thu, 05 Sep 2024 15:03:09 +0800 (CST) Received: from localhost.localdomain (unknown [223.64.68.71]) by front1 (Coremail) with SMTP id qMiowMBxbNyhV9lmDcMEAA--.21040S3; Thu, 05 Sep 2024 15:03:04 +0800 (CST) From: Binbin Zhou To: Binbin Zhou , Huacai Chen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai Cc: Huacai Chen , devicetree@vger.kernel.org, linux-sound@vger.kernel.org, Xuerui Wang , loongarch@lists.linux.dev, Binbin Zhou Subject: [PATCH v1 05/10] ASoC: loongson: Improve code readability Date: Thu, 5 Sep 2024 15:02:54 +0800 Message-ID: X-Mailer: git-send-email 2.43.5 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: qMiowMBxbNyhV9lmDcMEAA--.21040S3 X-CM-SenderInfo: p2kr3uplqex0o6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBj9fXoW3CFWkCr1xGw4fJF18Zr43Arc_yoW8CFWfZo W0vF93X3y5Xr18CFs0g34rWrnrZa15CF9Iyr92yrWqkw1jyF18W3y5ur47uFyfWay5Krs5 JF9xtFs3GanxArWxl-sFpf9Il3svdjkaLaAFLSUrUUUU0b8apTn2vfkv8UJUUUU8wcxFpf 9Il3svdxBIdaVrn0xqx4xG64xvF2IEw4CE5I8CrVC2j2Jv73VFW2AGmfu7bjvjm3AaLaJ3 UjIYCTnIWjp_UUUYu7kC6x804xWl14x267AKxVWUJVW8JwAFc2x0x2IEx4CE42xK8VAvwI 8IcIk0rVWrJVCq3wAFIxvE14AKwVWUXVWUAwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xG Y2AK021l84ACjcxK6xIIjxv20xvE14v26F1j6w1UM28EF7xvwVC0I7IYx2IY6xkF7I0E14 v26F4j6r4UJwA2z4x0Y4vEx4A2jsIE14v26r4UJVWxJr1l84ACjcxK6I8E87Iv6xkF7I0E 14v26r4UJVWxJr1ln4kS14v26r126r1DM2AIxVAIcxkEcVAq07x20xvEncxIr21l57IF6x kI12xvs2x26I8E6xACxx1l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v2 6rWY6Fy7McIj6I8E87Iv67AKxVW8JVWxJwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2 Ij64vIr41lc7CjxVAaw2AFwI0_JF0_Jw1l42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Y z7v_Jr0_Gr1l4IxYO2xFxVAFwI0_JF0_Jw1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x 8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r1q6r43MIIYrxkI7VAKI48JMIIF0xvE 2Ix0cI8IcVAFwI0_Ar0_tr1lIxAIcVC0I7IYx2IY6xkF7I0E14v26F4j6r4UJwCI42IY6x AIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aVCY 1x0267AKxVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7IU0_WrPUUUUU== This patch attempts to clean up driver code formatting issues. Mainly as follows: 1. Use the BIT macro; 2. Use dev_err_probe() in every error path in probe in loongson_card driver; 3. Introduce loongson_card_acpi_find_device() to streamlined code. No functional change intended. Signed-off-by: Binbin Zhou --- sound/soc/loongson/loongson_card.c | 144 +++++++++++++------------- sound/soc/loongson/loongson_dma.c | 10 +- sound/soc/loongson/loongson_i2s.c | 110 ++++++++++---------- sound/soc/loongson/loongson_i2s.h | 24 ++--- sound/soc/loongson/loongson_i2s_pci.c | 51 ++++----- 5 files changed, 166 insertions(+), 173 deletions(-) diff --git a/sound/soc/loongson/loongson_card.c b/sound/soc/loongson/loongson_card.c index 2c8dbdba27c5..a25287efdd5c 100644 --- a/sound/soc/loongson/loongson_card.c +++ b/sound/soc/loongson/loongson_card.c @@ -24,27 +24,27 @@ static int loongson_card_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); struct loongson_card_data *ls_card = snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); int ret, mclk; - if (ls_card->mclk_fs) { - mclk = ls_card->mclk_fs * params_rate(params); - ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk, - SND_SOC_CLOCK_OUT); - if (ret < 0) { - dev_err(codec_dai->dev, "cpu_dai clock not set\n"); - return ret; - } + if (!ls_card->mclk_fs) + return 0; - ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, - SND_SOC_CLOCK_IN); - if (ret < 0) { - dev_err(codec_dai->dev, "codec_dai clock not set\n"); - return ret; - } + mclk = ls_card->mclk_fs * params_rate(params); + ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk, SND_SOC_CLOCK_OUT); + if (ret < 0) { + dev_err(codec_dai->dev, "cpu_dai clock not set\n"); + return ret; } + + ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(codec_dai->dev, "codec_dai clock not set\n"); + return ret; + } + return 0; } @@ -68,54 +68,61 @@ static struct snd_soc_dai_link loongson_dai_links[] = { }, }; -static int loongson_card_parse_acpi(struct loongson_card_data *data) +static struct acpi_device * +loongson_card_acpi_find_device(struct snd_soc_card *card, const char *name) { - struct snd_soc_card *card = &data->snd_card; struct fwnode_handle *fwnode = card->dev->fwnode; struct fwnode_reference_args args; + int status; + + memset(&args, 0, sizeof(args)); + status = acpi_node_get_property_reference(fwnode, name, 0, &args); + if (ACPI_FAILURE(status) || !is_acpi_device_node(args.fwnode)) { + dev_err(card->dev, "No matching phy in ACPI table\n"); + return NULL; + } + + return to_acpi_device_node(args.fwnode); +} + +static int loongson_card_parse_acpi(struct loongson_card_data *data) +{ + struct snd_soc_card *card = &data->snd_card; const char *codec_dai_name; struct acpi_device *adev; struct device *phy_dev; - int ret, i; + int i; /* fixup platform name based on reference node */ - memset(&args, 0, sizeof(args)); - ret = acpi_node_get_property_reference(fwnode, "cpu", 0, &args); - if (ret || !is_acpi_device_node(args.fwnode)) { - dev_err(card->dev, "No matching phy in ACPI table\n"); - return ret ?: -ENOENT; - } - adev = to_acpi_device_node(args.fwnode); + adev = loongson_card_acpi_find_device(card, "cpu"); + if (!adev) + return -ENOENT; + phy_dev = acpi_get_first_physical_node(adev); if (!phy_dev) return -EPROBE_DEFER; - for (i = 0; i < card->num_links; i++) - loongson_dai_links[i].platforms->name = dev_name(phy_dev); /* fixup codec name based on reference node */ - memset(&args, 0, sizeof(args)); - ret = acpi_node_get_property_reference(fwnode, "codec", 0, &args); - if (ret || !is_acpi_device_node(args.fwnode)) { - dev_err(card->dev, "No matching phy in ACPI table\n"); - return ret ?: -ENOENT; - } - adev = to_acpi_device_node(args.fwnode); + adev = loongson_card_acpi_find_device(card, "codec"); + if (!adev) + return -ENOENT; snprintf(codec_name, sizeof(codec_name), "i2c-%s", acpi_dev_name(adev)); - for (i = 0; i < card->num_links; i++) - loongson_dai_links[i].codecs->name = codec_name; - device_property_read_string(card->dev, "codec-dai-name", - &codec_dai_name); - for (i = 0; i < card->num_links; i++) + device_property_read_string(card->dev, "codec-dai-name", &codec_dai_name); + + for (i = 0; i < card->num_links; i++) { + loongson_dai_links[i].platforms->name = dev_name(phy_dev); + loongson_dai_links[i].codecs->name = codec_name; loongson_dai_links[i].codecs->dai_name = codec_dai_name; + } return 0; } static int loongson_card_parse_of(struct loongson_card_data *data) { - struct device_node *cpu, *codec; struct snd_soc_card *card = &data->snd_card; + struct device_node *cpu, *codec; struct device *dev = card->dev; int ret, i; @@ -124,77 +131,68 @@ static int loongson_card_parse_of(struct loongson_card_data *data) dev_err(dev, "platform property missing or invalid\n"); return -EINVAL; } + codec = of_get_child_by_name(dev->of_node, "codec"); if (!codec) { dev_err(dev, "audio-codec property missing or invalid\n"); - of_node_put(cpu); - return -EINVAL; + ret = -EINVAL; + goto free_cpu; } for (i = 0; i < card->num_links; i++) { ret = snd_soc_of_get_dlc(cpu, NULL, loongson_dai_links[i].cpus, 0); - if (ret < 0) { + if (ret) { dev_err(dev, "getting cpu dlc error (%d)\n", ret); - goto err; + goto free_codec; } ret = snd_soc_of_get_dlc(codec, NULL, loongson_dai_links[i].codecs, 0); - if (ret < 0) { + if (ret) { dev_err(dev, "getting codec dlc error (%d)\n", ret); - goto err; + goto free_codec; } } - of_node_put(cpu); +free_codec: of_node_put(codec); - - return 0; - -err: +free_cpu: of_node_put(cpu); - of_node_put(codec); return ret; } static int loongson_asoc_card_probe(struct platform_device *pdev) { struct loongson_card_data *ls_priv; + struct device *dev = &pdev->dev; struct snd_soc_card *card; int ret; - ls_priv = devm_kzalloc(&pdev->dev, sizeof(*ls_priv), GFP_KERNEL); + ls_priv = devm_kzalloc(dev, sizeof(*ls_priv), GFP_KERNEL); if (!ls_priv) return -ENOMEM; card = &ls_priv->snd_card; - card->dev = &pdev->dev; + card->dev = dev; card->owner = THIS_MODULE; card->dai_link = loongson_dai_links; card->num_links = ARRAY_SIZE(loongson_dai_links); snd_soc_card_set_drvdata(card, ls_priv); - ret = device_property_read_string(&pdev->dev, "model", &card->name); - if (ret) { - dev_err(&pdev->dev, "Error parsing card name: %d\n", ret); - return ret; - } - ret = device_property_read_u32(&pdev->dev, "mclk-fs", &ls_priv->mclk_fs); - if (ret) { - dev_err(&pdev->dev, "Error parsing mclk-fs: %d\n", ret); - return ret; - } + ret = device_property_read_string(dev, "model", &card->name); + if (ret) + dev_err_probe(dev, ret, "Error parsing card name.\n"); - if (has_acpi_companion(&pdev->dev)) - ret = loongson_card_parse_acpi(ls_priv); - else - ret = loongson_card_parse_of(ls_priv); - if (ret < 0) - return ret; + ret = device_property_read_u32(dev, "mclk-fs", &ls_priv->mclk_fs); + if (ret) + dev_err_probe(dev, ret, "Error parsing mclk-fs.\n"); - ret = devm_snd_soc_register_card(&pdev->dev, card); + ret = has_acpi_companion(dev) ? loongson_card_parse_acpi(ls_priv) + : loongson_card_parse_of(ls_priv); + if (ret) + dev_err_probe(dev, ret, "Error parsing acpi/of properties.\n"); - return ret; + return devm_snd_soc_register_card(dev, card); } static const struct of_device_id loongson_asoc_dt_ids[] = { diff --git a/sound/soc/loongson/loongson_dma.c b/sound/soc/loongson/loongson_dma.c index 0238f88bc674..20e4a0641340 100644 --- a/sound/soc/loongson/loongson_dma.c +++ b/sound/soc/loongson/loongson_dma.c @@ -17,11 +17,11 @@ #include "loongson_i2s.h" /* DMA dma_order Register */ -#define DMA_ORDER_STOP (1 << 4) /* DMA stop */ -#define DMA_ORDER_START (1 << 3) /* DMA start */ -#define DMA_ORDER_ASK_VALID (1 << 2) /* DMA ask valid flag */ -#define DMA_ORDER_AXI_UNCO (1 << 1) /* Uncache access */ -#define DMA_ORDER_ADDR_64 (1 << 0) /* 64bits address support */ +#define DMA_ORDER_STOP BIT(4) /* DMA stop */ +#define DMA_ORDER_START BIT(3) /* DMA start */ +#define DMA_ORDER_ASK_VALID BIT(2) /* DMA ask valid flag */ +#define DMA_ORDER_AXI_UNCO BIT(1) /* Uncache access */ +#define DMA_ORDER_ADDR_64 BIT(0) /* 64bits address support */ #define DMA_ORDER_ASK_MASK (~0x1fUL) /* Ask addr mask */ #define DMA_ORDER_CTRL_MASK (0x0fUL) /* Control mask */ diff --git a/sound/soc/loongson/loongson_i2s.c b/sound/soc/loongson/loongson_i2s.c index 3b9786076501..40bbf3205391 100644 --- a/sound/soc/loongson/loongson_i2s.c +++ b/sound/soc/loongson/loongson_i2s.c @@ -21,34 +21,33 @@ SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE) +#define LOONGSON_I2S_TX_ENABLE (I2S_CTRL_TX_EN | I2S_CTRL_TX_DMA_EN) +#define LOONGSON_I2S_RX_ENABLE (I2S_CTRL_RX_EN | I2S_CTRL_RX_DMA_EN) + +#define LOONGSON_I2S_DEF_DELAY 10 +#define LOONGSON_I2S_DEF_TIMEOUT 500000 + static int loongson_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct loongson_i2s *i2s = snd_soc_dai_get_drvdata(dai); + unsigned int mask; int ret = 0; switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - regmap_update_bits(i2s->regmap, LS_I2S_CTRL, - I2S_CTRL_TX_EN | I2S_CTRL_TX_DMA_EN, - I2S_CTRL_TX_EN | I2S_CTRL_TX_DMA_EN); - else - regmap_update_bits(i2s->regmap, LS_I2S_CTRL, - I2S_CTRL_RX_EN | I2S_CTRL_RX_DMA_EN, - I2S_CTRL_RX_EN | I2S_CTRL_RX_DMA_EN); + mask = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? + LOONGSON_I2S_TX_ENABLE : LOONGSON_I2S_RX_ENABLE; + regmap_update_bits(i2s->regmap, LS_I2S_CTRL, mask, mask); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - regmap_update_bits(i2s->regmap, LS_I2S_CTRL, - I2S_CTRL_TX_EN | I2S_CTRL_TX_DMA_EN, 0); - else - regmap_update_bits(i2s->regmap, LS_I2S_CTRL, - I2S_CTRL_RX_EN | I2S_CTRL_RX_DMA_EN, 0); + mask = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? + LOONGSON_I2S_TX_ENABLE : LOONGSON_I2S_RX_ENABLE; + regmap_update_bits(i2s->regmap, LS_I2S_CTRL, mask, 0); break; default: ret = -EINVAL; @@ -123,10 +122,40 @@ static int loongson_i2s_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, return 0; } +static int loongson_i2s_enable_mclk(struct loongson_i2s *i2s) +{ + u32 val; + + if (i2s->rev_id == 0) + return 0; + + regmap_update_bits(i2s->regmap, LS_I2S_CTRL, + I2S_CTRL_MCLK_EN, I2S_CTRL_MCLK_EN); + + return regmap_read_poll_timeout_atomic(i2s->regmap, + LS_I2S_CTRL, val, + val & I2S_CTRL_MCLK_READY, + LOONGSON_I2S_DEF_DELAY, + LOONGSON_I2S_DEF_TIMEOUT); +} + +static int loongson_i2s_enable_bclk(struct loongson_i2s *i2s) +{ + u32 val; + + if (i2s->rev_id == 0) + return 0; + + return regmap_read_poll_timeout_atomic(i2s->regmap, + LS_I2S_CTRL, val, + val & I2S_CTRL_CLK_READY, + LOONGSON_I2S_DEF_DELAY, + LOONGSON_I2S_DEF_TIMEOUT); +} + static int loongson_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct loongson_i2s *i2s = snd_soc_dai_get_drvdata(dai); - u32 val; int ret; switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -148,54 +177,29 @@ static int loongson_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) /* Enable master mode */ regmap_update_bits(i2s->regmap, LS_I2S_CTRL, I2S_CTRL_MASTER, I2S_CTRL_MASTER); - if (i2s->rev_id == 1) { - ret = regmap_read_poll_timeout_atomic(i2s->regmap, - LS_I2S_CTRL, val, - val & I2S_CTRL_CLK_READY, - 10, 500000); - if (ret < 0) - dev_warn(dai->dev, "wait BCLK ready timeout\n"); - } + ret = loongson_i2s_enable_bclk(i2s); + if (ret < 0) + dev_warn(dai->dev, "wait BCLK ready timeout\n"); break; case SND_SOC_DAIFMT_BC_FP: /* Enable MCLK */ - if (i2s->rev_id == 1) { - regmap_update_bits(i2s->regmap, LS_I2S_CTRL, - I2S_CTRL_MCLK_EN, - I2S_CTRL_MCLK_EN); - ret = regmap_read_poll_timeout_atomic(i2s->regmap, - LS_I2S_CTRL, val, - val & I2S_CTRL_MCLK_READY, - 10, 500000); - if (ret < 0) - dev_warn(dai->dev, "wait MCLK ready timeout\n"); - } + ret = loongson_i2s_enable_mclk(i2s); + if (ret < 0) + dev_warn(dai->dev, "wait MCLK ready timeout\n"); break; case SND_SOC_DAIFMT_BP_FP: /* Enable MCLK */ - if (i2s->rev_id == 1) { - regmap_update_bits(i2s->regmap, LS_I2S_CTRL, - I2S_CTRL_MCLK_EN, - I2S_CTRL_MCLK_EN); - ret = regmap_read_poll_timeout_atomic(i2s->regmap, - LS_I2S_CTRL, val, - val & I2S_CTRL_MCLK_READY, - 10, 500000); - if (ret < 0) - dev_warn(dai->dev, "wait MCLK ready timeout\n"); - } + ret = loongson_i2s_enable_mclk(i2s); + if (ret < 0) + dev_warn(dai->dev, "wait MCLK ready timeout\n"); /* Enable master mode */ regmap_update_bits(i2s->regmap, LS_I2S_CTRL, I2S_CTRL_MASTER, I2S_CTRL_MASTER); - if (i2s->rev_id == 1) { - ret = regmap_read_poll_timeout_atomic(i2s->regmap, - LS_I2S_CTRL, val, - val & I2S_CTRL_CLK_READY, - 10, 500000); - if (ret < 0) - dev_warn(dai->dev, "wait BCLK ready timeout\n"); - } + + ret = loongson_i2s_enable_bclk(i2s); + if (ret < 0) + dev_warn(dai->dev, "wait BCLK ready timeout\n"); break; default: return -EINVAL; diff --git a/sound/soc/loongson/loongson_i2s.h b/sound/soc/loongson/loongson_i2s.h index 89492eebf834..c8052a762c1b 100644 --- a/sound/soc/loongson/loongson_i2s.h +++ b/sound/soc/loongson/loongson_i2s.h @@ -27,18 +27,18 @@ #define LS_I2S_RX_ORDER 0x110 /* RX DMA Order */ /* Loongson I2S Control Register */ -#define I2S_CTRL_MCLK_READY (1 << 16) /* MCLK ready */ -#define I2S_CTRL_MASTER (1 << 15) /* Master mode */ -#define I2S_CTRL_MSB (1 << 14) /* MSB bit order */ -#define I2S_CTRL_RX_EN (1 << 13) /* RX enable */ -#define I2S_CTRL_TX_EN (1 << 12) /* TX enable */ -#define I2S_CTRL_RX_DMA_EN (1 << 11) /* DMA RX enable */ -#define I2S_CTRL_CLK_READY (1 << 8) /* BCLK ready */ -#define I2S_CTRL_TX_DMA_EN (1 << 7) /* DMA TX enable */ -#define I2S_CTRL_RESET (1 << 4) /* Controller soft reset */ -#define I2S_CTRL_MCLK_EN (1 << 3) /* Enable MCLK */ -#define I2S_CTRL_RX_INT_EN (1 << 1) /* RX interrupt enable */ -#define I2S_CTRL_TX_INT_EN (1 << 0) /* TX interrupt enable */ +#define I2S_CTRL_MCLK_READY BIT(16) /* MCLK ready */ +#define I2S_CTRL_MASTER BIT(15) /* Master mode */ +#define I2S_CTRL_MSB BIT(14) /* MSB bit order */ +#define I2S_CTRL_RX_EN BIT(13) /* RX enable */ +#define I2S_CTRL_TX_EN BIT(12) /* TX enable */ +#define I2S_CTRL_RX_DMA_EN BIT(11) /* DMA RX enable */ +#define I2S_CTRL_CLK_READY BIT(8) /* BCLK ready */ +#define I2S_CTRL_TX_DMA_EN BIT(7) /* DMA TX enable */ +#define I2S_CTRL_RESET BIT(4) /* Controller soft reset */ +#define I2S_CTRL_MCLK_EN BIT(3) /* Enable MCLK */ +#define I2S_CTRL_RX_INT_EN BIT(1) /* RX interrupt enable */ +#define I2S_CTRL_TX_INT_EN BIT(0) /* TX interrupt enable */ #define LS_I2S_DRVNAME "loongson-i2s" diff --git a/sound/soc/loongson/loongson_i2s_pci.c b/sound/soc/loongson/loongson_i2s_pci.c index ec18b122cd79..3872b1d8fce0 100644 --- a/sound/soc/loongson/loongson_i2s_pci.c +++ b/sound/soc/loongson/loongson_i2s_pci.c @@ -75,34 +75,34 @@ static int loongson_i2s_pci_probe(struct pci_dev *pdev, { const struct fwnode_handle *fwnode = pdev->dev.fwnode; struct loongson_dma_data *tx_data, *rx_data; + struct device *dev = &pdev->dev; struct loongson_i2s *i2s; int ret; if (pcim_enable_device(pdev)) { - dev_err(&pdev->dev, "pci_enable_device failed\n"); + dev_err(dev, "pci_enable_device failed\n"); return -ENODEV; } - i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); + i2s = devm_kzalloc(dev, sizeof(*i2s), GFP_KERNEL); if (!i2s) return -ENOMEM; i2s->rev_id = pdev->revision; - i2s->dev = &pdev->dev; + i2s->dev = dev; pci_set_drvdata(pdev, i2s); - ret = pcim_iomap_regions(pdev, 1 << 0, dev_name(&pdev->dev)); + ret = pcim_iomap_regions(pdev, 1 << 0, dev_name(dev)); if (ret < 0) { - dev_err(&pdev->dev, "iomap_regions failed\n"); + dev_err(dev, "iomap_regions failed\n"); return ret; } + i2s->reg_base = pcim_iomap_table(pdev)[0]; - i2s->regmap = devm_regmap_init_mmio(&pdev->dev, i2s->reg_base, + i2s->regmap = devm_regmap_init_mmio(dev, i2s->reg_base, &loongson_i2s_regmap_config); - if (IS_ERR(i2s->regmap)) { - dev_err(&pdev->dev, "regmap_init_mmio failed\n"); - return PTR_ERR(i2s->regmap); - } + if (IS_ERR(i2s->regmap)) + dev_err_probe(dev, PTR_ERR(i2s->regmap), "regmap_init_mmio failed\n"); tx_data = &i2s->tx_dma_data; rx_data = &i2s->rx_dma_data; @@ -114,37 +114,28 @@ static int loongson_i2s_pci_probe(struct pci_dev *pdev, rx_data->order_addr = i2s->reg_base + LS_I2S_RX_ORDER; tx_data->irq = fwnode_irq_get_byname(fwnode, "tx"); - if (tx_data->irq < 0) { - dev_err(&pdev->dev, "dma tx irq invalid\n"); - return tx_data->irq; - } + if (tx_data->irq < 0) + dev_err_probe(dev, tx_data->irq, "dma tx irq invalid\n"); rx_data->irq = fwnode_irq_get_byname(fwnode, "rx"); - if (rx_data->irq < 0) { - dev_err(&pdev->dev, "dma rx irq invalid\n"); - return rx_data->irq; - } + if (rx_data->irq < 0) + dev_err_probe(dev, rx_data->irq, "dma rx irq invalid\n"); - device_property_read_u32(&pdev->dev, "clock-frequency", &i2s->clk_rate); - if (!i2s->clk_rate) { - dev_err(&pdev->dev, "clock-frequency property invalid\n"); - return -EINVAL; - } + ret = device_property_read_u32(dev, "clock-frequency", &i2s->clk_rate); + if (ret) + dev_err_probe(dev, ret, "clock-frequency property invalid\n"); - dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); if (i2s->rev_id == 1) { regmap_write(i2s->regmap, LS_I2S_CTRL, I2S_CTRL_RESET); udelay(200); } - ret = devm_snd_soc_register_component(&pdev->dev, - &loongson_i2s_component, + ret = devm_snd_soc_register_component(dev, &loongson_i2s_component, &loongson_i2s_dai, 1); - if (ret) { - dev_err(&pdev->dev, "register DAI failed %d\n", ret); - return ret; - } + if (ret) + dev_err_probe(dev, ret, "register DAI failed\n"); return 0; } From patchwork Thu Sep 5 07:02:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Binbin Zhou X-Patchwork-Id: 13791799 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id E823A1925B2; Thu, 5 Sep 2024 07:03:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725519795; cv=none; b=LxV1xNJzR/jxyV6MNdKJpNoU8VvcTHXPzybpBTqiKFIBEMhVm5AsHvWSJlWezXW8QytdmAY395BBUsa+WnxqaTizbRBwzeqZ/JP9wOjJZd5pkV5xymTQu3V7SHEEMaBlWKQ/bn+ocodj4jExoxGov6hcVCyMi/kD1JoVtNOclzA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725519795; c=relaxed/simple; bh=QcX2O7XnndxNWIhO8kVlxa928zU/85PG+bWjbsYou3I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dUmEyWHwYUIjvz23+KSgDMOY5izzHDrkz7YcdeIuplhZ8QcR/f+GuzMVIN4qsNh0o+jL2Hp7g6QxHxan2wVCMwWwMcnBgxCrp5fDU0WUv/jaUdFuj5UdLLiqN7HwHhZLsmq80PFbpy/g29L67018RaLuTmZ/T+5+jyplBKNKxt8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn; spf=pass smtp.mailfrom=loongson.cn; arc=none smtp.client-ip=114.242.206.163 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=loongson.cn Received: from loongson.cn (unknown [223.64.68.71]) by gateway (Coremail) with SMTP id _____8AxGuqwV9lmERorAA--.18043S3; Thu, 05 Sep 2024 15:03:12 +0800 (CST) Received: from localhost.localdomain (unknown [223.64.68.71]) by front1 (Coremail) with SMTP id qMiowMBxbNyhV9lmDcMEAA--.21040S4; Thu, 05 Sep 2024 15:03:09 +0800 (CST) From: Binbin Zhou To: Binbin Zhou , Huacai Chen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai Cc: Huacai Chen , devicetree@vger.kernel.org, linux-sound@vger.kernel.org, Xuerui Wang , loongarch@lists.linux.dev, Binbin Zhou Subject: [PATCH v1 06/10] ASoC: loongson: Fix codec detection failure on FDT systems Date: Thu, 5 Sep 2024 15:02:55 +0800 Message-ID: X-Mailer: git-send-email 2.43.5 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: qMiowMBxbNyhV9lmDcMEAA--.21040S4 X-CM-SenderInfo: p2kr3uplqex0o6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBj93XoWxXr17GFyUXw1kZw1UJF15Jrc_yoW5KF4Upr 45uayYkryrJr1xuwnYqrW8Aa4akry8WrsrJay7K3WSk3Z3Z3s8Ww1j9F1UZF4ayFyUA34U XFW8Ka97Ka4UJFXCm3ZEXasCq-sJn29KB7ZKAUJUUUUx529EdanIXcx71UUUUU7KY7ZEXa sCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU 0xBIdaVrnRJUUUBvb4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2 IYs7xG6rWj6s0DM7CIcVAFz4kK6r1Y6r17M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Ar0_tr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Cr0_Gr1UM28EF7xvwVC2z280aVAFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIEc7CjxVAF wI0_Gr1j6F4UJwAaw2AFwI0_JF0_Jw1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqjxCEc2 xF0cIa020Ex4CE44I27wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2Ix0cI8IcVAFwI0_ Wrv_ZF1lYx0Ex4A2jsIE14v26F4j6r4UJwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2 Ij64vIr41lc7CjxVAaw2AFwI0_JF0_Jw1l42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Y z7v_Jr0_Gr1l4IxYO2xFxVAFwI0_JF0_Jw1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x 8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r1q6r43MIIYrxkI7VAKI48JMIIF0xvE 2Ix0cI8IcVAFwI0_Ar0_tr1lIxAIcVC0I7IYx2IY6xkF7I0E14v26F4j6r4UJwCI42IY6x AIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Cr0_Gr1UMIIF0xvEx4A2jsIE c7CjxVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x07jxxhdUUUUU= When the Codec is compiled into a module, we can't use snd_soc_of_get_dlc() to get the codec dai_name, use snd_soc_get_dai_name() instead. Also, for the cpu dailink, its dai_name is already defined as "loongson-i2s", so just get the corresponding of_node attribute here. Signed-off-by: Binbin Zhou --- sound/soc/loongson/loongson_card.c | 89 +++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 26 deletions(-) diff --git a/sound/soc/loongson/loongson_card.c b/sound/soc/loongson/loongson_card.c index a25287efdd5c..d45a3e77cb90 100644 --- a/sound/soc/loongson/loongson_card.c +++ b/sound/soc/loongson/loongson_card.c @@ -119,44 +119,81 @@ static int loongson_card_parse_acpi(struct loongson_card_data *data) return 0; } -static int loongson_card_parse_of(struct loongson_card_data *data) +static int loongson_parse_cpu(struct device *dev, struct device_node **dai_node) { - struct snd_soc_card *card = &data->snd_card; - struct device_node *cpu, *codec; - struct device *dev = card->dev; - int ret, i; + struct device_node *cpu; + int ret = 0; cpu = of_get_child_by_name(dev->of_node, "cpu"); - if (!cpu) { - dev_err(dev, "platform property missing or invalid\n"); + if (!cpu) return -EINVAL; - } + + *dai_node = of_parse_phandle(cpu, "sound-dai", 0); + if (!*dai_node) + ret = -EINVAL; + + of_node_put(cpu); + return ret; +} + +static int loongson_parse_codec(struct device *dev, struct device_node **dai_node, + const char **dai_name) +{ + struct of_phandle_args args; + struct device_node *codec; + int ret = 0; codec = of_get_child_by_name(dev->of_node, "codec"); - if (!codec) { - dev_err(dev, "audio-codec property missing or invalid\n"); + if (!codec) + return -EINVAL; + + ret = of_parse_phandle_with_args(codec, "sound-dai", "#sound-dai-cells", 0, &args); + if (ret) + goto free_codec; + + ret = snd_soc_get_dai_name(&args, dai_name); + if (ret) + goto free_codec; + + *dai_node = of_parse_phandle(codec, "sound-dai", 0); + if (!*dai_node) ret = -EINVAL; - goto free_cpu; + +free_codec: + of_node_put(codec); + return ret; +} + +static int loongson_card_parse_of(struct loongson_card_data *data) +{ + struct device_node *codec_dai_node, *cpu_dai_node; + struct snd_soc_card *card = &data->snd_card; + struct device *dev = card->dev; + const char *codec_dai_name; + int ret = 0, i; + + ret = loongson_parse_cpu(dev, &cpu_dai_node); + if (ret) { + dev_err(dev, "cpu property missing or invalid.\n"); + goto out; + } + + ret = loongson_parse_codec(dev, &codec_dai_node, &codec_dai_name); + if (ret) { + dev_err(dev, "audio-codec property missing or invalid.\n"); + goto out; } for (i = 0; i < card->num_links; i++) { - ret = snd_soc_of_get_dlc(cpu, NULL, loongson_dai_links[i].cpus, 0); - if (ret) { - dev_err(dev, "getting cpu dlc error (%d)\n", ret); - goto free_codec; - } - - ret = snd_soc_of_get_dlc(codec, NULL, loongson_dai_links[i].codecs, 0); - if (ret) { - dev_err(dev, "getting codec dlc error (%d)\n", ret); - goto free_codec; - } + loongson_dai_links[i].platforms->of_node = cpu_dai_node; + loongson_dai_links[i].cpus->of_node = cpu_dai_node; + loongson_dai_links[i].codecs->of_node = codec_dai_node; + loongson_dai_links[i].codecs->dai_name = codec_dai_name; } -free_codec: - of_node_put(codec); -free_cpu: - of_node_put(cpu); +out: + of_node_put(codec_dai_node); + of_node_put(cpu_dai_node); return ret; } From patchwork Thu Sep 5 07:02:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Binbin Zhou X-Patchwork-Id: 13791800 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 1C0B919342F; Thu, 5 Sep 2024 07:03:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725519797; cv=none; b=AjSb98hwrvwIVyrc6lH9tdkIBHXvp5FQx4vFb0wPzCdkJKFwVJHzE88aZnQrcWK9p4i7rHeT/97J4WeK6P0jhWt9/X/ghqO1evP7qilpBCbSJQGPAmpHUUKlZEzWf+B6AGttcVCCwgJYqIgFO9Sb6c83CIp1p/CbUjTqX+ZFosE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725519797; c=relaxed/simple; bh=jpGjkbzJxSCA+HrW5dH8ifnm+jLwmmzP+V0ZX3DJ314=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tkxy7uZrHahsc3EpzC2q044nvaMGKKYj5vy88zzOHUAeS3c0W3KtmOPo7Ll0JsuhECUKBwoQk3WkM+68kIu2x0J3AxvdwNxc+Z3Mvn/FMp1wSqyUJeJmLErAksrm4qh0GkUR+GhxsKO8pO4m+ZIxX0QHkdPyybCjVk3VbSMJf9g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn; spf=pass smtp.mailfrom=loongson.cn; arc=none smtp.client-ip=114.242.206.163 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=loongson.cn Received: from loongson.cn (unknown [223.64.68.71]) by gateway (Coremail) with SMTP id _____8AxipqxV9lmGhorAA--.46594S3; Thu, 05 Sep 2024 15:03:13 +0800 (CST) Received: from localhost.localdomain (unknown [223.64.68.71]) by front1 (Coremail) with SMTP id qMiowMBxbNyhV9lmDcMEAA--.21040S5; Thu, 05 Sep 2024 15:03:12 +0800 (CST) From: Binbin Zhou To: Binbin Zhou , Huacai Chen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai Cc: Huacai Chen , devicetree@vger.kernel.org, linux-sound@vger.kernel.org, Xuerui Wang , loongarch@lists.linux.dev, Binbin Zhou Subject: [PATCH v1 07/10] ASoC: dt-bindings: Add Loongson I2S controller Date: Thu, 5 Sep 2024 15:02:56 +0800 Message-ID: X-Mailer: git-send-email 2.43.5 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: qMiowMBxbNyhV9lmDcMEAA--.21040S5 X-CM-SenderInfo: p2kr3uplqex0o6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBj93XoW7uw13GrW3CFWfCr45Xr1DArc_yoW8CFykpF srCrWUGrW0qF17u39xJFy8Cw1fZ3s5A3W7XFW7Jw12kr9ag3WFqw4akFyUZ3W3Cry2gFW7 uFWfK3y5W3W8GabCm3ZEXasCq-sJn29KB7ZKAUJUUUUx529EdanIXcx71UUUUU7KY7ZEXa sCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU 0xBIdaVrnRJUUUBGb4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2 IYs7xG6rWj6s0DM7CIcVAFz4kK6r1Y6r17M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Ar0_tr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIE14v26r4UJVWxJr1l84ACjcxK6I8E87Iv6xkF7I0E 14v26r4UJVWxJr1ln4kS14v26r126r1DM2AIxVAIcxkEcVAq07x20xvEncxIr21l57IF6x kI12xvs2x26I8E6xACxx1l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v2 6rWY6Fy7McIj6I8E87Iv67AKxVWxJVW8Jr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48Icx kI7VAKI48JMxkF7I0En4kS14v26r126r1DMxAIw28IcxkI7VAKI48JMxC20s026xCaFVCj c4AY6r1j6r4UMxCIbckI1I0E14v26r126r1DMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxV Cjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUtVW8ZwCIc40Y0x0EwIxGrwCI42IY 6xIIjxv20xvE14v26F1j6w1UMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UMIIF0x vE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWxJVW8Jr1lIxAIcVC2z280 aVCY1x0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZFpf9x07jxxhdUUUUU= Add Loongson I2S controller binding with DT schema format using json-schema. Signed-off-by: Binbin Zhou --- .../bindings/sound/loongson,ls2k-i2s.yaml | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/loongson,ls2k-i2s.yaml diff --git a/Documentation/devicetree/bindings/sound/loongson,ls2k-i2s.yaml b/Documentation/devicetree/bindings/sound/loongson,ls2k-i2s.yaml new file mode 100644 index 000000000000..a2e3bbe00dab --- /dev/null +++ b/Documentation/devicetree/bindings/sound/loongson,ls2k-i2s.yaml @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/loongson,ls2k-i2s.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Loongson-2K I2S controller + +maintainers: + - Binbin Zhou + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: loongson,ls2k1000-i2s + + reg: + maxItems: 2 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + dmas: + maxItems: 2 + + dma-names: + items: + - const: tx + - const: rx + + '#sound-dai-cells': + const: 0 + +required: + - compatible + - reg + - interrupts + - clocks + - dmas + - dma-names + - '#sound-dai-cells' + +additionalProperties: false + +examples: + - | + #include + #include + + i2s@1fe2d000 { + compatible = "loongson,ls2k1000-i2s"; + reg = <0x1fe2d000 0x14>, + <0x1fe00438 0x8>; + interrupt-parent = <&liointc0>; + interrupts = <5 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk LOONGSON2_APB_CLK>; + dmas = <&apbdma2 0>, <&apbdma3 0>; + dma-names = "tx", "rx"; + #sound-dai-cells = <0>; + }; +... From patchwork Thu Sep 5 07:07:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Binbin Zhou X-Patchwork-Id: 13791817 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B29A9192B65; Thu, 5 Sep 2024 07:07:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725520055; cv=none; b=DGOlus/AxFaA8CeT7uzq9yS3mo4jdIYGEtvf9HFvRKXt/ukeNHvoZaHy/zM0rg2/AbbR9FGJHuLlajmaI361cfmYu19XYeD5b++QOReNqZkkZ3Vt+smV56Mf1s1Z1iZclaOP6AhX7joupPzjUs9M4yURA/SZExu7Y4ID8k0uHyg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725520055; c=relaxed/simple; bh=k6pGTSoXIAZvbUg772WpwKzLAVHeia6tLs8cfs5heZU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ldfTtnNBypnGQ721iGIRcmNeoCjeLJM2hr4gDPKxU2WxrCA3FbXUmqXfjPNpCXOk+73Cpb9xoC4CFyBRDvLC5fCi3N5+18tEygHFmlLQYFIogX3YOZoETUCyi6D6xC32cjXPGCjl+oZgEsxTk1e3EDyVOCaJb0f3GrfOhEGgdBU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn; spf=pass smtp.mailfrom=loongson.cn; arc=none smtp.client-ip=114.242.206.163 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=loongson.cn Received: from loongson.cn (unknown [223.64.68.71]) by gateway (Coremail) with SMTP id _____8BxXZuyWNlmERsrAA--.57583S3; Thu, 05 Sep 2024 15:07:30 +0800 (CST) Received: from localhost.localdomain (unknown [223.64.68.71]) by front1 (Coremail) with SMTP id qMiowMAxG9yrWNlmcMQEAA--.5106S2; Thu, 05 Sep 2024 15:07:26 +0800 (CST) From: Binbin Zhou To: Binbin Zhou , Huacai Chen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai Cc: Huacai Chen , devicetree@vger.kernel.org, linux-sound@vger.kernel.org, Xuerui Wang , loongarch@lists.linux.dev, Binbin Zhou Subject: [PATCH v1 08/10] ASoC: loongson: Add I2S controller driver as platform device Date: Thu, 5 Sep 2024 15:07:21 +0800 Message-ID: <282dadefdaac7917fd681a6e84a5f0f07d0557bc.1725518229.git.zhoubinbin@loongson.cn> X-Mailer: git-send-email 2.43.5 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: qMiowMAxG9yrWNlmcMQEAA--.5106S2 X-CM-SenderInfo: p2kr3uplqex0o6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBj93XoW3WrW3Cr1UGw4kCw1fJF1fAFc_yoW3tryxpF s3AayfWrWYyr4ayr9xJry8Cr15AryfCasxGFW7G34xAr9rA348uryDtF1FvF4jkFWUWry7 XFWkurWrCFs8GFcCm3ZEXasCq-sJn29KB7ZKAUJUUUU7529EdanIXcx71UUUUU7KY7ZEXa sCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU 0xBIdaVrnRJUUUBCb4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2 IYs7xG6rWj6s0DM7CIcVAFz4kK6r1Y6r17M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Ar0_tr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIE14v26r4UJVWxJr1l84ACjcxK6I8E87Iv6xkF7I0E 14v26r4UJVWxJr1ln4kS14v26r1Y6r17M2AIxVAIcxkEcVAq07x20xvEncxIr21l57IF6x kI12xvs2x26I8E6xACxx1l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v2 6Fy26r45twAv7VC2z280aVAFwI0_Cr0_Gr1UMcvjeVCFs4IE7xkEbVWUJVW8JwACjcxG0x vY0x0EwIxGrwCY1x0262kKe7AKxVWUAVWUtwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE 7xkEbVWUJVW8JwCFI7km07C267AKxVWUXVWUAwC20s026c02F40E14v26r1j6r18MI8I3I 0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw0_GFylIxkGc2Ij64vIr41lIxAI cVC0I7IYx2IY67AKxVW7JVWDJwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJwCI42 IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Cr0_Gr1UMIIF0xvEx4A2 jsIEc7CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuYvjxUI9NVUUUUU The Loongson I2S controller exists not only in PCI form (LS7A bridge chip), but also in platform device form (Loongson-2K1000 SoC). This patch adds support for platform device I2S controller. Signed-off-by: Binbin Zhou --- sound/soc/loongson/Kconfig | 12 +- sound/soc/loongson/Makefile | 3 + sound/soc/loongson/loongson_i2s_plat.c | 186 +++++++++++++++++++++++++ 3 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 sound/soc/loongson/loongson_i2s_plat.c diff --git a/sound/soc/loongson/Kconfig b/sound/soc/loongson/Kconfig index b8d7e2bade24..cd298f8b54cd 100644 --- a/sound/soc/loongson/Kconfig +++ b/sound/soc/loongson/Kconfig @@ -13,10 +13,20 @@ config SND_SOC_LOONGSON_I2S_PCI The controller is found in loongson bridge chips or SoCs, and work as a PCI device. +config SND_SOC_LOONGSON_I2S_PLATFORM + tristate "Loongson I2S controller as platform device" + select SND_SOC_GENERIC_DMAENGINE_PCM + help + Say Y or M if you want to add support for I2S driver for + Loongson I2S controller. + + The controller work as a platform device, found in loongson + SoCs. + config SND_SOC_LOONGSON_CARD tristate "Loongson Sound Card Driver" select SND_SOC_LOONGSON_I2S_PCI - depends on PCI + select SND_SOC_LOONGSON_I2S_PLATFORM help Say Y or M if you want to add support for SoC audio using loongson I2S controller. diff --git a/sound/soc/loongson/Makefile b/sound/soc/loongson/Makefile index 578030ad6563..f396259244a3 100644 --- a/sound/soc/loongson/Makefile +++ b/sound/soc/loongson/Makefile @@ -3,6 +3,9 @@ snd-soc-loongson-i2s-pci-y := loongson_i2s_pci.o loongson_i2s.o loongson_dma.o obj-$(CONFIG_SND_SOC_LOONGSON_I2S_PCI) += snd-soc-loongson-i2s-pci.o +snd-soc-loongson-i2s-plat-y := loongson_i2s_plat.o loongson_i2s.o +obj-$(CONFIG_SND_SOC_LOONGSON_I2S_PLATFORM) += snd-soc-loongson-i2s-plat.o + #Machine Support snd-soc-loongson-card-y := loongson_card.o obj-$(CONFIG_SND_SOC_LOONGSON_CARD) += snd-soc-loongson-card.o diff --git a/sound/soc/loongson/loongson_i2s_plat.c b/sound/soc/loongson/loongson_i2s_plat.c new file mode 100644 index 000000000000..668067753b1c --- /dev/null +++ b/sound/soc/loongson/loongson_i2s_plat.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Loongson I2S controller master mode dirver(platform device) + * + * Copyright (C) 2023-2024 Loongson Technology Corporation Limited + * + * Author: Yingkun Meng + * Binbin Zhou + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "loongson_i2s.h" + +#define LOONGSON_I2S_RX_DMA_OFFSET 21 +#define LOONGSON_I2S_TX_DMA_OFFSET 18 + +#define LOONGSON_DMA0_CONF 0x0 +#define LOONGSON_DMA1_CONF 0x1 +#define LOONGSON_DMA2_CONF 0x2 +#define LOONGSON_DMA3_CONF 0x3 +#define LOONGSON_DMA4_CONF 0x4 + +/* periods_max = PAGE_SIZE / sizeof(struct ls_dma_chan_reg) */ +static const struct snd_pcm_hardware loongson_pcm_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_RESUME | + SNDRV_PCM_INFO_PAUSE, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S20_3LE | + SNDRV_PCM_FMTBIT_S24_LE, + .period_bytes_min = 128, + .period_bytes_max = 128 * 1024, + .periods_min = 1, + .periods_max = 64, + .buffer_bytes_max = 1024 * 1024, +}; + +static const struct snd_dmaengine_pcm_config loongson_dmaengine_pcm_config = { + .pcm_hardware = &loongson_pcm_hardware, + .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, + .prealloc_buffer_size = 128 * 1024, +}; + +static int loongson_pcm_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + if (substream->pcm->device & 1) { + runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED; + runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED; + } + + if (substream->pcm->device & 2) + runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID); + /* + * For mysterious reasons (and despite what the manual says) + * playback samples are lost if the DMA count is not a multiple + * of the DMA burst size. Let's add a rule to enforce that. + */ + snd_pcm_hw_constraint_step(runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128); + snd_pcm_hw_constraint_step(runtime, 0, + SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 128); + snd_pcm_hw_constraint_integer(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + + return 0; +} + +static const struct snd_soc_component_driver loongson_i2s_component_driver = { + .name = LS_I2S_DRVNAME, + .open = loongson_pcm_open, +}; + +static const struct regmap_config loongson_i2s_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x14, + .cache_type = REGCACHE_FLAT, +}; + +static int loongson_i2s_apbdma_config(struct platform_device *pdev) +{ + int val; + void __iomem *regs; + + regs = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + val = readl(regs); + val |= LOONGSON_DMA2_CONF << LOONGSON_I2S_TX_DMA_OFFSET; + val |= LOONGSON_DMA3_CONF << LOONGSON_I2S_RX_DMA_OFFSET; + writel(val, regs); + + return 0; +} + +static int loongson_i2s_plat_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct loongson_i2s *i2s; + struct resource *res; + struct clk *i2s_clk; + int ret; + + i2s = devm_kzalloc(dev, sizeof(*i2s), GFP_KERNEL); + if (!i2s) + return -ENOMEM; + + ret = loongson_i2s_apbdma_config(pdev); + if (ret) + return ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + i2s->reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(i2s->reg_base)) + return dev_err_probe(dev, PTR_ERR(i2s->reg_base), + "devm_ioremap_resource failed\n"); + + i2s->regmap = devm_regmap_init_mmio(dev, i2s->reg_base, + &loongson_i2s_regmap_config); + if (IS_ERR(i2s->regmap)) + return dev_err_probe(dev, PTR_ERR(i2s->regmap), + "devm_regmap_init_mmio failed\n"); + + i2s->playback_dma_data.addr = res->start + LS_I2S_TX_DATA; + i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + i2s->playback_dma_data.maxburst = 4; + + i2s->capture_dma_data.addr = res->start + LS_I2S_RX_DATA; + i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + i2s->capture_dma_data.maxburst = 4; + + i2s_clk = devm_clk_get_enabled(dev, NULL); + if (IS_ERR(i2s_clk)) + return dev_err_probe(dev, PTR_ERR(i2s_clk), "clock property invalid\n"); + i2s->clk_rate = clk_get_rate(i2s_clk); + + dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); + dev_set_name(dev, LS_I2S_DRVNAME); + dev_set_drvdata(dev, i2s); + + ret = devm_snd_soc_register_component(dev, &loongson_i2s_component_driver, + &loongson_i2s_dai, 1); + if (ret) + return dev_err_probe(dev, ret, "failed to register DAI\n"); + + return devm_snd_dmaengine_pcm_register(dev, &loongson_dmaengine_pcm_config, + SND_DMAENGINE_PCM_FLAG_COMPAT); +} + +static const struct of_device_id loongson_i2s_ids[] = { + { .compatible = "loongson,ls2k1000-i2s" }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, loongson_i2s_ids); + +static struct platform_driver loongson_i2s_driver = { + .probe = loongson_i2s_plat_probe, + .driver = { + .name = "loongson-i2s-plat", + .pm = pm_sleep_ptr(&loongson_i2s_pm), + .of_match_table = loongson_i2s_ids, + }, +}; +module_platform_driver(loongson_i2s_driver); + +MODULE_DESCRIPTION("Loongson I2S Master Mode ASoC Driver"); +MODULE_AUTHOR("Loongson Technology Corporation Limited"); +MODULE_LICENSE("GPL"); From patchwork Thu Sep 5 07:07:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Binbin Zhou X-Patchwork-Id: 13791818 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id D55F3192B72; Thu, 5 Sep 2024 07:07:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725520057; cv=none; b=OAK2+hi4jtUQC9IMCz4+gd8N6zVhSg+obVEi9VBp3Po4rL35hrEvWuyaq070NAW4dlAUQo64UafjzSMz0BRPnvQKh1Fk58gst8cVkqUiBMyUV7wnwG66Z5fPnCkbt/U7bizy45NK8IrFME9JVUClLLcrFJ47qiFgnP0UbJkfvUE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725520057; c=relaxed/simple; bh=kvECuzNV2lAaWFEHINyazo7DSpunYfNvVEjFErJoZuA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Sr6zKflSYPJP7EIetMzpybw/LQV/HQxqXt9N8n6k/wdtbC2pd3NtV6lUlP7eKK/rLkSg0AsgruBAmVTU9osMx7sL32c/lz48ZTBDernrgPwFbuNKqbhhoPsRWZ7/E8f+ZB9c6Q9hCQXd8X43QMIgUApnjPNoheld9HyEMwxEbFE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn; spf=pass smtp.mailfrom=loongson.cn; arc=none smtp.client-ip=114.242.206.163 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=loongson.cn Received: from loongson.cn (unknown [223.64.68.71]) by gateway (Coremail) with SMTP id _____8Dxvpu1WNlmGxsrAA--.57056S3; Thu, 05 Sep 2024 15:07:33 +0800 (CST) Received: from localhost.localdomain (unknown [223.64.68.71]) by front1 (Coremail) with SMTP id qMiowMAxG9yrWNlmcMQEAA--.5106S3; Thu, 05 Sep 2024 15:07:31 +0800 (CST) From: Binbin Zhou To: Binbin Zhou , Huacai Chen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai Cc: Huacai Chen , devicetree@vger.kernel.org, linux-sound@vger.kernel.org, Xuerui Wang , loongarch@lists.linux.dev, Binbin Zhou Subject: [PATCH v1 09/10] LoongArch: dts: Add I2S support to Loongson-2K1000 Date: Thu, 5 Sep 2024 15:07:22 +0800 Message-ID: <226f850ad459b44de0d89a7f4a2a4d07ee03b707.1725518229.git.zhoubinbin@loongson.cn> X-Mailer: git-send-email 2.43.5 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: qMiowMAxG9yrWNlmcMQEAA--.5106S3 X-CM-SenderInfo: p2kr3uplqex0o6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBj93XoW7ArWrJryDCF1fJrW7tw4rtFc_yoW8tr43p3 ZFvw4DGrWFqF429as8JFyUJr1rZas5AF97uanxCry7G39Iq3Wjqr48tF93ZF1jgr4fX3y2 qFs5t347CF1qqwcCm3ZEXasCq-sJn29KB7ZKAUJUUUUx529EdanIXcx71UUUUU7KY7ZEXa sCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU 0xBIdaVrnRJUUUBCb4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2 IYs7xG6rWj6s0DM7CIcVAFz4kK6r1Y6r17M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_tr0E3s1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIE14v26r4UJVWxJr1l84ACjcxK6I8E87Iv6xkF7I0E 14v26r4UJVWxJr1ln4kS14v26r126r1DM2AIxVAIcxkEcVAq07x20xvEncxIr21l57IF6x kI12xvs2x26I8E6xACxx1l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v2 6Fy26r45twAv7VC2z280aVAFwI0_Cr0_Gr1UMcvjeVCFs4IE7xkEbVWUJVW8JwACjcxG0x vY0x0EwIxGrwCY1x0262kKe7AKxVWUAVWUtwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE 7xkEbVWUJVW8JwCFI7km07C267AKxVWUAVWUtwC20s026c02F40E14v26r1j6r18MI8I3I 0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw0_GFylIxkGc2Ij64vIr41lIxAI cVC0I7IYx2IY67AKxVW7JVWDJwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJwCI42 IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Cr0_Gr1UMIIF0xvEx4A2 jsIEc7CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuYvjxUxNeODUUUU The module is supported, enable it. Not all Loongson-2K1000 development boards have an i2s interface, here is an example of adding one: sound { compatible = "loongson,ls-audio-card"; model = "Loongson-ASoC"; mclk-fs = <512>; cpu { sound-dai = <&i2s>; }; codec { sound-dai = <&uda1342>; }; }; &apbdma2 { status = "okay"; }; &apbdma3 { status = "okay"; }; &i2c3 { status = "okay"; pinctrl-0 = <&i2c1_pins_default>; pinctrl-names = "default"; #address-cells = <1>; #size-cells = <0>; uda1342: codec@1a { compatible = "nxp,uda1342"; reg = <0x1a>; #sound-dai-cells = <0>; }; }; &i2s { status = "okay"; pinctrl-0 = <&hda_pins_default>; pinctrl-names = "default"; }; Signed-off-by: Binbin Zhou --- arch/loongarch/boot/dts/loongson-2k1000.dtsi | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/arch/loongarch/boot/dts/loongson-2k1000.dtsi b/arch/loongarch/boot/dts/loongson-2k1000.dtsi index 92180140eb56..8dff2aa52417 100644 --- a/arch/loongarch/boot/dts/loongson-2k1000.dtsi +++ b/arch/loongarch/boot/dts/loongson-2k1000.dtsi @@ -266,7 +266,7 @@ dma-controller@1fe00c10 { status = "disabled"; }; - dma-controller@1fe00c20 { + apbdma2: dma-controller@1fe00c20 { compatible = "loongson,ls2k1000-apbdma"; reg = <0x0 0x1fe00c20 0x0 0x8>; interrupt-parent = <&liointc1>; @@ -276,7 +276,7 @@ dma-controller@1fe00c20 { status = "disabled"; }; - dma-controller@1fe00c30 { + apbdma3: dma-controller@1fe00c30 { compatible = "loongson,ls2k1000-apbdma"; reg = <0x0 0x1fe00c30 0x0 0x8>; interrupt-parent = <&liointc1>; @@ -352,6 +352,19 @@ rtc0: rtc@1fe27800 { status = "disabled"; }; + i2s: i2s@1fe2d000 { + compatible = "loongson,ls2k1000-i2s"; + reg = <0 0x1fe2d000 0 0x14>, + <0 0x1fe00438 0 0x8>; + interrupt-parent = <&liointc0>; + interrupts = <5 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk LOONGSON2_APB_CLK>; + dmas = <&apbdma2 0>, <&apbdma3 0>; + dma-names = "tx", "rx"; + #sound-dai-cells = <0>; + status = "disabled"; + }; + spi0: spi@1fff0220 { compatible = "loongson,ls2k1000-spi"; reg = <0x0 0x1fff0220 0x0 0x10>; From patchwork Thu Sep 5 07:07:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Binbin Zhou X-Patchwork-Id: 13791819 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id C376218BC2D; Thu, 5 Sep 2024 07:07:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725520065; cv=none; b=VkvbEYUXsmhov+Nbs+2mpdlTPe1NCso2iQOgy5qjd79nOnS0o74MnRZNwa0sEas0tkx6b2x6Ncapy1Q903I3BBAApchhssbe8JmGrhTmzmZClUhEFt/hPnvUCM84FNLT6qDz+GxpoIK54pgusETsGzUI85SN7J84FaZV3vFJMXw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725520065; c=relaxed/simple; bh=MF3Y0CzgDsFpC7wFl5LNuW07mCgfBqWYRf36whn2acA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SVLZcPrNyn8031Y2IOwsL3xEe60n3G8gs7vXyZRkq2SnUXLBvb891SnwVUjjRNiya+Tzj/8o7DjqKiSM0ldaaRWCaluRjOJETYd4eE8JpBJtrzNMBi3BY6A/1MNuchusgLzUHN20B51hM9o0ENyPGSzxzh8WdB1SRW/XrGc19ys= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn; spf=pass smtp.mailfrom=loongson.cn; arc=none smtp.client-ip=114.242.206.163 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=loongson.cn Received: from loongson.cn (unknown [223.64.68.71]) by gateway (Coremail) with SMTP id _____8DxOJq+WNlmNBsrAA--.45907S3; Thu, 05 Sep 2024 15:07:42 +0800 (CST) Received: from localhost.localdomain (unknown [223.64.68.71]) by front1 (Coremail) with SMTP id qMiowMAx3ty7WNlmfMQEAA--.23872S2; Thu, 05 Sep 2024 15:07:40 +0800 (CST) From: Binbin Zhou To: Binbin Zhou , Huacai Chen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai Cc: Huacai Chen , devicetree@vger.kernel.org, linux-sound@vger.kernel.org, Xuerui Wang , loongarch@lists.linux.dev, Binbin Zhou Subject: [PATCH v1 10/10] LoongArch: dts: Add I2S support to Loongson-2K2000 Date: Thu, 5 Sep 2024 15:07:38 +0800 Message-ID: <2c488201cd704d312bd9586e7bccea0179ad920f.1725518229.git.zhoubinbin@loongson.cn> X-Mailer: git-send-email 2.43.5 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: qMiowMAx3ty7WNlmfMQEAA--.23872S2 X-CM-SenderInfo: p2kr3uplqex0o6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBj93XoW7ArWrJryDCF1fXrWDWr47Jrc_yoW8CFWUpF Zru3yDJr4FqF42ka15JFWUJr1rJF9YkF93W3ZIy3y8Gw4qgw1jvr48tF92vF1xWrZ5X3y2 qrnYkryjka1UJwcCm3ZEXasCq-sJn29KB7ZKAUJUUUUx529EdanIXcx71UUUUU7KY7ZEXa sCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU 0xBIdaVrnRJUUUBCb4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2 IYs7xG6rWj6s0DM7CIcVAFz4kK6r1Y6r17M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_tr0E3s1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIE14v26r4UJVWxJr1l84ACjcxK6I8E87Iv6xkF7I0E 14v26r4UJVWxJr1ln4kS14v26r126r1DM2AIxVAIcxkEcVAq07x20xvEncxIr21l57IF6x kI12xvs2x26I8E6xACxx1l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v2 6Fy26r45twAv7VC2z280aVAFwI0_Cr0_Gr1UMcvjeVCFs4IE7xkEbVWUJVW8JwACjcxG0x vY0x0EwIxGrwCY1x0262kKe7AKxVWUAVWUtwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE 7xkEbVWUJVW8JwCFI7km07C267AKxVWUAVWUtwC20s026c02F40E14v26r1j6r18MI8I3I 0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw0_GFylIxkGc2Ij64vIr41lIxAI cVC0I7IYx2IY67AKxVWDJVCq3wCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJwCI42 IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Cr0_Gr1UMIIF0xvEx4A2 jsIEc7CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuYvjxUxNeODUUUU The module is supported, enable it. Not all Loongson-2K2000 development boards have an i2s interface, here is an example of adding one: sound { compatible = "loongson,ls-audio-card"; model = "Loongson-ASoC"; mclk-fs = <512>; cpu { sound-dai = <&i2s>; }; codec { sound-dai = <&es8323>; }; }; &i2c1 { status = "okay"; #address-cells = <1>; #size-cells = <0>; es8323:es8323@10 { compatible = "everest,es8323"; reg = <0x10>; #sound-dai-cells = <0>; }; }; &i2s { status = "okay"; clock-frequency = <175000000>; #sound-dai-cells = <0>; }; Signed-off-by: Binbin Zhou --- arch/loongarch/boot/dts/loongson-2k2000.dtsi | 22 ++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/arch/loongarch/boot/dts/loongson-2k2000.dtsi b/arch/loongarch/boot/dts/loongson-2k2000.dtsi index 0953c5707825..b4ff55a33e90 100644 --- a/arch/loongarch/boot/dts/loongson-2k2000.dtsi +++ b/arch/loongarch/boot/dts/loongson-2k2000.dtsi @@ -173,6 +173,22 @@ rtc0: rtc@100d0100 { status = "disabled"; }; + i2c@1fe00120 { + compatible = "loongson,ls2k-i2c"; + reg = <0x0 0x1fe00120 0x0 0x8>; + interrupt-parent = <&liointc>; + interrupts = <8 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + i2c@1fe00130 { + compatible = "loongson,ls2k-i2c"; + reg = <0x0 0x1fe00130 0x0 0x8>; + interrupt-parent = <&liointc>; + interrupts = <9 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + uart0: serial@1fe001e0 { compatible = "ns16550a"; reg = <0x0 0x1fe001e0 0x0 0x10>; @@ -243,9 +259,11 @@ display@6,1 { status = "disabled"; }; - hda@7,0 { + i2s@7,0 { reg = <0x3800 0x0 0x0 0x0 0x0>; - interrupts = <58 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <78 IRQ_TYPE_LEVEL_HIGH>, + <79 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tx", "rx"; interrupt-parent = <&pic>; status = "disabled"; };