History log of /linux-master/sound/soc/rockchip/rockchip_i2s_tdm.c
Revision Date Author Comments
# 9e2ab4b1 05-Mar-2024 Luca Ceresoli <luca.ceresoli@bootlin.com>

ASoC: rockchip: i2s-tdm: Fix inaccurate sampling rates

The sample rates set by the rockchip_i2s_tdm driver in master mode are
inaccurate up to 5% in several cases, due to the driver logic to configure
clocks and a nasty interaction with the Common Clock Framework.

To understand what happens, here is the relevant section of the clock tree
(slightly simplified), along with the names used in the driver:

vpll0 _OR_ vpll1 "mclk_root"
clk_i2s2_8ch_tx_src "mclk_parent"
clk_i2s2_8ch_tx_mux
clk_i2s2_8ch_tx "mclk" or "mclk_tx"

This is what happens when playing back e.g. at 192 kHz using
audio-graph-card (when recording the same applies, only s/tx/rx/):

0. at probe, rockchip_i2s_tdm_set_sysclk() stores the passed frequency in
i2s_tdm->mclk_tx_freq (*) which is 50176000, and that is never modified
afterwards

1. when playback is started, rockchip_i2s_tdm_hw_params() is called and
does the following two calls

2. rockchip_i2s_tdm_calibrate_mclk():

2a. selects mclk_root0 (vpll0) as a parent for mclk_parent
(mclk_tx_src), which is OK because the vpll0 rate is a good for
192000 (and sumbultiple) rates

2b. sets the mclk_root frequency based on ppm calibration computations

2c. sets mclk_tx_src to 49152000 (= 256 * 192000), which is also OK as
it is a multiple of the required bit clock

3. rockchip_i2s_tdm_set_mclk()

3a. calls clk_set_rate() to set the rate of mclk_tx (clk_i2s2_8ch_tx)
to the value of i2s_tdm->mclk_tx_freq (*), i.e. 50176000 which is
not a multiple of the sampling frequency -- this is not OK

3a1. clk_set_rate() reacts by reparenting clk_i2s2_8ch_tx_src to
vpll1 -- this is not OK because the default vpll1 rate can be
divided to get 44.1 kHz and related rates, not 192 kHz

The result is that the driver does a lot of ad-hoc decisions about clocks
and ends up in using the wrong parent at an unoptimal rate.

Step 0 is one part of the problem: unless the card driver calls set_sysclk
at each stream start, whatever rate is set in mclk_tx_freq during boot will
be taken and used until reboot. Moreover the driver does not care if its
value is not a multiple of any audio frequency.

Another part of the problem is that the whole reparenting and clock rate
setting logic is conflicting with the CCF algorithms to achieve largely the
same goal: selecting the best parent and setting the closest clock
rate. And it turns out that only calling once clk_set_rate() on
clk_i2s2_8ch_tx picks the correct vpll and sets the correct rate.

The fix is based on removing the custom logic in the driver to select the
parent and set the various clocks, and just let the Clock Framework do it
all. As a side effect, the set_sysclk() op becomes useless because we now
let the CCF compute the appropriate value for the sampling rate. It also
implies that the whole calibration logic is now dead code and so it is
removed along with the "PCM Clock Compensation in PPM" kcontrol, which has
always been broken anyway. The handling of the 4 optional clocks also
becomes dead code and is removed.

The actual rates have been tested playing 30 seconds of audio at various
sampling rates before and after this change using sox:

time play -r <sample_rate> -n synth 30 sine 950 gain -3

The time reported in the table below is the 'real' value reported by the
'time' command in the above command line.

rate before after
--------- ------ ------
8000 Hz 30.60s 30.63s
11025 Hz 30.45s 30.51s
16000 Hz 30.47s 30.50s
22050 Hz 30.78s 30.41s
32000 Hz 31.02s 30.43s
44100 Hz 30.78s 30.41s
48000 Hz 29.81s 30.45s
88200 Hz 30.78s 30.41s
96000 Hz 29.79s 30.42s
176400 Hz 27.40s 30.41s
192000 Hz 29.79s 30.42s

While the tests are running the clock tree confirms that:

