Received: by 2002:a05:6a11:4021:0:0:0:0 with SMTP id ky33csp1797520pxb; Thu, 16 Sep 2021 16:10:34 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxR1NdNqhBl4yw9x0e8aHzGAlPSiserU/EN0018bc70cWBl5me9GNwTYpvAOp7ItR+prPQf X-Received: by 2002:a5d:9e0f:: with SMTP id h15mr5958817ioh.133.1631833834191; Thu, 16 Sep 2021 16:10:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1631833834; cv=none; d=google.com; s=arc-20160816; b=gHXfnEw/KZEmZxXeyxcpVp3BIyCvBSZPYnqrqSllqib2uNBhQWKuBDLMbF5xi4JnNw La0D++8i8q/nn1lcnDv7tl9n4HqsHQNeDrO3NayMSO83NNJgxkWYdv5g3m1XgMUswDTq eUi+TPxsSl3xnmkV3pNpXKwjOftCthfSPMPkjrAg9CmRA/jI3pet4exIVqWjvkLvVqLB 72JYwYpaqJtyzPytZK+98cNDSl1yp0JQ2cwSQ2GAXDYhuwozEguDvn7rRS/rbZYKXcwr vWOryWEmAwP8je2vF3Y18QOM+AG8ZMWlGyT1ih+2hGGf3BQYTdb88EpiRhjneycPlDOU xS0g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=RqO+bDLX9cthk0Wvur17BR2FO8dJ8g+5Z/CRS2Q06DE=; b=eFxaEaEfVmFI6LvdmiwgF+IxmtfA1ra4hktrUl46DDOihWQaWFg/H17dvLbVZWeN64 tut9ksN5H9NL1yA5My/0Fb0GBmpOQR10PesQTOddIgWdsUYBmH6D+xp6p4bHv5+zduvh UZ5yryplpVhxdF6j25+ToG4HObtCO2vehiGkSDeIVcWDs73h+e+Rb6pg3b0zSGkRGQWj FI0fCMPtJHLFk6HIc0B6IvOmwEZBMpXqCUCAxBXYxVc0yIUs2/554Eiz0DwVzyPBFcgE eAvTCWWbD3aGU+f7+SKFU1m2xiWIeshS5Xwd6+FGwZ5jh8P5r0Ect6PerWd+6tJXQg/u rgDg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=RpmKYH44; 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=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id s5si3777541ilv.155.2021.09.16.16.10.22; Thu, 16 Sep 2021 16:10:34 -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; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=RpmKYH44; 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=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S245369AbhIPQsT (ORCPT + 99 others); Thu, 16 Sep 2021 12:48:19 -0400 Received: from mail.kernel.org ([198.145.29.99]:57628 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243152AbhIPQmk (ORCPT ); Thu, 16 Sep 2021 12:42:40 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 8E9B961A40; Thu, 16 Sep 2021 16:24:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1631809496; bh=3H2CGtzj5AyQYxclvlEPAno04RtxxTH9cpkPY2g9dMY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RpmKYH44HBnG0dT+R536zMB/LN72wzyFCMWnJ4lGvyhgiXivJodirFCrdzHsuzJk7 DQc4vHxWbDiYZ5jB2eD6Iyrgt7m1+m0W62TEZJcEd7O0rhgLKTOBU6ePVv1FbpVANn +X8i0qDlQ5u32L9g27MlHZFD1ePKVnb9OtaqJc/M= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Peter Ujfalusi , Mark Brown , Sasha Levin Subject: [PATCH 5.13 144/380] ASoC: ti: davinci-mcasp: Fix DIT mode support Date: Thu, 16 Sep 2021 17:58:21 +0200 Message-Id: <20210916155808.955440935@linuxfoundation.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210916155803.966362085@linuxfoundation.org> References: <20210916155803.966362085@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Peter Ujfalusi [ Upstream commit bbdd3f4dbe81e19b9123bc54e23ed54517615524 ] The DIT mode support has not been tested due to lack of platform where it can be tested. To be able to use the McASP on OMAP4/5 (only supporting DIT mode) we need to have DIT mode working in the McASP driver on a know platform. After hacking around (on BBW, mcasp1.axr1 can be routed out for this) it appeared that DIT mode is broken. This patch fixes it up and 16/24 bit audio works along with passthrough, but I have only tested with DTS example and test files. Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20210705194249.2385-2-peter.ujfalusi@gmail.com Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/ti/davinci-mcasp.c | 150 ++++++++++++++++++++++++++++++----- 1 file changed, 129 insertions(+), 21 deletions(-) diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index b94220306d1a..41d7cb132198 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -83,6 +83,8 @@ struct davinci_mcasp { struct snd_pcm_substream *substreams[2]; unsigned int dai_fmt; + u32 iec958_status; + /* Audio can not be enabled due to missing parameter(s) */ bool missing_audio_param; @@ -757,6 +759,9 @@ static int davinci_mcasp_set_tdm_slot(struct snd_soc_dai *dai, { struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); + if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) + return 0; + dev_dbg(mcasp->dev, "%s() tx_mask 0x%08x rx_mask 0x%08x slots %d width %d\n", __func__, tx_mask, rx_mask, slots, slot_width); @@ -827,6 +832,20 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp, mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXROT(rx_rotate), RXROT(7)); mcasp_set_reg(mcasp, DAVINCI_MCASP_RXMASK_REG, mask); + } else { + /* + * according to the TRM it should be TXROT=0, this one works: + * 16 bit to 23-8 (TXROT=6, rotate 24 bits) + * 24 bit to 23-0 (TXROT=0, rotate 0 bits) + * + * TXROT = 0 only works with 24bit samples + */ + tx_rotate = (sample_width / 4 + 2) & 0x7; + + mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(tx_rotate), + TXROT(7)); + mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(15), + TXSSZ(0x0F)); } mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask); @@ -842,10 +861,16 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, u8 tx_ser = 0; u8 rx_ser = 0; u8 slots = mcasp->tdm_slots; - u8 max_active_serializers = (channels + slots - 1) / slots; - u8 max_rx_serializers, max_tx_serializers; + u8 max_active_serializers, max_rx_serializers, max_tx_serializers; int active_serializers, numevt; u32 reg; + + /* In DIT mode we only allow maximum of one serializers for now */ + if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) + max_active_serializers = 1; + else + max_active_serializers = (channels + slots - 1) / slots; + /* Default configuration */ if (mcasp->version < MCASP_VERSION_3) mcasp_set_bits(mcasp, DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT); @@ -1031,16 +1056,18 @@ static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream, static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp, unsigned int rate) { - u32 cs_value = 0; - u8 *cs_bytes = (u8*) &cs_value; + u8 *cs_bytes = (u8 *)&mcasp->iec958_status; - /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0 - and LSB first */ - mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(6) | TXSSZ(15)); + if (!mcasp->dat_port) + mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSEL); + else + mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSEL); /* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */ mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE | FSXMOD(0x180)); + mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, 0xFFFF); + /* Set the TX tdm : for all the slots */ mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF); @@ -1049,16 +1076,8 @@ static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp, mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS); - /* Only 44100 and 48000 are valid, both have the same setting */ - mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3)); - - /* Enable the DIT */ - mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN); - /* Set S/PDIF channel status bits */ - cs_bytes[0] = IEC958_AES0_CON_NOT_COPYRIGHT; - cs_bytes[1] = IEC958_AES1_CON_PCM_CODER; - + cs_bytes[3] &= ~IEC958_AES3_CON_FS; switch (rate) { case 22050: cs_bytes[3] |= IEC958_AES3_CON_FS_22050; @@ -1088,12 +1107,15 @@ static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp, cs_bytes[3] |= IEC958_AES3_CON_FS_192000; break; default: - printk(KERN_WARNING "unsupported sampling rate: %d\n", rate); + dev_err(mcasp->dev, "unsupported sampling rate: %d\n", rate); return -EINVAL; } - mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRA_REG, cs_value); - mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRB_REG, cs_value); + mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRA_REG, mcasp->iec958_status); + mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRB_REG, mcasp->iec958_status); + + /* Enable the DIT */ + mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN); return 0; } @@ -1237,12 +1259,18 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, int slots = mcasp->tdm_slots; int rate = params_rate(params); int sbits = params_width(params); + unsigned int bclk_target; if (mcasp->slot_width) sbits = mcasp->slot_width; + if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) + bclk_target = rate * sbits * slots; + else + bclk_target = rate * 128; + davinci_mcasp_calc_clk_div(mcasp, mcasp->sysclk_freq, - rate * sbits * slots, true); + bclk_target, true); } ret = mcasp_common_hw_param(mcasp, substream->stream, @@ -1598,6 +1626,77 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { .set_tdm_slot = davinci_mcasp_set_tdm_slot, }; +static int davinci_mcasp_iec958_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; + uinfo->count = 1; + + return 0; +} + +static int davinci_mcasp_iec958_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uctl) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); + + memcpy(uctl->value.iec958.status, &mcasp->iec958_status, + sizeof(mcasp->iec958_status)); + + return 0; +} + +static int davinci_mcasp_iec958_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uctl) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); + + memcpy(&mcasp->iec958_status, uctl->value.iec958.status, + sizeof(mcasp->iec958_status)); + + return 0; +} + +static int davinci_mcasp_iec958_con_mask_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); + + memset(ucontrol->value.iec958.status, 0xff, sizeof(mcasp->iec958_status)); + return 0; +} + +static const struct snd_kcontrol_new davinci_mcasp_iec958_ctls[] = { + { + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_VOLATILE), + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), + .info = davinci_mcasp_iec958_info, + .get = davinci_mcasp_iec958_get, + .put = davinci_mcasp_iec958_put, + }, { + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK), + .info = davinci_mcasp_iec958_info, + .get = davinci_mcasp_iec958_con_mask_get, + }, +}; + +static void davinci_mcasp_init_iec958_status(struct davinci_mcasp *mcasp) +{ + unsigned char *cs = (u8 *)&mcasp->iec958_status; + + cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE; + cs[1] = IEC958_AES1_CON_PCM_CODER; + cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC; + cs[3] = IEC958_AES3_CON_CLOCK_1000PPM; +} + static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai) { struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); @@ -1605,6 +1704,12 @@ static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai) dai->playback_dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; dai->capture_dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE]; + if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) { + davinci_mcasp_init_iec958_status(mcasp); + snd_soc_add_dai_controls(dai, davinci_mcasp_iec958_ctls, + ARRAY_SIZE(davinci_mcasp_iec958_ctls)); + } + return 0; } @@ -1651,7 +1756,8 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { .channels_min = 1, .channels_max = 384, .rates = DAVINCI_MCASP_RATES, - .formats = DAVINCI_MCASP_PCM_FMTS, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE, }, .ops = &davinci_mcasp_dai_ops, }, @@ -1871,6 +1977,8 @@ static int davinci_mcasp_get_config(struct davinci_mcasp *mcasp, } else { mcasp->tdm_slots = pdata->tdm_slots; } + } else { + mcasp->tdm_slots = 32; } mcasp->num_serializer = pdata->num_serializer; -- 2.30.2