Loading MAINTAINERS +1 −1 Original line number Diff line number Diff line Loading @@ -16078,7 +16078,7 @@ S: Maintained F: drivers/net/ethernet/ti/netcp* TI PCM3060 ASoC CODEC DRIVER M: Kirill Marinushkin <kmarinushkin@birdec.tech> M: Kirill Marinushkin <kmarinushkin@birdec.com> L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Maintained F: Documentation/devicetree/bindings/sound/pcm3060.txt Loading include/sound/simple_card_utils.h +4 −0 Original line number Diff line number Diff line Loading @@ -141,6 +141,10 @@ inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv, { struct device *dev = simple_priv_to_dev(priv); /* dai might be NULL */ if (!dai) return; if (dai->name) dev_dbg(dev, "%s dai name = %s\n", name, dai->name); Loading include/uapi/sound/sof/fw.h +9 −7 Original line number Diff line number Diff line Loading @@ -13,6 +13,8 @@ #ifndef __INCLUDE_UAPI_SOF_FW_H__ #define __INCLUDE_UAPI_SOF_FW_H__ #include <linux/types.h> #define SND_SOF_FW_SIG_SIZE 4 #define SND_SOF_FW_ABI 1 #define SND_SOF_FW_SIG "Reef" Loading Loading @@ -46,8 +48,8 @@ enum snd_sof_fw_blk_type { struct snd_sof_blk_hdr { enum snd_sof_fw_blk_type type; uint32_t size; /* bytes minus this header */ uint32_t offset; /* offset from base */ __u32 size; /* bytes minus this header */ __u32 offset; /* offset from base */ } __packed; /* Loading @@ -61,8 +63,8 @@ enum snd_sof_fw_mod_type { struct snd_sof_mod_hdr { enum snd_sof_fw_mod_type type; uint32_t size; /* bytes minus this header */ uint32_t num_blocks; /* number of blocks */ __u32 size; /* bytes minus this header */ __u32 num_blocks; /* number of blocks */ } __packed; /* Loading @@ -70,9 +72,9 @@ struct snd_sof_mod_hdr { */ struct snd_sof_fw_header { unsigned char sig[SND_SOF_FW_SIG_SIZE]; /* "Reef" */ uint32_t file_size; /* size of file minus this header */ uint32_t num_modules; /* number of modules */ uint32_t abi; /* version of header format */ __u32 file_size; /* size of file minus this header */ __u32 num_modules; /* number of modules */ __u32 abi; /* version of header format */ } __packed; #endif include/uapi/sound/sof/header.h +8 −6 Original line number Diff line number Diff line Loading @@ -9,6 +9,8 @@ #ifndef __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__ #define __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__ #include <linux/types.h> /* * Header for all non IPC ABI data. * Loading @@ -16,12 +18,12 @@ * Used by any bespoke component data structures or binary blobs. */ struct sof_abi_hdr { uint32_t magic; /**< 'S', 'O', 'F', '\0' */ uint32_t type; /**< component specific type */ uint32_t size; /**< size in bytes of data excl. this struct */ uint32_t abi; /**< SOF ABI version */ uint32_t reserved[4]; /**< reserved for future use */ uint32_t data[0]; /**< Component data - opaque to core */ __u32 magic; /**< 'S', 'O', 'F', '\0' */ __u32 type; /**< component specific type */ __u32 size; /**< size in bytes of data excl. this struct */ __u32 abi; /**< SOF ABI version */ __u32 reserved[4]; /**< reserved for future use */ __u32 data[0]; /**< Component data - opaque to core */ } __packed; #endif sound/soc/codecs/cs42xx8.c +97 −19 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ struct cs42xx8_priv { unsigned long sysclk; u32 tx_channels; struct gpio_desc *gpiod_reset; u32 rate[2]; }; /* -127.5dB to 0dB with step of 0.5dB */ Loading Loading @@ -176,21 +177,27 @@ static const struct snd_soc_dapm_route cs42xx8_adc3_dapm_routes[] = { }; struct cs42xx8_ratios { unsigned int ratio; unsigned char speed; unsigned char mclk; unsigned int mfreq; unsigned int min_mclk; unsigned int max_mclk; unsigned int ratio[3]; }; /* * According to reference mannual, define the cs42xx8_ratio struct * MFreq2 | MFreq1 | MFreq0 | Description | SSM | DSM | QSM | * 0 | 0 | 0 |1.029MHz to 12.8MHz | 256 | 128 | 64 | * 0 | 0 | 1 |1.536MHz to 19.2MHz | 384 | 192 | 96 | * 0 | 1 | 0 |2.048MHz to 25.6MHz | 512 | 256 | 128 | * 0 | 1 | 1 |3.072MHz to 38.4MHz | 768 | 384 | 192 | * 1 | x | x |4.096MHz to 51.2MHz |1024 | 512 | 256 | */ static const struct cs42xx8_ratios cs42xx8_ratios[] = { { 64, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_256(4) }, { 96, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_384(4) }, { 128, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_512(4) }, { 192, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_768(4) }, { 256, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_256(1) }, { 384, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_384(1) }, { 512, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_512(1) }, { 768, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_768(1) }, { 1024, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_1024(1) } { 0, 1029000, 12800000, {256, 128, 64} }, { 2, 1536000, 19200000, {384, 192, 96} }, { 4, 2048000, 25600000, {512, 256, 128} }, { 6, 3072000, 38400000, {768, 384, 192} }, { 8, 4096000, 51200000, {1024, 512, 256} }, }; static int cs42xx8_set_dai_sysclk(struct snd_soc_dai *codec_dai, Loading Loading @@ -257,14 +264,68 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; u32 ratio = cs42xx8->sysclk / params_rate(params); u32 i, fm, val, mask; u32 ratio[2]; u32 rate[2]; u32 fm[2]; u32 i, val, mask; bool condition1, condition2; if (tx) cs42xx8->tx_channels = params_channels(params); rate[tx] = params_rate(params); rate[!tx] = cs42xx8->rate[!tx]; ratio[tx] = rate[tx] > 0 ? cs42xx8->sysclk / rate[tx] : 0; ratio[!tx] = rate[!tx] > 0 ? cs42xx8->sysclk / rate[!tx] : 0; /* Get functional mode for tx and rx according to rate */ for (i = 0; i < 2; i++) { if (cs42xx8->slave_mode) { fm[i] = CS42XX8_FM_AUTO; } else { if (rate[i] < 50000) { fm[i] = CS42XX8_FM_SINGLE; } else if (rate[i] > 50000 && rate[i] < 100000) { fm[i] = CS42XX8_FM_DOUBLE; } else if (rate[i] > 100000 && rate[i] < 200000) { fm[i] = CS42XX8_FM_QUAD; } else { dev_err(component->dev, "unsupported sample rate\n"); return -EINVAL; } } } for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) { if (cs42xx8_ratios[i].ratio == ratio) /* Is the ratio[tx] valid ? */ condition1 = ((fm[tx] == CS42XX8_FM_AUTO) ? (cs42xx8_ratios[i].ratio[0] == ratio[tx] || cs42xx8_ratios[i].ratio[1] == ratio[tx] || cs42xx8_ratios[i].ratio[2] == ratio[tx]) : (cs42xx8_ratios[i].ratio[fm[tx]] == ratio[tx])) && cs42xx8->sysclk >= cs42xx8_ratios[i].min_mclk && cs42xx8->sysclk <= cs42xx8_ratios[i].max_mclk; if (!ratio[tx]) condition1 = true; /* Is the ratio[!tx] valid ? */ condition2 = ((fm[!tx] == CS42XX8_FM_AUTO) ? (cs42xx8_ratios[i].ratio[0] == ratio[!tx] || cs42xx8_ratios[i].ratio[1] == ratio[!tx] || cs42xx8_ratios[i].ratio[2] == ratio[!tx]) : (cs42xx8_ratios[i].ratio[fm[!tx]] == ratio[!tx])); if (!ratio[!tx]) condition2 = true; /* * Both ratio[tx] and ratio[!tx] is valid, then we get * a proper MFreq. */ if (condition1 && condition2) break; } Loading @@ -273,18 +334,34 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } mask = CS42XX8_FUNCMOD_MFREQ_MASK; val = cs42xx8_ratios[i].mclk; cs42xx8->rate[tx] = params_rate(params); fm = cs42xx8->slave_mode ? CS42XX8_FM_AUTO : cs42xx8_ratios[i].speed; mask = CS42XX8_FUNCMOD_MFREQ_MASK; val = cs42xx8_ratios[i].mfreq; regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD, CS42XX8_FUNCMOD_xC_FM_MASK(tx) | mask, CS42XX8_FUNCMOD_xC_FM(tx, fm) | val); CS42XX8_FUNCMOD_xC_FM(tx, fm[tx]) | val); return 0; } static int cs42xx8_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; /* Clear stored rate */ cs42xx8->rate[tx] = 0; regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD, CS42XX8_FUNCMOD_xC_FM_MASK(tx), CS42XX8_FUNCMOD_xC_FM(tx, CS42XX8_FM_AUTO)); return 0; } static int cs42xx8_digital_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_component *component = dai->component; Loading @@ -302,6 +379,7 @@ static const struct snd_soc_dai_ops cs42xx8_dai_ops = { .set_fmt = cs42xx8_set_dai_fmt, .set_sysclk = cs42xx8_set_dai_sysclk, .hw_params = cs42xx8_hw_params, .hw_free = cs42xx8_hw_free, .digital_mute = cs42xx8_digital_mute, }; Loading Loading
MAINTAINERS +1 −1 Original line number Diff line number Diff line Loading @@ -16078,7 +16078,7 @@ S: Maintained F: drivers/net/ethernet/ti/netcp* TI PCM3060 ASoC CODEC DRIVER M: Kirill Marinushkin <kmarinushkin@birdec.tech> M: Kirill Marinushkin <kmarinushkin@birdec.com> L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Maintained F: Documentation/devicetree/bindings/sound/pcm3060.txt Loading
include/sound/simple_card_utils.h +4 −0 Original line number Diff line number Diff line Loading @@ -141,6 +141,10 @@ inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv, { struct device *dev = simple_priv_to_dev(priv); /* dai might be NULL */ if (!dai) return; if (dai->name) dev_dbg(dev, "%s dai name = %s\n", name, dai->name); Loading
include/uapi/sound/sof/fw.h +9 −7 Original line number Diff line number Diff line Loading @@ -13,6 +13,8 @@ #ifndef __INCLUDE_UAPI_SOF_FW_H__ #define __INCLUDE_UAPI_SOF_FW_H__ #include <linux/types.h> #define SND_SOF_FW_SIG_SIZE 4 #define SND_SOF_FW_ABI 1 #define SND_SOF_FW_SIG "Reef" Loading Loading @@ -46,8 +48,8 @@ enum snd_sof_fw_blk_type { struct snd_sof_blk_hdr { enum snd_sof_fw_blk_type type; uint32_t size; /* bytes minus this header */ uint32_t offset; /* offset from base */ __u32 size; /* bytes minus this header */ __u32 offset; /* offset from base */ } __packed; /* Loading @@ -61,8 +63,8 @@ enum snd_sof_fw_mod_type { struct snd_sof_mod_hdr { enum snd_sof_fw_mod_type type; uint32_t size; /* bytes minus this header */ uint32_t num_blocks; /* number of blocks */ __u32 size; /* bytes minus this header */ __u32 num_blocks; /* number of blocks */ } __packed; /* Loading @@ -70,9 +72,9 @@ struct snd_sof_mod_hdr { */ struct snd_sof_fw_header { unsigned char sig[SND_SOF_FW_SIG_SIZE]; /* "Reef" */ uint32_t file_size; /* size of file minus this header */ uint32_t num_modules; /* number of modules */ uint32_t abi; /* version of header format */ __u32 file_size; /* size of file minus this header */ __u32 num_modules; /* number of modules */ __u32 abi; /* version of header format */ } __packed; #endif
include/uapi/sound/sof/header.h +8 −6 Original line number Diff line number Diff line Loading @@ -9,6 +9,8 @@ #ifndef __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__ #define __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__ #include <linux/types.h> /* * Header for all non IPC ABI data. * Loading @@ -16,12 +18,12 @@ * Used by any bespoke component data structures or binary blobs. */ struct sof_abi_hdr { uint32_t magic; /**< 'S', 'O', 'F', '\0' */ uint32_t type; /**< component specific type */ uint32_t size; /**< size in bytes of data excl. this struct */ uint32_t abi; /**< SOF ABI version */ uint32_t reserved[4]; /**< reserved for future use */ uint32_t data[0]; /**< Component data - opaque to core */ __u32 magic; /**< 'S', 'O', 'F', '\0' */ __u32 type; /**< component specific type */ __u32 size; /**< size in bytes of data excl. this struct */ __u32 abi; /**< SOF ABI version */ __u32 reserved[4]; /**< reserved for future use */ __u32 data[0]; /**< Component data - opaque to core */ } __packed; #endif
sound/soc/codecs/cs42xx8.c +97 −19 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ struct cs42xx8_priv { unsigned long sysclk; u32 tx_channels; struct gpio_desc *gpiod_reset; u32 rate[2]; }; /* -127.5dB to 0dB with step of 0.5dB */ Loading Loading @@ -176,21 +177,27 @@ static const struct snd_soc_dapm_route cs42xx8_adc3_dapm_routes[] = { }; struct cs42xx8_ratios { unsigned int ratio; unsigned char speed; unsigned char mclk; unsigned int mfreq; unsigned int min_mclk; unsigned int max_mclk; unsigned int ratio[3]; }; /* * According to reference mannual, define the cs42xx8_ratio struct * MFreq2 | MFreq1 | MFreq0 | Description | SSM | DSM | QSM | * 0 | 0 | 0 |1.029MHz to 12.8MHz | 256 | 128 | 64 | * 0 | 0 | 1 |1.536MHz to 19.2MHz | 384 | 192 | 96 | * 0 | 1 | 0 |2.048MHz to 25.6MHz | 512 | 256 | 128 | * 0 | 1 | 1 |3.072MHz to 38.4MHz | 768 | 384 | 192 | * 1 | x | x |4.096MHz to 51.2MHz |1024 | 512 | 256 | */ static const struct cs42xx8_ratios cs42xx8_ratios[] = { { 64, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_256(4) }, { 96, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_384(4) }, { 128, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_512(4) }, { 192, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_768(4) }, { 256, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_256(1) }, { 384, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_384(1) }, { 512, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_512(1) }, { 768, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_768(1) }, { 1024, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_1024(1) } { 0, 1029000, 12800000, {256, 128, 64} }, { 2, 1536000, 19200000, {384, 192, 96} }, { 4, 2048000, 25600000, {512, 256, 128} }, { 6, 3072000, 38400000, {768, 384, 192} }, { 8, 4096000, 51200000, {1024, 512, 256} }, }; static int cs42xx8_set_dai_sysclk(struct snd_soc_dai *codec_dai, Loading Loading @@ -257,14 +264,68 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; u32 ratio = cs42xx8->sysclk / params_rate(params); u32 i, fm, val, mask; u32 ratio[2]; u32 rate[2]; u32 fm[2]; u32 i, val, mask; bool condition1, condition2; if (tx) cs42xx8->tx_channels = params_channels(params); rate[tx] = params_rate(params); rate[!tx] = cs42xx8->rate[!tx]; ratio[tx] = rate[tx] > 0 ? cs42xx8->sysclk / rate[tx] : 0; ratio[!tx] = rate[!tx] > 0 ? cs42xx8->sysclk / rate[!tx] : 0; /* Get functional mode for tx and rx according to rate */ for (i = 0; i < 2; i++) { if (cs42xx8->slave_mode) { fm[i] = CS42XX8_FM_AUTO; } else { if (rate[i] < 50000) { fm[i] = CS42XX8_FM_SINGLE; } else if (rate[i] > 50000 && rate[i] < 100000) { fm[i] = CS42XX8_FM_DOUBLE; } else if (rate[i] > 100000 && rate[i] < 200000) { fm[i] = CS42XX8_FM_QUAD; } else { dev_err(component->dev, "unsupported sample rate\n"); return -EINVAL; } } } for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) { if (cs42xx8_ratios[i].ratio == ratio) /* Is the ratio[tx] valid ? */ condition1 = ((fm[tx] == CS42XX8_FM_AUTO) ? (cs42xx8_ratios[i].ratio[0] == ratio[tx] || cs42xx8_ratios[i].ratio[1] == ratio[tx] || cs42xx8_ratios[i].ratio[2] == ratio[tx]) : (cs42xx8_ratios[i].ratio[fm[tx]] == ratio[tx])) && cs42xx8->sysclk >= cs42xx8_ratios[i].min_mclk && cs42xx8->sysclk <= cs42xx8_ratios[i].max_mclk; if (!ratio[tx]) condition1 = true; /* Is the ratio[!tx] valid ? */ condition2 = ((fm[!tx] == CS42XX8_FM_AUTO) ? (cs42xx8_ratios[i].ratio[0] == ratio[!tx] || cs42xx8_ratios[i].ratio[1] == ratio[!tx] || cs42xx8_ratios[i].ratio[2] == ratio[!tx]) : (cs42xx8_ratios[i].ratio[fm[!tx]] == ratio[!tx])); if (!ratio[!tx]) condition2 = true; /* * Both ratio[tx] and ratio[!tx] is valid, then we get * a proper MFreq. */ if (condition1 && condition2) break; } Loading @@ -273,18 +334,34 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } mask = CS42XX8_FUNCMOD_MFREQ_MASK; val = cs42xx8_ratios[i].mclk; cs42xx8->rate[tx] = params_rate(params); fm = cs42xx8->slave_mode ? CS42XX8_FM_AUTO : cs42xx8_ratios[i].speed; mask = CS42XX8_FUNCMOD_MFREQ_MASK; val = cs42xx8_ratios[i].mfreq; regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD, CS42XX8_FUNCMOD_xC_FM_MASK(tx) | mask, CS42XX8_FUNCMOD_xC_FM(tx, fm) | val); CS42XX8_FUNCMOD_xC_FM(tx, fm[tx]) | val); return 0; } static int cs42xx8_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; /* Clear stored rate */ cs42xx8->rate[tx] = 0; regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD, CS42XX8_FUNCMOD_xC_FM_MASK(tx), CS42XX8_FUNCMOD_xC_FM(tx, CS42XX8_FM_AUTO)); return 0; } static int cs42xx8_digital_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_component *component = dai->component; Loading @@ -302,6 +379,7 @@ static const struct snd_soc_dai_ops cs42xx8_dai_ops = { .set_fmt = cs42xx8_set_dai_fmt, .set_sysclk = cs42xx8_set_dai_sysclk, .hw_params = cs42xx8_hw_params, .hw_free = cs42xx8_hw_free, .digital_mute = cs42xx8_digital_mute, }; Loading