* without the patch, vpll1 is always used and clk_i2s2_8ch_tx always
produces 50176000 Hz, which cannot be divided for most audio rates
except the slowest ones, generating inaccurate rates
* with the patch:
- for 192000 Hz vpll0 is used
- for 176400 Hz vpll1 is used
- clk_i2s2_8ch_tx always produces (256 * <rate>) Hz

Tested on the RK3308 using the internal audio codec.

Fixes: 081068fd6414 ("ASoC: rockchip: add support for i2s-tdm controller")
Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
Link: https://msgid.link/r/20240305-rk3308-audio-codec-v4-1-312acdbe628f@bootlin.com
Signed-off-by: Mark Brown <broonie@kernel.org>


# 04f8c76d 30-Oct-2023 Rob Herring <robh@kernel.org>

ASoC: rockchip: Fix unused rockchip_i2s_tdm_match warning for !CONFIG_OF

Commit 9958d85968ed ("ASoC: Use device_get_match_data()") dropped the
unconditional use of rockchip_i2s_tdm_match resulting in this warning:

sound/soc/rockchip/rockchip_i2s_tdm.c:1315:34: warning: 'rockchip_i2s_tdm_match' defined but not used [-Wunused-const-variable=]

The fix is to drop of_match_ptr() which is not necessary because DT is
always used for this driver.

Fixes: 9958d85968ed ("ASoC: Use device_get_match_data()")
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202310121802.CDAGVdF2-lkp@intel.com/
Signed-off-by: Rob Herring <robh@kernel.org>
Link: https://lore.kernel.org/r/20231030142337.814907-2-robh@kernel.org
Signed-off-by: Mark Brown <broonie@kernel.org>


# 46dd58be 13-Oct-2023 Uwe Kleine-König <u.kleine-koenig@pengutronix.de>

ASoC: rockchip: i2s_tdm: Convert to platform remove callback returning void

The .remove() callback for a platform driver returns an int which makes
many driver authors wrongly assume it's possible to do error handling by
returning an error code. However the value returned is (mostly) ignored
and this typically results in resource leaks. To improve here there is a
quest to make the remove callback return void. In the first step of this
quest all drivers are converted to .remove_new() which already returns
void.

Trivially convert this driver from always returning zero in the remove
callback to the void returning variant.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Link: https://lore.kernel.org/r/20231013221945.1489203-10-u.kleine-koenig@pengutronix.de
Signed-off-by: Mark Brown <broonie@kernel.org>


# 9958d859 06-Oct-2023 Rob Herring <robh@kernel.org>

ASoC: Use device_get_match_data()

Use preferred device_get_match_data() instead of of_match_device() to
get the driver match data. With this, adjust the includes to explicitly
include the correct headers.

Signed-off-by: Rob Herring <robh@kernel.org>
Link: https://lore.kernel.org/r/20231006-dt-asoc-header-cleanups-v3-5-13a4f0f7fee6@kernel.org
Signed-off-by: Mark Brown <broonie@kernel.org>


# bd6af1bc 08-Aug-2023 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

ASoC: rockchip: merge DAI call back functions into ops

ALSA SoC merges DAI call backs into .ops.
This patch merge these into one.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Link: https://lore.kernel.org/r/87r0od9m6i.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>


# 7575bec5 08-Aug-2023 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

ASoC: rockchip: merge DAI call back functions into ops

ALSA SoC merges DAI call backs into .ops.
This patch merge these into one.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Acked-by: Heiko Stuebner <heiko@sntech.de>
Link: https://lore.kernel.org/r/87r0od9m6i.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>


# 67cc2426 30-Jan-2023 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

ASoC: rockchip: use helper function

Current ASoC has many helper function.
This patch use it.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Link: https://lore.kernel.org/r/87pmavea3l.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>


# c619bd42 25-Oct-2022 Nicolas Frattaroli <frattaroli.nicolas@gmail.com>

ASoC: rockchip: i2s_tdm: Add support for RK3588

This adds support for the RK3588 SoC to the I2S/TDM driver.

Signed-off-by: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
Link: https://lore.kernel.org/r/20221025124132.399729-5-frattaroli.nicolas@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>


# d980004e 25-Oct-2022 Nicolas Frattaroli <frattaroli.nicolas@gmail.com>

ASoC: rockchip: i2s_tdm: Make the grf property optional

Only IO Multiplex and two TRCM modes need access to the GRF, so
making it a hard requirement is not a wise idea, as it complicates
support for newer SoCs which do not do these things.

