linux/sound/soc
Thomas Gleixner 6dd21ad81b ALSA: hda: Make proper use of timecounter
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>
2021-11-29 17:42:31 +01:00
..
adi ASoC: axi-i2s: Use devm_platform_get_and_ioremap_resource() 2021-06-14 15:01:03 +01:00
amd ASoC: amd: acp: select CONFIG_SND_SOC_ACPI 2021-10-29 14:57:16 +01:00
atmel ASoC: atmel: Convert to new style DAI format definitions 2021-09-16 14:11:30 +01:00
au1x ASoC: au1x: Convert to modern terminology for DAI clocking 2021-09-16 14:11:37 +01:00
bcm ASoC: bcm: Convert to modern clocking terminology 2021-09-27 13:01:09 +01:00
cirrus ARM: SoC drivers for 5.16 2021-11-03 17:00:52 -07:00
codecs TTY / Serial driver update for 5.16-rc1 2021-11-04 09:09:37 -07:00
dwc ASoC: dwc-i2s: Update to modern clocking terminology 2021-09-27 13:01:12 +01:00
fsl Merge branch 'asoc-5.15' into asoc-5.16 2021-10-18 21:15:13 +01:00
generic ASoC: soc-component: add snd_soc_component_is_codec() 2021-10-18 13:56:37 +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 2021-11-29 17:42:31 +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 machine driver with mt6359, rt1011 and rt5682 2021-10-29 16:49:47 +01:00
meson ASoC: meson: axg-tdm-interface: manage formatters in trigger 2021-10-22 13:25:48 +01:00
mxs
pxa ALSA: pxa2xx: Use managed PCM buffer allocation 2021-08-04 08:08:21 +02:00
qcom ASoC: qdsp6: audioreach: Fix clang -Wimplicit-fallthrough 2021-10-28 13:28:18 +01:00
rockchip ASoC: rockchip: i2s_tdm: improve return value handling 2021-10-27 11:31:16 +01:00
samsung ASoC: samsung: add missing "fallthrough;" 2021-09-27 13:00:53 +01:00
sh ASoC: rsnd: Fix an error handling path in 'rsnd_node_count()' 2021-10-29 18:55:25 +01:00
sof ASoC: Updates for v5.16 2021-11-01 16:58:27 +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: spdifrx: Use devm_platform_get_and_ioremap_resource() 2021-06-17 13:47:02 +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: Set default card name for Trimslice 2021-10-25 12:36:17 +01:00
ti TTY / Serial driver update for 5.16-rc1 2021-11-04 09:09:37 -07:00
uniphier ASoC: uniphier: make arrays mul and div static const, makes object smaller 2021-08-19 18:21:23 +01:00
ux500 ASoC: ux500: mop500: Constify static snd_soc_ops 2021-09-29 13:06:38 +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
soc-ac97.c ASoC: soc-ac97: cleanup cppcheck warning 2021-08-16 13:29:36 +01:00
soc-acpi.c ASoC: soc-acpi: add comp_ids field for machine driver matching 2021-10-29 18:55:16 +01:00
soc-card.c
soc-component.c ASoC: soc-component: improve error reporting for register access 2021-10-15 16:10:57 +01:00
soc-compress.c ASoC: compress/component: Use module_get_when_open/put_when_close for cstream 2021-09-20 13:30:18 +01:00
soc-core.c ASoC: core: Remove invalid snd_soc_component_set_jack call 2021-10-29 16:49:40 +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 Merge branch 'asoc-5.15' into asoc-5.16 2021-10-18 21:15:13 +01:00
soc-devres.c
soc-generic-dmaengine-pcm.c ASoC: dmaengine: Introduce module option prealloc_buffer_size_kbytes 2021-09-27 13:01:13 +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: soc-pcm: tidyup soc_pcm_hw_clean() - step2 2021-10-18 13:56:36 +01:00
soc-topology-test.c
soc-topology.c ASoC: topology: Change topology device to card device 2021-10-29 16:49:44 +01:00
soc-utils.c ASoC: Stop dummy from overriding hwparams 2021-10-29 16:49:45 +01:00