summaryrefslogtreecommitdiff
path: root/sound/soc/rockchip/rockchip_i2s_tdm.c
AgeCommit message (Collapse)AuthorFilesLines
2024-06-05ASoC: rockchip: i2s-tdm: Fix trcm mode by setting clock on right mclkAlibek Omarov1-2/+11
When TRCM mode is enabled, I2S RX and TX clocks are synchronized through selected clock source. Without this fix BCLK and LRCK might get parented to an uninitialized MCLK and the DAI will receive data at wrong pace. However, unlike in original i2s-tdm driver, there is no need to manually synchronize mclk_rx and mclk_tx, as only one gets used anyway. Tested on a board with RK3568 SoC and Silergy SY24145S codec with enabled and disabled TRCM mode. Fixes: 9e2ab4b18ebd ("ASoC: rockchip: i2s-tdm: Fix inaccurate sampling rates") Signed-off-by: Alibek Omarov <a1ba.omarov@gmail.com> Reviewed-by: Luca Ceresoli <luca.ceresoli@bootlin.com> Link: https://msgid.link/r/20240604184752.697313-1-a1ba.omarov@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
2024-03-12ASoC: rockchip: i2s-tdm: Fix inaccurate sampling ratesLuca Ceresoli1-346/+6
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>
2023-10-30ASoC: rockchip: Fix unused rockchip_i2s_tdm_match warning for !CONFIG_OFRob Herring1-1/+1
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>
2023-10-23ASoC: rockchip: i2s_tdm: Convert to platform remove callback returning voidUwe Kleine-König1-4/+2
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>
2023-10-09ASoC: Use device_get_match_data()Rob Herring1-16/+8
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>
2023-08-14ASoC: rockchip: merge DAI call back functions into opsKuninori Morimoto1-1/+1
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>
2023-01-31ASoC: rockchip: use helper functionKuninori Morimoto1-2/+2
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>
2022-11-25ASoC: rockchip: i2s_tdm: Add support for RK3588Nicolas Frattaroli1-1/+2
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>
2022-11-25ASoC: rockchip: i2s_tdm: Make the grf property optionalNicolas Frattaroli1-4/+12
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>
2022-06-29ASoC: Refactor non_legacy_dai_naming flagMark Brown1-0/+1
Merge series from Charles Keepax <ckeepax@opensource.cirrus.com>: Historically, the legacy DAI naming scheme was applied to platform drivers and the newer scheme to CODEC drivers. During componentisation the core lost the knowledge of if a driver was a CODEC or platform, they were all now components. To continue to support the legacy naming on older platform drivers a flag was added to the snd_soc_component_driver structure, non_legacy_dai_naming, to indicate to use the new scheme and this was applied to all CODECs as part of the migration. However, a slight issue appears to be developing with respect to this flag being opt in for the non-legacy scheme, which presumably we want to be the primary scheme used. Many codec drivers appear to forget to include this flag: grep -l -r "snd_soc_component_driver" sound/soc/codecs/*.c | xargs grep -L "non_legacy_dai_naming" | wc 48 48 556 Whilst in many cases the configuration of the DAIs themselves will cause the core to apply the new scheme anyway, it would seem more sensible to change the flag to legacy_dai_naming making the new scheme opt out. This patch series migrates across to such a scheme.
2022-06-27ASoC: rockchip: i2s_tdm: use pm_runtime_resume_and_get()Pierre-Louis Bossart1-4/+2
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>
2022-06-27ASoC: rockchip: Migrate to new style legacy DAI naming flagCharles Keepax1-0/+1
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>
2022-06-06ASoC: rockchip: Rename set_fmt_new back to set_fmtCharles Keepax1-1/+1
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>
2022-06-06ASoC: rockchip: Update to use set_fmt_new callbackCharles Keepax1-4/+4
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>
2022-03-23ASoC: rockchip: i2s_tdm: Fixup config for SND_SOC_DAIFMT_DSP_A/BMeng Tang1-5/+5
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>
2022-03-16ASoC: rockchip: Fix PM usage reference of rockchip_i2s_tdm_resumezhangqilong1-1/+1
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>
2021-11-30ASoC: rockchip: i2s_tdm: Dup static DAI templateNicolas Frattaroli1-21/+31
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>
2021-10-27ASoC: rockchip: i2s_tdm: improve return value handlingPierre-Louis Bossart1-1/+1
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>
2021-10-18ASoC: rockchip: i2s-tdm: Fix refcount testNicolas Frattaroli1-1/+1
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>
2021-10-17ASoC: rockchip: i2s-tdm: Strip out direct CRU useNicolas Frattaroli1-105/+21
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>
2021-10-08ASoC: rockchip: i2s-tdm: Fix error handling on i2s_tdm_prepare_enable_mclk ↵Colin Ian King1-2/+2
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>
2021-10-08ASoC: rockchip: i2s-tdm: Remove call to rockchip_i2s_ch_to_ioColin Ian King1-2/+0
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>
2021-10-07ASoC: rockchip: add support for i2s-tdm controllerNicolas Frattaroli1-0/+1848
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>