Signed-off-by: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
Link: https://lore.kernel.org/r/20221025124132.399729-3-frattaroli.nicolas@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>


# 8c8a13e8 16-Jun-2022 Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>

ASoC: rockchip: i2s_tdm: use pm_runtime_resume_and_get()

simplify the flow. No functionality change, except that on -EACCESS
the reference count will be decreased.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Cezary Rojewski <cezary.rojewski@intel.com>
Link: https://lore.kernel.org/r/20220616220427.136036-7-pierre-louis.bossart@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>


# d48a7717 23-Jun-2022 Charles Keepax <ckeepax@opensource.cirrus.com>

ASoC: rockchip: Migrate to new style legacy DAI naming flag

Change the legacy DAI naming flag from opting in to the new scheme
(non_legacy_dai_naming), to opting out of it (legacy_dai_naming).
These drivers appear to be on the CPU side of the DAI link and
currently uses the legacy naming, so add the new flag.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Link: https://lore.kernel.org/r/20220623125250.2355471-27-ckeepax@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>


# 059f16bc 19-May-2022 Charles Keepax <ckeepax@opensource.cirrus.com>

ASoC: rockchip: Rename set_fmt_new back to set_fmt

Now the core has been migrated across to the new direct clock
specification we can move the drivers back to the normal set_fmt
callback.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Link: https://lore.kernel.org/r/20220519154318.2153729-46-ckeepax@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>


# 27646d26 19-May-2022 Charles Keepax <ckeepax@opensource.cirrus.com>

ASoC: rockchip: Update to use set_fmt_new callback

As part of updating the core to directly tell drivers if they are clock
provider or consumer update these CPU side drivers to use the new direct
callback.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Tested-by: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
Link: https://lore.kernel.org/r/20220519154318.2153729-19-ckeepax@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>


# 2f45a4e2 18-Mar-2022 Meng Tang <tangmeng@uniontech.com>

ASoC: rockchip: i2s_tdm: Fixup config for SND_SOC_DAIFMT_DSP_A/B

SND_SOC_DAIFMT_DSP_A: PCM delay 1 bit mode, L data MSB after FRM LRC
SND_SOC_DAIFMT_DSP_B: PCM no delay mode, L data MSB during FRM LRC

Fixes: 081068fd64140 (ASoC: rockchip: add support for i2s-tdm controller)

Signed-off-by: Meng Tang <tangmeng@uniontech.com>
Link: https://lore.kernel.org/r/20220318100146.23991-1-tangmeng@uniontech.com
Signed-off-by: Mark Brown <broonie@kernel.org>


# cc5d8ac9 14-Mar-2022 zhangqilong <zhangqilong3@huawei.com>

ASoC: rockchip: Fix PM usage reference of rockchip_i2s_tdm_resume

pm_runtime_get_sync will increment pm usage counter
even it failed. Forgetting to putting operation will
result in reference leak here. We fix it by replacing
it with pm_runtime_resume_and_get to keep usage counter
balanced.

Fixes:081068fd64140 ("ASoC: rockchip: add support for i2s-tdm controller")

Signed-off-by: Zhang Qilong <zhangqilong3@huawei.com>
Link: https://lore.kernel.org/r/20220315025415.2593762-1-zhangqilong3@huawei.com
Signed-off-by: Mark Brown <broonie@kernel.org>


# 53689f7f 25-Nov-2021 Nicolas Frattaroli <frattaroli.nicolas@gmail.com>

ASoC: rockchip: i2s_tdm: Dup static DAI template

Previously, the DAI template was used directly, which lead to
fun bugs such as "why is my channels_max changing?" when one
instantiated more than one i2s_tdm IP block in a device tree.

This change makes it so that we instead duplicate the template
struct, and then use that.

Fixes: 081068fd6414 ("ASoC: rockchip: add support for i2s-tdm controller")
Signed-off-by: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
Link: https://lore.kernel.org/r/20211125084900.417102-1-frattaroli.nicolas@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>


# f9135821 25-Oct-2021 Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>

ASoC: rockchip: i2s_tdm: improve return value handling

cppcheck reports the following warning:

sound/soc/rockchip/rockchip_i2s_tdm.c:599:9: warning: Identical
condition and return expression 'ret', return value is always 0
[identicalConditionAfterEarlyExit]

