linux/sound/soc
Thomas Gleixner 9de9858d7b ALSA: hda: Make proper use of timecounter
[ Upstream commit 6dd21ad81b ]

HDA uses a timecounter to read a hardware clock running at 24 MHz. The
conversion factor is set with a mult value of 125 and a shift value of 0,
which is not converting the hardware clock to nanoseconds, it is converting
to 1/3 nanoseconds because the conversion factor from 24Mhz to nanoseconds
is 125/3. The usage sites divide the "nanoseconds" value returned by
timecounter_read() by 3 to get a real nanoseconds value.

There is a lengthy comment in azx_timecounter_init() explaining this
choice. That comment makes blatantly wrong assumptions about how
timecounters work and what can overflow.

The comment says:

     * Applying the 1/3 factor as part of the multiplication
     * requires at least 20 bits for a decent precision, however
     * overflows occur after about 4 hours or less, not a option.

timecounters operate on time deltas between two readouts of a clock and use
the mult/shift pair to calculate a precise nanoseconds value:

    delta_nsec = (delta_clock * mult) >> shift;

The fractional part is also taken into account and preserved to prevent
accumulated rounding errors. For details see cyclecounter_cyc2ns().

The mult/shift pair has to be chosen so that the multiplication of the
maximum expected delta value does not result in a 64bit overflow. As the
counter wraps around on 32bit, the maximum observable delta between two
reads is (1 << 32) - 1 which is about 178.9 seconds.

That in turn means the maximum multiplication factor which fits into an u32
will not cause a 64bit overflow ever because it's guaranteed that:

     ((1 << 32) - 1) ^ 2 < (1 << 64)

The resulting correct multiplication factor is 2796202667 and the shift
value is 26, i.e. 26 bit precision. The overflow of the multiplication
would happen exactly at a clock readout delta of 6597069765 which is way
after the wrap around of the hardware clock at around 274.8 seconds which
is off from the claimed 4 hours by more than an order of magnitude.

If the counter ever wraps around the last read value then the calculation
is off by the number of wrap arounds times 178.9 seconds because the
overflow cannot be observed.

Use clocks_calc_mult_shift(), which calculates the most accurate mult/shift
pair based on the given clock frequency, and remove the bogus comment along
with the divisions at the readout sites.

