Received: by 2002:a05:6a10:22f:0:0:0:0 with SMTP id 15csp1397309pxk; Thu, 10 Sep 2020 14:23:19 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzCFPQE9Rt6mpETOv5B0zcSEs1SHG705gaBbiZB2qohrDSzf2y/MtW6c1EaG6Est7zMwxut X-Received: by 2002:a17:906:a2d2:: with SMTP id by18mr10776281ejb.37.1599772998963; Thu, 10 Sep 2020 14:23:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1599772998; cv=none; d=google.com; s=arc-20160816; b=R9QcTS9w6MhcZsm8ABm8Oqoss0RFfIirvGSzC+DrzB1K4d4SNxBz6AdnTiV36bx/pd pT+PioI9SCvQH/6ewUnKBXrAVJvbFDr3i1xmumxeWTw5qnUfdmZTtBleAOl8Xy/svWia /+Qc9vZN0LZvIU7lHLDgvefaGksNnI8agYvgZ+EVAmW9boVauDR19hnSpxOGkszFbrTh jgb2uScLZi7QQGEyJiI39I1jCGJZws1JMEiAzuzXxVzgvc9vMNbVxhgHshMi68r+Igz+ pa0Co6/ZSc7caSfiTLROPpHMR3xyCphCAsJf9KeemI6EoG3rEVOZ3Qcit+sPltp8cCTA BrIQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:to:from; bh=od9hv159OdUf3KiFubDUkYEUyZPSJ/geTSXsmisl/i0=; b=jE49ZzDxTZ1w6dQ58oMWxd7XG40JSHj1tXzzO5T+OM9Gzlca73g4vmWpiQxyQGg/V2 cpfA9b3dHac6rUH0dcaJS0kUMlnQ3bl3zce0JOjVBYxB1MqJUwlDzASajC/bjwZc9Ctt R7TLmaQwIMJGXWWrmp5nZfOSp+YQz2Bo/jiXvV6zBsAdyEe8g4l6sYXTiiHQ9vZbLOoO dCpPyYizWe1wEqAYCc7dB9PdUcAmQCG3QsrAw73Z0sYECTQt7GZIJw6ytBePdo01XVtF 6+1xu2VNPOhWNq015Ll3xjGt78aVEOAFSL5T4QfelXiYo0UfCDhsGzwNavHfyO5Ixe6s I46Q== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=nxp.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id r20si4077604ejc.678.2020.09.10.14.22.56; Thu, 10 Sep 2020 14:23:18 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=nxp.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728112AbgIJVWA (ORCPT + 99 others); Thu, 10 Sep 2020 17:22:00 -0400 Received: from inva021.nxp.com ([92.121.34.21]:34786 "EHLO inva021.nxp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731092AbgIJOYG (ORCPT ); Thu, 10 Sep 2020 10:24:06 -0400 Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 784D020182C; Thu, 10 Sep 2020 16:17:04 +0200 (CEST) Received: from invc005.ap-rdc01.nxp.com (invc005.ap-rdc01.nxp.com [165.114.16.14]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 940D0200788; Thu, 10 Sep 2020 16:17:01 +0200 (CEST) Received: from 10.192.242.69 (shlinux2.ap.freescale.net [10.192.224.44]) by invc005.ap-rdc01.nxp.com (Postfix) with ESMTP id E0D26402CA; Thu, 10 Sep 2020 16:16:57 +0200 (CEST) From: Shengjiu Wang To: lgirdwood@gmail.com, broonie@kernel.org, perex@perex.cz, tiwai@suse.com, alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org Subject: [PATCH] ASoC: ak4458: Add DSD support for ak4458 and ak4497 Date: Thu, 10 Sep 2020 22:10:32 +0800 Message-Id: <1599747032-20055-1-git-send-email-shengjiu.wang@nxp.com> X-Mailer: git-send-email 2.7.4 X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org ak4458 can't support DSD512 format, but ak4497 can, so add a new variable in ak4458_drvdata to distinguish these two platform. In hw_params(), calculate bit clock according to different DSD format and configure DSD register. Signed-off-by: Shengjiu Wang --- sound/soc/codecs/ak4458.c | 82 +++++++++++++++++++++++++++++++++++---- sound/soc/codecs/ak4458.h | 5 ++- 2 files changed, 79 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/ak4458.c b/sound/soc/codecs/ak4458.c index 763e6839428f..9054964d5cfa 100644 --- a/sound/soc/codecs/ak4458.c +++ b/sound/soc/codecs/ak4458.c @@ -31,11 +31,13 @@ static const char *ak4458_supply_names[AK4458_NUM_SUPPLIES] = { struct ak4458_drvdata { struct snd_soc_dai_driver *dai_drv; const struct snd_soc_component_driver *comp_drv; + bool dsd512; /* DSD512 is supported or not */ }; /* AK4458 Codec Private Data */ struct ak4458_priv { struct regulator_bulk_data supplies[AK4458_NUM_SUPPLIES]; + const struct ak4458_drvdata *drvdata; struct device *dev; struct regmap *regmap; struct gpio_desc *reset_gpiod; @@ -136,6 +138,10 @@ static const char * const ak4458_ats_select_texts[] = { /* DIF2 bit Audio Interface Format Setting(BICK fs) */ static const char * const ak4458_dif_select_texts[] = {"32fs,48fs", "64fs",}; +/* DSD input pin select */ +static const char * const ak4497_dsd_input_path_select[] = { + "16_17_19pin", "3_4_5pin"}; + static const struct soc_enum ak4458_dac1_dem_enum = SOC_ENUM_SINGLE(AK4458_01_CONTROL2, 1, ARRAY_SIZE(ak4458_dem_select_texts), @@ -175,6 +181,10 @@ static const struct soc_enum ak4458_dif_enum = SOC_ENUM_SINGLE(AK4458_00_CONTROL1, 3, ARRAY_SIZE(ak4458_dif_select_texts), ak4458_dif_select_texts); +static const struct soc_enum ak4497_dsdp_enum = + SOC_ENUM_SINGLE(AK4458_09_DSD2, 2, + ARRAY_SIZE(ak4497_dsd_input_path_select), + ak4497_dsd_input_path_select); static int get_digfil(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -282,6 +292,7 @@ static const struct snd_kcontrol_new ak4497_snd_controls[] = { SOC_ENUM("AK4497 Sound Mode", ak4458_sm_enum), SOC_ENUM("AK4497 Attenuation transition Time Setting", ak4458_ats_enum), + SOC_ENUM("AK4497 DSD Data Input Pin", ak4497_dsdp_enum), }; /* ak4497 dapm widgets */ @@ -325,12 +336,54 @@ static int ak4458_hw_params(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component); int pcm_width = max(params_physical_width(params), ak4458->slot_width); - int nfs1; - u8 format; + u8 format, dsdsel0, dsdsel1; + int nfs1, dsd_bclk; nfs1 = params_rate(params); ak4458->fs = nfs1; + /* calculate bit clock */ + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_DSD_U8: + case SNDRV_PCM_FORMAT_DSD_U16_LE: + case SNDRV_PCM_FORMAT_DSD_U16_BE: + case SNDRV_PCM_FORMAT_DSD_U32_LE: + case SNDRV_PCM_FORMAT_DSD_U32_BE: + dsd_bclk = nfs1 * params_physical_width(params); + switch (dsd_bclk) { + case 2822400: + dsdsel0 = 0; + dsdsel1 = 0; + break; + case 5644800: + dsdsel0 = 1; + dsdsel1 = 0; + break; + case 11289600: + dsdsel0 = 0; + dsdsel1 = 1; + break; + case 22579200: + if (ak4458->drvdata->dsd512) { + dsdsel0 = 1; + dsdsel1 = 1; + } else { + dev_err(dai->dev, "DSD512 not supported.\n"); + return -EINVAL; + } + break; + default: + dev_err(dai->dev, "Unsupported dsd bclk.\n"); + return -EINVAL; + } + + snd_soc_component_update_bits(component, AK4458_06_DSD1, + AK4458_DSDSEL_MASK, dsdsel0); + snd_soc_component_update_bits(component, AK4458_09_DSD2, + AK4458_DSDSEL_MASK, dsdsel1); + break; + } + /* Master Clock Frequency Auto Setting Mode Enable */ snd_soc_component_update_bits(component, AK4458_00_CONTROL1, 0x80, 0x80); @@ -355,6 +408,9 @@ static int ak4458_hw_params(struct snd_pcm_substream *substream, case SND_SOC_DAIFMT_DSP_B: format = AK4458_DIF_32BIT_MSB; break; + case SND_SOC_DAIFMT_PDM: + format = AK4458_DIF_32BIT_MSB; + break; default: return -EINVAL; } @@ -393,6 +449,7 @@ static int ak4458_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) case SND_SOC_DAIFMT_LEFT_J: case SND_SOC_DAIFMT_RIGHT_J: case SND_SOC_DAIFMT_DSP_B: + case SND_SOC_DAIFMT_PDM: ak4458->fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; break; default: @@ -401,6 +458,12 @@ static int ak4458_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) return -EINVAL; } + /* DSD mode */ + snd_soc_component_update_bits(component, AK4458_02_CONTROL3, + AK4458_DP_MASK, + ak4458->fmt == SND_SOC_DAIFMT_PDM ? + AK4458_DP_MASK : 0); + ak4458_rstn_control(component, 0); ak4458_rstn_control(component, 1); @@ -472,7 +535,10 @@ static int ak4458_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, #define AK4458_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ SNDRV_PCM_FMTBIT_S24_LE |\ - SNDRV_PCM_FMTBIT_S32_LE) + SNDRV_PCM_FMTBIT_S32_LE |\ + SNDRV_PCM_FMTBIT_DSD_U8 |\ + SNDRV_PCM_FMTBIT_DSD_U16_LE |\ + SNDRV_PCM_FMTBIT_DSD_U32_LE) static const unsigned int ak4458_rates[] = { 8000, 11025, 16000, 22050, @@ -668,11 +734,13 @@ static const struct regmap_config ak4458_regmap = { static const struct ak4458_drvdata ak4458_drvdata = { .dai_drv = &ak4458_dai, .comp_drv = &soc_codec_dev_ak4458, + .dsd512 = false, }; static const struct ak4458_drvdata ak4497_drvdata = { .dai_drv = &ak4497_dai, .comp_drv = &soc_codec_dev_ak4497, + .dsd512 = true, }; static const struct dev_pm_ops ak4458_pm = { @@ -684,7 +752,6 @@ static const struct dev_pm_ops ak4458_pm = { static int ak4458_i2c_probe(struct i2c_client *i2c) { struct ak4458_priv *ak4458; - const struct ak4458_drvdata *drvdata; int ret, i; ak4458 = devm_kzalloc(&i2c->dev, sizeof(*ak4458), GFP_KERNEL); @@ -698,7 +765,7 @@ static int ak4458_i2c_probe(struct i2c_client *i2c) i2c_set_clientdata(i2c, ak4458); ak4458->dev = &i2c->dev; - drvdata = of_device_get_match_data(&i2c->dev); + ak4458->drvdata = of_device_get_match_data(&i2c->dev); ak4458->reset_gpiod = devm_gpiod_get_optional(ak4458->dev, "reset", GPIOD_OUT_LOW); @@ -720,8 +787,9 @@ static int ak4458_i2c_probe(struct i2c_client *i2c) return ret; } - ret = devm_snd_soc_register_component(ak4458->dev, drvdata->comp_drv, - drvdata->dai_drv, 1); + ret = devm_snd_soc_register_component(ak4458->dev, + ak4458->drvdata->comp_drv, + ak4458->drvdata->dai_drv, 1); if (ret < 0) { dev_err(ak4458->dev, "Failed to register CODEC: %d\n", ret); return ret; diff --git a/sound/soc/codecs/ak4458.h b/sound/soc/codecs/ak4458.h index f906215f7e4e..9548c5d78621 100644 --- a/sound/soc/codecs/ak4458.h +++ b/sound/soc/codecs/ak4458.h @@ -83,4 +83,7 @@ #define AK4458_ATS_SHIFT 6 #define AK4458_ATS_MASK GENMASK(7, 6) -#endif /* _AK4458_H */ +#define AK4458_DSDSEL_MASK (0x1 << 0) +#define AK4458_DP_MASK (0x1 << 7) + +#endif -- 2.27.0