return ret;
^
sound/soc/rockchip/rockchip_i2s_tdm.c:594:6: note: If condition 'ret'
is true, the function will return/exit
if (ret)
^
sound/soc/rockchip/rockchip_i2s_tdm.c:599:9: note: Returning identical
expression 'ret'

return ret;
^

While the code is not wrong, it's clearer to return 0 directly.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20211025185933.144327-9-pierre-louis.bossart@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>


# 0ea15e98 15-Oct-2021 Nicolas Frattaroli <frattaroli.nicolas@gmail.com>

ASoC: rockchip: i2s-tdm: Fix refcount test

During development of V5 of the i2s-tdm patch series, I replaced
the atomic refcount with a regular integer, as it was only ever
accessed within a spinlock.

Foolishly, I got the semantics of atomic_dec_and_test wrong, which
resulted in a test for 0 actually becoming a test for >0.

The result was that setting the audio frequency broke; switching
from 44100 Hz audio playback to 96000 Hz audio playback would
garble the sound most unpleasantly.

Fix this by checking for --refcount == 0, which is what it should
have been all along.

Fixes: 081068fd6414 ("ASoC: rockchip: add support for i2s-tdm controller")
Signed-off-by: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
Link: https://lore.kernel.org/r/20211015210730.308946-1-frattaroli.nicolas@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>


# d6365d0f 15-Oct-2021 Nicolas Frattaroli <frattaroli.nicolas@gmail.com>

ASoC: rockchip: i2s-tdm: Strip out direct CRU use

In cases where both rx and tx lrck are synced to the same source,
the resets for rx and tx need to be triggered simultaneously,
according to the downstream driver.

As there is no reset API to atomically bulk (de)assert two resets
at once, what the driver did was implement half a reset controller
specific to Rockchip, which tried to write the registers for the
resets within one write ideally or several writes within an irqsave
section.

This of course violates abstractions quite badly. The driver should
not write to the CRU's registers directly.

In practice, for the cases I tested the driver with, which is audio
playback, replacing the synchronised asserts with just individual
ones does not seem to make any difference.

If it turns out that this breaks something in the future, it should
be fixed through the specification and implementation of an atomic
bulk reset API, not with a CRU hack.

Signed-off-by: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Message-Id: <20211016105354.116513-2-frattaroli.nicolas@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>


# cacbce45 08-Oct-2021 Colin Ian King <colin.king@canonical.com>

ASoC: rockchip: i2s-tdm: Fix error handling on i2s_tdm_prepare_enable_mclk failure

In the case where the call to i2s_tdm_prepare_enable_mclk fails the
function returns before the error handling goto is executed. Fix this
by removing the return do perform the intended error handling exit.

Fixes: 081068fd6414 ("ASoC: rockchip: add support for i2s-tdm controller")
Addresses-Coverity: ("Structurally dead code")
Signed-off-by: Colin Ian King <colin.king@canonical.com>
Message-Id: <20211008095430.62680-2-colin.king@canonical.com>
Signed-off-by: Mark Brown <broonie@kernel.org>


# 74daadc7 08-Oct-2021 Colin Ian King <colin.king@canonical.com>

ASoC: rockchip: i2s-tdm: Remove call to rockchip_i2s_ch_to_io

The call to rockchip_i2s_ch_to_io is only useful for its return
value which is not being used. The function call also has no
side effects, the call is effectively useless and can be removed.

Addresses-Coverity: ("Useless call")
Signed-off-by: Colin Ian King <colin.king@canonical.com>
Message-Id: <20211008095430.62680-1-colin.king@canonical.com>
Signed-off-by: Mark Brown <broonie@kernel.org>


# 081068fd 01-Oct-2021 Nicolas Frattaroli <frattaroli.nicolas@gmail.com>

ASoC: rockchip: add support for i2s-tdm controller

This commit adds support for the rockchip i2s-tdm controller,
which enables audio output on the following rockchip SoCs:
- px30
- rk1808
- rk3308
- rk3566
- rk3568
- rv1126

This is a cleaned up version of the downstream vendor kernel's
driver. It can be enabled through the SND_SOC_ROCKCHIP_I2S_TDM
configuration option.

Signed-off-by: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
Link: https://lore.kernel.org/r/20211001171531.178775-2-frattaroli.nicolas@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>