Fixes: 5d890f591d ("ALSA: hda: support for wallclock timestamps")
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/871r35kwji.ffs@tglx
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2022-01-27 11:04:07 +01:00
..
adi ASoC: axi-i2s: Use devm_platform_get_and_ioremap_resource() 2021-06-14 15:01:03 +01:00
amd Merge some cs42l42 patches into asoc-5.15 2021-08-06 01:46:24 +01:00
atmel ASoC: atmel: ATMEL drivers don't need HAS_DMA 2021-07-11 23:48:35 +01:00
au1x
bcm ASoC: Updates for v5.15 2021-08-30 14:57:03 +02:00
cirrus
codecs ASoC: codecs: wcd938x: add SND_SOC_WCD938_SDW to codec list instead 2022-01-27 11:04:07 +01:00
dwc ASoC: dwc: Get IRQ optionally 2021-08-26 12:07:23 +01:00
fsl ASoC: Fixes for v5.15 2021-10-15 17:43:46 +02:00
generic ASoC: audio-graph: respawn Platform Support 2021-09-01 16:26:35 +01:00
hisilicon ASoC: hisilicon: Use devm_platform_get_and_ioremap_resource() 2021-06-15 16:39:49 +01:00
img ASoC: img-spdif-out: Use devm_platform_get_and_ioremap_resource() 2021-06-15 16:39:47 +01:00
intel ALSA: hda: Make proper use of timecounter 2022-01-27 11:04:07 +01:00
jz4740 ASoC: jz4740-i2s: Use devm_platform_get_and_ioremap_resource() 2021-06-15 16:39:48 +01:00
kirkwood ASoC: kirkwood: Fix reference to PCM buffer address 2021-07-30 17:20:51 +01:00
mediatek ASoC: mediatek: mt8195: Add missing of_node_put() 2021-11-25 09:48:24 +01:00
meson ASoC: meson: aiu: Move AIU_I2S_MISC hold setting to aiu-fifo-i2s 2021-12-29 12:28:52 +01:00
mxs ASoC: mxs-saif: drop unneeded snd_soc_dai_set_drvdata 2021-03-10 13:07:06 +00:00
pxa ALSA: pxa2xx: Use managed PCM buffer allocation 2021-08-04 08:08:21 +02:00
qcom ASoC: qdsp6: q6routing: Fix return value from msm_routing_put_audio_mixer 2021-12-14 10:57:16 +01:00
rockchip ASoC: rockchip: i2s: Fix concurrency between tx/rx 2021-09-03 16:19:01 +01:00
samsung ASoC: samsung: s3c24xx_simtec: fix spelling mistake "devicec" -> "device" 2021-09-01 16:46:48 +01:00
sh ASoC: rsnd: fixup DMAEngine API 2021-11-25 09:49:07 +01:00
sof ASoC: SOF: Intel: pci-tgl: add ADL-N support 2021-12-29 12:29:01 +01:00
spear ASoC: spear: spdif_out: Use devm_platform_get_and_ioremap_resource() 2021-06-17 13:47:06 +01:00
sprd ASoC: sprd: Use managed buffer allocation 2021-08-04 08:10:27 +02:00
sti ASoC: sti: sti_uniperif: Use devm_platform_get_and_ioremap_resource() 2021-06-17 13:47:03 +01:00
stm ASoC: stm32: i2s: fix 32 bits channel length without mclk 2021-12-01 09:04:47 +01:00
sunxi ASoC: sunxi: sun4i-spdif: Use devm_platform_get_and_ioremap_resource() 2021-06-21 13:04:18 +01:00
tegra ASoC: tegra: Restore headphones jack name on Nyan Big 2021-12-29 12:28:52 +01:00
ti Merge some cs42l42 patches into asoc-5.15 2021-08-06 01:46:24 +01:00
uniphier ASoC: uniphier: drop selecting non-existing SND_SOC_UNIPHIER_AIO_DMA 2022-01-27 11:04:06 +01:00
ux500 ASoC: ux500: mop500: align function prototype 2021-03-31 18:03:28 +01:00
xilinx ASoC: xilinx: Fix reference to PCM buffer address 2021-07-30 17:20:50 +01:00
xtensa
Kconfig ASoC: topology: Select SND_DYNAMIC_MINORS 2021-07-27 13:13:04 +01:00
Makefile ASoC: topology: adhere to KUNIT formatting standard 2021-04-14 15:26:24 +01:00
soc-ac97.c ASoC: soc-ac97: cleanup cppcheck warning 2021-08-16 13:29:36 +01:00
soc-acpi.c ASoC: soc-acpi: remove useless initialization 2021-04-19 14:03:29 +01:00
soc-card.c
soc-component.c ASoC: soc-component: cleanup cppcheck warning at snd_soc_pcm_component_pm_runtime_get() 2021-08-16 13:29:35 +01:00
soc-compress.c ALSA: compress: Initialize mutex in snd_compress_new() 2021-07-15 10:22:38 +02:00
soc-core.c ASoC: soc-core: fix null-ptr-deref in snd_soc_del_component_unlocked() 2021-10-11 13:19:14 +01:00
soc-dai.c ASoC: soc-dai: cleanup cppcheck warning at snd_soc_pcm_dai_new() 2021-08-16 13:29:32 +01:00
soc-dapm.c ASoC: DAPM: Cover regression by kctl change notification fix 2021-11-25 09:49:07 +01:00
soc-devres.c
soc-generic-dmaengine-pcm.c ASoC: soc-generic-dmaengine-pcm: cleanup cppcheck warning at dmaengine_copy_user() 2021-08-16 13:29:30 +01:00
soc-jack.c ASoC: soc-jack: cleanup cppcheck warning for CONFIG_GPIOLIB 2021-08-16 13:29:34 +01:00
soc-link.c
soc-ops.c ASoC: soc-ops: cleanup cppcheck warning at snd_soc_put_xr_sx() 2021-08-03 18:27:14 +01:00
soc-pcm.c ASoC: Revert PCM trigger changes 2021-08-30 12:15:15 +01:00
soc-topology-test.c
soc-topology.c ASoC: topology: Add missing rwsem around snd_ctl_remove() calls 2021-12-01 09:04:46 +01:00
soc-utils.c ASoC: soc-core: add snd_soc_runtime_get_dai_fmt() 2021-06-07 15:55:12 +01:00