// SPDX-License-Identifier: GPL-2.0 // // Socionext UniPhier AIO ALSA common driver. // // Copyright (c) 2016-2018 Socionext Inc. #include <linux/bitfield.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/module.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h> #include "aio.h" #include "aio-reg.h" static u64 rb_cnt(u64 wr, u64 rd, u64 len) { … } static u64 rb_cnt_to_end(u64 wr, u64 rd, u64 len) { … } static u64 rb_space(u64 wr, u64 rd, u64 len) { … } static u64 rb_space_to_end(u64 wr, u64 rd, u64 len) { … } u64 aio_rb_cnt(struct uniphier_aio_sub *sub) { … } u64 aio_rbt_cnt_to_end(struct uniphier_aio_sub *sub) { … } u64 aio_rb_space(struct uniphier_aio_sub *sub) { … } u64 aio_rb_space_to_end(struct uniphier_aio_sub *sub) { … } /** * aio_iecout_set_enable - setup IEC output via SoC glue * @chip: the AIO chip pointer * @enable: false to stop the output, true to start * * Set enabled or disabled S/PDIF signal output to out of SoC via AOnIEC pins. * This function need to call at driver startup. * * The regmap of SoC glue is specified by 'socionext,syscon' optional property * of DT. This function has no effect if no property. */ void aio_iecout_set_enable(struct uniphier_aio_chip *chip, bool enable) { … } /** * aio_chip_set_pll - set frequency to audio PLL * @chip: the AIO chip pointer * @pll_id: PLL * @freq: frequency in Hz, 0 is ignored * * Sets frequency of audio PLL. This function can be called anytime, * but it takes time till PLL is locked. * * Return: Zero if successful, otherwise a negative value on error. */ int aio_chip_set_pll(struct uniphier_aio_chip *chip, int pll_id, unsigned int freq) { … } /** * aio_chip_init - initialize AIO whole settings * @chip: the AIO chip pointer * * Sets AIO fixed and whole device settings to AIO. * This function need to call once at driver startup. * * The register area that is changed by this function is shared by all * modules of AIO. But there is not race condition since this function * has always set the same initialize values. */ void aio_chip_init(struct uniphier_aio_chip *chip) { … } /** * aio_init - initialize AIO substream * @sub: the AIO substream pointer * * Sets fixed settings of each AIO substreams. * This function need to call once at substream startup. * * Return: Zero if successful, otherwise a negative value on error. */ int aio_init(struct uniphier_aio_sub *sub) { … } /** * aio_port_reset - reset AIO port block * @sub: the AIO substream pointer * * Resets the digital signal input/output port block of AIO. */ void aio_port_reset(struct uniphier_aio_sub *sub) { … } /** * aio_port_set_ch - set channels of LPCM * @sub: the AIO substream pointer, PCM substream only * * Set suitable slot selecting to input/output port block of AIO. * * This function may return error if non-PCM substream. * * Return: Zero if successful, otherwise a negative value on error. */ static int aio_port_set_ch(struct uniphier_aio_sub *sub) { … } /** * aio_port_set_rate - set sampling rate of LPCM * @sub: the AIO substream pointer, PCM substream only * @rate: Sampling rate in Hz. * * Set suitable I2S format settings to input/output port block of AIO. * Parameter is specified by hw_params(). * * This function may return error if non-PCM substream. * * Return: Zero if successful, otherwise a negative value on error. */ static int aio_port_set_rate(struct uniphier_aio_sub *sub, int rate) { … } /** * aio_port_set_fmt - set format of I2S data * @sub: the AIO substream pointer, PCM substream only * This parameter has no effect if substream is I2S or PCM. * * Set suitable I2S format settings to input/output port block of AIO. * Parameter is specified by set_fmt(). * * This function may return error if non-PCM substream. * * Return: Zero if successful, otherwise a negative value on error. */ static int aio_port_set_fmt(struct uniphier_aio_sub *sub) { … } /** * aio_port_set_clk - set clock and divider of AIO port block * @sub: the AIO substream pointer * * Set suitable PLL clock divider and relational settings to * input/output port block of AIO. Parameters are specified by * set_sysclk() and set_pll(). * * Return: Zero if successful, otherwise a negative value on error. */ static int aio_port_set_clk(struct uniphier_aio_sub *sub) { … } /** * aio_port_set_param - set parameters of AIO port block * @sub: the AIO substream pointer * @pass_through: Zero if sound data is LPCM, otherwise if data is not LPCM. * This parameter has no effect if substream is I2S or PCM. * @params: hardware parameters of ALSA * * Set suitable setting to input/output port block of AIO to process the * specified in params. * * Return: Zero if successful, otherwise a negative value on error. */ int aio_port_set_param(struct uniphier_aio_sub *sub, int pass_through, const struct snd_pcm_hw_params *params) { … } /** * aio_port_set_enable - start or stop of AIO port block * @sub: the AIO substream pointer * @enable: zero to stop the block, otherwise to start * * Start or stop the signal input/output port block of AIO. */ void aio_port_set_enable(struct uniphier_aio_sub *sub, int enable) { … } /** * aio_port_get_volume - get volume of AIO port block * @sub: the AIO substream pointer * * Return: current volume, range is 0x0000 - 0xffff */ int aio_port_get_volume(struct uniphier_aio_sub *sub) { … } /** * aio_port_set_volume - set volume of AIO port block * @sub: the AIO substream pointer * @vol: target volume, range is 0x0000 - 0xffff. * * Change digital volume and perfome fade-out/fade-in effect for specified * output slot of port. Gained PCM value can calculate as the following: * Gained = Original * vol / 0x4000 */ void aio_port_set_volume(struct uniphier_aio_sub *sub, int vol) { … } /** * aio_if_set_param - set parameters of AIO DMA I/F block * @sub: the AIO substream pointer * @pass_through: Zero if sound data is LPCM, otherwise if data is not LPCM. * This parameter has no effect if substream is I2S or PCM. * * Set suitable setting to DMA interface block of AIO to process the * specified in settings. * * Return: Zero if successful, otherwise a negative value on error. */ int aio_if_set_param(struct uniphier_aio_sub *sub, int pass_through) { … } /** * aio_oport_set_stream_type - set parameters of AIO playback port block * @sub: the AIO substream pointer * @pc: Pc type of IEC61937 * * Set special setting to output port block of AIO to output the stream * via S/PDIF. * * Return: Zero if successful, otherwise a negative value on error. */ int aio_oport_set_stream_type(struct uniphier_aio_sub *sub, enum IEC61937_PC pc) { … } /** * aio_src_reset - reset AIO SRC block * @sub: the AIO substream pointer * * Resets the digital signal input/output port with sampling rate converter * block of AIO. * This function has no effect if substream is not supported rate converter. */ void aio_src_reset(struct uniphier_aio_sub *sub) { … } /** * aio_src_set_param - set parameters of AIO SRC block * @sub: the AIO substream pointer * @params: hardware parameters of ALSA * * Set suitable setting to input/output port with sampling rate converter * block of AIO to process the specified in params. * This function has no effect if substream is not supported rate converter. * * Return: Zero if successful, otherwise a negative value on error. */ int aio_src_set_param(struct uniphier_aio_sub *sub, const struct snd_pcm_hw_params *params) { … } int aio_srcif_set_param(struct uniphier_aio_sub *sub) { … } int aio_srcch_set_param(struct uniphier_aio_sub *sub) { … } void aio_srcch_set_enable(struct uniphier_aio_sub *sub, int enable) { … } int aiodma_ch_set_param(struct uniphier_aio_sub *sub) { … } void aiodma_ch_set_enable(struct uniphier_aio_sub *sub, int enable) { … } static u64 aiodma_rb_get_rp(struct uniphier_aio_sub *sub) { … } static void aiodma_rb_set_rp(struct uniphier_aio_sub *sub, u64 pos) { … } static u64 aiodma_rb_get_wp(struct uniphier_aio_sub *sub) { … } static void aiodma_rb_set_wp(struct uniphier_aio_sub *sub, u64 pos) { … } int aiodma_rb_set_threshold(struct uniphier_aio_sub *sub, u64 size, u32 th) { … } int aiodma_rb_set_buffer(struct uniphier_aio_sub *sub, u64 start, u64 end, int period) { … } void aiodma_rb_sync(struct uniphier_aio_sub *sub, u64 start, u64 size, int period) { … } bool aiodma_rb_is_irq(struct uniphier_aio_sub *sub) { … } void aiodma_rb_clear_irq(struct uniphier_aio_sub *sub) { … }