From 8bcfcb3bd3e38b8f3bb7e5eb3acb4120500994a0 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 29 Jul 2025 15:06:32 +0200 Subject: ASoC: Intel: avs: Parse conditional path tuples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Conditional paths need information about their source and sink paths to be created which is then stored to keep track of who their parents are. That information allows to change their state accordingly to what is currently happening to their parent paths. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250729130633.310388-2-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- include/uapi/sound/intel/avs/tokens.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'include') diff --git a/include/uapi/sound/intel/avs/tokens.h b/include/uapi/sound/intel/avs/tokens.h index c9f845b3c523..f3ff6aae09a9 100644 --- a/include/uapi/sound/intel/avs/tokens.h +++ b/include/uapi/sound/intel/avs/tokens.h @@ -133,6 +133,21 @@ enum avs_tplg_token { AVS_TKN_PATH_FE_FMT_ID_U32 = 1902, AVS_TKN_PATH_BE_FMT_ID_U32 = 1903, + /* struct avs_tplg_path_template (conditional) */ + AVS_TKN_CONDPATH_TMPL_ID_U32 = 1801, + AVS_TKN_CONDPATH_TMPL_SOURCE_TPLG_NAME_STRING = 2002, + AVS_TKN_CONDPATH_TMPL_SOURCE_PATH_TMPL_ID_U32 = 2003, + AVS_TKN_CONDPATH_TMPL_SINK_TPLG_NAME_STRING = 2004, + AVS_TKN_CONDPATH_TMPL_SINK_PATH_TMPL_ID_U32 = 2005, + AVS_TKN_CONDPATH_TMPL_COND_TYPE_U32 = 2006, + AVS_TKN_CONDPATH_TMPL_OVERRIDABLE_BOOL = 2007, + AVS_TKN_CONDPATH_TMPL_PRIORITY_U8 = 2008, + + /* struct avs_tplg_path (conditional) */ + AVS_TKN_CONDPATH_ID_U32 = 1901, + AVS_TKN_CONDPATH_SOURCE_PATH_ID_U32 = 2102, + AVS_TKN_CONDPATH_SINK_PATH_ID_U32 = 2103, + /* struct avs_tplg_pin_format */ AVS_TKN_PIN_FMT_INDEX_U32 = 2201, AVS_TKN_PIN_FMT_IOBS_U32 = 2202, -- cgit v1.2.3 From 40229ea9fa437d6a1feb86be9dd419e843ec754c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 6 Aug 2025 04:41:41 +0000 Subject: ASoC: soc-dapm: move snd_soc_dapm_get_bias_level() to soc-dpcm Because struct snd_soc_dapm_context is soc-dapm framework specific, user driver don't need to access its member directly, we would like to hide them. struct snd_soc_dapm_context will be removed from header in the future. Because dapm will not be used on user driver in the future, Let's move snd_soc_dapm_get_bias_level() to soc-dpcm.c Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/874iul83ju.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 13 +------------ sound/soc/soc-dapm.c | 12 ++++++++++++ 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 0b5c7e6a90c8..f1318cdcf7e4 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -722,6 +722,7 @@ struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm(struct snd_kcontrol *kco struct snd_soc_dapm_widget *snd_soc_dapm_kcontrol_widget(struct snd_kcontrol *kcontrol); int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level); +enum snd_soc_bias_level snd_soc_dapm_get_bias_level(struct snd_soc_dapm_context *dapm); #define for_each_dapm_widgets(list, i, widget) \ for ((i) = 0; \ @@ -747,18 +748,6 @@ static inline void snd_soc_dapm_init_bias_level( dapm->bias_level = level; } -/** - * snd_soc_dapm_get_bias_level() - Get current DAPM bias level - * @dapm: The context for which to get the bias level - * - * Returns: The current bias level of the passed DAPM context. - */ -static inline enum snd_soc_bias_level snd_soc_dapm_get_bias_level( - struct snd_soc_dapm_context *dapm) -{ - return dapm->bias_level; -} - /** * snd_soc_dapm_widget_for_each_path - Iterates over all paths in the * specified direction of a widget diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index a37d44cd04c6..6ee03cf16171 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1037,6 +1037,18 @@ out: return ret; } +/** + * snd_soc_dapm_get_bias_level() - Get current DAPM bias level + * @dapm: The context for which to get the bias level + * + * Returns: The current bias level of the passed DAPM context. + */ +enum snd_soc_bias_level snd_soc_dapm_get_bias_level(struct snd_soc_dapm_context *dapm) +{ + return dapm->bias_level; +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_get_bias_level); + static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm, struct snd_soc_dapm_widget *kcontrolw, const struct snd_kcontrol_new *kcontrol_new, -- cgit v1.2.3 From e93703687cd75a0c7d330e15a3d9ff20b12f3d1d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 6 Aug 2025 04:41:46 +0000 Subject: ASoC: soc-dapm: move snd_soc_dapm_init_bias_level() to soc-dpcm Because struct snd_soc_dapm_context is soc-dapm framework specific, user driver don't need to access its member directly, we would like to hide them. struct snd_soc_dapm_context will be removed from header in the future. Because dapm will not be used on user driver in the future, Let's move snd_soc_dapm_init_bias_level() to soc-dpcm.c Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/8734a583jp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 20 +------------------- sound/soc/soc-dapm.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index f1318cdcf7e4..53bf6590bd4b 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -723,31 +723,13 @@ struct snd_soc_dapm_widget *snd_soc_dapm_kcontrol_widget(struct snd_kcontrol *kc int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level); enum snd_soc_bias_level snd_soc_dapm_get_bias_level(struct snd_soc_dapm_context *dapm); +void snd_soc_dapm_init_bias_level(struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level); #define for_each_dapm_widgets(list, i, widget) \ for ((i) = 0; \ (i) < list->num_widgets && (widget = list->widgets[i]); \ (i)++) -/** - * snd_soc_dapm_init_bias_level() - Initialize DAPM bias level - * @dapm: The DAPM context to initialize - * @level: The DAPM level to initialize to - * - * This function only sets the driver internal state of the DAPM level and will - * not modify the state of the device. Hence it should not be used during normal - * operation, but only to synchronize the internal state to the device state. - * E.g. during driver probe to set the DAPM level to the one corresponding with - * the power-on reset state of the device. - * - * To change the DAPM state of the device use snd_soc_dapm_set_bias_level(). - */ -static inline void snd_soc_dapm_init_bias_level( - struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level) -{ - dapm->bias_level = level; -} - /** * snd_soc_dapm_widget_for_each_path - Iterates over all paths in the * specified direction of a widget diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 6ee03cf16171..6782a0d6cd47 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -999,6 +999,25 @@ int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm, } EXPORT_SYMBOL_GPL(snd_soc_dapm_force_bias_level); +/** + * snd_soc_dapm_init_bias_level() - Initialize DAPM bias level + * @dapm: The DAPM context to initialize + * @level: The DAPM level to initialize to + * + * This function only sets the driver internal state of the DAPM level and will + * not modify the state of the device. Hence it should not be used during normal + * operation, but only to synchronize the internal state to the device state. + * E.g. during driver probe to set the DAPM level to the one corresponding with + * the power-on reset state of the device. + * + * To change the DAPM state of the device use snd_soc_dapm_set_bias_level(). + */ +void snd_soc_dapm_init_bias_level(struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level) +{ + dapm->bias_level = level; +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_init_bias_level); + /** * snd_soc_dapm_set_bias_level - set the bias level for the system * @dapm: DAPM context -- cgit v1.2.3 From 7b900b5878a910d60ecfa67448bbe81e4e2bb8b7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 6 Aug 2025 04:41:51 +0000 Subject: ASoC: soc-component: unpack snd_soc_component_force_bias_level() Because struct snd_soc_dapm_context is soc-dapm framework specific, user driver don't need to access its member directly, we would like to hide them. struct snd_soc_dapm_context will be removed from header in the future. This patch unpack component wrapper to cleanup it. The function will be kept by using macro for a while, but will be replaced/cleanuped in the future. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/871ppp83jk.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 17 ----------------- include/sound/soc-dapm.h | 3 +++ 2 files changed, 3 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 2caa807c6249..c616f489c237 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -314,23 +314,6 @@ snd_soc_component_get_bias_level(struct snd_soc_component *component) snd_soc_component_get_dapm(component)); } -/** - * snd_soc_component_force_bias_level() - Set the COMPONENT DAPM bias level - * @component: The COMPONENT for which to set the level - * @level: The level to set to - * - * Forces the COMPONENT bias level to a specific state. See - * snd_soc_dapm_force_bias_level(). - */ -static inline int -snd_soc_component_force_bias_level(struct snd_soc_component *component, - enum snd_soc_bias_level level) -{ - return snd_soc_dapm_force_bias_level( - snd_soc_component_get_dapm(component), - level); -} - /** * snd_soc_dapm_kcontrol_component() - Returns the component associated to a * kcontrol diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 53bf6590bd4b..5bd9a27b12ba 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -725,6 +725,9 @@ int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm, enum snd_so enum snd_soc_bias_level snd_soc_dapm_get_bias_level(struct snd_soc_dapm_context *dapm); void snd_soc_dapm_init_bias_level(struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level); +// REMOVE ME !! +#define snd_soc_component_force_bias_level(c, l) snd_soc_dapm_force_bias_level(&(c)->dapm, l) + #define for_each_dapm_widgets(list, i, widget) \ for ((i) = 0; \ (i) < list->num_widgets && (widget = list->widgets[i]); \ -- cgit v1.2.3 From 7509e7e4288976e3028a6e8482d979ca77f584a7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 6 Aug 2025 04:41:55 +0000 Subject: ASoC: soc-component: unpack snd_soc_component_get_bias_level() Because struct snd_soc_dapm_context is soc-dapm framework specific, user driver don't need to access its member directly, we would like to hide them. struct snd_soc_dapm_context will be removed from header in the future. This patch unpack component wrapper to cleanup it. The function will be kept by using macro for a while, but will be replaced/cleanuped in the future. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87zfcd6oz0.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 13 ------------- include/sound/soc-dapm.h | 1 + 2 files changed, 1 insertion(+), 13 deletions(-) (limited to 'include') diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index c616f489c237..86ad2802879f 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -301,19 +301,6 @@ snd_soc_component_init_bias_level(struct snd_soc_component *component, snd_soc_component_get_dapm(component), level); } -/** - * snd_soc_component_get_bias_level() - Get current COMPONENT DAPM bias level - * @component: The COMPONENT for which to get the DAPM bias level - * - * Returns: The current DAPM bias level of the COMPONENT. - */ -static inline enum snd_soc_bias_level -snd_soc_component_get_bias_level(struct snd_soc_component *component) -{ - return snd_soc_dapm_get_bias_level( - snd_soc_component_get_dapm(component)); -} - /** * snd_soc_dapm_kcontrol_component() - Returns the component associated to a * kcontrol diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 5bd9a27b12ba..6e2db79d6a97 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -727,6 +727,7 @@ void snd_soc_dapm_init_bias_level(struct snd_soc_dapm_context *dapm, enum snd_so // REMOVE ME !! #define snd_soc_component_force_bias_level(c, l) snd_soc_dapm_force_bias_level(&(c)->dapm, l) +#define snd_soc_component_get_bias_level(c) snd_soc_dapm_get_bias_level(&(c)->dapm) #define for_each_dapm_widgets(list, i, widget) \ for ((i) = 0; \ -- cgit v1.2.3 From cf25eb8eae91bcae9b2065d84b0c0ba0f6d9dd34 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 6 Aug 2025 04:42:05 +0000 Subject: ASoC: soc-component: unpack snd_soc_component_init_bias_level() Because struct snd_soc_dapm_context is soc-dapm framework specific, user driver don't need to access its member directly, we would like to hide them. struct snd_soc_dapm_context will be removed from header in the future. This patch unpack component wrapper to cleanup it. This patch keeps compatible by using define, but old name will be replaced on each drivers and removed from ASoC in the future. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87y0rx6oyx.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 15 --------------- include/sound/soc-dapm.h | 1 + 2 files changed, 1 insertion(+), 15 deletions(-) (limited to 'include') diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 86ad2802879f..54bfa0cb1085 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -286,21 +286,6 @@ static inline struct snd_soc_dapm_context *snd_soc_component_get_dapm( return &component->dapm; } -/** - * snd_soc_component_init_bias_level() - Initialize COMPONENT DAPM bias level - * @component: The COMPONENT for which to initialize the DAPM bias level - * @level: The DAPM level to initialize to - * - * Initializes the COMPONENT DAPM bias level. See snd_soc_dapm_init_bias_level() - */ -static inline void -snd_soc_component_init_bias_level(struct snd_soc_component *component, - enum snd_soc_bias_level level) -{ - snd_soc_dapm_init_bias_level( - snd_soc_component_get_dapm(component), level); -} - /** * snd_soc_dapm_kcontrol_component() - Returns the component associated to a * kcontrol diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 6e2db79d6a97..2e9196b6ffba 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -728,6 +728,7 @@ void snd_soc_dapm_init_bias_level(struct snd_soc_dapm_context *dapm, enum snd_so // REMOVE ME !! #define snd_soc_component_force_bias_level(c, l) snd_soc_dapm_force_bias_level(&(c)->dapm, l) #define snd_soc_component_get_bias_level(c) snd_soc_dapm_get_bias_level(&(c)->dapm) +#define snd_soc_component_init_bias_level(c, l) snd_soc_dapm_init_bias_level(&(c)->dapm, l) #define for_each_dapm_widgets(list, i, widget) \ for ((i) = 0; \ -- cgit v1.2.3 From 32dffd4c3e3129e3d9bb378af8d80bb57dc3038b Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Fri, 8 Aug 2025 15:17:41 +0900 Subject: ASoC: dmaengine_pcm: Add port_window_size to DAI dma data struct The port_window_size is a struct member of dma slave channel runtime config. It's the length of the register area in words the data need to be accessed on the device side. It is only used for devices which is using an area instead of a single register to send or receive the data. Typically the DMA loops in this area in order to transfer the data. It's useful for cases that reading/writing multiple registers in DMA transactions. Signed-off-by: Chancel Liu Link: https://patch.msgid.link/20250808061741.187414-1-chancel.liu@nxp.com Signed-off-by: Mark Brown --- include/sound/dmaengine_pcm.h | 5 +++++ sound/core/pcm_dmaengine.c | 2 ++ 2 files changed, 7 insertions(+) (limited to 'include') diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h index 1ef13bcdc43f..9472f0a966a2 100644 --- a/include/sound/dmaengine_pcm.h +++ b/include/sound/dmaengine_pcm.h @@ -69,6 +69,10 @@ struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) * @peripheral_config: peripheral configuration for programming peripheral * for dmaengine transfer * @peripheral_size: peripheral configuration buffer size + * @port_window_size: The length of the register area in words the data need + * to be accessed on the device side. It is only used for devices which is using + * an area instead of a single register to send/receive the data. Typically the + * DMA loops in this area in order to transfer the data. */ struct snd_dmaengine_dai_dma_data { dma_addr_t addr; @@ -80,6 +84,7 @@ struct snd_dmaengine_dai_dma_data { unsigned int flags; void *peripheral_config; size_t peripheral_size; + u32 port_window_size; }; void snd_dmaengine_pcm_set_config_from_dai_data( diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c index 72040964b6fd..f0c17503df42 100644 --- a/sound/core/pcm_dmaengine.c +++ b/sound/core/pcm_dmaengine.c @@ -111,6 +111,7 @@ void snd_dmaengine_pcm_set_config_from_dai_data( if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { slave_config->dst_addr = dma_data->addr; slave_config->dst_maxburst = dma_data->maxburst; + slave_config->dst_port_window_size = dma_data->port_window_size; if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) slave_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED; @@ -119,6 +120,7 @@ void snd_dmaengine_pcm_set_config_from_dai_data( } else { slave_config->src_addr = dma_data->addr; slave_config->src_maxburst = dma_data->maxburst; + slave_config->src_port_window_size = dma_data->port_window_size; if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) slave_config->src_addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED; -- cgit v1.2.3 From e83dcd139e776ebb86d5e88e13282580407278e4 Mon Sep 17 00:00:00 2001 From: Shenghao Ding Date: Sun, 3 Aug 2025 21:11:10 +0800 Subject: ASoC: tas2781: Add keyword "init" in profile section Since version 0x105, the keyword 'init' was introduced into the profile, which is used for chip initialization, particularly to store common settings for other non-initialization profiles. Signed-off-by: Shenghao Ding Link: https://patch.msgid.link/20250803131110.1443-1-shenghao-ding@ti.com Signed-off-by: Mark Brown --- include/sound/tas2781-dsp.h | 8 ++++++++ sound/soc/codecs/tas2781-fmwlib.c | 12 ++++++++++++ sound/soc/codecs/tas2781-i2c.c | 6 ++++++ 3 files changed, 26 insertions(+) (limited to 'include') diff --git a/include/sound/tas2781-dsp.h b/include/sound/tas2781-dsp.h index c3a9efa73d5d..a21f34c0266e 100644 --- a/include/sound/tas2781-dsp.h +++ b/include/sound/tas2781-dsp.h @@ -198,6 +198,14 @@ struct tasdevice_rca { int ncfgs; struct tasdevice_config_info **cfg_info; int profile_cfg_id; + /* + * Since version 0x105, the keyword 'init' was introduced into the + * profile, which is used for chip initialization, particularly to + * store common settings for other non-initialization profiles. + * if (init_profile_id < 0) + * No init profile inside the RCA firmware. + */ + int init_profile_id; }; void tasdevice_select_cfg_blk(void *context, int conf_no, diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c index c9c1e608ddb7..8baf56237624 100644 --- a/sound/soc/codecs/tas2781-fmwlib.c +++ b/sound/soc/codecs/tas2781-fmwlib.c @@ -180,6 +180,16 @@ static struct tasdevice_config_info *tasdevice_add_config( dev_err(tas_priv->dev, "add conf: Out of boundary\n"); goto out; } + /* If in the RCA bin file are several profiles with the + * keyword "init", init_profile_id only store the last + * init profile id. + */ + if (strnstr(&config_data[config_offset], "init", 64)) { + tas_priv->rcabin.init_profile_id = + tas_priv->rcabin.ncfgs - 1; + dev_dbg(tas_priv->dev, "%s: init profile id = %d\n", + __func__, tas_priv->rcabin.init_profile_id); + } config_offset += 64; } @@ -283,6 +293,8 @@ int tasdevice_rca_parser(void *context, const struct firmware *fmw) int i; rca = &(tas_priv->rcabin); + /* Initialize to none */ + rca->init_profile_id = -1; fw_hdr = &(rca->fw_hdr); if (!fmw || !fmw->data) { dev_err(tas_priv->dev, "Failed to read %s\n", diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c index 9f4d965a1335..f8faeffd983d 100644 --- a/sound/soc/codecs/tas2781-i2c.c +++ b/sound/soc/codecs/tas2781-i2c.c @@ -1641,6 +1641,12 @@ static void tasdevice_fw_ready(const struct firmware *fmw, tasdevice_prmg_load(tas_priv, 0); tas_priv->cur_prog = 0; + /* Init common setting for different audio profiles */ + if (tas_priv->rcabin.init_profile_id >= 0) + tasdevice_select_cfg_blk(tas_priv, + tas_priv->rcabin.init_profile_id, + TASDEVICE_BIN_BLK_PRE_POWER_UP); + #ifdef CONFIG_SND_SOC_TAS2781_ACOUST_I2C if (tas_priv->name_prefix) acoustic_debugfs_node = devm_kasprintf(tas_priv->dev, -- cgit v1.2.3 From f4ee43ae6ea8c509d470f20e7b446adf5a167dba Mon Sep 17 00:00:00 2001 From: Baojun Xu Date: Sun, 10 Aug 2025 20:23:58 +0800 Subject: ALSA: hda: Add TAS5825 support Add TAS5825 support in TI's HDA driver. TAS5825 is an on-chip DSP, but no calibration is required, and no global address support smart amplifier devices. Signed-off-by: Baojun Xu Acked-by: Mark Brown Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250810122358.1575-1-baojun.xu@ti.com --- include/sound/tas2781-dsp.h | 3 ++ include/sound/tas2781.h | 4 +- include/sound/tas5825-tlv.h | 24 +++++++++ sound/hda/codecs/side-codecs/tas2781_hda_i2c.c | 28 +++++++++++ sound/soc/codecs/tas2781-fmwlib.c | 67 ++++++++++++++++++++++++-- 5 files changed, 121 insertions(+), 5 deletions(-) create mode 100644 include/sound/tas5825-tlv.h (limited to 'include') diff --git a/include/sound/tas2781-dsp.h b/include/sound/tas2781-dsp.h index c3a9efa73d5d..49bbf24d6559 100644 --- a/include/sound/tas2781-dsp.h +++ b/include/sound/tas2781-dsp.h @@ -34,6 +34,7 @@ #define PPC3_VERSION_TAS2781_BASIC_MIN 0x14600 #define PPC3_VERSION_TAS2781_ALPHA_MIN 0x4a00 #define PPC3_VERSION_TAS2781_BETA_MIN 0x19400 +#define PPC3_VERSION_TAS5825_BASE 0x114200 #define TASDEVICE_DEVICE_SUM 8 #define TASDEVICE_CONFIG_SUM 64 @@ -53,6 +54,8 @@ enum tasdevice_dsp_dev_idx { TASDEVICE_DSP_TAS_2781_DUAL_MONO, TASDEVICE_DSP_TAS_2781_21, TASDEVICE_DSP_TAS_2781_QUAD, + TASDEVICE_DSP_TAS_5825_MONO, + TASDEVICE_DSP_TAS_5825_DUAL, TASDEVICE_DSP_TAS_MAX_DEVICE }; diff --git a/include/sound/tas2781.h b/include/sound/tas2781.h index 3875e92f1ec5..f0aefc04a957 100644 --- a/include/sound/tas2781.h +++ b/include/sound/tas2781.h @@ -49,9 +49,9 @@ #define TASDEVICE_REG(book, page, reg) (((book * 256 * 128) + \ (page * 128)) + reg) -/* Software Reset */ +/* Software Reset, compatble with new device (TAS5825). */ #define TASDEVICE_REG_SWRESET TASDEVICE_REG(0x0, 0x0, 0x01) -#define TASDEVICE_REG_SWRESET_RESET BIT(0) +#define TASDEVICE_REG_SWRESET_RESET (BIT(0) | BIT(4)) /* Checksum */ #define TASDEVICE_CHECKSUM_REG TASDEVICE_REG(0x0, 0x0, 0x7e) diff --git a/include/sound/tas5825-tlv.h b/include/sound/tas5825-tlv.h new file mode 100644 index 000000000000..95f2d3fad120 --- /dev/null +++ b/include/sound/tas5825-tlv.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// +// ALSA SoC Texas Instruments TAS5825 Audio Smart Amplifier +// +// Copyright (C) 2025 Texas Instruments Incorporated +// https://www.ti.com +// +// The TAS5825 hda driver implements for one or two TAS5825 chips. +// +// Author: Baojun Xu +// + +#ifndef __TAS5825_TLV_H__ +#define __TAS5825_TLV_H__ + +#define TAS5825_DVC_LEVEL TASDEVICE_REG(0x0, 0x0, 0x4c) +#define TAS5825_AMP_LEVEL TASDEVICE_REG(0x0, 0x0, 0x54) + +static const __maybe_unused DECLARE_TLV_DB_SCALE( + tas5825_dvc_tlv, -10300, 50, 0); +static const __maybe_unused DECLARE_TLV_DB_SCALE( + tas5825_amp_tlv, -1550, 50, 0); + +#endif diff --git a/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c b/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c index e1d60da50897..8fae0fea37a0 100644 --- a/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c +++ b/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "hda_local.h" #include "hda_auto_parser.h" @@ -50,6 +51,7 @@ enum device_chip_id { HDA_TAS2563, HDA_TAS2770, HDA_TAS2781, + HDA_TAS5825, HDA_OTHERS }; @@ -272,6 +274,17 @@ static const struct snd_kcontrol_new tas2781_snd_controls[] = { tas2781_force_fwload_get, tas2781_force_fwload_put), }; +static const struct snd_kcontrol_new tas5825_snd_controls[] = { + ACARD_SINGLE_RANGE_EXT_TLV("Speaker Analog Volume", TAS5825_AMP_LEVEL, + 0, 0, 31, 1, tas2781_amp_getvol, + tas2781_amp_putvol, tas5825_amp_tlv), + ACARD_SINGLE_RANGE_EXT_TLV("Speaker Digital Volume", TAS5825_DVC_LEVEL, + 0, 0, 254, 1, tas2781_amp_getvol, + tas2781_amp_putvol, tas5825_dvc_tlv), + ACARD_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0, + tas2781_force_fwload_get, tas2781_force_fwload_put), +}; + static const struct snd_kcontrol_new tasdevice_prof_ctrl = { .name = "Speaker Profile Id", .iface = SNDRV_CTL_ELEM_IFACE_CARD, @@ -501,6 +514,12 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context) ARRAY_SIZE(tas2781_snd_controls)); tasdevice_dspfw_init(context); break; + case HDA_TAS5825: + tasdev_add_kcontrols(tas_priv, hda_priv->snd_ctls, codec, + &tas5825_snd_controls[0], + ARRAY_SIZE(tas5825_snd_controls)); + tasdevice_dspfw_init(context); + break; case HDA_TAS2563: tasdevice_dspfw_init(context); break; @@ -628,6 +647,7 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt) } else if (strstarts(dev_name(&clt->dev), "i2c-TXNW2781:00-tas2781-hda.0")) { device_name = "TXNW2781"; + hda_priv->hda_chip_id = HDA_TAS2781; hda_priv->save_calibration = tas2781_save_calibration; tas_hda->priv->global_addr = TAS2781_GLOBAL_ADDR; } else if (strstr(dev_name(&clt->dev), "INT8866")) { @@ -639,6 +659,13 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt) hda_priv->hda_chip_id = HDA_TAS2563; hda_priv->save_calibration = tas2563_save_calibration; tas_hda->priv->global_addr = TAS2563_GLOBAL_ADDR; + } else if (strstarts(dev_name(&clt->dev), "i2c-TXNW5825")) { + /* + * TAS5825, integrated on-chip DSP without + * global I2C address and calibration supported. + */ + device_name = "TXNW5825"; + hda_priv->hda_chip_id = HDA_TAS5825; } else { return -ENODEV; } @@ -775,6 +802,7 @@ static const struct acpi_device_id tas2781_acpi_hda_match[] = { {"TIAS2781", 0 }, {"TXNW2770", 0 }, {"TXNW2781", 0 }, + {"TXNW5825", 0 }, {} }; MODULE_DEVICE_TABLE(acpi, tas2781_acpi_hda_match); diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c index c9c1e608ddb7..d69faef8a4d7 100644 --- a/sound/soc/codecs/tas2781-fmwlib.c +++ b/sound/soc/codecs/tas2781-fmwlib.c @@ -91,7 +91,7 @@ struct blktyp_devidx_map { }; static const char deviceNumber[TASDEVICE_DSP_TAS_MAX_DEVICE] = { - 1, 2, 1, 2, 1, 1, 0, 2, 4, 3, 1, 2, 3, 4 + 1, 2, 1, 2, 1, 1, 0, 2, 4, 3, 1, 2, 3, 4, 1, 2 }; /* fixed m68k compiling issue: mapping table can save code field */ @@ -509,6 +509,56 @@ out: return offset; } +static int fw_parse_tas5825_program_data_kernel( + struct tasdevice_priv *tas_priv, struct tasdevice_fw *tas_fmw, + const struct firmware *fmw, int offset) +{ + struct tasdevice_prog *program; + unsigned int i; + + for (i = 0; i < tas_fmw->nr_programs; i++) { + program = &(tas_fmw->programs[i]); + if (offset + 72 > fmw->size) { + dev_err(tas_priv->dev, "%s: mpName error\n", __func__); + return -EINVAL; + } + /* Skip 65 unused byts*/ + offset += 65; + offset = fw_parse_data_kernel(tas_fmw, &(program->dev_data), + fmw, offset); + if (offset < 0) + return offset; + } + + return offset; +} + +static int fw_parse_tas5825_configuration_data_kernel( + struct tasdevice_priv *tas_priv, + struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset) +{ + const unsigned char *data = fmw->data; + struct tasdevice_config *config; + unsigned int i; + + for (i = 0; i < tas_fmw->nr_configurations; i++) { + config = &(tas_fmw->configs[i]); + if (offset + 80 > fmw->size) { + dev_err(tas_priv->dev, "%s: mpName error\n", __func__); + return -EINVAL; + } + memcpy(config->name, &data[offset], 64); + /* Skip extra 8 bytes*/ + offset += 72; + offset = fw_parse_data_kernel(tas_fmw, &(config->dev_data), + fmw, offset); + if (offset < 0) + return offset; + } + + return offset; +} + static int fw_parse_program_data_kernel( struct tasdevice_priv *tas_priv, struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset) @@ -1826,7 +1876,8 @@ static void dspbin_type_check(struct tasdevice_priv *tas_priv, else tas_priv->dspbin_typ = TASDEV_ALPHA; } - if (tas_priv->dspbin_typ != TASDEV_BASIC) + if ((tas_priv->dspbin_typ != TASDEV_BASIC) && + (ppcver < PPC3_VERSION_TAS5825_BASE)) tas_priv->fw_parse_fct_param_address = fw_parse_fct_param_address; } @@ -1837,7 +1888,17 @@ static int dspfw_default_callback(struct tasdevice_priv *tas_priv, int rc = 0; if (drv_ver == 0x100) { - if (ppcver >= PPC3_VERSION_BASE) { + if (ppcver >= PPC3_VERSION_TAS5825_BASE) { + tas_priv->fw_parse_variable_header = + fw_parse_variable_header_kernel; + tas_priv->fw_parse_program_data = + fw_parse_tas5825_program_data_kernel; + tas_priv->fw_parse_configuration_data = + fw_parse_tas5825_configuration_data_kernel; + tas_priv->tasdevice_load_block = + tasdevice_load_block_kernel; + dspbin_type_check(tas_priv, ppcver); + } else if (ppcver >= PPC3_VERSION_BASE) { tas_priv->fw_parse_variable_header = fw_parse_variable_header_kernel; tas_priv->fw_parse_program_data = -- cgit v1.2.3 From c308bb4190a8f6f09270b541457d6ae905d2f7bc Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Wed, 13 Aug 2025 22:55:02 +0200 Subject: ALSA: hda: Use min() to simplify snd_hda_get_devices() Use min() to simplify snd_hda_get_devices() and improve its readability. Change the function parameter 'max_devices' from 'int' to 'unsigned int' to avoid a min() signedness error. Update all related local variables and the function's return type to 'unsigned int' accordingly. No functional changes intended. Signed-off-by: Thorsten Blum Link: https://patch.msgid.link/20250813205507.215658-2-thorsten.blum@linux.dev Signed-off-by: Takashi Iwai --- include/sound/hda_codec.h | 4 ++-- sound/hda/common/codec.c | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h index ddc9c392f93f..006d4e4a8195 100644 --- a/include/sound/hda_codec.h +++ b/include/sound/hda_codec.h @@ -360,8 +360,8 @@ int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int nums, int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux, hda_nid_t nid, int recursive); unsigned int snd_hda_get_num_devices(struct hda_codec *codec, hda_nid_t nid); -int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, - u8 *dev_list, int max_devices); +unsigned int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, + u8 *dev_list, unsigned int max_devices); int snd_hda_get_dev_select(struct hda_codec *codec, hda_nid_t nid); int snd_hda_set_dev_select(struct hda_codec *codec, hda_nid_t nid, int dev_id); diff --git a/sound/hda/common/codec.c b/sound/hda/common/codec.c index cab479111603..7a72d4c7ae91 100644 --- a/sound/hda/common/codec.c +++ b/sound/hda/common/codec.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -323,18 +324,16 @@ EXPORT_SYMBOL_GPL(snd_hda_get_num_devices); * Copy the device list. This info is dynamic and so not cached. * Currently called only from hda_proc.c, so not exported. */ -int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, - u8 *dev_list, int max_devices) +unsigned int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, + u8 *dev_list, unsigned int max_devices) { - unsigned int parm; - int i, dev_len, devices; + unsigned int parm, i, dev_len, devices; parm = snd_hda_get_num_devices(codec, nid); if (!parm) /* not multi-stream capable */ return 0; - dev_len = parm + 1; - dev_len = dev_len < max_devices ? dev_len : max_devices; + dev_len = min(parm + 1, max_devices); devices = 0; while (devices < dev_len) { -- cgit v1.2.3 From 12cc0ff3cdd95f2bc0ffdc63bcd9da231eb33199 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 19 Aug 2025 11:01:46 +0100 Subject: ASoC: qcom: audioreach: deprecate AR_TKN_U32_MODULE_[IN/OUT]_PORTS Deprecate usage of AR_TKN_U32_MODULE_IN_PORTS and AR_TKN_U32_MODULE_OUT_PORTS as the connectivity of modules is taken care by AR_TKN_U32_MODULE_SRC_OP_PORT_ID* and AR_TKN_U32_MODULE_DST_IN_PORT_ID* Also this property is never used in the drivers. Signed-off-by: Srinivas Kandagatla Reviewed-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20250819100151.1294047-2-srinivas.kandagatla@oss.qualcomm.com Signed-off-by: Mark Brown --- include/uapi/sound/snd_ar_tokens.h | 4 ++-- sound/soc/qcom/qdsp6/audioreach.h | 3 --- sound/soc/qcom/qdsp6/topology.c | 10 +--------- 3 files changed, 3 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/include/uapi/sound/snd_ar_tokens.h b/include/uapi/sound/snd_ar_tokens.h index b9b9093b4396..bc0b1bede00c 100644 --- a/include/uapi/sound/snd_ar_tokens.h +++ b/include/uapi/sound/snd_ar_tokens.h @@ -184,8 +184,8 @@ enum ar_event_types { #define AR_TKN_U32_MODULE_INSTANCE_ID 201 #define AR_TKN_U32_MODULE_MAX_IP_PORTS 202 #define AR_TKN_U32_MODULE_MAX_OP_PORTS 203 -#define AR_TKN_U32_MODULE_IN_PORTS 204 -#define AR_TKN_U32_MODULE_OUT_PORTS 205 +#define AR_TKN_U32_MODULE_IN_PORTS 204 /* deprecated */ +#define AR_TKN_U32_MODULE_OUT_PORTS 205 /* deprecated */ #define AR_TKN_U32_MODULE_SRC_OP_PORT_ID 206 #define AR_TKN_U32_MODULE_DST_IN_PORT_ID 207 #define AR_TKN_U32_MODULE_SRC_INSTANCE_ID 208 diff --git a/sound/soc/qcom/qdsp6/audioreach.h b/sound/soc/qcom/qdsp6/audioreach.h index 61a69df4f50f..9b30177463e6 100644 --- a/sound/soc/qcom/qdsp6/audioreach.h +++ b/sound/soc/qcom/qdsp6/audioreach.h @@ -707,9 +707,6 @@ struct audioreach_module { uint32_t max_ip_port; uint32_t max_op_port; - uint32_t in_port; - uint32_t out_port; - uint32_t num_connections; /* Connections */ uint32_t src_mod_inst_id; diff --git a/sound/soc/qcom/qdsp6/topology.c b/sound/soc/qcom/qdsp6/topology.c index 83319a928f29..a3b0f558260c 100644 --- a/sound/soc/qcom/qdsp6/topology.c +++ b/sound/soc/qcom/qdsp6/topology.c @@ -412,7 +412,7 @@ static struct audioreach_module *audioreach_parse_common_tokens(struct q6apm *ap struct snd_soc_tplg_private *private, struct snd_soc_dapm_widget *w) { - uint32_t max_ip_port = 0, max_op_port = 0, in_port = 0, out_port = 0; + uint32_t max_ip_port = 0, max_op_port = 0; uint32_t src_mod_op_port_id[AR_MAX_MOD_LINKS] = { 0, }; uint32_t dst_mod_inst_id[AR_MAX_MOD_LINKS] = { 0, }; uint32_t dst_mod_ip_port_id[AR_MAX_MOD_LINKS] = { 0, }; @@ -455,12 +455,6 @@ static struct audioreach_module *audioreach_parse_common_tokens(struct q6apm *ap case AR_TKN_U32_MODULE_MAX_OP_PORTS: max_op_port = le32_to_cpu(mod_elem->value); break; - case AR_TKN_U32_MODULE_IN_PORTS: - in_port = le32_to_cpu(mod_elem->value); - break; - case AR_TKN_U32_MODULE_OUT_PORTS: - out_port = le32_to_cpu(mod_elem->value); - break; case AR_TKN_U32_MODULE_SRC_INSTANCE_ID: src_mod_inst_id = le32_to_cpu(mod_elem->value); break; @@ -550,8 +544,6 @@ static struct audioreach_module *audioreach_parse_common_tokens(struct q6apm *ap mod->module_id = module_id; mod->max_ip_port = max_ip_port; mod->max_op_port = max_op_port; - mod->in_port = in_port; - mod->out_port = out_port; mod->src_mod_inst_id = src_mod_inst_id; for (pn = 0; pn < mod->max_op_port; pn++) { if (src_mod_op_port_id[pn] && dst_mod_inst_id[pn] && -- cgit v1.2.3 From f07b81b573b28e5cae5c1482001ad0d6c0b7c051 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 19 Aug 2025 11:01:47 +0100 Subject: ASoC: qcom: audioreach: add documentation for i2s interface type Add documentation of possible values for I2S interface types, currently this is only documented for DMA module. Signed-off-by: Srinivas Kandagatla Reviewed-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20250819100151.1294047-3-srinivas.kandagatla@oss.qualcomm.com Signed-off-by: Mark Brown --- include/uapi/sound/snd_ar_tokens.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include') diff --git a/include/uapi/sound/snd_ar_tokens.h b/include/uapi/sound/snd_ar_tokens.h index bc0b1bede00c..92cf72a6fdd4 100644 --- a/include/uapi/sound/snd_ar_tokens.h +++ b/include/uapi/sound/snd_ar_tokens.h @@ -118,6 +118,12 @@ enum ar_event_types { * LPAIF_WSA = 2, * LPAIF_VA = 3, * LPAIF_AXI = 4 + * Possible values for MI2S + * I2S_INTF_TYPE_PRIMARY = 0, + * I2S_INTF_TYPE_SECONDARY = 1, + * I2S_INTF_TYPE_TERTIARY = 2, + * I2S_INTF_TYPE_QUATERNARY = 3, + * I2S_INTF_TYPE_QUINARY = 4, * * %AR_TKN_U32_MODULE_FMT_INTERLEAVE: PCM Interleaving * PCM_INTERLEAVED = 1, -- cgit v1.2.3 From c7ed4c2debfd192f6071f4ab33c092d419abb941 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 19 Aug 2025 11:01:48 +0100 Subject: ASoC: qcom: audioreach: add support for static calibration This change adds support for static calibration data via ASoC topology file. This static calibration data could include binary blob of data that is required by specific module and is not part of topology tokens. Reason for adding this support is to allow loading module specific data that can not be part of the tplg tokens, example, Echo and Noise cancelling module needs a blob of calibration data to function correctly. This support is also one of the building block for adding speaker protection support. Tested this with Single Mic ECNS(Echo and Noise Cancellation). tplg can now contain this calibration data like: SectionWidget."stream2.SMECNS_V224" { ... data [ ... "stream2.SMECNS_V224_cfg_data" ] } SectionData."stream2.SMECNS_V224_cfg_data" { words "0x00000330, 0x01001006,0x00000000,0x00000000, 0x00004145,0x08001026,0x00000004,0x00000000, ..." } } Signed-off-by: Srinivas Kandagatla Reviewed-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20250819100151.1294047-4-srinivas.kandagatla@oss.qualcomm.com Signed-off-by: Mark Brown --- include/uapi/sound/snd_ar_tokens.h | 10 ++++++++++ sound/soc/qcom/qdsp6/audioreach.h | 2 ++ sound/soc/qcom/qdsp6/topology.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+) (limited to 'include') diff --git a/include/uapi/sound/snd_ar_tokens.h b/include/uapi/sound/snd_ar_tokens.h index 92cf72a6fdd4..6b8102eaa121 100644 --- a/include/uapi/sound/snd_ar_tokens.h +++ b/include/uapi/sound/snd_ar_tokens.h @@ -3,6 +3,8 @@ #ifndef __SND_AR_TOKENS_H__ #define __SND_AR_TOKENS_H__ +#include + #define APM_SUB_GRAPH_PERF_MODE_LOW_POWER 0x1 #define APM_SUB_GRAPH_PERF_MODE_LOW_LATENCY 0x2 @@ -238,4 +240,12 @@ enum ar_event_types { #define AR_TKN_U32_MODULE_LOG_TAP_POINT_ID 260 #define AR_TKN_U32_MODULE_LOG_MODE 261 +#define SND_SOC_AR_TPLG_MODULE_CFG_TYPE 0x01001006 +struct audioreach_module_priv_data { + __le32 size; /* size in bytes of the array, including all elements */ + __le32 type; /* SND_SOC_AR_TPLG_MODULE_CFG_TYPE */ + __le32 priv[2]; /* Private data for future expansion */ + __le32 data[0]; /* config data */ +}; + #endif /* __SND_AR_TOKENS_H__ */ diff --git a/sound/soc/qcom/qdsp6/audioreach.h b/sound/soc/qcom/qdsp6/audioreach.h index 9b30177463e6..617bda051cf8 100644 --- a/sound/soc/qcom/qdsp6/audioreach.h +++ b/sound/soc/qcom/qdsp6/audioreach.h @@ -4,6 +4,7 @@ #define __AUDIOREACH_H__ #include #include +#include #include struct q6apm; struct q6apm_graph; @@ -742,6 +743,7 @@ struct audioreach_module { struct list_head node; struct audioreach_container *container; struct snd_soc_dapm_widget *widget; + struct audioreach_module_priv_data *data; }; struct audioreach_module_config { diff --git a/sound/soc/qcom/qdsp6/topology.c b/sound/soc/qcom/qdsp6/topology.c index a3b0f558260c..ec51fabd98cb 100644 --- a/sound/soc/qcom/qdsp6/topology.c +++ b/sound/soc/qcom/qdsp6/topology.c @@ -305,6 +305,34 @@ static struct snd_soc_tplg_vendor_array *audioreach_get_module_array( return NULL; } +static struct audioreach_module_priv_data *audioreach_get_module_priv_data( + struct snd_soc_tplg_private *private) +{ + int sz; + + for (sz = 0; sz < le32_to_cpu(private->size); ) { + struct snd_soc_tplg_vendor_array *mod_array; + + mod_array = (struct snd_soc_tplg_vendor_array *)((u8 *)private->array + sz); + if (mod_array->type == SND_SOC_AR_TPLG_MODULE_CFG_TYPE) { + struct audioreach_module_priv_data *pdata; + + pdata = kzalloc(struct_size(pdata, data, le32_to_cpu(mod_array->size)), + GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); + + memcpy(pdata, ((u8 *)private->data + sz), struct_size(pdata, data, + le32_to_cpu(mod_array->size))); + return pdata; + } + + sz = sz + le32_to_cpu(mod_array->size); + } + + return NULL; +} + static struct audioreach_sub_graph *audioreach_parse_sg_tokens(struct q6apm *apm, struct snd_soc_tplg_private *private) { @@ -582,6 +610,8 @@ static int audioreach_widget_load_module_common(struct snd_soc_component *compon if (IS_ERR(mod)) return PTR_ERR(mod); + mod->data = audioreach_get_module_priv_data(&tplg_w->priv); + dobj = &w->dobj; dobj->private = mod; @@ -939,6 +969,7 @@ static int audioreach_widget_unload(struct snd_soc_component *scomp, cont->num_modules--; list_del(&mod->node); + kfree(mod->data); kfree(mod); /* Graph Info has N sub-graphs, sub-graph has N containers, Container has N Modules */ if (list_empty(&cont->modules_list)) { /* if no modules in the container then remove it */ -- cgit v1.2.3 From 5d8c9c987fbdd65677315198c2b1f35a440d7cdf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 27 Aug 2025 09:28:41 +0200 Subject: ALSA: hda: Introduce auto cleanup macros for PM The temporary power up/down of the codec via snd_hda_power_up() and _down() (or snd_hda_power_up_pm() and _down_pm()) is seen in various places. This patch introduces simple auto-cleanup macros for those call patterns, so that the drivers don't have to call the corresponding power-down calls explicitly. Namely, err = snd_hda_power_up(codec); if (err < 0) return err; .... snd_power_down(codec); can drop the *_down() call by replacing with CLASS(snd_hda_power, pm)(codec); if (pm.err < 0) return pm.err; Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250827072916.31933-2-tiwai@suse.de --- include/sound/hda_codec.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'include') diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h index 006d4e4a8195..5d9f0ef228af 100644 --- a/include/sound/hda_codec.h +++ b/include/sound/hda_codec.h @@ -503,6 +503,36 @@ static inline bool hda_codec_need_resume(struct hda_codec *codec) return !codec->relaxed_resume && codec->jacktbl.used; } +/* + * PM with auto-cleanup: call like CLASS(snd_hda_power, pm)(codec) + * If the error handling is needed, refer pm.err. + */ +struct __hda_power_obj { + struct hda_codec *codec; + int err; +}; + +static inline struct __hda_power_obj __snd_hda_power_up(struct hda_codec *codec) +{ + struct __hda_power_obj T = { .codec = codec }; + T.err = snd_hda_power_up(codec); + return T; +} + +static inline struct __hda_power_obj __snd_hda_power_up_pm(struct hda_codec *codec) +{ + struct __hda_power_obj T = { .codec = codec }; + T.err = snd_hda_power_up_pm(codec); + return T; +} + +DEFINE_CLASS(snd_hda_power, struct __hda_power_obj, + snd_hda_power_down((_T).codec), __snd_hda_power_up(codec), + struct hda_codec *codec) +DEFINE_CLASS(snd_hda_power_pm, struct __hda_power_obj, + snd_hda_power_down_pm((_T).codec), __snd_hda_power_up_pm(codec), + struct hda_codec *codec) + #ifdef CONFIG_SND_HDA_PATCH_LOADER /* * patch firmware -- cgit v1.2.3 From a23160c87986732590e68c1788e9b4929950ef67 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 27 Aug 2025 09:28:46 +0200 Subject: ALSA: hda: Use auto cleanup macros for DSP loader locks There are temporary DSP locking/unlocking patterns found in various places, and those can be cleaned up nicely with the guard() macro calling snd_hdac_dsp_lock() and *_unlock(). Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250827072916.31933-7-tiwai@suse.de --- include/sound/hdaudio.h | 1 + sound/hda/common/controller.c | 47 ++++++++++++++++++------------------------- sound/hda/core/stream.c | 11 +++------- 3 files changed, 24 insertions(+), 35 deletions(-) (limited to 'include') diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index d38234f8fe44..4e0c1d8af09f 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -651,6 +651,7 @@ int snd_hdac_stream_set_lpib(struct hdac_stream *azx_dev, u32 value); #define snd_hdac_dsp_lock(dev) mutex_lock(&(dev)->dsp_mutex) #define snd_hdac_dsp_unlock(dev) mutex_unlock(&(dev)->dsp_mutex) #define snd_hdac_stream_is_locked(dev) ((dev)->locked) +DEFINE_GUARD(snd_hdac_dsp_lock, struct hdac_stream *, snd_hdac_dsp_lock(_T), snd_hdac_dsp_unlock(_T)) /* DSP loader helpers */ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format, unsigned int byte_size, struct snd_dma_buffer *bufp); diff --git a/sound/hda/common/controller.c b/sound/hda/common/controller.c index 84387ed761be..ceab8625bb1f 100644 --- a/sound/hda/common/controller.c +++ b/sound/hda/common/controller.c @@ -32,8 +32,11 @@ #include "controller_trace.h" /* DSP lock helpers */ -#define dsp_lock(dev) snd_hdac_dsp_lock(azx_stream(dev)) -#define dsp_unlock(dev) snd_hdac_dsp_unlock(azx_stream(dev)) +#ifdef CONFIG_SND_HDA_DSP_LOADER +#define guard_dsp_lock(dev) guard(snd_hdac_dsp_lock)(azx_stream(dev)) +#else +#define guard_dsp_lock(dev) do {} while (0) +#endif #define dsp_is_locked(dev) snd_hdac_stream_is_locked(azx_stream(dev)) /* assign a stream for the PCM */ @@ -110,14 +113,11 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream, struct azx *chip = apcm->chip; struct azx_dev *azx_dev = get_azx_dev(substream); struct hdac_stream *hdas = azx_stream(azx_dev); - int ret = 0; trace_azx_pcm_hw_params(chip, azx_dev); - dsp_lock(azx_dev); - if (dsp_is_locked(azx_dev)) { - ret = -EBUSY; - goto unlock; - } + guard_dsp_lock(azx_dev); + if (dsp_is_locked(azx_dev)) + return -EBUSY; /* Set up BDLEs here, return -ENOMEM if too many BDLEs are required */ hdas->bufsize = params_buffer_bytes(hw_params); @@ -127,11 +127,9 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream, (hw_params->info & SNDRV_PCM_INFO_NO_PERIOD_WAKEUP) && (hw_params->flags & SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP); if (snd_hdac_stream_setup_periods(hdas) < 0) - ret = -ENOMEM; + return -ENOMEM; -unlock: - dsp_unlock(azx_dev); - return ret; + return 0; } static int azx_pcm_hw_free(struct snd_pcm_substream *substream) @@ -141,14 +139,13 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream) struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); /* reset BDL address */ - dsp_lock(azx_dev); + guard_dsp_lock(azx_dev); if (!dsp_is_locked(azx_dev)) snd_hdac_stream_cleanup(azx_stream(azx_dev)); snd_hda_codec_cleanup(apcm->codec, hinfo, substream); azx_stream(azx_dev)->prepared = 0; - dsp_unlock(azx_dev); return 0; } @@ -166,11 +163,9 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) unsigned short ctls = spdif ? spdif->ctls : 0; trace_azx_pcm_prepare(chip, azx_dev); - dsp_lock(azx_dev); - if (dsp_is_locked(azx_dev)) { - err = -EBUSY; - goto unlock; - } + guard_dsp_lock(azx_dev); + if (dsp_is_locked(azx_dev)) + return -EBUSY; snd_hdac_stream_reset(azx_stream(azx_dev)); bits = snd_hdac_stream_format_bits(runtime->format, SNDRV_PCM_SUBFORMAT_STD, hinfo->maxbps); @@ -180,13 +175,12 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) dev_err(chip->card->dev, "invalid format_val, rate=%d, ch=%d, format=%d\n", runtime->rate, runtime->channels, runtime->format); - err = -EINVAL; - goto unlock; + return -EINVAL; } err = snd_hdac_stream_set_params(azx_stream(azx_dev), format_val); if (err < 0) - goto unlock; + return err; snd_hdac_stream_setup(azx_stream(azx_dev), false); @@ -197,12 +191,11 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) stream_tag -= chip->capture_streams; err = snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag, azx_dev->core.format_val, substream); + if (err < 0) + return err; - unlock: - if (!err) - azx_stream(azx_dev)->prepared = 1; - dsp_unlock(azx_dev); - return err; + azx_stream(azx_dev)->prepared = 1; + return 0; } static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) diff --git a/sound/hda/core/stream.c b/sound/hda/core/stream.c index 4a87bef8834f..0caeebcc591a 100644 --- a/sound/hda/core/stream.c +++ b/sound/hda/core/stream.c @@ -922,12 +922,11 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format, struct hdac_bus *bus = azx_dev->bus; int err; - snd_hdac_dsp_lock(azx_dev); + guard(snd_hdac_dsp_lock)(azx_dev); spin_lock_irq(&bus->reg_lock); if (azx_dev->running || azx_dev->locked) { spin_unlock_irq(&bus->reg_lock); - err = -EBUSY; - goto unlock; + return -EBUSY; } azx_dev->locked = true; spin_unlock_irq(&bus->reg_lock); @@ -951,7 +950,6 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format, goto error; snd_hdac_stream_setup(azx_dev, true); - snd_hdac_dsp_unlock(azx_dev); return azx_dev->stream_tag; error: @@ -960,8 +958,6 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format, spin_lock_irq(&bus->reg_lock); azx_dev->locked = false; spin_unlock_irq(&bus->reg_lock); - unlock: - snd_hdac_dsp_unlock(azx_dev); return err; } EXPORT_SYMBOL_GPL(snd_hdac_dsp_prepare); @@ -993,7 +989,7 @@ void snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev, if (!dmab->area || !azx_dev->locked) return; - snd_hdac_dsp_lock(azx_dev); + guard(snd_hdac_dsp_lock)(azx_dev); /* reset BDL address */ snd_hdac_stream_writel(azx_dev, SD_BDLPL, 0); snd_hdac_stream_writel(azx_dev, SD_BDLPU, 0); @@ -1008,7 +1004,6 @@ void snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev, spin_lock_irq(&bus->reg_lock); azx_dev->locked = false; spin_unlock_irq(&bus->reg_lock); - snd_hdac_dsp_unlock(azx_dev); } EXPORT_SYMBOL_GPL(snd_hdac_dsp_cleanup); #endif /* CONFIG_SND_HDA_DSP_LOADER */ -- cgit v1.2.3 From 782d4613171e271b1e28ee1db9616beb8e6ad8a1 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Fri, 29 Aug 2025 12:30:19 +0300 Subject: ASoC: SOF: IPC4: Add GET macros for module id and module instance id Add SOF_IPC4_MOD_INSTANCE_GET() and SOF_IPC4_MOD_ID_GET() for getting the ids from ipc4 header presentation. Signed-off-by: Jyri Sarha Reviewed-by: Liam Girdwood Signed-off-by: Peter Ujfalusi Message-ID: <20250829093022.32094-3-peter.ujfalusi@linux.intel.com> Signed-off-by: Mark Brown --- include/sound/sof/ipc4/header.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/sound/sof/ipc4/header.h b/include/sound/sof/ipc4/header.h index e85c7afd85a4..15fac532688e 100644 --- a/include/sound/sof/ipc4/header.h +++ b/include/sound/sof/ipc4/header.h @@ -326,10 +326,14 @@ struct sof_ipc4_base_module_cfg { #define SOF_IPC4_MOD_INSTANCE_SHIFT 16 #define SOF_IPC4_MOD_INSTANCE_MASK GENMASK(23, 16) #define SOF_IPC4_MOD_INSTANCE(x) ((x) << SOF_IPC4_MOD_INSTANCE_SHIFT) +#define SOF_IPC4_MOD_INSTANCE_GET(x) (((x) & SOF_IPC4_MOD_INSTANCE_MASK) \ + >> SOF_IPC4_MOD_INSTANCE_SHIFT) #define SOF_IPC4_MOD_ID_SHIFT 0 #define SOF_IPC4_MOD_ID_MASK GENMASK(15, 0) #define SOF_IPC4_MOD_ID(x) ((x) << SOF_IPC4_MOD_ID_SHIFT) +#define SOF_IPC4_MOD_ID_GET(x) (((x) & SOF_IPC4_MOD_ID_MASK) \ + >> SOF_IPC4_MOD_ID_SHIFT) /* init module ipc msg */ #define SOF_IPC4_MOD_EXT_PARAM_SIZE_SHIFT 0 -- cgit v1.2.3 From 3d439e1ec3368fae17db379354bd7a9e568ca0ab Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Fri, 29 Aug 2025 18:11:01 +0300 Subject: ASoC: sof: ipc4-topology: Add support to sched_domain attribute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add SOF_TKN_COMP_SCHED_DOMAIN and connect it to struct snd_sof_widget comp_domain member, with new get_token_comp_domain() function. The logic is such that if the topology attribute is not present in the widget node the corresponding IPC4 extension value is taken from the module's manifest like before. But if the attribute is found and recognized its value overrides what is there in the manifest. Signed-off-by: Jyri Sarha Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Message-ID: <20250829151101.27327-1-peter.ujfalusi@linux.intel.com> Signed-off-by: Mark Brown --- include/uapi/sound/sof/tokens.h | 2 ++ sound/soc/sof/ipc4-topology.c | 44 ++++++++++++++++++++++++++++++++++++++++- sound/soc/sof/ipc4-topology.h | 7 +++++++ sound/soc/sof/sof-audio.h | 3 +++ 4 files changed, 55 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h index c28c766270de..9ce72fbd6f11 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h @@ -106,6 +106,8 @@ */ #define SOF_TKN_COMP_NO_WNAME_IN_KCONTROL_NAME 417 +#define SOF_TKN_COMP_SCHED_DOMAIN 418 + /* SSP */ #define SOF_TKN_INTEL_SSP_CLKS_CONTROL 500 #define SOF_TKN_INTEL_SSP_MCLK_ID 501 diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 591ee30551ba..74a1319d4bd2 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -38,6 +38,36 @@ MODULE_PARM_DESC(ipc4_ignore_cpc, static DEFINE_IDA(alh_group_ida); static DEFINE_IDA(pipeline_ida); +struct sof_comp_domains { + const char *name; + enum sof_comp_domain domain; +}; + +static const struct sof_comp_domains sof_domains[] = { + { "LL", SOF_COMP_DOMAIN_LL, }, + { "DP", SOF_COMP_DOMAIN_DP, } +}; + +static enum sof_comp_domain find_domain(const char *name) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(sof_domains); i++) { + if (strcmp(name, sof_domains[i].name) == 0) + return sof_domains[i].domain; + } + /* No valid value found, fall back to manifest value */ + return SOF_COMP_DOMAIN_UNSET; +} + +static int get_token_comp_domain(void *elem, void *object, u32 offset) +{ + u32 *val = (u32 *)((u8 *)object + offset); + + *val = find_domain((const char *)elem); + return 0; +} + static const struct sof_topology_token ipc4_sched_tokens[] = { {SOF_TKN_SCHED_LP_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, offsetof(struct sof_ipc4_pipeline, lp_mode)}, @@ -127,6 +157,8 @@ static const struct sof_topology_token comp_ext_tokens[] = { offsetof(struct snd_sof_widget, uuid)}, {SOF_TKN_COMP_CORE_ID, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, offsetof(struct snd_sof_widget, core)}, + {SOF_TKN_COMP_SCHED_DOMAIN, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_comp_domain, + offsetof(struct snd_sof_widget, comp_domain)}, }; static const struct sof_topology_token gain_tokens[] = { @@ -497,7 +529,17 @@ static int sof_ipc4_widget_setup_msg(struct snd_sof_widget *swidget, struct sof_ msg->extension = SOF_IPC4_MOD_EXT_CORE_ID(swidget->core); - type = (fw_module->man4_module_entry.type & SOF_IPC4_MODULE_DP) ? 1 : 0; + switch (swidget->comp_domain) { + case SOF_COMP_DOMAIN_LL: + type = 0; + break; + case SOF_COMP_DOMAIN_DP: + type = 1; + break; + default: + type = (fw_module->man4_module_entry.type & SOF_IPC4_MODULE_DP) ? 1 : 0; + break; + } msg->extension |= SOF_IPC4_MOD_EXT_DOMAIN(type); return 0; diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 14ba58d2be03..e8e848233314 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -109,6 +109,13 @@ enum sof_ipc4_copier_module_config_params { SOF_IPC4_COPIER_MODULE_CFG_ATTENUATION, }; +/* Scheduling domain, unset, Low Latency, or Data Processing */ +enum sof_comp_domain { + SOF_COMP_DOMAIN_UNSET = 0, /* Take domain value from manifest */ + SOF_COMP_DOMAIN_LL, /* Low Latency scheduling domain */ + SOF_COMP_DOMAIN_DP, /* Data Processing scheduling domain */ +}; + struct sof_ipc4_copier_config_set_sink_format { /* Id of sink */ u32 sink_id; diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 36ab75e11779..db6973c8eac3 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -451,6 +451,9 @@ struct snd_sof_widget { */ bool dynamic_pipeline_widget; + /* Scheduling domain (enum sof_comp_domain), unset, Low Latency, or Data Processing */ + u32 comp_domain; + struct snd_soc_dapm_widget *widget; struct list_head list; /* list in sdev widget list */ struct snd_sof_pipeline *spipe; -- cgit v1.2.3 From 7c4a379e0622e7d8e7eb7dbc76445cdd6306aad8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 29 Aug 2025 16:43:02 +0200 Subject: ALSA: emu10k1: Use guard() for emu1010 FPGA locking The snd_emu1010_fpga_lock() and _unlock() call pairs can be simplified gracefully with the introduction of guard(). Only code refactoring, and no functional changes. Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250829144342.4290-28-tiwai@suse.de --- include/sound/emu10k1.h | 3 +-- sound/pci/emu10k1/emu10k1_main.c | 15 +++++---------- sound/pci/emu10k1/emumixer.c | 15 ++++++--------- sound/pci/emu10k1/emuproc.c | 8 ++------ sound/pci/emu10k1/io.c | 3 +-- 5 files changed, 15 insertions(+), 29 deletions(-) (limited to 'include') diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h index 38db50b280eb..4f94565c9d15 100644 --- a/include/sound/emu10k1.h +++ b/include/sound/emu10k1.h @@ -1842,8 +1842,7 @@ unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, unsigned int reg, void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data); int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, unsigned int data); int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, u32 reg, u32 value); -static inline void snd_emu1010_fpga_lock(struct snd_emu10k1 *emu) { mutex_lock(&emu->emu1010.lock); }; -static inline void snd_emu1010_fpga_unlock(struct snd_emu10k1 *emu) { mutex_unlock(&emu->emu1010.lock); }; +DEFINE_GUARD(snd_emu1010_fpga_lock, struct snd_emu10k1 *, mutex_lock(&(_T)->emu1010.lock), mutex_unlock(&(_T)->emu1010.lock)) void snd_emu1010_fpga_write_lock(struct snd_emu10k1 *emu, u32 reg, u32 value); void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value); void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value); diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index bbe252b8916c..a3d028e4a212 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -768,7 +768,7 @@ static void emu1010_work(struct work_struct *work) return; #endif - snd_emu1010_fpga_lock(emu); + guard(snd_emu1010_fpga_lock)(emu); snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &sts); @@ -779,8 +779,6 @@ static void emu1010_work(struct work_struct *work) if (sts & EMU_HANA_IRQ_WCLK_CHANGED) emu1010_clock_event(emu); - - snd_emu1010_fpga_unlock(emu); } static void emu1010_interrupt(struct snd_emu10k1 *emu) @@ -814,13 +812,13 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) * Proper init follows in snd_emu10k1_init(). */ outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG); - snd_emu1010_fpga_lock(emu); + guard(snd_emu1010_fpga_lock)(emu); dev_info(emu->card->dev, "emu1010: Loading Hana Firmware\n"); err = snd_emu1010_load_firmware(emu, 0, &emu->firmware); if (err < 0) { dev_info(emu->card->dev, "emu1010: Loading Firmware failed\n"); - goto fail; + return err; } /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ @@ -830,8 +828,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) dev_info(emu->card->dev, "emu1010: Loading Hana Firmware file failed, reg = 0x%x\n", reg); - err = -ENODEV; - goto fail; + return -ENODEV; } dev_info(emu->card->dev, "emu1010: Hana Firmware loaded\n"); @@ -891,9 +888,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) // so it is safe to simply enable the outputs. snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); -fail: - snd_emu1010_fpga_unlock(emu); - return err; + return 0; } /* * Create the EMU10K1 instance diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index d665d5d1ad7c..6d86584be750 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c @@ -662,9 +662,8 @@ static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol, change = (emu->emu1010.output_source[channel] != val); if (change) { emu->emu1010.output_source[channel] = val; - snd_emu1010_fpga_lock(emu); + guard(snd_emu1010_fpga_lock)(emu); snd_emu1010_output_source_apply(emu, channel, val); - snd_emu1010_fpga_unlock(emu); } return change; } @@ -708,9 +707,8 @@ static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol, change = (emu->emu1010.input_source[channel] != val); if (change) { emu->emu1010.input_source[channel] = val; - snd_emu1010_fpga_lock(emu); + guard(snd_emu1010_fpga_lock)(emu); snd_emu1010_input_source_apply(emu, channel, val); - snd_emu1010_fpga_unlock(emu); } return change; } @@ -985,7 +983,7 @@ static int snd_emu1010_clock_source_put(struct snd_kcontrol *kcontrol, val = ucontrol->value.enumerated.item[0] ; if (val >= emu_ci->num) return -EINVAL; - snd_emu1010_fpga_lock(emu); + guard(snd_emu1010_fpga_lock)(emu); spin_lock_irq(&emu->reg_lock); change = (emu->emu1010.clock_source != val); if (change) { @@ -1002,7 +1000,6 @@ static int snd_emu1010_clock_source_put(struct snd_kcontrol *kcontrol, } else { spin_unlock_irq(&emu->reg_lock); } - snd_emu1010_fpga_unlock(emu); return change; } @@ -2330,9 +2327,9 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu, for (i = 0; i < emu_ri->n_outs; i++) emu->emu1010.output_source[i] = emu1010_map_source(emu_ri, emu_ri->out_dflts[i]); - snd_emu1010_fpga_lock(emu); - snd_emu1010_apply_sources(emu); - snd_emu1010_fpga_unlock(emu); + scoped_guard(snd_emu1010_fpga_lock, emu) { + snd_emu1010_apply_sources(emu); + } kctl = emu->ctl_clock_source = snd_ctl_new1(&snd_emu1010_clock_source, emu); err = snd_ctl_add(card, kctl); diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c index bd4734dc04cd..a12518dd4eed 100644 --- a/sound/pci/emu10k1/emuproc.c +++ b/sound/pci/emu10k1/emuproc.c @@ -166,7 +166,7 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry, u32 value2; if (emu->card_capabilities->emu_model) { - snd_emu1010_fpga_lock(emu); + guard(snd_emu1010_fpga_lock)(emu); // This represents the S/PDIF lock status on 0404b, which is // kinda weird and unhelpful, because monitoring it via IRQ is @@ -200,8 +200,6 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry, snd_iprintf(buffer, "\nS/PDIF mode: %s%s\n", value & EMU_HANA_SPDIF_MODE_RX_PRO ? "professional" : "consumer", value & EMU_HANA_SPDIF_MODE_RX_NOCOPY ? ", no copy" : ""); - - snd_emu1010_fpga_unlock(emu); } else { snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS); snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS); @@ -464,7 +462,7 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry, u32 value; int i; - snd_emu1010_fpga_lock(emu); + guard(snd_emu1010_fpga_lock)(emu); snd_iprintf(buffer, "EMU1010 Registers:\n\n"); @@ -504,8 +502,6 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry, snd_emu_proc_emu1010_link_read(emu, buffer, 0x701); } } - - snd_emu1010_fpga_unlock(emu); } static void snd_emu_proc_io_reg_read(struct snd_info_entry *entry, diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c index b60ab5671e00..69debe781177 100644 --- a/sound/pci/emu10k1/io.c +++ b/sound/pci/emu10k1/io.c @@ -297,9 +297,8 @@ void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value) void snd_emu1010_fpga_write_lock(struct snd_emu10k1 *emu, u32 reg, u32 value) { - snd_emu1010_fpga_lock(emu); + guard(snd_emu1010_fpga_lock)(emu); snd_emu1010_fpga_write_locked(emu, reg, value); - snd_emu1010_fpga_unlock(emu); } void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value) -- cgit v1.2.3 From 3abb538fffc8af73859f16e6e274962d9b53c907 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 29 Aug 2025 16:52:47 +0200 Subject: ALSA: gus: Use guard() for mutex locks Replace the manual mutex lock/unlock pairs with guard() for code simplification. As replaced with the guard(mutex), no longer used snd_gf1_mem_lock() is dropped, too. Only code refactoring, and no behavior change. Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250829145300.5460-8-tiwai@suse.de --- include/sound/gus.h | 1 - sound/isa/gus/gus_dma.c | 10 +++------- sound/isa/gus/gus_main.c | 1 - sound/isa/gus/gus_mem.c | 33 ++++++--------------------------- 4 files changed, 9 insertions(+), 36 deletions(-) (limited to 'include') diff --git a/include/sound/gus.h b/include/sound/gus.h index 1c8fb6c93e50..321ae93625eb 100644 --- a/include/sound/gus.h +++ b/include/sound/gus.h @@ -515,7 +515,6 @@ struct _SND_IW_LFO_PROGRAM { /* gus_mem.c */ -void snd_gf1_mem_lock(struct snd_gf1_mem * alloc, int xup); int snd_gf1_mem_xfree(struct snd_gf1_mem * alloc, struct snd_gf1_mem_block * block); struct snd_gf1_mem_block *snd_gf1_mem_alloc(struct snd_gf1_mem * alloc, int owner, char *name, int size, int w_16, diff --git a/sound/isa/gus/gus_dma.c b/sound/isa/gus/gus_dma.c index bb5a4e2fbfb3..7b2e7878adc7 100644 --- a/sound/isa/gus/gus_dma.c +++ b/sound/isa/gus/gus_dma.c @@ -143,18 +143,15 @@ static void snd_gf1_dma_interrupt(struct snd_gus_card * gus) int snd_gf1_dma_init(struct snd_gus_card * gus) { - mutex_lock(&gus->dma_mutex); + guard(mutex)(&gus->dma_mutex); gus->gf1.dma_shared++; - if (gus->gf1.dma_shared > 1) { - mutex_unlock(&gus->dma_mutex); + if (gus->gf1.dma_shared > 1) return 0; - } gus->gf1.interrupt_handler_dma_write = snd_gf1_dma_interrupt; gus->gf1.dma_data_pcm = gus->gf1.dma_data_pcm_last = gus->gf1.dma_data_synth = gus->gf1.dma_data_synth_last = NULL; - mutex_unlock(&gus->dma_mutex); return 0; } @@ -162,7 +159,7 @@ int snd_gf1_dma_done(struct snd_gus_card * gus) { struct snd_gf1_dma_block *block; - mutex_lock(&gus->dma_mutex); + guard(mutex)(&gus->dma_mutex); gus->gf1.dma_shared--; if (!gus->gf1.dma_shared) { snd_dma_disable(gus->gf1.dma1); @@ -179,7 +176,6 @@ int snd_gf1_dma_done(struct snd_gus_card * gus) gus->gf1.dma_data_pcm_last = gus->gf1.dma_data_synth_last = NULL; } - mutex_unlock(&gus->dma_mutex); return 0; } diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c index 873ef4046cd6..a82185c86143 100644 --- a/sound/isa/gus/gus_main.c +++ b/sound/isa/gus/gus_main.c @@ -447,4 +447,3 @@ EXPORT_SYMBOL(snd_gf1_translate_freq); EXPORT_SYMBOL(snd_gf1_mem_alloc); EXPORT_SYMBOL(snd_gf1_mem_xfree); EXPORT_SYMBOL(snd_gf1_mem_free); -EXPORT_SYMBOL(snd_gf1_mem_lock); diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c index 054058779db6..8d95d8d5abdf 100644 --- a/sound/isa/gus/gus_mem.c +++ b/sound/isa/gus/gus_mem.c @@ -15,15 +15,6 @@ static void snd_gf1_mem_info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer); #endif -void snd_gf1_mem_lock(struct snd_gf1_mem * alloc, int xup) -{ - if (!xup) { - mutex_lock(&alloc->memory_mutex); - } else { - mutex_unlock(&alloc->memory_mutex); - } -} - static struct snd_gf1_mem_block * snd_gf1_mem_xalloc(struct snd_gf1_mem *alloc, struct snd_gf1_mem_block *block, const char *name) @@ -50,7 +41,6 @@ snd_gf1_mem_xalloc(struct snd_gf1_mem *alloc, struct snd_gf1_mem_block *block, alloc->first = nblock; else nblock->prev->next = nblock; - mutex_unlock(&alloc->memory_mutex); return nblock; } pblock = pblock->next; @@ -71,7 +61,6 @@ int snd_gf1_mem_xfree(struct snd_gf1_mem * alloc, struct snd_gf1_mem_block * blo { if (block->share) { /* ok.. shared block */ block->share--; - mutex_unlock(&alloc->memory_mutex); return 0; } if (alloc->first == block) { @@ -183,7 +172,7 @@ struct snd_gf1_mem_block *snd_gf1_mem_alloc(struct snd_gf1_mem * alloc, int owne { struct snd_gf1_mem_block block, *nblock; - snd_gf1_mem_lock(alloc, 0); + guard(mutex)(&alloc->memory_mutex); if (share_id != NULL) { nblock = snd_gf1_mem_share(alloc, share_id); if (nblock != NULL) { @@ -193,36 +182,27 @@ struct snd_gf1_mem_block *snd_gf1_mem_alloc(struct snd_gf1_mem * alloc, int owne goto __std; } nblock->share++; - snd_gf1_mem_lock(alloc, 1); return NULL; } } __std: - if (snd_gf1_mem_find(alloc, &block, size, w_16, align) < 0) { - snd_gf1_mem_lock(alloc, 1); + if (snd_gf1_mem_find(alloc, &block, size, w_16, align) < 0) return NULL; - } if (share_id != NULL) memcpy(&block.share_id, share_id, sizeof(block.share_id)); block.owner = owner; nblock = snd_gf1_mem_xalloc(alloc, &block, name); - snd_gf1_mem_lock(alloc, 1); return nblock; } int snd_gf1_mem_free(struct snd_gf1_mem * alloc, unsigned int address) { - int result; struct snd_gf1_mem_block *block; - snd_gf1_mem_lock(alloc, 0); + guard(mutex)(&alloc->memory_mutex); block = snd_gf1_mem_look(alloc, address); - if (block) { - result = snd_gf1_mem_xfree(alloc, block); - snd_gf1_mem_lock(alloc, 1); - return result; - } - snd_gf1_mem_lock(alloc, 1); + if (block) + return snd_gf1_mem_xfree(alloc, block); return -EINVAL; } @@ -282,7 +262,7 @@ static void snd_gf1_mem_info_read(struct snd_info_entry *entry, gus = entry->private_data; alloc = &gus->gf1.mem_alloc; - mutex_lock(&alloc->memory_mutex); + guard(mutex)(&alloc->memory_mutex); snd_iprintf(buffer, "8-bit banks : \n "); for (i = 0; i < 4; i++) snd_iprintf(buffer, "0x%06x (%04ik)%s", alloc->banks_8[i].address, alloc->banks_8[i].size >> 10, i + 1 < 4 ? "," : ""); @@ -326,7 +306,6 @@ static void snd_gf1_mem_info_read(struct snd_info_entry *entry, } snd_iprintf(buffer, " Total: memory = %i, used = %i, free = %i\n", total, used, total - used); - mutex_unlock(&alloc->memory_mutex); #if 0 ultra_iprintf(buffer, " Verify: free = %i, max 8-bit block = %i, max 16-bit block = %i\n", ultra_memory_free_size(card, &card->gf1.mem_alloc), -- cgit v1.2.3 From 826f35b829f43dc62fb847eca6f79e8698b4994d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 29 Aug 2025 17:13:19 +0200 Subject: ALSA: synth: Use guard() for preset locks Define a macro for the preset locking/unlocking pairs for soundfont using guard() macro as a further code cleanup. The new macro is put in soundfont.h (and some function renames) along with it for avoiding unnecessary troubles with clang. Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250829151335.7342-6-tiwai@suse.de --- include/sound/soundfont.h | 18 ++++++++++++++ sound/synth/emux/soundfont.c | 56 ++++++++++---------------------------------- 2 files changed, 30 insertions(+), 44 deletions(-) (limited to 'include') diff --git a/include/sound/soundfont.h b/include/sound/soundfont.h index 8a40cc15f66d..48f8cf6de3ac 100644 --- a/include/sound/soundfont.h +++ b/include/sound/soundfont.h @@ -114,5 +114,23 @@ int snd_sf_calc_parm_decay(int msec); extern int snd_sf_vol_table[128]; int snd_sf_linear_to_log(unsigned int amount, int offset, int ratio); +/* lock access to sflist */ +static inline void snd_soundfont_lock_preset(struct snd_sf_list *sflist) +{ + mutex_lock(&sflist->presets_mutex); + guard(spinlock_irqsave)(&sflist->lock); + sflist->presets_locked = 1; +} + +/* remove lock */ +static inline void snd_soundfont_unlock_preset(struct snd_sf_list *sflist) +{ + guard(spinlock_irqsave)(&sflist->lock); + sflist->presets_locked = 0; + mutex_unlock(&sflist->presets_mutex); +} + +DEFINE_GUARD(snd_soundfont_lock_preset, struct snd_sf_list *, + snd_soundfont_lock_preset(_T), snd_soundfont_unlock_preset(_T)) #endif /* __SOUND_SOUNDFONT_H */ diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c index cbff9f7ad38c..59f3b1b6df4a 100644 --- a/sound/synth/emux/soundfont.c +++ b/sound/synth/emux/soundfont.c @@ -60,30 +60,6 @@ static int get_index(int bank, int instr, int key); static void snd_sf_init(struct snd_sf_list *sflist); static void snd_sf_clear(struct snd_sf_list *sflist); -/* - * lock access to sflist - */ -static void -lock_preset(struct snd_sf_list *sflist) -{ - mutex_lock(&sflist->presets_mutex); - guard(spinlock_irqsave)(&sflist->lock); - sflist->presets_locked = 1; -} - - -/* - * remove lock - */ -static void -unlock_preset(struct snd_sf_list *sflist) -{ - guard(spinlock_irqsave)(&sflist->lock); - sflist->presets_locked = 0; - mutex_unlock(&sflist->presets_mutex); -} - - /* * close the patch if the patch was opened by this client. */ @@ -140,10 +116,8 @@ snd_soundfont_load(struct snd_card *card, if (patch.type == SNDRV_SFNT_OPEN_PATCH) { /* grab sflist to open */ - lock_preset(sflist); - rc = open_patch(sflist, data, count, client); - unlock_preset(sflist); - return rc; + guard(snd_soundfont_lock_preset)(sflist); + return open_patch(sflist, data, count, client); } /* check if other client already opened patch */ @@ -152,7 +126,7 @@ snd_soundfont_load(struct snd_card *card, return -EBUSY; } - lock_preset(sflist); + guard(snd_soundfont_lock_preset)(sflist); rc = -EINVAL; switch (patch.type) { case SNDRV_SFNT_LOAD_INFO: @@ -190,7 +164,6 @@ snd_soundfont_load(struct snd_card *card, } break; } - unlock_preset(sflist); return rc; } @@ -1153,11 +1126,8 @@ snd_soundfont_load_guspatch(struct snd_card *card, struct snd_sf_list *sflist, const char __user *data, long count) { - int rc; - lock_preset(sflist); - rc = load_guspatch(card, sflist, data, count); - unlock_preset(sflist); - return rc; + guard(snd_soundfont_lock_preset)(sflist); + return load_guspatch(card, sflist, data, count); } @@ -1446,11 +1416,11 @@ snd_sf_free(struct snd_sf_list *sflist) if (sflist == NULL) return; - lock_preset(sflist); - if (sflist->callback.sample_reset) - sflist->callback.sample_reset(sflist->callback.private_data); - snd_sf_clear(sflist); - unlock_preset(sflist); + scoped_guard(snd_soundfont_lock_preset, sflist) { + if (sflist->callback.sample_reset) + sflist->callback.sample_reset(sflist->callback.private_data); + snd_sf_clear(sflist); + } kfree(sflist); } @@ -1462,11 +1432,10 @@ snd_sf_free(struct snd_sf_list *sflist) int snd_soundfont_remove_samples(struct snd_sf_list *sflist) { - lock_preset(sflist); + guard(snd_soundfont_lock_preset)(sflist); if (sflist->callback.sample_reset) sflist->callback.sample_reset(sflist->callback.private_data); snd_sf_clear(sflist); - unlock_preset(sflist); return 0; } @@ -1482,7 +1451,7 @@ snd_soundfont_remove_unlocked(struct snd_sf_list *sflist) struct snd_sf_zone *zp, *nextzp; struct snd_sf_sample *sp, *nextsp; - lock_preset(sflist); + guard(snd_soundfont_lock_preset)(sflist); if (sflist->callback.sample_reset) sflist->callback.sample_reset(sflist->callback.private_data); @@ -1516,6 +1485,5 @@ snd_soundfont_remove_unlocked(struct snd_sf_list *sflist) rebuild_presets(sflist); - unlock_preset(sflist); return 0; } -- cgit v1.2.3 From bbf7a84787d0dc5910d121b025dd5f4dea060768 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 26 Aug 2025 06:22:05 +0000 Subject: ASoC: soc-dapm: rename snd_soc_dapm_kcontrol_widget() to snd_soc_dapm_kcontrol_to_widget() snd_soc_dapm_kcontrol_widget() is unclear naming, rename it to snd_soc_dapm_kcontrol_to_widget(). This is prepare for dapm cleanup. This patch keeps compatible by using define, but old name will be replaced on each drivers and removed from ASoC in the future. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/875xeay54j.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 3 ++- sound/soc/soc-dapm.c | 7 +++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 2e9196b6ffba..220eb6d08534 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -719,7 +719,7 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, void snd_soc_dapm_dai_free_widgets(struct snd_soc_dapm_widget_list **list); struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm(struct snd_kcontrol *kcontrol); -struct snd_soc_dapm_widget *snd_soc_dapm_kcontrol_widget(struct snd_kcontrol *kcontrol); +struct snd_soc_dapm_widget *snd_soc_dapm_kcontrol_to_widget(struct snd_kcontrol *kcontrol); int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level); enum snd_soc_bias_level snd_soc_dapm_get_bias_level(struct snd_soc_dapm_context *dapm); @@ -729,6 +729,7 @@ void snd_soc_dapm_init_bias_level(struct snd_soc_dapm_context *dapm, enum snd_so #define snd_soc_component_force_bias_level(c, l) snd_soc_dapm_force_bias_level(&(c)->dapm, l) #define snd_soc_component_get_bias_level(c) snd_soc_dapm_get_bias_level(&(c)->dapm) #define snd_soc_component_init_bias_level(c, l) snd_soc_dapm_init_bias_level(&(c)->dapm, l) +#define snd_soc_dapm_kcontrol_widget snd_soc_dapm_kcontrol_to_widget #define for_each_dapm_widgets(list, i, widget) \ for ((i) = 0; \ diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 6782a0d6cd47..bfb2edc2f91d 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -877,16 +877,15 @@ static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol, } /** - * snd_soc_dapm_kcontrol_widget() - Returns the widget associated to a + * snd_soc_dapm_kcontrol_to_widget() - Returns the widget associated to a * kcontrol * @kcontrol: The kcontrol */ -struct snd_soc_dapm_widget *snd_soc_dapm_kcontrol_widget( - struct snd_kcontrol *kcontrol) +struct snd_soc_dapm_widget *snd_soc_dapm_kcontrol_to_widget(struct snd_kcontrol *kcontrol) { return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]; } -EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_widget); +EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_to_widget); /** * snd_soc_dapm_kcontrol_dapm() - Returns the dapm context associated to a -- cgit v1.2.3 From 2532041865305594e37c4c22bd650d52ea805ec8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 26 Aug 2025 06:22:12 +0000 Subject: ASoC: soc-dapm: rename snd_soc_dapm_kcontrol_dapm() to snd_soc_dapm_kcontrol_to_dapm() snd_soc_dapm_kcontrol_dapm() is unclear naming, rename it to snd_soc_dapm_kcontrol_to_dapm(). This is prepare for dapm cleanup. This patch keeps compatible by using define, but old name will be replaced on each drivers and removed from ASoC in the future. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/874ituy54c.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 3 ++- sound/soc/soc-dapm.c | 8 +++----- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 220eb6d08534..8add8de7a8c9 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -718,7 +718,7 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, bool (*custom_stop_condition)(struct snd_soc_dapm_widget *, enum snd_soc_dapm_direction)); void snd_soc_dapm_dai_free_widgets(struct snd_soc_dapm_widget_list **list); -struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm(struct snd_kcontrol *kcontrol); +struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_to_dapm(struct snd_kcontrol *kcontrol); struct snd_soc_dapm_widget *snd_soc_dapm_kcontrol_to_widget(struct snd_kcontrol *kcontrol); int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level); @@ -730,6 +730,7 @@ void snd_soc_dapm_init_bias_level(struct snd_soc_dapm_context *dapm, enum snd_so #define snd_soc_component_get_bias_level(c) snd_soc_dapm_get_bias_level(&(c)->dapm) #define snd_soc_component_init_bias_level(c, l) snd_soc_dapm_init_bias_level(&(c)->dapm, l) #define snd_soc_dapm_kcontrol_widget snd_soc_dapm_kcontrol_to_widget +#define snd_soc_dapm_kcontrol_dapm snd_soc_dapm_kcontrol_to_dapm #define for_each_dapm_widgets(list, i, widget) \ for ((i) = 0; \ diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index bfb2edc2f91d..25b2ea14d659 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -888,19 +888,17 @@ struct snd_soc_dapm_widget *snd_soc_dapm_kcontrol_to_widget(struct snd_kcontrol EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_to_widget); /** - * snd_soc_dapm_kcontrol_dapm() - Returns the dapm context associated to a - * kcontrol + * snd_soc_dapm_kcontrol_to_dapm() - Returns the dapm context associated to a kcontrol * @kcontrol: The kcontrol * * Note: This function must only be used on kcontrols that are known to have * been registered for a CODEC. Otherwise the behaviour is undefined. */ -struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm( - struct snd_kcontrol *kcontrol) +struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_to_dapm(struct snd_kcontrol *kcontrol) { return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->dapm; } -EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_dapm); +EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_to_dapm); static void dapm_reset(struct snd_soc_card *card) { -- cgit v1.2.3 From f6883f0f03575ecc8c4c5d2a04339bac91eb33d7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 26 Aug 2025 06:22:19 +0000 Subject: ASoC: soc-dapm: rename dapm_kcontrol_get_value() to snd_soc_dapm_kcontrol_get_value() dapm_kcontrol_get_value() is global function, adds snd_soc_ prefix This patch keeps compatible by using define, but old name will be replaced on each drivers and removed from ASoC in the future. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87349ey546.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 3 ++- sound/soc/soc-dapm.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 8add8de7a8c9..cd02fedb2624 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -699,7 +699,6 @@ int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm); int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin); int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, const char *pin); int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, const char *pin); -unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol); void snd_soc_dapm_mark_endpoints_dirty(struct snd_soc_card *card); /* @@ -720,6 +719,7 @@ void snd_soc_dapm_dai_free_widgets(struct snd_soc_dapm_widget_list **list); struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_to_dapm(struct snd_kcontrol *kcontrol); struct snd_soc_dapm_widget *snd_soc_dapm_kcontrol_to_widget(struct snd_kcontrol *kcontrol); +unsigned int snd_soc_dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol); int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level); enum snd_soc_bias_level snd_soc_dapm_get_bias_level(struct snd_soc_dapm_context *dapm); @@ -731,6 +731,7 @@ void snd_soc_dapm_init_bias_level(struct snd_soc_dapm_context *dapm, enum snd_so #define snd_soc_component_init_bias_level(c, l) snd_soc_dapm_init_bias_level(&(c)->dapm, l) #define snd_soc_dapm_kcontrol_widget snd_soc_dapm_kcontrol_to_widget #define snd_soc_dapm_kcontrol_dapm snd_soc_dapm_kcontrol_to_dapm +#define dapm_kcontrol_get_value snd_soc_dapm_kcontrol_get_value #define for_each_dapm_widgets(list, i, widget) \ for ((i) = 0; \ diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 25b2ea14d659..f8ecf86a3d2b 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -838,13 +838,13 @@ static struct list_head *dapm_kcontrol_get_path_list( list_for_each_entry(path, dapm_kcontrol_get_path_list(kcontrol), \ list_kcontrol) -unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol) +unsigned int snd_soc_dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol) { struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol); return data->value; } -EXPORT_SYMBOL_GPL(dapm_kcontrol_get_value); +EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_get_value); static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol, unsigned int value) -- cgit v1.2.3 From 8a9772ec08f87c9e45ab1ad2c8d2b8c1763836eb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 26 Aug 2025 06:22:26 +0000 Subject: ASoC: soc-dapm: rename snd_soc_kcontrol_component() to snd_soc_kcontrol_to_component() We have 2 similar functions, both converts date from snd_kcontrol to snd_soc_component. (A) snd_soc_kcontrol_component() (B) snd_soc_dapm_kcontrol_component() (A) is just wrapper for snd_kcontrol_chip(). (B) is for more complex conversion. Having similar functions is confusable. So (A) will be replaced to original snd_kcontrol_chip(). (B) will be stay, but the function name should be xx_to_xx(). And it is defined at soc-component.h. It should be implemented at soc-dapm.c. This patch renames it to snd_soc_dapm_kcontrol_to_component(), and move to soc-dapm.c. This patch keeps compatible by using define, but old name will be replaced on each drivers and removed from ASoC in the future. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/871poyy53x.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 14 -------------- include/sound/soc-dapm.h | 2 ++ sound/soc/soc-dapm.c | 14 ++++++++++++++ 3 files changed, 16 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 54bfa0cb1085..48e45cbe82e5 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -286,20 +286,6 @@ static inline struct snd_soc_dapm_context *snd_soc_component_get_dapm( return &component->dapm; } -/** - * snd_soc_dapm_kcontrol_component() - Returns the component associated to a - * kcontrol - * @kcontrol: The kcontrol - * - * This function must only be used on DAPM contexts that are known to be part of - * a COMPONENT (e.g. in a COMPONENT driver). Otherwise the behavior is undefined - */ -static inline struct snd_soc_component *snd_soc_dapm_kcontrol_component( - struct snd_kcontrol *kcontrol) -{ - return snd_soc_dapm_to_component(snd_soc_dapm_kcontrol_dapm(kcontrol)); -} - /** * snd_soc_component_cache_sync() - Sync the register cache with the hardware * @component: COMPONENT to sync diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index cd02fedb2624..ed39458b94bf 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -719,6 +719,7 @@ void snd_soc_dapm_dai_free_widgets(struct snd_soc_dapm_widget_list **list); struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_to_dapm(struct snd_kcontrol *kcontrol); struct snd_soc_dapm_widget *snd_soc_dapm_kcontrol_to_widget(struct snd_kcontrol *kcontrol); +struct snd_soc_component *snd_soc_dapm_kcontrol_to_component(struct snd_kcontrol *kcontrol); unsigned int snd_soc_dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol); int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level); @@ -732,6 +733,7 @@ void snd_soc_dapm_init_bias_level(struct snd_soc_dapm_context *dapm, enum snd_so #define snd_soc_dapm_kcontrol_widget snd_soc_dapm_kcontrol_to_widget #define snd_soc_dapm_kcontrol_dapm snd_soc_dapm_kcontrol_to_dapm #define dapm_kcontrol_get_value snd_soc_dapm_kcontrol_get_value +#define snd_soc_dapm_kcontrol_component snd_soc_dapm_kcontrol_to_component #define for_each_dapm_widgets(list, i, widget) \ for ((i) = 0; \ diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index f8ecf86a3d2b..d74c096cc208 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -900,6 +900,20 @@ struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_to_dapm(struct snd_kcontrol * } EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_to_dapm); +/** + * snd_soc_dapm_kcontrol_to_component() - Returns the component associated to a + * kcontrol + * @kcontrol: The kcontrol + * + * This function must only be used on DAPM contexts that are known to be part of + * a COMPONENT (e.g. in a COMPONENT driver). Otherwise the behavior is undefined + */ +struct snd_soc_component *snd_soc_dapm_kcontrol_to_component(struct snd_kcontrol *kcontrol) +{ + return snd_soc_dapm_to_component(snd_soc_dapm_kcontrol_to_dapm(kcontrol)); +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_to_component); + static void dapm_reset(struct snd_soc_card *card) { struct snd_soc_dapm_widget *w; -- cgit v1.2.3 From 2c92e2fbe9e22cefdae87d8a0d654691ee4c1957 Mon Sep 17 00:00:00 2001 From: Joris Verhaegen Date: Fri, 5 Sep 2025 10:12:54 +0100 Subject: ALSA: compress_offload: Add 64-bit safe timestamp infrastructure The copied_total field in struct snd_compr_tstamp is a 32-bit value that can overflow on long-running high-bitrate streams, leading to incorrect calculations for buffer availablility. This patch adds a 64-bit safe timestamping mechanism. A new UAPI struct, snd_compr_tstamp64, is added which uses 64-bit types for byte counters. The relevant ops structures across the ASoC and core compress code are updated to use this new struct. ASoC drivers are updated to use u64 counters. Internal timestamps being u64 now, a compatibility function is added to convert the 64-bit timestamp back to the 32-bit format for legacy ioctl callers. Reviewed-by: Miller Liang Tested-by: Joris Verhaegen Signed-off-by: Joris Verhaegen Reviewed-by: Srinivas Kandagatla Reviewed-by: Charles Keepax Acked-by: Mark Brown Acked-by: Vinod Koul Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250905091301.2711705-2-verhaegen@google.com --- include/sound/compress_driver.h | 2 +- include/sound/soc-component.h | 4 +- include/sound/soc-dai.h | 7 +-- include/uapi/sound/compress_offload.h | 19 +++++++++ sound/core/compress_offload.c | 52 +++++++++++++++-------- sound/soc/codecs/wm_adsp.c | 4 +- sound/soc/codecs/wm_adsp.h | 2 +- sound/soc/intel/atom/sst-mfld-platform-compress.c | 12 +++--- sound/soc/intel/atom/sst-mfld-platform.h | 2 +- sound/soc/intel/atom/sst/sst_drv_interface.c | 9 ++-- sound/soc/intel/avs/probes.c | 2 +- sound/soc/qcom/qdsp6/q6apm-dai.c | 26 +++++++----- sound/soc/qcom/qdsp6/q6asm-dai.c | 26 +++++++----- sound/soc/soc-component.c | 2 +- sound/soc/soc-compress.c | 2 +- sound/soc/soc-dai.c | 2 +- sound/soc/sof/amd/acp-probes.c | 2 +- sound/soc/sof/compress.c | 2 +- sound/soc/sof/intel/hda-probes.c | 2 +- sound/soc/sof/sof-client-probes.c | 2 +- sound/soc/sof/sof-client-probes.h | 4 +- sound/soc/sprd/sprd-pcm-compress.c | 6 +-- sound/soc/sprd/sprd-pcm-dma.h | 4 +- sound/soc/uniphier/aio-compress.c | 2 +- 24 files changed, 125 insertions(+), 72 deletions(-) (limited to 'include') diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index b55c9eeb2b54..9e3d801e45ec 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h @@ -161,7 +161,7 @@ struct snd_compr_ops { struct snd_compr_metadata *metadata); int (*trigger)(struct snd_compr_stream *stream, int cmd); int (*pointer)(struct snd_compr_stream *stream, - struct snd_compr_tstamp *tstamp); + struct snd_compr_tstamp64 *tstamp); int (*copy)(struct snd_compr_stream *stream, char __user *buf, size_t count); int (*mmap)(struct snd_compr_stream *stream, diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 2caa807c6249..cdb536c4ab2b 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -47,7 +47,7 @@ struct snd_compress_ops { struct snd_compr_stream *stream, int cmd); int (*pointer)(struct snd_soc_component *component, struct snd_compr_stream *stream, - struct snd_compr_tstamp *tstamp); + struct snd_compr_tstamp64 *tstamp); int (*copy)(struct snd_soc_component *component, struct snd_compr_stream *stream, char __user *buf, size_t count); @@ -498,7 +498,7 @@ int snd_soc_component_compr_get_codec_caps(struct snd_compr_stream *cstream, struct snd_compr_codec_caps *codec); int snd_soc_component_compr_ack(struct snd_compr_stream *cstream, size_t bytes); int snd_soc_component_compr_pointer(struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp); + struct snd_compr_tstamp64 *tstamp); int snd_soc_component_compr_copy(struct snd_compr_stream *cstream, char __user *buf, size_t count); int snd_soc_component_compr_set_metadata(struct snd_compr_stream *cstream, diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 166c29557e9d..224396927aef 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -256,7 +256,7 @@ int snd_soc_dai_compr_ack(struct snd_soc_dai *dai, size_t bytes); int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai, struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp); + struct snd_compr_tstamp64 *tstamp); int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai, struct snd_compr_stream *cstream, struct snd_compr_metadata *metadata); @@ -383,8 +383,9 @@ struct snd_soc_cdai_ops { struct snd_compr_metadata *, struct snd_soc_dai *); int (*trigger)(struct snd_compr_stream *, int, struct snd_soc_dai *); - int (*pointer)(struct snd_compr_stream *, - struct snd_compr_tstamp *, struct snd_soc_dai *); + int (*pointer)(struct snd_compr_stream *stream, + struct snd_compr_tstamp64 *tstamp, + struct snd_soc_dai *dai); int (*ack)(struct snd_compr_stream *, size_t, struct snd_soc_dai *); }; diff --git a/include/uapi/sound/compress_offload.h b/include/uapi/sound/compress_offload.h index d62eb93af0ed..abd0ea3f86ee 100644 --- a/include/uapi/sound/compress_offload.h +++ b/include/uapi/sound/compress_offload.h @@ -56,6 +56,25 @@ struct snd_compr_tstamp { __u32 sampling_rate; } __attribute__((packed, aligned(4))); +/** + * struct snd_compr_tstamp64 - timestamp descriptor with fields in 64 bit + * @byte_offset: Byte offset in ring buffer to DSP + * @copied_total: Total number of bytes copied from/to ring buffer to/by DSP + * @pcm_frames: Frames decoded or encoded by DSP. This field will evolve by + * large steps and should only be used to monitor encoding/decoding + * progress. It shall not be used for timing estimates. + * @pcm_io_frames: Frames rendered or received by DSP into a mixer or an audio + * output/input. This field should be used for A/V sync or time estimates. + * @sampling_rate: sampling rate of audio + */ +struct snd_compr_tstamp64 { + __u32 byte_offset; + __u64 copied_total; + __u64 pcm_frames; + __u64 pcm_io_frames; + __u32 sampling_rate; +} __attribute__((packed, aligned(4))); + /** * struct snd_compr_avail - avail descriptor * @avail: Number of bytes available in ring buffer for writing/reading diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index a66f258cafaa..d3164aa07158 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -176,14 +176,25 @@ static int snd_compr_free(struct inode *inode, struct file *f) return 0; } +static void +snd_compr_tstamp32_from_64(struct snd_compr_tstamp *tstamp32, + const struct snd_compr_tstamp64 *tstamp64) +{ + tstamp32->byte_offset = tstamp64->byte_offset; + tstamp32->copied_total = (u32)tstamp64->copied_total; + tstamp32->pcm_frames = (u32)tstamp64->pcm_frames; + tstamp32->pcm_io_frames = (u32)tstamp64->pcm_io_frames; + tstamp32->sampling_rate = tstamp64->sampling_rate; +} + static int snd_compr_update_tstamp(struct snd_compr_stream *stream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { if (!stream->ops->pointer) return -ENOTSUPP; stream->ops->pointer(stream, tstamp); - pr_debug("dsp consumed till %d total %d bytes\n", - tstamp->byte_offset, tstamp->copied_total); + pr_debug("dsp consumed till %u total %llu bytes\n", tstamp->byte_offset, + tstamp->copied_total); if (stream->direction == SND_COMPRESS_PLAYBACK) stream->runtime->total_bytes_transferred = tstamp->copied_total; else @@ -194,8 +205,11 @@ static int snd_compr_update_tstamp(struct snd_compr_stream *stream, static size_t snd_compr_calc_avail(struct snd_compr_stream *stream, struct snd_compr_avail *avail) { + struct snd_compr_tstamp64 tstamp64 = { 0 }; + memset(avail, 0, sizeof(*avail)); - snd_compr_update_tstamp(stream, &avail->tstamp); + snd_compr_update_tstamp(stream, &tstamp64); + snd_compr_tstamp32_from_64(&avail->tstamp, &tstamp64); /* Still need to return avail even if tstamp can't be filled in */ if (stream->runtime->total_bytes_available == 0 && @@ -204,9 +218,9 @@ static size_t snd_compr_calc_avail(struct snd_compr_stream *stream, pr_debug("detected init and someone forgot to do a write\n"); return stream->runtime->buffer_size; } - pr_debug("app wrote %lld, DSP consumed %lld\n", - stream->runtime->total_bytes_available, - stream->runtime->total_bytes_transferred); + pr_debug("app wrote %llu, DSP consumed %llu\n", + stream->runtime->total_bytes_available, + stream->runtime->total_bytes_transferred); if (stream->runtime->total_bytes_available == stream->runtime->total_bytes_transferred) { if (stream->direction == SND_COMPRESS_PLAYBACK) { @@ -223,7 +237,7 @@ static size_t snd_compr_calc_avail(struct snd_compr_stream *stream, if (stream->direction == SND_COMPRESS_PLAYBACK) avail->avail = stream->runtime->buffer_size - avail->avail; - pr_debug("ret avail as %lld\n", avail->avail); + pr_debug("ret avail as %llu\n", avail->avail); return avail->avail; } @@ -274,8 +288,7 @@ static int snd_compr_write_data(struct snd_compr_stream *stream, (app_pointer * runtime->buffer_size); dstn = runtime->buffer + app_pointer; - pr_debug("copying %ld at %lld\n", - (unsigned long)count, app_pointer); + pr_debug("copying %lu at %llu\n", (unsigned long)count, app_pointer); if (count < runtime->buffer_size - app_pointer) { if (copy_from_user(dstn, buf, count)) return -EFAULT; @@ -318,7 +331,7 @@ static ssize_t snd_compr_write(struct file *f, const char __user *buf, } avail = snd_compr_get_avail(stream); - pr_debug("avail returned %ld\n", (unsigned long)avail); + pr_debug("avail returned %lu\n", (unsigned long)avail); /* calculate how much we can write to buffer */ if (avail > count) avail = count; @@ -374,7 +387,7 @@ static ssize_t snd_compr_read(struct file *f, char __user *buf, } avail = snd_compr_get_avail(stream); - pr_debug("avail returned %ld\n", (unsigned long)avail); + pr_debug("avail returned %lu\n", (unsigned long)avail); /* calculate how much we can read from buffer */ if (avail > count) avail = count; @@ -443,7 +456,7 @@ static __poll_t snd_compr_poll(struct file *f, poll_table *wait) #endif avail = snd_compr_get_avail(stream); - pr_debug("avail is %ld\n", (unsigned long)avail); + pr_debug("avail is %lu\n", (unsigned long)avail); /* check if we have at least one fragment to fill */ switch (runtime->state) { case SNDRV_PCM_STATE_DRAINING: @@ -726,13 +739,18 @@ snd_compr_set_metadata(struct snd_compr_stream *stream, unsigned long arg) static inline int snd_compr_tstamp(struct snd_compr_stream *stream, unsigned long arg) { - struct snd_compr_tstamp tstamp = {0}; + struct snd_compr_tstamp64 tstamp64 = { 0 }; + struct snd_compr_tstamp tstamp32 = { 0 }; int ret; - ret = snd_compr_update_tstamp(stream, &tstamp); - if (ret == 0) + ret = snd_compr_update_tstamp(stream, &tstamp64); + if (ret == 0) { + snd_compr_tstamp32_from_64(&tstamp32, &tstamp64); ret = copy_to_user((struct snd_compr_tstamp __user *)arg, - &tstamp, sizeof(tstamp)) ? -EFAULT : 0; + &tstamp32, sizeof(tstamp32)) ? + -EFAULT : + 0; + } return ret; } diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 8a1d5cc75d6c..f197034fd594 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -173,7 +173,7 @@ struct wm_adsp_compr { struct snd_compressed_buffer size; u32 *raw_buf; - unsigned int copied_total; + u64 copied_total; unsigned int sample_rate; @@ -1860,7 +1860,7 @@ static int wm_adsp_buffer_reenable_irq(struct wm_adsp_compr_buf *buf) int wm_adsp_compr_pointer(struct snd_soc_component *component, struct snd_compr_stream *stream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { struct wm_adsp_compr *compr = stream->runtime->private_data; struct wm_adsp *dsp = compr->dsp; diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index 25210d404bf1..8035fda71f8d 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h @@ -131,7 +131,7 @@ int wm_adsp_compr_trigger(struct snd_soc_component *component, int wm_adsp_compr_handle_irq(struct wm_adsp *dsp); int wm_adsp_compr_pointer(struct snd_soc_component *component, struct snd_compr_stream *stream, - struct snd_compr_tstamp *tstamp); + struct snd_compr_tstamp64 *tstamp); int wm_adsp_compr_copy(struct snd_soc_component *component, struct snd_compr_stream *stream, char __user *buf, size_t count); diff --git a/sound/soc/intel/atom/sst-mfld-platform-compress.c b/sound/soc/intel/atom/sst-mfld-platform-compress.c index 89c9c5ad6b21..9dfb0a814b94 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-compress.c +++ b/sound/soc/intel/atom/sst-mfld-platform-compress.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "sst-mfld-platform.h" /* compress stream operations */ @@ -202,15 +203,16 @@ static int sst_platform_compr_trigger(struct snd_soc_component *component, static int sst_platform_compr_pointer(struct snd_soc_component *component, struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { struct sst_runtime_stream *stream; + u64 temp_copied_total = tstamp->copied_total; - stream = cstream->runtime->private_data; + stream = cstream->runtime->private_data; stream->compr_ops->tstamp(sst->dev, stream->id, tstamp); - tstamp->byte_offset = tstamp->copied_total % - (u32)cstream->runtime->buffer_size; - pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset); + tstamp->byte_offset = + do_div(temp_copied_total, cstream->runtime->buffer_size); + pr_debug("calc bytes offset/copied bytes as %u\n", tstamp->byte_offset); return 0; } diff --git a/sound/soc/intel/atom/sst-mfld-platform.h b/sound/soc/intel/atom/sst-mfld-platform.h index 8b5777d3229a..a0e33f7f01c5 100644 --- a/sound/soc/intel/atom/sst-mfld-platform.h +++ b/sound/soc/intel/atom/sst-mfld-platform.h @@ -105,7 +105,7 @@ struct compress_sst_ops { int (*stream_pause_release)(struct device *dev, unsigned int str_id); int (*tstamp)(struct device *dev, unsigned int str_id, - struct snd_compr_tstamp *tstamp); + struct snd_compr_tstamp64 *tstamp); int (*ack)(struct device *dev, unsigned int str_id, unsigned long bytes); int (*close)(struct device *dev, unsigned int str_id); diff --git a/sound/soc/intel/atom/sst/sst_drv_interface.c b/sound/soc/intel/atom/sst/sst_drv_interface.c index 8bb27f86eb65..2646c4632ca1 100644 --- a/sound/soc/intel/atom/sst/sst_drv_interface.c +++ b/sound/soc/intel/atom/sst/sst_drv_interface.c @@ -326,7 +326,7 @@ static int sst_cdev_stream_partial_drain(struct device *dev, } static int sst_cdev_tstamp(struct device *dev, unsigned int str_id, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { struct snd_sst_tstamp fw_tstamp = {0,}; struct stream_info *stream; @@ -349,10 +349,11 @@ static int sst_cdev_tstamp(struct device *dev, unsigned int str_id, (u64)stream->num_ch * SST_GET_BYTES_PER_SAMPLE(24)); tstamp->sampling_rate = fw_tstamp.sampling_frequency; - dev_dbg(dev, "PCM = %u\n", tstamp->pcm_io_frames); - dev_dbg(dev, "Ptr Query on strid = %d copied_total %d, decodec %d\n", + dev_dbg(dev, "PCM = %llu\n", tstamp->pcm_io_frames); + dev_dbg(dev, + "Ptr Query on strid = %d copied_total %llu, decodec %llu\n", str_id, tstamp->copied_total, tstamp->pcm_frames); - dev_dbg(dev, "rendered %d\n", tstamp->pcm_io_frames); + dev_dbg(dev, "rendered %llu\n", tstamp->pcm_io_frames); return 0; } diff --git a/sound/soc/intel/avs/probes.c b/sound/soc/intel/avs/probes.c index a42736b9aa55..b5b4b0754b71 100644 --- a/sound/soc/intel/avs/probes.c +++ b/sound/soc/intel/avs/probes.c @@ -213,7 +213,7 @@ static int avs_probe_compr_trigger(struct snd_compr_stream *cstream, int cmd, } static int avs_probe_compr_pointer(struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp, struct snd_soc_dai *dai) + struct snd_compr_tstamp64 *tstamp, struct snd_soc_dai *dai) { struct hdac_ext_stream *host_stream = avs_compr_get_host_stream(cstream); struct snd_soc_pcm_stream *pstream; diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index 2cd522108221..09da26f712a6 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -65,9 +66,9 @@ struct q6apm_dai_rtd { unsigned int pcm_size; unsigned int pcm_count; unsigned int periods; - unsigned int bytes_sent; - unsigned int bytes_received; - unsigned int copied_total; + uint64_t bytes_sent; + uint64_t bytes_received; + uint64_t copied_total; uint16_t bits_per_sample; snd_pcm_uframes_t queue_ptr; bool next_track; @@ -575,15 +576,17 @@ static int q6apm_dai_compr_get_codec_caps(struct snd_soc_component *component, static int q6apm_dai_compr_pointer(struct snd_soc_component *component, struct snd_compr_stream *stream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { struct snd_compr_runtime *runtime = stream->runtime; struct q6apm_dai_rtd *prtd = runtime->private_data; unsigned long flags; + uint64_t temp_copied_total; spin_lock_irqsave(&prtd->lock, flags); tstamp->copied_total = prtd->copied_total; - tstamp->byte_offset = prtd->copied_total % prtd->pcm_size; + temp_copied_total = tstamp->copied_total; + tstamp->byte_offset = do_div(temp_copied_total, prtd->pcm_size); spin_unlock_irqrestore(&prtd->lock, flags); return 0; @@ -760,21 +763,24 @@ static int q6apm_compr_copy(struct snd_soc_component *component, size_t copy; u32 wflags = 0; u32 app_pointer; - u32 bytes_received; + uint64_t bytes_received; + uint64_t temp_bytes_received; uint32_t bytes_to_write; - int avail, bytes_in_flight = 0; + uint64_t avail, bytes_in_flight = 0; bytes_received = prtd->bytes_received; + temp_bytes_received = bytes_received; /** * Make sure that next track data pointer is aligned at 32 bit boundary * This is a Mandatory requirement from DSP data buffers alignment */ - if (prtd->next_track) + if (prtd->next_track) { bytes_received = ALIGN(prtd->bytes_received, prtd->pcm_count); + temp_bytes_received = bytes_received; + } - app_pointer = bytes_received/prtd->pcm_size; - app_pointer = bytes_received - (app_pointer * prtd->pcm_size); + app_pointer = do_div(temp_bytes_received, prtd->pcm_size); dstn = prtd->dma_buffer.area + app_pointer; if (count < prtd->pcm_size - app_pointer) { diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index a400c9a31fea..b616ce316d2f 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -59,9 +60,9 @@ struct q6asm_dai_rtd { unsigned int pcm_count; unsigned int pcm_irq_pos; /* IRQ position */ unsigned int periods; - unsigned int bytes_sent; - unsigned int bytes_received; - unsigned int copied_total; + uint64_t bytes_sent; + uint64_t bytes_received; + uint64_t copied_total; uint16_t bits_per_sample; uint16_t source; /* Encoding source bit mask */ struct audio_client *audio_client; @@ -1026,16 +1027,18 @@ static int q6asm_dai_compr_trigger(struct snd_soc_component *component, static int q6asm_dai_compr_pointer(struct snd_soc_component *component, struct snd_compr_stream *stream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { struct snd_compr_runtime *runtime = stream->runtime; struct q6asm_dai_rtd *prtd = runtime->private_data; unsigned long flags; + uint64_t temp_copied_total; spin_lock_irqsave(&prtd->lock, flags); tstamp->copied_total = prtd->copied_total; - tstamp->byte_offset = prtd->copied_total % prtd->pcm_size; + temp_copied_total = tstamp->copied_total; + tstamp->byte_offset = do_div(temp_copied_total, prtd->pcm_size); spin_unlock_irqrestore(&prtd->lock, flags); @@ -1050,23 +1053,26 @@ static int q6asm_compr_copy(struct snd_soc_component *component, struct q6asm_dai_rtd *prtd = runtime->private_data; unsigned long flags; u32 wflags = 0; - int avail, bytes_in_flight = 0; + uint64_t avail, bytes_in_flight = 0; void *dstn; size_t copy; u32 app_pointer; - u32 bytes_received; + uint64_t bytes_received; + uint64_t temp_bytes_received; bytes_received = prtd->bytes_received; + temp_bytes_received = bytes_received; /** * Make sure that next track data pointer is aligned at 32 bit boundary * This is a Mandatory requirement from DSP data buffers alignment */ - if (prtd->next_track) + if (prtd->next_track) { bytes_received = ALIGN(prtd->bytes_received, prtd->pcm_count); + temp_bytes_received = bytes_received; + } - app_pointer = bytes_received/prtd->pcm_size; - app_pointer = bytes_received - (app_pointer * prtd->pcm_size); + app_pointer = do_div(temp_bytes_received, prtd->pcm_size); dstn = prtd->dma_buffer.area + app_pointer; if (count < prtd->pcm_size - app_pointer) { diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index 65c495094024..c815fd1b3fd1 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -637,7 +637,7 @@ int snd_soc_component_compr_ack(struct snd_compr_stream *cstream, size_t bytes) EXPORT_SYMBOL_GPL(snd_soc_component_compr_ack); int snd_soc_component_compr_pointer(struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_soc_component *component; diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 01d1d6bee28c..7b81dffc6a93 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -457,7 +457,7 @@ err: } static int soc_compr_pointer(struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; int ret; diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 32f46a38682b..f231b4174b5f 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -774,7 +774,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_compr_ack); int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai, struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { int ret = 0; diff --git a/sound/soc/sof/amd/acp-probes.c b/sound/soc/sof/amd/acp-probes.c index 0d0f8ec4aed8..ce51ed108a47 100644 --- a/sound/soc/sof/amd/acp-probes.c +++ b/sound/soc/sof/amd/acp-probes.c @@ -108,7 +108,7 @@ static int acp_probes_compr_trigger(struct sof_client_dev *cdev, static int acp_probes_compr_pointer(struct sof_client_dev *cdev, struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp, + struct snd_compr_tstamp64 *tstamp, struct snd_soc_dai *dai) { struct acp_dsp_stream *stream = cstream->runtime->private_data; diff --git a/sound/soc/sof/compress.c b/sound/soc/sof/compress.c index d7b044f33d79..90b932ae3bab 100644 --- a/sound/soc/sof/compress.c +++ b/sound/soc/sof/compress.c @@ -361,7 +361,7 @@ static int sof_compr_copy(struct snd_soc_component *component, static int sof_compr_pointer(struct snd_soc_component *component, struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { struct snd_sof_pcm *spcm; struct snd_soc_pcm_runtime *rtd = cstream->private_data; diff --git a/sound/soc/sof/intel/hda-probes.c b/sound/soc/sof/intel/hda-probes.c index c645346c2c84..b06933cebc45 100644 --- a/sound/soc/sof/intel/hda-probes.c +++ b/sound/soc/sof/intel/hda-probes.c @@ -112,7 +112,7 @@ static int hda_probes_compr_trigger(struct sof_client_dev *cdev, static int hda_probes_compr_pointer(struct sof_client_dev *cdev, struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp, + struct snd_compr_tstamp64 *tstamp, struct snd_soc_dai *dai) { struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream); diff --git a/sound/soc/sof/sof-client-probes.c b/sound/soc/sof/sof-client-probes.c index 663c0d3c314c..1353e911501a 100644 --- a/sound/soc/sof/sof-client-probes.c +++ b/sound/soc/sof/sof-client-probes.c @@ -137,7 +137,7 @@ static int sof_probes_compr_trigger(struct snd_compr_stream *cstream, int cmd, } static int sof_probes_compr_pointer(struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp, + struct snd_compr_tstamp64 *tstamp, struct snd_soc_dai *dai) { struct snd_soc_card *card = snd_soc_component_get_drvdata(dai->component); diff --git a/sound/soc/sof/sof-client-probes.h b/sound/soc/sof/sof-client-probes.h index da04d65b8d99..8713b69cda4b 100644 --- a/sound/soc/sof/sof-client-probes.h +++ b/sound/soc/sof/sof-client-probes.h @@ -4,7 +4,7 @@ #define __SOF_CLIENT_PROBES_H struct snd_compr_stream; -struct snd_compr_tstamp; +struct snd_compr_tstamp64; struct snd_compr_params; struct sof_client_dev; struct snd_soc_dai; @@ -24,7 +24,7 @@ struct sof_probes_host_ops { int (*trigger)(struct sof_client_dev *cdev, struct snd_compr_stream *cstream, int cmd, struct snd_soc_dai *dai); int (*pointer)(struct sof_client_dev *cdev, struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp, + struct snd_compr_tstamp64 *tstamp, struct snd_soc_dai *dai); }; diff --git a/sound/soc/sprd/sprd-pcm-compress.c b/sound/soc/sprd/sprd-pcm-compress.c index 57bd1a0728ac..4b6ebfa5b033 100644 --- a/sound/soc/sprd/sprd-pcm-compress.c +++ b/sound/soc/sprd/sprd-pcm-compress.c @@ -85,9 +85,9 @@ struct sprd_compr_stream { int info_size; /* Data size copied to IRAM buffer */ - int copied_total; + u64 copied_total; /* Total received data size from userspace */ - int received_total; + u64 received_total; /* Stage 0 IRAM buffer received data size */ int received_stage0; /* Stage 1 DDR buffer received data size */ @@ -513,7 +513,7 @@ static int sprd_platform_compr_trigger(struct snd_soc_component *component, static int sprd_platform_compr_pointer(struct snd_soc_component *component, struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { struct snd_compr_runtime *runtime = cstream->runtime; struct sprd_compr_stream *stream = runtime->private_data; diff --git a/sound/soc/sprd/sprd-pcm-dma.h b/sound/soc/sprd/sprd-pcm-dma.h index be5e385f5e42..c5935a1367e6 100644 --- a/sound/soc/sprd/sprd-pcm-dma.h +++ b/sound/soc/sprd/sprd-pcm-dma.h @@ -19,7 +19,7 @@ struct sprd_compr_playinfo { int total_time; int current_time; int total_data_length; - int current_data_offset; + u64 current_data_offset; }; struct sprd_compr_params { @@ -46,7 +46,7 @@ struct sprd_compr_ops { int (*stop)(int str_id); int (*pause)(int str_id); int (*pause_release)(int str_id); - int (*drain)(int received_total); + int (*drain)(u64 received_total); int (*set_params)(int str_id, struct sprd_compr_params *params); }; diff --git a/sound/soc/uniphier/aio-compress.c b/sound/soc/uniphier/aio-compress.c index 4a19d4908ffd..b18af98a552b 100644 --- a/sound/soc/uniphier/aio-compress.c +++ b/sound/soc/uniphier/aio-compress.c @@ -249,7 +249,7 @@ static int uniphier_aio_compr_trigger(struct snd_soc_component *component, static int uniphier_aio_compr_pointer(struct snd_soc_component *component, struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp64 *tstamp) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_compr_runtime *runtime = cstream->runtime; -- cgit v1.2.3 From f20a53974f79619d0ef6c9f17bb8693499fb6ebb Mon Sep 17 00:00:00 2001 From: Joris Verhaegen Date: Fri, 5 Sep 2025 10:12:55 +0100 Subject: ALSA: compress_offload: Add SNDRV_COMPRESS_TSTAMP64 ioctl The previous patch introduced the internal infrastructure for handling 64-bit timestamps. This patch exposes this capability to user-space. Define the new ioctl command SNDRV_COMPRESS_TSTAMP64, which allows applications to fetch the overflow-safe struct snd_compr_tstamp64. The ioctl dispatch table is updated to handle the new command by calling a new snd_compr_tstamp64 handler, while the legacy path is renamed to snd_compr_tstamp32 for clarity. This patch bumps the SNDRV_COMPRESS_VERSION to 0.4.0. Reviewed-by: Miller Liang Tested-by: Joris Verhaegen Signed-off-by: Joris Verhaegen Reviewed-by: Charles Keepax Acked-by: Mark Brown Acked-by: Vinod Koul Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250905091301.2711705-3-verhaegen@google.com --- include/uapi/sound/compress_offload.h | 5 +++-- sound/core/compress_offload.c | 19 +++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/include/uapi/sound/compress_offload.h b/include/uapi/sound/compress_offload.h index abd0ea3f86ee..70b8921601f9 100644 --- a/include/uapi/sound/compress_offload.h +++ b/include/uapi/sound/compress_offload.h @@ -13,8 +13,7 @@ #include #include - -#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 3, 0) +#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 4, 0) /** * struct snd_compressed_buffer - compressed buffer * @fragment_size: size of buffer fragment in bytes @@ -208,6 +207,7 @@ struct snd_compr_task_status { * Note: only codec params can be changed runtime and stream params cant be * SNDRV_COMPRESS_GET_PARAMS: Query codec params * SNDRV_COMPRESS_TSTAMP: get the current timestamp value + * SNDRV_COMPRESS_TSTAMP64: get the current timestamp value in 64 bit format * SNDRV_COMPRESS_AVAIL: get the current buffer avail value. * This also queries the tstamp properties * SNDRV_COMPRESS_PAUSE: Pause the running stream @@ -230,6 +230,7 @@ struct snd_compr_task_status { struct snd_compr_metadata) #define SNDRV_COMPRESS_TSTAMP _IOR('C', 0x20, struct snd_compr_tstamp) #define SNDRV_COMPRESS_AVAIL _IOR('C', 0x21, struct snd_compr_avail) +#define SNDRV_COMPRESS_TSTAMP64 _IOR('C', 0x22, struct snd_compr_tstamp64) #define SNDRV_COMPRESS_PAUSE _IO('C', 0x30) #define SNDRV_COMPRESS_RESUME _IO('C', 0x31) #define SNDRV_COMPRESS_START _IO('C', 0x32) diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index d3164aa07158..445220fdb6a0 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -736,18 +736,23 @@ snd_compr_set_metadata(struct snd_compr_stream *stream, unsigned long arg) return retval; } -static inline int -snd_compr_tstamp(struct snd_compr_stream *stream, unsigned long arg) +static inline int snd_compr_tstamp(struct snd_compr_stream *stream, + unsigned long arg, bool is_32bit) { struct snd_compr_tstamp64 tstamp64 = { 0 }; struct snd_compr_tstamp tstamp32 = { 0 }; + const void *copy_from = &tstamp64; + size_t copy_size = sizeof(tstamp64); int ret; ret = snd_compr_update_tstamp(stream, &tstamp64); if (ret == 0) { - snd_compr_tstamp32_from_64(&tstamp32, &tstamp64); - ret = copy_to_user((struct snd_compr_tstamp __user *)arg, - &tstamp32, sizeof(tstamp32)) ? + if (is_32bit) { + snd_compr_tstamp32_from_64(&tstamp32, &tstamp64); + copy_from = &tstamp32; + copy_size = sizeof(tstamp32); + } + ret = copy_to_user((void __user *)arg, copy_from, copy_size) ? -EFAULT : 0; } @@ -1327,7 +1332,9 @@ static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg) switch (cmd) { case SNDRV_COMPRESS_TSTAMP: - return snd_compr_tstamp(stream, arg); + return snd_compr_tstamp(stream, arg, true); + case SNDRV_COMPRESS_TSTAMP64: + return snd_compr_tstamp(stream, arg, false); case SNDRV_COMPRESS_AVAIL: return snd_compr_ioctl_avail(stream, arg); case SNDRV_COMPRESS_PAUSE: -- cgit v1.2.3 From 86eec88c5bddf9a57bfebe701d9c7a4d439aed9b Mon Sep 17 00:00:00 2001 From: Joris Verhaegen Date: Fri, 5 Sep 2025 10:12:56 +0100 Subject: ALSA: compress_offload: Add SNDRV_COMPRESS_AVAIL64 ioctl The previous patch introduced a 64-bit timestamp ioctl (SNDRV_COMPRESS_TSTAMP64). To provide a consistent API, this patch adds a corresponding 64-bit version of the SNDRV_COMPRESS_AVAIL ioctl. A new struct snd_compr_avail64 is added to the UAPI, which includes the 64-bit timestamp. The existing ioctl implementation is refactored to handle both the 32-bit and 64-bit variants. Reviewed-by: Miller Liang Tested-by: Joris Verhaegen Signed-off-by: Joris Verhaegen Acked-by: Vinod Koul Reviewed-by: Charles Keepax Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250905091301.2711705-4-verhaegen@google.com --- include/uapi/sound/compress_offload.h | 11 +++++++++ sound/core/compress_offload.c | 43 +++++++++++++++++++++++------------ 2 files changed, 39 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/include/uapi/sound/compress_offload.h b/include/uapi/sound/compress_offload.h index 70b8921601f9..26f756cc2e62 100644 --- a/include/uapi/sound/compress_offload.h +++ b/include/uapi/sound/compress_offload.h @@ -84,6 +84,16 @@ struct snd_compr_avail { struct snd_compr_tstamp tstamp; } __attribute__((packed, aligned(4))); +/** + * struct snd_compr_avail64 - avail descriptor with tstamp in 64 bit format + * @avail: Number of bytes available in ring buffer for writing/reading + * @tstamp: timestamp information + */ +struct snd_compr_avail64 { + __u64 avail; + struct snd_compr_tstamp64 tstamp; +} __attribute__((packed, aligned(4))); + enum snd_compr_direction { SND_COMPRESS_PLAYBACK = 0, SND_COMPRESS_CAPTURE, @@ -231,6 +241,7 @@ struct snd_compr_task_status { #define SNDRV_COMPRESS_TSTAMP _IOR('C', 0x20, struct snd_compr_tstamp) #define SNDRV_COMPRESS_AVAIL _IOR('C', 0x21, struct snd_compr_avail) #define SNDRV_COMPRESS_TSTAMP64 _IOR('C', 0x22, struct snd_compr_tstamp64) +#define SNDRV_COMPRESS_AVAIL64 _IOR('C', 0x23, struct snd_compr_avail64) #define SNDRV_COMPRESS_PAUSE _IO('C', 0x30) #define SNDRV_COMPRESS_RESUME _IO('C', 0x31) #define SNDRV_COMPRESS_START _IO('C', 0x32) diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 445220fdb6a0..da514fef45bc 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -203,13 +203,10 @@ static int snd_compr_update_tstamp(struct snd_compr_stream *stream, } static size_t snd_compr_calc_avail(struct snd_compr_stream *stream, - struct snd_compr_avail *avail) + struct snd_compr_avail64 *avail) { - struct snd_compr_tstamp64 tstamp64 = { 0 }; - memset(avail, 0, sizeof(*avail)); - snd_compr_update_tstamp(stream, &tstamp64); - snd_compr_tstamp32_from_64(&avail->tstamp, &tstamp64); + snd_compr_update_tstamp(stream, &avail->tstamp); /* Still need to return avail even if tstamp can't be filled in */ if (stream->runtime->total_bytes_available == 0 && @@ -237,28 +234,43 @@ static size_t snd_compr_calc_avail(struct snd_compr_stream *stream, if (stream->direction == SND_COMPRESS_PLAYBACK) avail->avail = stream->runtime->buffer_size - avail->avail; - pr_debug("ret avail as %llu\n", avail->avail); + pr_debug("ret avail as %zu\n", (size_t)avail->avail); return avail->avail; } static inline size_t snd_compr_get_avail(struct snd_compr_stream *stream) { - struct snd_compr_avail avail; + struct snd_compr_avail64 avail; return snd_compr_calc_avail(stream, &avail); } -static int -snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg) +static void snd_compr_avail32_from_64(struct snd_compr_avail *avail32, + const struct snd_compr_avail64 *avail64) { - struct snd_compr_avail ioctl_avail; + avail32->avail = avail64->avail; + snd_compr_tstamp32_from_64(&avail32->tstamp, &avail64->tstamp); +} + +static int snd_compr_ioctl_avail(struct snd_compr_stream *stream, + unsigned long arg, bool is_32bit) +{ + struct snd_compr_avail64 ioctl_avail64; + struct snd_compr_avail ioctl_avail32; size_t avail; + const void *copy_from = &ioctl_avail64; + size_t copy_size = sizeof(ioctl_avail64); if (stream->direction == SND_COMPRESS_ACCEL) return -EBADFD; - avail = snd_compr_calc_avail(stream, &ioctl_avail); - ioctl_avail.avail = avail; + avail = snd_compr_calc_avail(stream, &ioctl_avail64); + ioctl_avail64.avail = avail; + if (is_32bit) { + snd_compr_avail32_from_64(&ioctl_avail32, &ioctl_avail64); + copy_from = &ioctl_avail32; + copy_size = sizeof(ioctl_avail32); + } switch (stream->runtime->state) { case SNDRV_PCM_STATE_OPEN: @@ -269,8 +281,7 @@ snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg) break; } - if (copy_to_user((__u64 __user *)arg, - &ioctl_avail, sizeof(ioctl_avail))) + if (copy_to_user((__u64 __user *)arg, copy_from, copy_size)) return -EFAULT; return 0; } @@ -1336,7 +1347,9 @@ static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg) case SNDRV_COMPRESS_TSTAMP64: return snd_compr_tstamp(stream, arg, false); case SNDRV_COMPRESS_AVAIL: - return snd_compr_ioctl_avail(stream, arg); + return snd_compr_ioctl_avail(stream, arg, true); + case SNDRV_COMPRESS_AVAIL64: + return snd_compr_ioctl_avail(stream, arg, false); case SNDRV_COMPRESS_PAUSE: return snd_compr_pause(stream); case SNDRV_COMPRESS_RESUME: -- cgit v1.2.3 From 06aba2126b414248a34b13584f22a78787c95450 Mon Sep 17 00:00:00 2001 From: Alex Tran Date: Mon, 1 Sep 2025 11:40:08 -0700 Subject: ASoC: codecs: tlv320dac33: Remove unused struct tlv320dac33_platform_data and header file tlv320dac33-plat.h Remove the tlv320dac33_platform_data struct and header file tlv320dac33-plat.h as they are not used anywhere in the kernel or outside this driver. Signed-off-by: Alex Tran Message-ID: <20250901184008.1249535-3-alex.t.tran@gmail.com> Signed-off-by: Mark Brown --- include/sound/tlv320dac33-plat.h | 21 --------------------- sound/soc/codecs/tlv320dac33.c | 12 ------------ 2 files changed, 33 deletions(-) delete mode 100644 include/sound/tlv320dac33-plat.h (limited to 'include') diff --git a/include/sound/tlv320dac33-plat.h b/include/sound/tlv320dac33-plat.h deleted file mode 100644 index 7a7249a896e3..000000000000 --- a/include/sound/tlv320dac33-plat.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Platform header for Texas Instruments TLV320DAC33 codec driver - * - * Author: Peter Ujfalusi - * - * Copyright: (C) 2009 Nokia Corporation - */ - -#ifndef __TLV320DAC33_PLAT_H -#define __TLV320DAC33_PLAT_H - -struct tlv320dac33_platform_data { - int power_gpio; - int mode1_latency; /* latency caused by the i2c writes in us */ - int auto_fifo_config; /* FIFO config based on the period size */ - int keep_bclk; /* Keep the BCLK running in FIFO modes */ - u8 burst_bclkdiv; -}; - -#endif /* __TLV320DAC33_PLAT_H */ diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 423b9264a205..36b3de75a3f4 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -24,7 +24,6 @@ #include #include -#include #include "tlv320dac33.h" /* @@ -1462,16 +1461,9 @@ static struct snd_soc_dai_driver dac33_dai = { static int dac33_i2c_probe(struct i2c_client *client) { - struct tlv320dac33_platform_data *pdata; struct tlv320dac33_priv *dac33; int ret, i; - if (client->dev.platform_data == NULL) { - dev_err(&client->dev, "Platform data not set\n"); - return -ENODEV; - } - pdata = client->dev.platform_data; - dac33 = devm_kzalloc(&client->dev, sizeof(struct tlv320dac33_priv), GFP_KERNEL); if (dac33 == NULL) @@ -1488,10 +1480,6 @@ static int dac33_i2c_probe(struct i2c_client *client) i2c_set_clientdata(client, dac33); - dac33->power_gpio = pdata->power_gpio; - dac33->burst_bclkdiv = pdata->burst_bclkdiv; - dac33->keep_bclk = pdata->keep_bclk; - dac33->mode1_latency = pdata->mode1_latency; if (!dac33->mode1_latency) dac33->mode1_latency = 10000; /* 10ms */ dac33->irq = client->irq; -- cgit v1.2.3 From 7ceb69ca82b1456a66783a1472d6e677e00065a1 Mon Sep 17 00:00:00 2001 From: Baojun Xu Date: Sat, 30 Aug 2025 14:14:58 +0800 Subject: ASoC: tas2781: Add tas2118, tas2x20, tas5825 support Add tas2020, tas2118, tas2120, tas2320, tas2570, tas2572, tas5825 tas5827 support in tas2781 driver. Tas2118, tas2x20, tas257x have no on-chip DSP, tas582x have on-chip DSP but have no calibration required stereo smart amplifier. Signed-off-by: Baojun Xu Acked-by: Mark Brown Signed-off-by: Takashi Iwai --- include/sound/tas2781.h | 14 +- include/sound/tas2x20-tlv.h | 259 ++++++++++++++++++++++++++++++++++ sound/soc/codecs/tas2781-comlib-i2c.c | 2 + sound/soc/codecs/tas2781-i2c.c | 184 +++++++++++++++++------- 4 files changed, 410 insertions(+), 49 deletions(-) create mode 100644 include/sound/tas2x20-tlv.h (limited to 'include') diff --git a/include/sound/tas2781.h b/include/sound/tas2781.h index f0aefc04a957..ddd997ac3216 100644 --- a/include/sound/tas2781.h +++ b/include/sound/tas2781.h @@ -51,7 +51,9 @@ /* Software Reset, compatble with new device (TAS5825). */ #define TASDEVICE_REG_SWRESET TASDEVICE_REG(0x0, 0x0, 0x01) -#define TASDEVICE_REG_SWRESET_RESET (BIT(0) | BIT(4)) +#define TASDEVICE_REG_SWRESET_RESET BIT(0) + +#define TAS5825_REG_SWRESET_RESET (BIT(0) | BIT(4)) /* Checksum */ #define TASDEVICE_CHECKSUM_REG TASDEVICE_REG(0x0, 0x0, 0x7e) @@ -110,8 +112,17 @@ #define TAS2781_RUNTIME_RE_REG TASDEVICE_REG(0x64, 0x63, 0x44) enum audio_device { + TAS2020, + TAS2118, + TAS2120, + TAS2320, TAS2563, + TAS2570, + TAS2572, TAS2781, + TAS5825, + TAS5827, + TAS_OTHERS, }; enum dspbin_type { @@ -194,6 +205,7 @@ struct tasdevice_priv { unsigned char coef_binaryname[64]; unsigned char rca_binaryname[64]; unsigned char dev_name[32]; + const unsigned char (*dvc_tlv_table)[4]; const char *name_prefix; unsigned char ndev; unsigned int dspbin_typ; diff --git a/include/sound/tas2x20-tlv.h b/include/sound/tas2x20-tlv.h new file mode 100644 index 000000000000..6e6bcec4a0a1 --- /dev/null +++ b/include/sound/tas2x20-tlv.h @@ -0,0 +1,259 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// +// ALSA SoC Texas Instruments TAS2x20/TAS2118 Audio Smart Amplifier +// +// Copyright (C) 2025 Texas Instruments Incorporated +// https://www.ti.com +// +// The TAS2x20/TAS2118 hda driver implements for one, two, or even multiple +// TAS2x20/TAS2118 chips. +// +// Author: Baojun Xu +// + +#ifndef __TAS2X20_TLV_H__ +#define __TAS2X20_TLV_H__ + +#define TAS2X20_DVC_LEVEL TASDEVICE_REG(0x0, 0x2, 0x0c) +#define TAS2X20_AMP_LEVEL TASDEVICE_REG(0x0, 0x0, 0x07) + +static const __maybe_unused DECLARE_TLV_DB_SCALE(tas2x20_dvc_tlv, 1650, 50, 0); +static const __maybe_unused DECLARE_TLV_DB_SCALE(tas2x20_amp_tlv, 2100, 50, 0); + +/* pow(10, db/20) * pow(2,22) */ +static const __maybe_unused unsigned char tas2x20_dvc_table[][4] = { + { 0X00, 0X00, 0X0D, 0X00 }, /* -110.0db */ + { 0X00, 0X00, 0X0E, 0X00 }, /* -109.5db */ + { 0X00, 0X00, 0X0E, 0X00 }, /* -109.0db */ + { 0X00, 0X00, 0X0F, 0X00 }, /* -108.5db */ + { 0X00, 0X00, 0X10, 0X00 }, /* -108.0db */ + { 0X00, 0X00, 0X11, 0X00 }, /* -107.5db */ + { 0X00, 0X00, 0X12, 0X00 }, /* -107.0db */ + { 0X00, 0X00, 0X13, 0X00 }, /* -106.5db */ + { 0X00, 0X00, 0X15, 0X00 }, /* -106.0db */ + { 0X00, 0X00, 0X16, 0X00 }, /* -105.5db */ + { 0X00, 0X00, 0X17, 0X00 }, /* -105.0db */ + { 0X00, 0X00, 0X18, 0X00 }, /* -104.5db */ + { 0X00, 0X00, 0X1A, 0X00 }, /* -104.0db */ + { 0X00, 0X00, 0X1C, 0X00 }, /* -103.5db */ + { 0X00, 0X00, 0X1D, 0X00 }, /* -103.0db */ + { 0X00, 0X00, 0X1F, 0X00 }, /* -102.5db */ + { 0X00, 0X00, 0X21, 0X00 }, /* -102.0db */ + { 0X00, 0X00, 0X23, 0X00 }, /* -101.5db */ + { 0X00, 0X00, 0X25, 0X00 }, /* -101.0db */ + { 0X00, 0X00, 0X27, 0X00 }, /* -100.5db */ + { 0X00, 0X00, 0X29, 0X00 }, /* -100.0db */ + { 0X00, 0X00, 0X2C, 0X00 }, /* -99.5db */ + { 0X00, 0X00, 0X2F, 0X00 }, /* -99.0db */ + { 0X00, 0X00, 0X31, 0X00 }, /* -98.5db */ + { 0X00, 0X00, 0X34, 0X00 }, /* -98.0db */ + { 0X00, 0X00, 0X37, 0X00 }, /* -97.5db */ + { 0X00, 0X00, 0X3B, 0X00 }, /* -97.0db */ + { 0X00, 0X00, 0X3E, 0X00 }, /* -96.5db */ + { 0X00, 0X00, 0X42, 0X00 }, /* -96.0db */ + { 0X00, 0X00, 0X46, 0X00 }, /* -95.5db */ + { 0X00, 0X00, 0X4A, 0X00 }, /* -95.0db */ + { 0X00, 0X00, 0X4F, 0X00 }, /* -94.5db */ + { 0X00, 0X00, 0X53, 0X00 }, /* -94.0db */ + { 0X00, 0X00, 0X58, 0X00 }, /* -93.5db */ + { 0X00, 0X00, 0X5D, 0X00 }, /* -93.0db */ + { 0X00, 0X00, 0X63, 0X00 }, /* -92.5db */ + { 0X00, 0X00, 0X69, 0X00 }, /* -92.0db */ + { 0X00, 0X00, 0X6F, 0X00 }, /* -91.5db */ + { 0X00, 0X00, 0X76, 0X00 }, /* -91.0db */ + { 0X00, 0X00, 0X7D, 0X00 }, /* -90.5db */ + { 0X00, 0X00, 0X84, 0X00 }, /* -90.0db */ + { 0X00, 0X00, 0X8C, 0X00 }, /* -89.5db */ + { 0X00, 0X00, 0X94, 0X00 }, /* -89.0db */ + { 0X00, 0X00, 0X9D, 0X00 }, /* -88.5db */ + { 0X00, 0X00, 0XA6, 0X00 }, /* -88.0db */ + { 0X00, 0X00, 0XB0, 0X00 }, /* -87.5db */ + { 0X00, 0X00, 0XBB, 0X00 }, /* -87.0db */ + { 0X00, 0X00, 0XC6, 0X00 }, /* -86.5db */ + { 0X00, 0X00, 0XD2, 0X00 }, /* -86.0db */ + { 0X00, 0X00, 0XDE, 0X00 }, /* -85.5db */ + { 0X00, 0X00, 0XEB, 0X00 }, /* -85.0db */ + { 0X00, 0X00, 0XF9, 0X00 }, /* -84.5db */ + { 0X00, 0X01, 0X08, 0X00 }, /* -84.0db */ + { 0X00, 0X01, 0X18, 0X00 }, /* -83.5db */ + { 0X00, 0X01, 0X28, 0X00 }, /* -83.0db */ + { 0X00, 0X01, 0X3A, 0X00 }, /* -82.5db */ + { 0X00, 0X01, 0X4D, 0X00 }, /* -82.0db */ + { 0X00, 0X01, 0X60, 0X00 }, /* -81.5db */ + { 0X00, 0X01, 0X75, 0X00 }, /* -81.0db */ + { 0X00, 0X01, 0X8B, 0X00 }, /* -80.5db */ + { 0X00, 0X01, 0XA3, 0X00 }, /* -80.0db */ + { 0X00, 0X01, 0XBC, 0X00 }, /* -79.5db */ + { 0X00, 0X01, 0XD6, 0X00 }, /* -79.0db */ + { 0X00, 0X01, 0XF2, 0X00 }, /* -78.5db */ + { 0X00, 0X02, 0X10, 0X00 }, /* -78.0db */ + { 0X00, 0X02, 0X2F, 0X00 }, /* -77.5db */ + { 0X00, 0X02, 0X50, 0X00 }, /* -77.0db */ + { 0X00, 0X02, 0X73, 0X00 }, /* -76.5db */ + { 0X00, 0X02, 0X98, 0X00 }, /* -76.0db */ + { 0X00, 0X02, 0XC0, 0X00 }, /* -75.5db */ + { 0X00, 0X02, 0XE9, 0X00 }, /* -75.0db */ + { 0X00, 0X03, 0X16, 0X00 }, /* -74.5db */ + { 0X00, 0X03, 0X44, 0X00 }, /* -74.0db */ + { 0X00, 0X03, 0X76, 0X00 }, /* -73.5db */ + { 0X00, 0X03, 0XAA, 0X00 }, /* -73.0db */ + { 0X00, 0X03, 0XE2, 0X00 }, /* -72.5db */ + { 0X00, 0X04, 0X1D, 0X00 }, /* -72.0db */ + { 0X00, 0X04, 0X5B, 0X00 }, /* -71.5db */ + { 0X00, 0X04, 0X9E, 0X00 }, /* -71.0db */ + { 0X00, 0X04, 0XE4, 0X00 }, /* -70.5db */ + { 0X00, 0X05, 0X2E, 0X00 }, /* -70.0db */ + { 0X00, 0X05, 0X7C, 0X00 }, /* -69.5db */ + { 0X00, 0X05, 0XD0, 0X00 }, /* -69.0db */ + { 0X00, 0X06, 0X28, 0X00 }, /* -68.5db */ + { 0X00, 0X06, 0X85, 0X00 }, /* -68.0db */ + { 0X00, 0X06, 0XE8, 0X00 }, /* -67.5db */ + { 0X00, 0X07, 0X51, 0X00 }, /* -67.0db */ + { 0X00, 0X07, 0XC0, 0X00 }, /* -66.5db */ + { 0X00, 0X08, 0X36, 0X00 }, /* -66.0db */ + { 0X00, 0X08, 0XB2, 0X00 }, /* -65.5db */ + { 0X00, 0X09, 0X36, 0X00 }, /* -65.0db */ + { 0X00, 0X09, 0XC2, 0X00 }, /* -64.5db */ + { 0X00, 0X0A, 0X56, 0X00 }, /* -64.0db */ + { 0X00, 0X0A, 0XF3, 0X00 }, /* -63.5db */ + { 0X00, 0X0B, 0X99, 0X00 }, /* -63.0db */ + { 0X00, 0X0C, 0X49, 0X00 }, /* -62.5db */ + { 0X00, 0X0D, 0X03, 0X00 }, /* -62.0db */ + { 0X00, 0X0D, 0XC9, 0X00 }, /* -61.5db */ + { 0X00, 0X0E, 0X9A, 0X00 }, /* -61.0db */ + { 0X00, 0X0F, 0X77, 0X00 }, /* -60.5db */ + { 0X00, 0X10, 0X62, 0X00 }, /* -60.0db */ + { 0X00, 0X11, 0X5A, 0X00 }, /* -59.5db */ + { 0X00, 0X12, 0X62, 0X00 }, /* -59.0db */ + { 0X00, 0X13, 0X78, 0X00 }, /* -58.5db */ + { 0X00, 0X14, 0XA0, 0X00 }, /* -58.0db */ + { 0X00, 0X15, 0XD9, 0X00 }, /* -57.5db */ + { 0X00, 0X17, 0X24, 0X00 }, /* -57.0db */ + { 0X00, 0X18, 0X83, 0X00 }, /* -56.5db */ + { 0X00, 0X19, 0XF7, 0X00 }, /* -56.0db */ + { 0X00, 0X1B, 0X81, 0X00 }, /* -55.5db */ + { 0X00, 0X1D, 0X22, 0X00 }, /* -55.0db */ + { 0X00, 0X1E, 0XDC, 0X00 }, /* -54.5db */ + { 0X00, 0X20, 0XB0, 0X00 }, /* -54.0db */ + { 0X00, 0X22, 0XA0, 0X00 }, /* -53.5db */ + { 0X00, 0X24, 0XAD, 0X00 }, /* -53.0db */ + { 0X00, 0X26, 0XDA, 0X00 }, /* -52.5db */ + { 0X00, 0X29, 0X27, 0X00 }, /* -52.0db */ + { 0X00, 0X2B, 0X97, 0X00 }, /* -51.5db */ + { 0X00, 0X2E, 0X2D, 0X00 }, /* -51.0db */ + { 0X00, 0X30, 0XE9, 0X00 }, /* -50.5db */ + { 0X00, 0X33, 0XCF, 0X00 }, /* -50.0db */ + { 0X00, 0X36, 0XE1, 0X00 }, /* -49.5db */ + { 0X00, 0X3A, 0X21, 0X00 }, /* -49.0db */ + { 0X00, 0X3D, 0X93, 0X00 }, /* -48.5db */ + { 0X00, 0X41, 0X39, 0X00 }, /* -48.0db */ + { 0X00, 0X45, 0X17, 0X00 }, /* -47.5db */ + { 0X00, 0X49, 0X2F, 0X00 }, /* -47.0db */ + { 0X00, 0X4D, 0X85, 0X00 }, /* -46.5db */ + { 0X00, 0X52, 0X1D, 0X00 }, /* -46.0db */ + { 0X00, 0X56, 0XFA, 0X00 }, /* -45.5db */ + { 0X00, 0X5C, 0X22, 0X00 }, /* -45.0db */ + { 0X00, 0X61, 0X97, 0X00 }, /* -44.5db */ + { 0X00, 0X67, 0X60, 0X00 }, /* -44.0db */ + { 0X00, 0X6D, 0X80, 0X00 }, /* -43.5db */ + { 0X00, 0X73, 0XFD, 0X00 }, /* -43.0db */ + { 0X00, 0X7A, 0XDC, 0X00 }, /* -42.5db */ + { 0X00, 0X82, 0X24, 0X00 }, /* -42.0db */ + { 0X00, 0X89, 0XDA, 0X00 }, /* -41.5db */ + { 0X00, 0X92, 0X05, 0X00 }, /* -41.0db */ + { 0X00, 0X9A, 0XAC, 0X00 }, /* -40.5db */ + { 0X00, 0XA3, 0XD7, 0X00 }, /* -40.0db */ + { 0X00, 0XAD, 0X8C, 0X00 }, /* -39.5db */ + { 0X00, 0XB7, 0XD4, 0X00 }, /* -39.0db */ + { 0X00, 0XC2, 0XB9, 0X00 }, /* -38.5db */ + { 0X00, 0XCE, 0X43, 0X00 }, /* -38.0db */ + { 0X00, 0XDA, 0X7B, 0X00 }, /* -37.5db */ + { 0X00, 0XE7, 0X6E, 0X00 }, /* -37.0db */ + { 0X00, 0XF5, 0X24, 0X00 }, /* -36.5db */ + { 0X01, 0X03, 0XAB, 0X00 }, /* -36.0db */ + { 0X01, 0X13, 0X0E, 0X00 }, /* -35.5db */ + { 0X01, 0X23, 0X5A, 0X00 }, /* -35.0db */ + { 0X01, 0X34, 0X9D, 0X00 }, /* -34.5db */ + { 0X01, 0X46, 0XE7, 0X00 }, /* -34.0db */ + { 0X01, 0X5A, 0X46, 0X00 }, /* -33.5db */ + { 0X01, 0X6E, 0XCA, 0X00 }, /* -33.0db */ + { 0X01, 0X84, 0X86, 0X00 }, /* -32.5db */ + { 0X01, 0X9B, 0X8C, 0X00 }, /* -32.0db */ + { 0X01, 0XB3, 0XEE, 0X00 }, /* -31.5db */ + { 0X01, 0XCD, 0XC3, 0X00 }, /* -31.0db */ + { 0X01, 0XE9, 0X20, 0X00 }, /* -30.5db */ + { 0X02, 0X06, 0X1B, 0X00 }, /* -30.0db */ + { 0X02, 0X24, 0XCE, 0X00 }, /* -29.5db */ + { 0X02, 0X45, 0X53, 0X00 }, /* -29.0db */ + { 0X02, 0X67, 0XC5, 0X00 }, /* -28.5db */ + { 0X02, 0X8C, 0X42, 0X00 }, /* -28.0db */ + { 0X02, 0XB2, 0XE8, 0X00 }, /* -27.5db */ + { 0X02, 0XDB, 0XD8, 0X00 }, /* -27.0db */ + { 0X03, 0X07, 0X36, 0X00 }, /* -26.5db */ + { 0X03, 0X35, 0X25, 0X00 }, /* -26.0db */ + { 0X03, 0X65, 0XCD, 0X00 }, /* -25.5db */ + { 0X03, 0X99, 0X57, 0X00 }, /* -25.0db */ + { 0X03, 0XCF, 0XEE, 0X00 }, /* -24.5db */ + { 0X04, 0X09, 0XC2, 0X00 }, /* -24.0db */ + { 0X04, 0X47, 0X03, 0X00 }, /* -23.5db */ + { 0X04, 0X87, 0XE5, 0X00 }, /* -23.0db */ + { 0X04, 0XCC, 0XA0, 0X00 }, /* -22.5db */ + { 0X05, 0X15, 0X6D, 0X00 }, /* -22.0db */ + { 0X05, 0X62, 0X8A, 0X00 }, /* -21.5db */ + { 0X05, 0XB4, 0X39, 0X00 }, /* -21.0db */ + { 0X06, 0X0A, 0XBF, 0X00 }, /* -20.5db */ + { 0X06, 0X66, 0X66, 0X00 }, /* -20.0db */ + { 0X06, 0XC7, 0X7B, 0X00 }, /* -19.5db */ + { 0X07, 0X2E, 0X50, 0X00 }, /* -19.0db */ + { 0X07, 0X9B, 0X3D, 0X00 }, /* -18.5db */ + { 0X08, 0X0E, 0X9F, 0X00 }, /* -18.0db */ + { 0X08, 0X88, 0XD7, 0X00 }, /* -17.5db */ + { 0X09, 0X0A, 0X4D, 0X00 }, /* -17.0db */ + { 0X09, 0X93, 0X6E, 0X00 }, /* -16.5db */ + { 0X0A, 0X24, 0XB0, 0X00 }, /* -16.0db */ + { 0X0A, 0XBE, 0X8D, 0X00 }, /* -15.5db */ + { 0X0B, 0X61, 0X88, 0X00 }, /* -15.0db */ + { 0X0C, 0X0E, 0X2B, 0X00 }, /* -14.5db */ + { 0X0C, 0XC5, 0X09, 0X00 }, /* -14.0db */ + { 0X0D, 0X86, 0XBD, 0X00 }, /* -13.5db */ + { 0X0E, 0X53, 0XEB, 0X00 }, /* -13.0db */ + { 0X0F, 0X2D, 0X42, 0X00 }, /* -12.5db */ + { 0X10, 0X13, 0X79, 0X00 }, /* -12.0db */ + { 0X11, 0X07, 0X54, 0X00 }, /* -11.5db */ + { 0X12, 0X09, 0XA3, 0X00 }, /* -11.0db */ + { 0X13, 0X1B, 0X40, 0X00 }, /* -10.5db */ + { 0X14, 0X3D, 0X13, 0X00 }, /* -10.0db */ + { 0X15, 0X70, 0X12, 0X00 }, /* -9.5db */ + { 0X16, 0XB5, 0X43, 0X00 }, /* -9.0db */ + { 0X18, 0X0D, 0XB8, 0X00 }, /* -8.5db */ + { 0X19, 0X7A, 0X96, 0X00 }, /* -8.0db */ + { 0X1A, 0XFD, 0X13, 0X00 }, /* -7.5db */ + { 0X1C, 0X96, 0X76, 0X00 }, /* -7.0db */ + { 0X1E, 0X48, 0X1C, 0X00 }, /* -6.5db */ + { 0X20, 0X13, 0X73, 0X00 }, /* -6.0db */ + { 0X21, 0XFA, 0X02, 0X00 }, /* -5.5db */ + { 0X23, 0XFD, 0X66, 0X00 }, /* -5.0db */ + { 0X26, 0X1F, 0X54, 0X00 }, /* -4.5db */ + { 0X28, 0X61, 0X9A, 0X00 }, /* -4.0db */ + { 0X2A, 0XC6, 0X25, 0X00 }, /* -3.5db */ + { 0X2D, 0X4E, 0XFB, 0X00 }, /* -3.0db */ + { 0X2F, 0XFE, 0X44, 0X00 }, /* -2.5db */ + { 0X32, 0XD6, 0X46, 0X00 }, /* -2.0db */ + { 0X35, 0XD9, 0X6B, 0X00 }, /* -1.5db */ + { 0X39, 0X0A, 0X41, 0X00 }, /* -1.0db */ + { 0X3C, 0X6B, 0X7E, 0X00 }, /* -0.5db */ + { 0X40, 0X00, 0X00, 0X00 }, /* 0.0db */ + { 0X43, 0XCA, 0XD0, 0X00 }, /* 0.5db */ + { 0X47, 0XCF, 0X26, 0X00 }, /* 1.0db */ + { 0X4C, 0X10, 0X6B, 0X00 }, /* 1.5db */ + { 0X50, 0X92, 0X3B, 0X00 }, /* 2.0db */ + { 0X55, 0X58, 0X6A, 0X00 }, /* 2.5db */ + { 0X5A, 0X67, 0X03, 0X00 }, /* 3.0db */ + { 0X5F, 0XC2, 0X53, 0X00 }, /* 3.5db */ + { 0X65, 0X6E, 0XE3, 0X00 }, /* 4.0db */ + { 0X6B, 0X71, 0X86, 0X00 }, /* 4.5db */ + { 0X71, 0XCF, 0X54, 0X00 }, /* 5.0db */ + { 0X78, 0X8D, 0XB4, 0X00 }, /* 5.5db */ + { 0X7F, 0XB2, 0X61, 0X00 }, /* 6.0db */ +}; +#endif diff --git a/sound/soc/codecs/tas2781-comlib-i2c.c b/sound/soc/codecs/tas2781-comlib-i2c.c index c078bb0a8437..b3fd7350143b 100644 --- a/sound/soc/codecs/tas2781-comlib-i2c.c +++ b/sound/soc/codecs/tas2781-comlib-i2c.c @@ -320,6 +320,8 @@ void tasdevice_reset(struct tasdevice_priv *tas_dev) for (i = 0; i < tas_dev->ndev; i++) { ret = tasdevice_dev_write(tas_dev, i, TASDEVICE_REG_SWRESET, + tas_dev->chip_id >= TAS5825 ? + TAS5825_REG_SWRESET_RESET : TASDEVICE_REG_SWRESET_RESET); if (ret < 0) dev_err(tas_dev->dev, diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c index 0e09d794516f..0b8e3638c2ac 100644 --- a/sound/soc/codecs/tas2781-i2c.c +++ b/sound/soc/codecs/tas2781-i2c.c @@ -30,8 +30,10 @@ #include #include #include +#include #include #include +#include #include #define X2563_CL_STT_VAL(xreg, xval) \ @@ -98,16 +100,32 @@ static const struct bulk_reg_val tas2781_cali_start_reg[] = { }; static const struct i2c_device_id tasdevice_id[] = { + { "tas2020", TAS2020 }, + { "tas2118", TAS2118 }, + { "tas2120", TAS2120 }, + { "tas2320", TAS2320 }, { "tas2563", TAS2563 }, + { "tas2570", TAS2570 }, + { "tas2572", TAS2572 }, { "tas2781", TAS2781 }, + { "tas5825", TAS5825 }, + { "tas5827", TAS5827 }, {} }; MODULE_DEVICE_TABLE(i2c, tasdevice_id); #ifdef CONFIG_OF static const struct of_device_id tasdevice_of_match[] = { + { .compatible = "ti,tas2020" }, + { .compatible = "ti,tas2118" }, + { .compatible = "ti,tas2120" }, + { .compatible = "ti,tas2320" }, { .compatible = "ti,tas2563" }, + { .compatible = "ti,tas2570" }, + { .compatible = "ti,tas2572" }, { .compatible = "ti,tas2781" }, + { .compatible = "ti,tas5825" }, + { .compatible = "ti,tas5827" }, {}, }; MODULE_DEVICE_TABLE(of, tasdevice_of_match); @@ -797,7 +815,7 @@ static int tasdev_nop_get( return 0; } -static int tas2563_digital_gain_get( +static int tasdevice_digital_gain_get( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -823,15 +841,15 @@ static int tas2563_digital_gain_get( while (r > 1 + l) { mid = (l + r) / 2; - ar_mid = get_unaligned_be32(tas2563_dvc_table[mid]); + ar_mid = get_unaligned_be32(tas_dev->dvc_tlv_table[mid]); if (target < ar_mid) r = mid; else l = mid; } - ar_l = get_unaligned_be32(tas2563_dvc_table[l]); - ar_r = get_unaligned_be32(tas2563_dvc_table[r]); + ar_l = get_unaligned_be32(tas_dev->dvc_tlv_table[l]); + ar_r = get_unaligned_be32(tas_dev->dvc_tlv_table[r]); /* find out the member same as or closer to the current volume */ ucontrol->value.integer.value[0] = @@ -841,7 +859,7 @@ out: return 0; } -static int tas2563_digital_gain_put( +static int tasdevice_digital_gain_put( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -867,7 +885,7 @@ static int tas2563_digital_gain_put( } volrd = get_unaligned_be32(&data[0]); - volwr = get_unaligned_be32(tas2563_dvc_table[vol]); + volwr = get_unaligned_be32(tas_dev->dvc_tlv_table[vol]); if (volrd == volwr) { rc = 0; @@ -876,7 +894,7 @@ static int tas2563_digital_gain_put( for (i = 0; i < tas_dev->ndev; i++) { ret = tasdevice_dev_bulk_write(tas_dev, i, reg, - (unsigned char *)tas2563_dvc_table[vol], 4); + (unsigned char *)tas_dev->dvc_tlv_table[vol], 4); if (ret) { dev_err(tas_dev->dev, "%s, set digital vol error in dev %d\n", @@ -892,11 +910,6 @@ out: return rc; } -static const struct snd_kcontrol_new tasdevice_snd_controls[] = { - SOC_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0, - tasdev_force_fwload_get, tasdev_force_fwload_put), -}; - static const struct snd_kcontrol_new tasdevice_cali_controls[] = { SOC_SINGLE_EXT("Calibration Stop", SND_SOC_NOPM, 0, 1, 0, tasdev_nop_get, tasdev_calib_stop_put), @@ -907,6 +920,16 @@ static const struct snd_kcontrol_new tasdevice_cali_controls[] = { SND_SOC_BYTES_EXT("Amp XMA2 Data", 6, tasdev_XMA2_data_get, NULL), }; +static const struct snd_kcontrol_new tas2x20_snd_controls[] = { + SOC_SINGLE_RANGE_EXT_TLV("Speaker Analog Volume", TAS2X20_AMP_LEVEL, + 0, 0, 42, 1, tas2781_amp_getvol, + tas2781_amp_putvol, tas2x20_amp_tlv), + SOC_SINGLE_RANGE_EXT_TLV("Speaker Digital Volume", TAS2X20_DVC_LEVEL, + 0, 0, ARRAY_SIZE(tas2x20_dvc_table) - 1, 0, + tasdevice_digital_gain_get, tasdevice_digital_gain_put, + tas2x20_dvc_tlv), +}; + static const struct snd_kcontrol_new tas2781_snd_controls[] = { SOC_SINGLE_RANGE_EXT_TLV("Speaker Analog Volume", TAS2781_AMP_LEVEL, 1, 0, 20, 0, tas2781_amp_getvol, @@ -916,6 +939,15 @@ static const struct snd_kcontrol_new tas2781_snd_controls[] = { tas2781_digital_putvol, tas2781_dvc_tlv), }; +static const struct snd_kcontrol_new tas5825_snd_controls[] = { + SOC_SINGLE_RANGE_EXT_TLV("Speaker Analog Volume", TAS5825_AMP_LEVEL, + 0, 0, 31, 1, tas2781_amp_getvol, + tas2781_amp_putvol, tas5825_amp_tlv), + SOC_SINGLE_RANGE_EXT_TLV("Speaker Digital Volume", TAS5825_DVC_LEVEL, + 0, 0, 254, 1, tas2781_amp_getvol, + tas2781_amp_putvol, tas5825_dvc_tlv), +}; + static const struct snd_kcontrol_new tas2781_cali_controls[] = { SND_SOC_BYTES_EXT("Amp Latch Data", 3, tas2781_latch_reg_get, NULL), }; @@ -923,7 +955,7 @@ static const struct snd_kcontrol_new tas2781_cali_controls[] = { static const struct snd_kcontrol_new tas2563_snd_controls[] = { SOC_SINGLE_RANGE_EXT_TLV("Speaker Digital Volume", TAS2563_DVC_LVL, 0, 0, ARRAY_SIZE(tas2563_dvc_table) - 1, 0, - tas2563_digital_gain_get, tas2563_digital_gain_put, + tasdevice_digital_gain_get, tasdevice_digital_gain_put, tas2563_dvc_tlv), }; @@ -968,8 +1000,8 @@ static int tasdevice_info_chip_id(struct snd_kcontrol *kcontrol, { uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; - uinfo->value.integer.min = TAS2563; - uinfo->value.integer.max = TAS2781; + uinfo->value.integer.min = TAS2020; + uinfo->value.integer.max = TAS_OTHERS; return 0; } @@ -1168,9 +1200,9 @@ static int tasdevice_active_num_put(struct snd_kcontrol *kcontrol, static int tasdevice_dsp_create_ctrls(struct tasdevice_priv *tas_priv) { struct snd_kcontrol_new *dsp_ctrls; - char *active_dev_num, *chip_id; + char *active_dev_num, *chip_id, *fw_load; char *conf_name, *prog_name; - int nr_controls = 4; + int nr_controls = 5; int mix_index = 0; /* Alloc kcontrol via devm_kzalloc, which don't manually @@ -1228,6 +1260,19 @@ static int tasdevice_dsp_create_ctrls(struct tasdevice_priv *tas_priv) dsp_ctrls[mix_index].get = tasdevice_get_chip_id; mix_index++; + fw_load = devm_kstrdup(tas_priv->dev, "Speaker Force Firmware Load", + GFP_KERNEL); + if (!fw_load) + return -ENOMEM; + + dsp_ctrls[mix_index].name = fw_load; + dsp_ctrls[mix_index].iface = SNDRV_CTL_ELEM_IFACE_MIXER; + dsp_ctrls[mix_index].info = snd_soc_info_bool_ext; + dsp_ctrls[mix_index].put = tasdev_force_fwload_put; + dsp_ctrls[mix_index].get = tasdev_force_fwload_get; + dsp_ctrls[mix_index].private_value = 0UL; + mix_index++; + return snd_soc_add_component_controls(tas_priv->codec, dsp_ctrls, nr_controls < mix_index ? nr_controls : mix_index); } @@ -1587,6 +1632,16 @@ static void tasdevice_fw_ready(const struct firmware *fmw, * failing to load DSP firmware is NOT an error. */ tas_priv->fw_state = TASDEVICE_RCA_FW_OK; + /* There is no DSP firmware required for TAS2118/2X20/257X. */ + switch (tas_priv->chip_id) { + case TAS2020: + case TAS2118: + case TAS2120: + case TAS2320: + case TAS2570: + case TAS2572: + goto out; + } if (tas_priv->name_prefix) scnprintf(tas_priv->coef_binaryname, 64, "%s-%s_coef.bin", tas_priv->name_prefix, tas_priv->dev_name); @@ -1608,34 +1663,37 @@ static void tasdevice_fw_ready(const struct firmware *fmw, dev_err(tas_priv->dev, "dsp controls error\n"); goto out; } - - ret = tasdevice_create_cali_ctrls(tas_priv); - if (ret) { - dev_err(tas_priv->dev, "cali controls error\n"); - goto out; - } - tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK; - /* If calibrated data occurs error, dsp will still works with default - * calibrated data inside algo. - */ - for (i = 0; i < tas_priv->ndev; i++) { - if (tas_priv->name_prefix) - scnprintf(tas_priv->cal_binaryname[i], 64, - "%s-%s_cal_0x%02x.bin", tas_priv->name_prefix, - tas_priv->dev_name, - tas_priv->tasdevice[i].dev_addr); - else - scnprintf(tas_priv->cal_binaryname[i], 64, - "%s_cal_0x%02x.bin", tas_priv->dev_name, - tas_priv->tasdevice[i].dev_addr); - ret = tas2781_load_calibration(tas_priv, - tas_priv->cal_binaryname[i], i); - if (ret != 0) - dev_err(tas_priv->dev, - "%s: load %s error, default will effect\n", - __func__, tas_priv->cal_binaryname[i]); + /* There is no calibration required for TAS5825/TAS5827. */ + if (tas_priv->chip_id < TAS5825) { + ret = tasdevice_create_cali_ctrls(tas_priv); + if (ret) { + dev_err(tas_priv->dev, "cali controls error\n"); + goto out; + } + /* If calibrated data occurs error, dsp will still works + * with default calibrated data inside algo. + */ + for (i = 0; i < tas_priv->ndev; i++) { + if (tas_priv->name_prefix) + scnprintf(tas_priv->cal_binaryname[i], 64, + "%s-%s_cal_0x%02x.bin", + tas_priv->name_prefix, + tas_priv->dev_name, + tas_priv->tasdevice[i].dev_addr); + else + scnprintf(tas_priv->cal_binaryname[i], 64, + "%s_cal_0x%02x.bin", + tas_priv->dev_name, + tas_priv->tasdevice[i].dev_addr); + ret = tas2781_load_calibration(tas_priv, + tas_priv->cal_binaryname[i], i); + if (ret != 0) + dev_err(tas_priv->dev, + "%s: load %s error, keep default.\n", + __func__, tas_priv->cal_binaryname[i]); + } } tasdevice_prmg_load(tas_priv, 0); @@ -1653,8 +1711,14 @@ static void tasdevice_fw_ready(const struct firmware *fmw, #endif out: if (tas_priv->fw_state == TASDEVICE_RCA_FW_OK) { - /* If DSP FW fail, DSP kcontrol won't be created. */ - tasdevice_dsp_remove(tas_priv); + switch (tas_priv->chip_id) { + case TAS2563: + case TAS2781: + case TAS5825: + case TAS5827: + /* If DSP FW fail, DSP kcontrol won't be created. */ + tasdevice_dsp_remove(tas_priv); + } } mutex_unlock(&tas_priv->codec_lock); release_firmware(fmw); @@ -1798,13 +1862,30 @@ static int tasdevice_codec_probe(struct snd_soc_component *codec) int rc; switch (tas_priv->chip_id) { + case TAS2020: + case TAS2118: + case TAS2120: + case TAS2320: + case TAS2570: + case TAS2572: + p = (struct snd_kcontrol_new *)tas2x20_snd_controls; + size = ARRAY_SIZE(tas2x20_snd_controls); + tas_priv->dvc_tlv_table = tas2x20_dvc_table; + break; case TAS2781: p = (struct snd_kcontrol_new *)tas2781_snd_controls; size = ARRAY_SIZE(tas2781_snd_controls); break; + case TAS5825: + case TAS5827: + p = (struct snd_kcontrol_new *)tas5825_snd_controls; + size = ARRAY_SIZE(tas5825_snd_controls); + break; default: p = (struct snd_kcontrol_new *)tas2563_snd_controls; size = ARRAY_SIZE(tas2563_snd_controls); + tas_priv->dvc_tlv_table = tas2563_dvc_table; + break; } rc = snd_soc_add_component_controls(codec, p, size); @@ -1844,8 +1925,6 @@ static const struct snd_soc_component_driver soc_codec_driver_tasdevice = { .probe = tasdevice_codec_probe, .remove = tasdevice_codec_remove, - .controls = tasdevice_snd_controls, - .num_controls = ARRAY_SIZE(tasdevice_snd_controls), .dapm_widgets = tasdevice_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(tasdevice_dapm_widgets), .dapm_routes = tasdevice_audio_map, @@ -1961,7 +2040,16 @@ static void tasdevice_i2c_remove(struct i2c_client *client) #ifdef CONFIG_ACPI static const struct acpi_device_id tasdevice_acpi_match[] = { - { "TAS2781", TAS2781 }, + { "TXNW2020", TAS2020 }, + { "TXNW2118", TAS2118 }, + { "TXNW2120", TAS2120 }, + { "TXNW2320", TAS2320 }, + { "TXNW2563", TAS2563 }, + { "TXNW2570", TAS2570 }, + { "TXNW2572", TAS2572 }, + { "TXNW2781", TAS2781 }, + { "TXNW5825", TAS5825 }, + { "TXNW5827", TAS5827 }, {}, }; -- cgit v1.2.3 From 267b9cdee522d03f95acf7c77de91056a4e004b3 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 9 Sep 2025 12:30:35 +0100 Subject: ASoC: cs-amp-lib: Add handling for Lenovo and HP UEFI speaker ID Add handling of the Lenovo-specific and HP-specific EFI variables for speaker ID. Future Lenovo and HP models will not give the codec driver access to the speaker detect GPIO. Instead, the BIOS will read the GPIO and create an EFI variable with a value indicating the state of the GPIO. The Lenovo and HP EFI variables are both defined to have only two valid values. But the variable name, GUID and values are different. This adds a new exported function cs_amp_get_vendor_spkid(). Signed-off-by: Richard Fitzgerald Message-ID: <20250909113039.922065-3-rf@opensource.cirrus.com> Signed-off-by: Mark Brown --- include/sound/cs-amp-lib.h | 1 + sound/soc/codecs/cs-amp-lib.c | 101 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) (limited to 'include') diff --git a/include/sound/cs-amp-lib.h b/include/sound/cs-amp-lib.h index 5459c221badf..43a87a39110c 100644 --- a/include/sound/cs-amp-lib.h +++ b/include/sound/cs-amp-lib.h @@ -49,6 +49,7 @@ int cs_amp_write_cal_coeffs(struct cs_dsp *dsp, const struct cirrus_amp_cal_data *data); int cs_amp_get_efi_calibration_data(struct device *dev, u64 target_uid, int amp_index, struct cirrus_amp_cal_data *out_data); +int cs_amp_get_vendor_spkid(struct device *dev); struct cs_amp_test_hooks { efi_status_t (*get_efi_variable)(efi_char16_t *name, diff --git a/sound/soc/codecs/cs-amp-lib.c b/sound/soc/codecs/cs-amp-lib.c index b1530e7c75e8..9b51d056d863 100644 --- a/sound/soc/codecs/cs-amp-lib.c +++ b/sound/soc/codecs/cs-amp-lib.c @@ -20,6 +20,14 @@ #define CIRRUS_LOGIC_CALIBRATION_EFI_GUID \ EFI_GUID(0x02f9af02, 0x7734, 0x4233, 0xb4, 0x3d, 0x93, 0xfe, 0x5a, 0xa3, 0x5d, 0xb3) +#define LENOVO_SPEAKER_ID_EFI_NAME L"SdwSpeaker" +#define LENOVO_SPEAKER_ID_EFI_GUID \ + EFI_GUID(0x48df970e, 0xe27f, 0x460a, 0xb5, 0x86, 0x77, 0x19, 0x80, 0x1d, 0x92, 0x82) + +#define HP_SPEAKER_ID_EFI_NAME L"HPSpeakerID" +#define HP_SPEAKER_ID_EFI_GUID \ + EFI_GUID(0xc49593a4, 0xd099, 0x419b, 0xa2, 0xc3, 0x67, 0xe9, 0x80, 0xe6, 0x1d, 0x1e) + static int cs_amp_write_cal_coeff(struct cs_dsp *dsp, const struct cirrus_amp_cal_controls *controls, const char *ctl_name, u32 val) @@ -114,6 +122,24 @@ static efi_status_t cs_amp_get_efi_variable(efi_char16_t *name, return EFI_NOT_FOUND; } +static int cs_amp_convert_efi_status(efi_status_t status) +{ + switch (status) { + case EFI_SUCCESS: + return 0; + case EFI_NOT_FOUND: + return -ENOENT; + case EFI_BUFFER_TOO_SMALL: + return -EFBIG; + case EFI_UNSUPPORTED: + case EFI_ACCESS_DENIED: + case EFI_SECURITY_VIOLATION: + return -EACCES; + default: + return -EIO; + } +} + static struct cirrus_amp_efi_data *cs_amp_get_cal_efi_buffer(struct device *dev) { struct cirrus_amp_efi_data *efi_data; @@ -276,6 +302,81 @@ int cs_amp_get_efi_calibration_data(struct device *dev, u64 target_uid, int amp_ } EXPORT_SYMBOL_NS_GPL(cs_amp_get_efi_calibration_data, "SND_SOC_CS_AMP_LIB"); +struct cs_amp_spkid_efi { + efi_char16_t *name; + efi_guid_t *guid; + u8 values[2]; +}; + +static int cs_amp_get_efi_byte_spkid(struct device *dev, const struct cs_amp_spkid_efi *info) +{ + efi_status_t status; + unsigned long size; + u8 spkid; + int i, ret; + + size = sizeof(spkid); + status = cs_amp_get_efi_variable(info->name, info->guid, &size, &spkid); + ret = cs_amp_convert_efi_status(status); + if (ret < 0) + return ret; + + if (size == 0) + return -ENOENT; + + for (i = 0; i < ARRAY_SIZE(info->values); i++) { + if (info->values[i] == spkid) + return i; + } + + dev_err(dev, "EFI speaker ID bad value %#x\n", spkid); + + return -EINVAL; +} + +static const struct cs_amp_spkid_efi cs_amp_spkid_byte_types[] = { + { + .name = LENOVO_SPEAKER_ID_EFI_NAME, + .guid = &LENOVO_SPEAKER_ID_EFI_GUID, + .values = { 0xd0, 0xd1 }, + }, + { + .name = HP_SPEAKER_ID_EFI_NAME, + .guid = &HP_SPEAKER_ID_EFI_GUID, + .values = { 0x30, 0x31 }, + }, +}; + +/** + * cs_amp_get_vendor_spkid - get a speaker ID from vendor-specific storage + * @dev: pointer to struct device + * + * Known vendor-specific methods of speaker ID are checked and if one is + * found its speaker ID value is returned. + * + * Return: >=0 is a valid speaker ID. -ENOENT if a vendor-specific method + * was not found. -EACCES if the vendor-specific storage could not + * be read. Other error values indicate that the data from the + * vendor-specific storage was found but could not be understood. + */ +int cs_amp_get_vendor_spkid(struct device *dev) +{ + int i, ret; + + if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE) && + !IS_ENABLED(CONFIG_SND_SOC_CS_AMP_LIB_TEST)) + return -ENOENT; + + for (i = 0; i < ARRAY_SIZE(cs_amp_spkid_byte_types); i++) { + ret = cs_amp_get_efi_byte_spkid(dev, &cs_amp_spkid_byte_types[i]); + if (ret != -ENOENT) + return ret; + } + + return -ENOENT; +} +EXPORT_SYMBOL_NS_GPL(cs_amp_get_vendor_spkid, "SND_SOC_CS_AMP_LIB"); + static const struct cs_amp_test_hooks cs_amp_test_hook_ptrs = { .get_efi_variable = cs_amp_get_efi_variable, .write_cal_coeff = cs_amp_write_cal_coeff, -- cgit v1.2.3 From 6b8ba0db92cd01450acaf375caf4c126aa913d72 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 4 Sep 2025 05:21:08 +0000 Subject: ASoC: soc-dapm: add snd_soc_dapm_to_dev() Because struct snd_soc_dapm_context is soc-dapm framework specific, user driver don't need to access its member directly, we would like to hide them. struct snd_soc_dapm_context will be removed from header in the future. Some drivers need to get dev from dapm (which will be removed). We need such function. Add it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87cy86x06z.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 3 ++- sound/soc/soc-dapm.c | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index ed39458b94bf..ccd36a198a13 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -587,7 +587,7 @@ struct snd_soc_dapm_context { unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ unsigned int suspend_bias_off:1; /* Use BIAS_OFF in suspend if the DAPM is idle */ - struct device *dev; /* from parent - for debug */ + struct device *dev; /* from parent - for debug */ /* REMOVE ME */ struct snd_soc_component *component; /* parent component */ struct snd_soc_card *card; /* parent card */ @@ -660,6 +660,7 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card); int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai); int snd_soc_dapm_widget_name_cmp(struct snd_soc_dapm_widget *widget, const char *s); +struct device *snd_soc_dapm_to_dev(struct snd_soc_dapm_context *dapm); /* dapm path setup */ int snd_soc_dapm_new_widgets(struct snd_soc_card *card); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index d74c096cc208..83cdf97edb9d 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -165,6 +165,15 @@ static void pop_dbg(struct device *dev, u32 pop_time, const char *fmt, ...) kfree(buf); } +struct device *snd_soc_dapm_to_dev(struct snd_soc_dapm_context *dapm) +{ + if (dapm->component) + return dapm->component->dev; + + return dapm->card->dev; +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_to_dev); + static bool dapm_dirty_widget(struct snd_soc_dapm_widget *w) { return !list_empty(&w->dirty); -- cgit v1.2.3 From c8df096bca84c9eb04b656015c8430d0b87ebbcf Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 4 Sep 2025 05:21:13 +0000 Subject: ASoC: soc-dapm: add snd_soc_dapm_to_card() Because struct snd_soc_dapm_context is soc-dapm framework specific, user driver don't need to access its member directly, we would like to hide them. struct snd_soc_dapm_context will be removed from header in the future. Some drivers need to get card from dapm (which will be removed). We need such function. Add it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87bjnqx06v.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 1 + sound/soc/soc-dapm.c | 6 ++++++ 2 files changed, 7 insertions(+) (limited to 'include') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index ccd36a198a13..dbb71e396feb 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -661,6 +661,7 @@ int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai); int snd_soc_dapm_widget_name_cmp(struct snd_soc_dapm_widget *widget, const char *s); struct device *snd_soc_dapm_to_dev(struct snd_soc_dapm_context *dapm); +struct snd_soc_card *snd_soc_dapm_to_card(struct snd_soc_dapm_context *dapm); /* dapm path setup */ int snd_soc_dapm_new_widgets(struct snd_soc_card *card); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 83cdf97edb9d..cd8d38579886 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -174,6 +174,12 @@ struct device *snd_soc_dapm_to_dev(struct snd_soc_dapm_context *dapm) } EXPORT_SYMBOL_GPL(snd_soc_dapm_to_dev); +struct snd_soc_card *snd_soc_dapm_to_card(struct snd_soc_dapm_context *dapm) +{ + return dapm->card; +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_to_card); + static bool dapm_dirty_widget(struct snd_soc_dapm_widget *w) { return !list_empty(&w->dirty); -- cgit v1.2.3 From 96e311b561a2d393a786a2aeb50cd5e02d06afb3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 4 Sep 2025 05:21:17 +0000 Subject: ASoC: soc-dapm: use dapm->component instead of container_of() Because struct snd_soc_dapm_context is soc-dapm framework specific, user driver don't need to access its member directly, we would like to hide them. struct snd_soc_dapm_context will be removed from header in the future. Now, snd_soc_dapm_to_component() (A) will convert dapm to component by container_of() (a). (A) static inline struct snd_soc_component *snd_soc_dapm_to_component( struct snd_soc_dapm_context *dapm) { (a) return container_of(dapm, struct snd_soc_component, dapm); } dapm of component works, but dapm of card will be "unknown" pointer (= not NULL), because (a) is using "container_of()". OTOH, ASoC will call snd_soc_dapm_init() (X) to initialize dapm, and it will be called from snd_soc_bind_card() (p) (for card) or soc_probe_component() (q) (for component) with component pointer. (p) static int snd_soc_bind_card(...) { ... (X) snd_soc_dapm_init(..., NULL); ... ^^^^ } (q) static int soc_probe_component(...) { ... (X) snd_soc_dapm_init(..., component); ... ^^^^^^^^^ } And snd_soc_dapm_init() (X) will fill dapm->component (x) (X) void snd_soc_dapm_init(..., component, ...) { ... (x) dapm->component = component; ... } We can simply use dapm->component in snd_soc_dapm_to_component() (A). In this case, dapm of card (p) will be just NULL. Use dapm->component instead of container_of(). The picky note can be removed by this patch. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87a53ax06q.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 15 --------------- include/sound/soc-dapm.h | 1 + sound/soc/soc-dapm.c | 6 ++++++ 3 files changed, 7 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 48e45cbe82e5..7322d5d4c0bd 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -260,21 +260,6 @@ struct snd_soc_component { #define for_each_component_dais_safe(component, dai, _dai)\ list_for_each_entry_safe(dai, _dai, &(component)->dai_list, list) -/** - * snd_soc_dapm_to_component() - Casts a DAPM context to the component it is - * embedded in - * @dapm: The DAPM context to cast to the component - * - * This function must only be used on DAPM contexts that are known to be part of - * a component (e.g. in a component driver). Otherwise the behavior is - * undefined. - */ -static inline struct snd_soc_component *snd_soc_dapm_to_component( - struct snd_soc_dapm_context *dapm) -{ - return container_of(dapm, struct snd_soc_component, dapm); -} - /** * snd_soc_component_get_dapm() - Returns the DAPM context associated with a * component diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index dbb71e396feb..c6470d391eef 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -662,6 +662,7 @@ int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream, int snd_soc_dapm_widget_name_cmp(struct snd_soc_dapm_widget *widget, const char *s); struct device *snd_soc_dapm_to_dev(struct snd_soc_dapm_context *dapm); struct snd_soc_card *snd_soc_dapm_to_card(struct snd_soc_dapm_context *dapm); +struct snd_soc_component *snd_soc_dapm_to_component(struct snd_soc_dapm_context *dapm); /* dapm path setup */ int snd_soc_dapm_new_widgets(struct snd_soc_card *card); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index cd8d38579886..4550bf33add2 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -180,6 +180,12 @@ struct snd_soc_card *snd_soc_dapm_to_card(struct snd_soc_dapm_context *dapm) } EXPORT_SYMBOL_GPL(snd_soc_dapm_to_card); +struct snd_soc_component *snd_soc_dapm_to_component(struct snd_soc_dapm_context *dapm) +{ + return dapm->component; +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_to_component); + static bool dapm_dirty_widget(struct snd_soc_dapm_widget *w) { return !list_empty(&w->dirty); -- cgit v1.2.3 From a1c99b6097afe64ed493c05b522ee4d6f9b0094d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 4 Sep 2025 05:21:21 +0000 Subject: ASoC: soc-component: add snd_soc_component_to_dapm() Because struct snd_soc_dapm_context is soc-dapm framework specific, user driver don't need to access its member directly, we would like to hide them. struct snd_soc_dapm_context will be removed from header in the future. Current dapm of card/component are using "instance", but it will be "pointer" if snd_soc_dapm_context was removed from header. snd_soc_component_to_dapm() is needed to switch to the new style while maintaining compatibility Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/878qiux06m.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 7322d5d4c0bd..b954f34d6025 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -261,16 +261,19 @@ struct snd_soc_component { list_for_each_entry_safe(dai, _dai, &(component)->dai_list, list) /** - * snd_soc_component_get_dapm() - Returns the DAPM context associated with a + * snd_soc_component_to_dapm() - Returns the DAPM context associated with a * component * @component: The component for which to get the DAPM context */ -static inline struct snd_soc_dapm_context *snd_soc_component_get_dapm( +static inline struct snd_soc_dapm_context *snd_soc_component_to_dapm( struct snd_soc_component *component) { return &component->dapm; } +// FIXME +#define snd_soc_component_get_dapm snd_soc_component_to_dapm + /** * snd_soc_component_cache_sync() - Sync the register cache with the hardware * @component: COMPONENT to sync -- cgit v1.2.3 From e38a80c5c24f3058bd5da6f2910e2b672493f4f2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 4 Sep 2025 05:21:25 +0000 Subject: ASoC: soc-card: add snd_soc_card_to_dapm() Because struct snd_soc_dapm_context is soc-dapm framework specific, user driver don't need to access its member directly, we would like to hide them. struct snd_soc_dapm_context will be removed from header in the future. Current dapm of card/component are using "instance", but it will be "pointer" if snd_soc_dapm_context was removed from header. snd_soc_card_to_dapm() is needed to switch to the new style while maintaining compatibility Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/877byex06i.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/sound/soc.h b/include/sound/soc.h index 1fffef311c41..ddc508ff7b9b 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1120,6 +1120,11 @@ static inline int snd_soc_card_is_instantiated(struct snd_soc_card *card) return card && card->instantiated; } +static inline struct snd_soc_dapm_context *snd_soc_card_to_dapm(struct snd_soc_card *card) +{ + return &card->dapm; +} + /* SoC machine DAI configuration, glues a codec and cpu DAI together */ struct snd_soc_pcm_runtime { struct device *dev; -- cgit v1.2.3 From 3bc0a92cb2062fce54ddd97ad68ad6fe358c3ff0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 4 Sep 2025 05:21:29 +0000 Subject: ASoC: soc-dapm: remove suspend_bias_off from snd_soc_dapm_context We can directly use suspend_bias_off via snd_soc_component, no need to keep it on dapm. Remove it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/875xdyx06e.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 1 - sound/soc/soc-dapm.c | 6 ++++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index c6470d391eef..498f8af79cfa 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -585,7 +585,6 @@ struct snd_soc_dapm_context { /* bit field */ unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ - unsigned int suspend_bias_off:1; /* Use BIAS_OFF in suspend if the DAPM is idle */ struct device *dev; /* from parent - for debug */ /* REMOVE ME */ struct snd_soc_component *component; /* parent component */ diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 4550bf33add2..b90d0adb7713 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2182,13 +2182,16 @@ end: static bool dapm_idle_bias_off(struct snd_soc_dapm_context *dapm) { + struct snd_soc_component *component = snd_soc_dapm_to_component(dapm); if (dapm->idle_bias_off) return true; switch (snd_power_get_state(dapm->card->snd_card)) { case SNDRV_CTL_POWER_D3hot: case SNDRV_CTL_POWER_D3cold: - return dapm->suspend_bias_off; + if (component) + return component->driver->suspend_bias_off; + fallthrough; default: break; } @@ -4823,7 +4826,6 @@ void snd_soc_dapm_init(struct snd_soc_dapm_context *dapm, if (component) { dapm->dev = component->dev; dapm->idle_bias_off = !component->driver->idle_bias_on; - dapm->suspend_bias_off = component->driver->suspend_bias_off; } else { dapm->dev = card->dev; } -- cgit v1.2.3 From 889dd56f8c03586e5489050e7457a405fae6a420 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 4 Sep 2025 05:21:33 +0000 Subject: ASoC: soc-dapm: tidyup idle_bias handling - step1 Current soc-dapm is using "idle_bias_off", and its default settings came from snd_soc_component "idle_bias_on". It is complicated/confusable. Let's handling it as "idle_bias". Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/874itix06a.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 3 +-- sound/soc/codecs/wm8993.c | 2 +- sound/soc/codecs/wm8994.c | 6 +++--- sound/soc/intel/avs/boards/es8336.c | 2 +- sound/soc/intel/avs/boards/rt274.c | 2 +- sound/soc/intel/avs/boards/rt5640.c | 2 +- sound/soc/intel/boards/bytcht_cx2072x.c | 2 +- sound/soc/intel/boards/bytcht_es8316.c | 2 +- sound/soc/intel/boards/bytcr_rt5640.c | 2 +- sound/soc/intel/boards/bytcr_rt5651.c | 2 +- sound/soc/intel/boards/bytcr_wm5102.c | 2 +- sound/soc/intel/boards/sof_es8336.c | 2 +- sound/soc/soc-core.c | 4 ++-- sound/soc/soc-dapm.c | 20 ++++++++++---------- sound/soc/sof/sof-client-probes.c | 2 +- 15 files changed, 27 insertions(+), 28 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 498f8af79cfa..9618a54a5348 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -583,8 +583,7 @@ struct snd_soc_dapm_update { struct snd_soc_dapm_context { enum snd_soc_bias_level bias_level; - /* bit field */ - unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ + bool idle_bias; /* Use BIAS_OFF instead of STANDBY when false */ struct device *dev; /* from parent - for debug */ /* REMOVE ME */ struct snd_soc_component *component; /* parent component */ diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 9be4f6cadba3..75d923c2c9ca 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -1536,7 +1536,7 @@ static int wm8993_probe(struct snd_soc_component *component) * VMID as an output and can disable it. */ if (wm8993->pdata.lineout1_diff && wm8993->pdata.lineout2_diff) - dapm->idle_bias_off = 1; + dapm->idle_bias = false; return 0; diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 240ec1bed234..128c3a59beac 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -4182,8 +4182,8 @@ static int wm8994_component_probe(struct snd_soc_component *component) wm8994->micdet_irq = control->pdata.micdet_irq; - /* By default use idle_bias_off, will override for WM8994 */ - dapm->idle_bias_off = 1; + /* By default use idle_bias false, will override for WM8994 */ + dapm->idle_bias = false; /* Set revision-specific configuration */ switch (control->type) { @@ -4191,7 +4191,7 @@ static int wm8994_component_probe(struct snd_soc_component *component) /* Single ended line outputs should have VMID on. */ if (!control->pdata.lineout1_diff || !control->pdata.lineout2_diff) - dapm->idle_bias_off = 0; + dapm->idle_bias = true; switch (control->revision) { case 2: diff --git a/sound/soc/intel/avs/boards/es8336.c b/sound/soc/intel/avs/boards/es8336.c index 12e4e0aba5fa..eb2b40894e3f 100644 --- a/sound/soc/intel/avs/boards/es8336.c +++ b/sound/soc/intel/avs/boards/es8336.c @@ -132,7 +132,7 @@ static int avs_es8336_codec_init(struct snd_soc_pcm_runtime *runtime) snd_jack_set_key(data->jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); snd_soc_component_set_jack(component, &data->jack, NULL); - card->dapm.idle_bias_off = true; + card->dapm.idle_bias = false; return 0; } diff --git a/sound/soc/intel/avs/boards/rt274.c b/sound/soc/intel/avs/boards/rt274.c index 67d2c4585cdd..4055ecc60838 100644 --- a/sound/soc/intel/avs/boards/rt274.c +++ b/sound/soc/intel/avs/boards/rt274.c @@ -117,7 +117,7 @@ static int avs_rt274_codec_init(struct snd_soc_pcm_runtime *runtime) return ret; } - card->dapm.idle_bias_off = true; + card->dapm.idle_bias = false; return 0; } diff --git a/sound/soc/intel/avs/boards/rt5640.c b/sound/soc/intel/avs/boards/rt5640.c index 706b84ffe1ef..97d1fa944188 100644 --- a/sound/soc/intel/avs/boards/rt5640.c +++ b/sound/soc/intel/avs/boards/rt5640.c @@ -67,7 +67,7 @@ static int avs_rt5640_codec_init(struct snd_soc_pcm_runtime *runtime) return ret; snd_soc_component_set_jack(codec_dai->component, jack, NULL); - card->dapm.idle_bias_off = true; + card->dapm.idle_bias = false; return 0; } diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c index 68a3d345dc25..27b63a853a48 100644 --- a/sound/soc/intel/boards/bytcht_cx2072x.c +++ b/sound/soc/intel/boards/bytcht_cx2072x.c @@ -77,7 +77,7 @@ static int byt_cht_cx2072x_init(struct snd_soc_pcm_runtime *rtd) byt_cht_cx2072x_acpi_gpios)) dev_warn(rtd->dev, "Unable to add GPIO mapping table\n"); - card->dapm.idle_bias_off = true; + card->dapm.idle_bias = false; /* set the default PLL rate, the clock is handled by the codec driver */ ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_codec(rtd, 0), CX2072X_MCLK_EXTERNAL_PLL, diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index b384d38654e6..3b5f63112237 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -179,7 +179,7 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime) int num_routes; int ret; - card->dapm.idle_bias_off = true; + card->dapm.idle_bias = false; switch (BYT_CHT_ES8316_MAP(quirk)) { case BYT_CHT_ES8316_INTMIC_IN1_MAP: diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index bc846558480e..1e9b1903fae8 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -1324,7 +1324,7 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) int num_routes = 0; int ret; - card->dapm.idle_bias_off = true; + card->dapm.idle_bias = false; jack_data->use_platform_clock = true; /* Start with RC clk for jack-detect (we disable MCLK below) */ diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 604a35d380e9..ca540a66f22c 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -586,7 +586,7 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime) int report; int ret; - card->dapm.idle_bias_off = true; + card->dapm.idle_bias = false; /* Start with RC clk for jack-detect (we disable MCLK below) */ if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) diff --git a/sound/soc/intel/boards/bytcr_wm5102.c b/sound/soc/intel/boards/bytcr_wm5102.c index a6dfbcfdf74e..72c0e5941ae8 100644 --- a/sound/soc/intel/boards/bytcr_wm5102.c +++ b/sound/soc/intel/boards/bytcr_wm5102.c @@ -288,7 +288,7 @@ static int byt_wm5102_init(struct snd_soc_pcm_runtime *runtime) const struct snd_soc_dapm_route *custom_map = NULL; int ret, jack_type, num_routes = 0; - card->dapm.idle_bias_off = true; + card->dapm.idle_bias = false; ret = snd_soc_add_card_controls(card, byt_wm5102_controls, ARRAY_SIZE(byt_wm5102_controls)); diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c index 1211a2b8a2a2..10b189ea88db 100644 --- a/sound/soc/intel/boards/sof_es8336.c +++ b/sound/soc/intel/boards/sof_es8336.c @@ -276,7 +276,7 @@ static int sof_es8316_init(struct snd_soc_pcm_runtime *runtime) int num_routes; int ret; - card->dapm.idle_bias_off = true; + card->dapm.idle_bias = false; if (quirk & SOC_ES8336_HEADSET_MIC1) { custom_map = sof_es8316_headset_mic1_map; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index cc9125ffe92a..9dd84d73046b 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -717,7 +717,7 @@ int snd_soc_suspend(struct device *dev) * means it's doing something, * otherwise fall through. */ - if (dapm->idle_bias_off) { + if (!dapm->idle_bias) { dev_dbg(component->dev, "ASoC: idle_bias_off CODEC on over suspend\n"); break; @@ -1652,7 +1652,7 @@ static int soc_probe_component(struct snd_soc_card *card, if (ret < 0) goto err_probe; - WARN(dapm->idle_bias_off && + WARN(!dapm->idle_bias && dapm->bias_level != SND_SOC_BIAS_OFF, "codec %s can not start from non-off bias with idle_bias_off==1\n", component->name); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index b90d0adb7713..cbe945f1dc9c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2180,23 +2180,23 @@ end: dapm_seq_insert(w, down_list, false); } -static bool dapm_idle_bias_off(struct snd_soc_dapm_context *dapm) +static bool dapm_get_idle_bias(struct snd_soc_dapm_context *dapm) { struct snd_soc_component *component = snd_soc_dapm_to_component(dapm); - if (dapm->idle_bias_off) - return true; + if (!dapm->idle_bias) + return false; switch (snd_power_get_state(dapm->card->snd_card)) { case SNDRV_CTL_POWER_D3hot: case SNDRV_CTL_POWER_D3cold: if (component) - return component->driver->suspend_bias_off; + return !component->driver->suspend_bias_off; fallthrough; default: break; } - return false; + return true; } /* @@ -2224,10 +2224,10 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event, trace_snd_soc_dapm_start(card, event); for_each_card_dapms(card, d) { - if (dapm_idle_bias_off(d)) - d->target_bias_level = SND_SOC_BIAS_OFF; - else + if (dapm_get_idle_bias(d)) d->target_bias_level = SND_SOC_BIAS_STANDBY; + else + d->target_bias_level = SND_SOC_BIAS_OFF; } dapm_reset(card); @@ -2291,7 +2291,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event, if (d->target_bias_level > bias) bias = d->target_bias_level; for_each_card_dapms(card, d) - if (!dapm_idle_bias_off(d)) + if (dapm_get_idle_bias(d)) d->target_bias_level = bias; trace_snd_soc_dapm_walk_done(card); @@ -4825,7 +4825,7 @@ void snd_soc_dapm_init(struct snd_soc_dapm_context *dapm, if (component) { dapm->dev = component->dev; - dapm->idle_bias_off = !component->driver->idle_bias_on; + dapm->idle_bias = component->driver->idle_bias_on; } else { dapm->dev = card->dev; } diff --git a/sound/soc/sof/sof-client-probes.c b/sound/soc/sof/sof-client-probes.c index 3ca8460774bb..aaf0ae4bf01f 100644 --- a/sound/soc/sof/sof-client-probes.c +++ b/sound/soc/sof/sof-client-probes.c @@ -525,7 +525,7 @@ static int sof_probes_client_probe(struct auxiliary_device *auxdev, card->dai_link = links; /* set idle_bias_off to prevent the core from resuming the card->dev */ - card->dapm.idle_bias_off = true; + card->dapm.idle_bias = false; snd_soc_card_set_drvdata(card, cdev); -- cgit v1.2.3 From 2e7f0a86123d54a94fa3d309efdfbac02f2999b8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 4 Sep 2025 05:21:41 +0000 Subject: ASoC: soc-dapm: add snd_soc_dapm_get_bias_level() Because struct snd_soc_dapm_context is soc-dapm framework specific, user driver don't need to access its member directly, we would like to hide them. struct snd_soc_dapm_context will be removed from header in the future. Many drivers are directly using dapm->idle_bias, but it should get it via get_idle_bias() function. Makes it as global function. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/871pomx062.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 2 ++ sound/soc/soc-dapm.c | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 9618a54a5348..e978be4010b8 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -662,6 +662,8 @@ struct device *snd_soc_dapm_to_dev(struct snd_soc_dapm_context *dapm); struct snd_soc_card *snd_soc_dapm_to_card(struct snd_soc_dapm_context *dapm); struct snd_soc_component *snd_soc_dapm_to_component(struct snd_soc_dapm_context *dapm); +bool snd_soc_dapm_get_idle_bias(struct snd_soc_dapm_context *dapm); + /* dapm path setup */ int snd_soc_dapm_new_widgets(struct snd_soc_card *card); void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index a263696ef8ac..209da43bc023 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2180,7 +2180,7 @@ end: dapm_seq_insert(w, down_list, false); } -static bool dapm_get_idle_bias(struct snd_soc_dapm_context *dapm) +bool snd_soc_dapm_get_idle_bias(struct snd_soc_dapm_context *dapm) { if (dapm->idle_bias) { struct snd_soc_component *component = snd_soc_dapm_to_component(dapm); @@ -2193,6 +2193,7 @@ static bool dapm_get_idle_bias(struct snd_soc_dapm_context *dapm) return dapm->idle_bias; } +EXPORT_SYMBOL_GPL(snd_soc_dapm_get_idle_bias); /* * Scan each dapm widget for complete audio path. @@ -2219,7 +2220,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event, trace_snd_soc_dapm_start(card, event); for_each_card_dapms(card, d) { - if (dapm_get_idle_bias(d)) + if (snd_soc_dapm_get_idle_bias(d)) d->target_bias_level = SND_SOC_BIAS_STANDBY; else d->target_bias_level = SND_SOC_BIAS_OFF; @@ -2286,7 +2287,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event, if (d->target_bias_level > bias) bias = d->target_bias_level; for_each_card_dapms(card, d) - if (dapm_get_idle_bias(d)) + if (snd_soc_dapm_get_idle_bias(d)) d->target_bias_level = bias; trace_snd_soc_dapm_walk_done(card); -- cgit v1.2.3 From cb3c715d89607f8896c0f20fe528a08e7ebffea9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 4 Sep 2025 05:21:45 +0000 Subject: ASoC: soc-dapm: add snd_soc_dapm_set_idle_bias() Because struct snd_soc_dapm_context is soc-dapm framework specific, user driver don't need to access its member directly, we would like to hide them. struct snd_soc_dapm_context will be removed from header in the future. Many drivers are directly setting dapm->idle_bias, but it will be impossible soon. adds snd_soc_dapm_set_idle_bias() for them. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87zfbavllj.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 1 + sound/soc/soc-dapm.c | 6 ++++++ 2 files changed, 7 insertions(+) (limited to 'include') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index e978be4010b8..75941324886b 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -663,6 +663,7 @@ struct snd_soc_card *snd_soc_dapm_to_card(struct snd_soc_dapm_context *dapm); struct snd_soc_component *snd_soc_dapm_to_component(struct snd_soc_dapm_context *dapm); bool snd_soc_dapm_get_idle_bias(struct snd_soc_dapm_context *dapm); +void snd_soc_dapm_set_idle_bias(struct snd_soc_dapm_context *dapm, bool on); /* dapm path setup */ int snd_soc_dapm_new_widgets(struct snd_soc_card *card); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 209da43bc023..51fb09d56c5a 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2195,6 +2195,12 @@ bool snd_soc_dapm_get_idle_bias(struct snd_soc_dapm_context *dapm) } EXPORT_SYMBOL_GPL(snd_soc_dapm_get_idle_bias); +void snd_soc_dapm_set_idle_bias(struct snd_soc_dapm_context *dapm, bool on) +{ + dapm->idle_bias = on; +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_set_idle_bias); + /* * Scan each dapm widget for complete audio path. * A complete path is a route that has valid endpoints i.e.:- -- cgit v1.2.3 From 76cffc3eb1bdee0a7e8cca090adfd46a740f1cb0 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 9 Sep 2025 13:19:44 +0100 Subject: soundwire: bus: add of_sdw_find_device_by_node helper There has been more than 3 instances of this helper in multiple codec drivers, it does not make sense to keep duplicating this part of code. Lets add a helper of_sdw_find_device_by_node for codec drivers to use it. Signed-off-by: Srinivas Kandagatla Reviewed-by: Dmitry Baryshkov Acked-by: Vinod Koul Link: https://patch.msgid.link/20250909121954.225833-4-srinivas.kandagatla@oss.qualcomm.com Signed-off-by: Mark Brown --- drivers/soundwire/slave.c | 6 ++++++ include/linux/soundwire/sdw.h | 9 +++++++++ 2 files changed, 15 insertions(+) (limited to 'include') diff --git a/drivers/soundwire/slave.c b/drivers/soundwire/slave.c index d2d99555ec5a..3d4d00188c26 100644 --- a/drivers/soundwire/slave.c +++ b/drivers/soundwire/slave.c @@ -273,4 +273,10 @@ int sdw_of_find_slaves(struct sdw_bus *bus) return 0; } +struct device *of_sdw_find_device_by_node(struct device_node *np) +{ + return bus_find_device_by_of_node(&sdw_bus_type, np); +} +EXPORT_SYMBOL_GPL(of_sdw_find_device_by_node); + MODULE_IMPORT_NS("SND_SOC_SDCA"); diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 0832776262ac..096213956d31 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -19,6 +19,7 @@ struct dentry; struct fwnode_handle; +struct device_node; struct sdw_bus; struct sdw_slave; @@ -1086,6 +1087,8 @@ int sdw_stream_add_slave(struct sdw_slave *slave, int sdw_stream_remove_slave(struct sdw_slave *slave, struct sdw_stream_runtime *stream); +struct device *of_sdw_find_device_by_node(struct device_node *np); + int sdw_slave_get_scale_index(struct sdw_slave *slave, u8 *base); /* messaging and data APIs */ @@ -1119,6 +1122,12 @@ static inline int sdw_stream_remove_slave(struct sdw_slave *slave, return -EINVAL; } +static inline struct device *of_sdw_find_device_by_node(struct device_node *np) +{ + WARN_ONCE(1, "SoundWire API is disabled"); + return NULL; +} + /* messaging and data APIs */ static inline int sdw_read(struct sdw_slave *slave, u32 addr) { -- cgit v1.2.3 From 2e07017b28e8bbace4a4973d11d0646575d36f94 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 9 Sep 2025 13:19:45 +0100 Subject: soundwire: bus: add sdw_slave_get_current_bank helper There has been 2 instances of this helper in codec drivers, it does not make sense to keep duplicating this part of code. Lets add a helper sdw_get_current_bank() for codec drivers to use it. Signed-off-by: Srinivas Kandagatla Acked-by: Vinod Koul Reviewed-by: Dmitry Baryshkov Link: https://patch.msgid.link/20250909121954.225833-5-srinivas.kandagatla@oss.qualcomm.com Signed-off-by: Mark Brown --- drivers/soundwire/bus.c | 12 ++++++++++++ include/linux/soundwire/sdw.h | 8 ++++++++ 2 files changed, 20 insertions(+) (limited to 'include') diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 4fd5cac799c5..55c1db816534 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -1360,6 +1360,18 @@ int sdw_slave_get_scale_index(struct sdw_slave *slave, u8 *base) } EXPORT_SYMBOL(sdw_slave_get_scale_index); +int sdw_slave_get_current_bank(struct sdw_slave *slave) +{ + int tmp; + + tmp = sdw_read(slave, SDW_SCP_CTRL); + if (tmp < 0) + return tmp; + + return FIELD_GET(SDW_SCP_STAT_CURR_BANK, tmp); +} +EXPORT_SYMBOL_GPL(sdw_slave_get_current_bank); + static int sdw_slave_set_frequency(struct sdw_slave *slave) { int scale_index; diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 096213956d31..e6a3476bcef1 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -1089,6 +1089,8 @@ int sdw_stream_remove_slave(struct sdw_slave *slave, struct device *of_sdw_find_device_by_node(struct device_node *np); +int sdw_slave_get_current_bank(struct sdw_slave *sdev); + int sdw_slave_get_scale_index(struct sdw_slave *slave, u8 *base); /* messaging and data APIs */ @@ -1128,6 +1130,12 @@ static inline struct device *of_sdw_find_device_by_node(struct device_node *np) return NULL; } +static inline int sdw_slave_get_current_bank(struct sdw_slave *sdev) +{ + WARN_ONCE(1, "SoundWire API is disabled"); + return -EINVAL; +} + /* messaging and data APIs */ static inline int sdw_read(struct sdw_slave *slave, u32 addr) { -- cgit v1.2.3 From 5d36370f34312776d202e5c35d1a786d8b07a9c3 Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Wed, 17 Sep 2025 08:32:50 +0100 Subject: ALSA: compress: add raw opus codec define and opus decoder structs Adds a raw opus codec define and raw opus decoder structs. This is for raw OPUS packets not packed in any type of container (for instance OGG container). The decoder struct fields are taken from corresponding RFC document: RFC 7845 Section 5. Cc: Srinivas Kandagatla Cc: Vinod Koul Co-developed-by: Annemarie Porter Signed-off-by: Annemarie Porter Signed-off-by: Alexey Klimov Signed-off-by: Takashi Iwai --- include/uapi/sound/compress_params.h | 43 +++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/uapi/sound/compress_params.h b/include/uapi/sound/compress_params.h index bc7648a30746..faf4fa911f7f 100644 --- a/include/uapi/sound/compress_params.h +++ b/include/uapi/sound/compress_params.h @@ -43,7 +43,8 @@ #define SND_AUDIOCODEC_BESPOKE ((__u32) 0x0000000E) #define SND_AUDIOCODEC_ALAC ((__u32) 0x0000000F) #define SND_AUDIOCODEC_APE ((__u32) 0x00000010) -#define SND_AUDIOCODEC_MAX SND_AUDIOCODEC_APE +#define SND_AUDIOCODEC_OPUS_RAW ((__u32) 0x00000011) +#define SND_AUDIOCODEC_MAX SND_AUDIOCODEC_OPUS_RAW /* * Profile and modes are listed with bit masks. This allows for a @@ -324,6 +325,45 @@ struct snd_dec_ape { __u32 seek_table_present; } __attribute__((packed, aligned(4))); +/** + * struct snd_dec_opus - Opus decoder parameters (raw opus packets) + * @version: Usually should be '1' but can be split into major (4 upper bits) + * and minor (4 lower bits) sub-fields. + * @num_channels: Number of output channels. + * @pre_skip: Number of samples to discard at 48 kHz. + * @sample_rate: Sample rate of original input. + * @output_gain: Gain to apply when decoding (in Q7.8 format). + * @mapping_family: Order and meaning of output channels. Only values 0 and 1 + * are expected; values 2..255 are not recommended for playback. + * + * Optional channel mapping table. Describes mapping of opus streams to decoded + * channels. + * @struct snd_dec_opus_ch_map + * @stream_count: Number of streams encoded in each Ogg packet. + * @coupled_count: Number of streams whose decoders are used for two + * channels. + * @channel_map: describes which decoded channel to be used for each one. + * See RFC doc for details. + * This supports only mapping families 0 and 1, therefore max + * number of channels is 8. + * + * These options were extracted from RFC7845 Section 5. + */ + +struct snd_dec_opus { + __u8 version; + __u8 num_channels; + __u16 pre_skip; + __u32 sample_rate; + __u16 output_gain; + __u8 mapping_family; + struct snd_dec_opus_ch_map { + __u8 stream_count; + __u8 coupled_count; + __u8 channel_map[8]; + } chan_map; +} __attribute__((packed, aligned(4))); + union snd_codec_options { struct snd_enc_wma wma; struct snd_enc_vorbis vorbis; @@ -334,6 +374,7 @@ union snd_codec_options { struct snd_dec_wma wma_d; struct snd_dec_alac alac_d; struct snd_dec_ape ape_d; + struct snd_dec_opus opus_d; struct { __u32 out_sample_rate; } src_d; -- cgit v1.2.3 From b07d2514b91c30ab16fdf8f9cc3523bef969becf Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Wed, 17 Sep 2025 08:32:51 +0100 Subject: ALSA: compress_offload: increase SNDRV_COMPRESS_VERSION minor version by 1 Since addition of raw opus codec support we need to update compress API minor version by one. Bump the SNDRV_COMPRESS_VERSION to 0.4.1. Signed-off-by: Alexey Klimov Acked-by: Vinod Koul Signed-off-by: Takashi Iwai --- include/uapi/sound/compress_offload.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/uapi/sound/compress_offload.h b/include/uapi/sound/compress_offload.h index 26f756cc2e62..b610683fd8db 100644 --- a/include/uapi/sound/compress_offload.h +++ b/include/uapi/sound/compress_offload.h @@ -13,7 +13,7 @@ #include #include -#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 4, 0) +#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 4, 1) /** * struct snd_compressed_buffer - compressed buffer * @fragment_size: size of buffer fragment in bytes -- cgit v1.2.3 From 96384a34dd15b0e7357a34af5c848d1115a35e62 Mon Sep 17 00:00:00 2001 From: Niranjan H Y Date: Fri, 12 Sep 2025 14:06:22 +0530 Subject: ASoc: tas2783A: machine driver amp utility for TI devices Machine driver amp utility file to initialize and support multiple tas2783a devices are added. Reviewed-by: Bard Liao Signed-off-by: Niranjan H Y -- v5: - removed empty line in soc_sdw_ti_amp.c Link: https://patch.msgid.link/20250912083624.804-3-niranjan.hy@ti.com Signed-off-by: Mark Brown --- include/sound/soc_sdw_utils.h | 8 ++++ sound/soc/sdw_utils/Makefile | 3 +- sound/soc/sdw_utils/soc_sdw_ti_amp.c | 92 ++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 sound/soc/sdw_utils/soc_sdw_ti_amp.c (limited to 'include') diff --git a/include/sound/soc_sdw_utils.h b/include/sound/soc_sdw_utils.h index 6049a5d0cfcd..3c5e9b2af7f1 100644 --- a/include/sound/soc_sdw_utils.h +++ b/include/sound/soc_sdw_utils.h @@ -248,5 +248,13 @@ int asoc_sdw_cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_so int asoc_sdw_cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); int asoc_sdw_cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); int asoc_sdw_maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +/* TI */ +int asoc_sdw_ti_amp_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback); +int asoc_sdw_ti_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_ti_amp_initial_settings(struct snd_soc_card *card, + const char *name_prefix); #endif diff --git a/sound/soc/sdw_utils/Makefile b/sound/soc/sdw_utils/Makefile index daf019113553..a87c53e1a2c1 100644 --- a/sound/soc/sdw_utils/Makefile +++ b/sound/soc/sdw_utils/Makefile @@ -6,5 +6,6 @@ snd-soc-sdw-utils-y := soc_sdw_utils.o soc_sdw_dmic.o soc_sdw_rt_dmic.o \ soc_sdw_bridge_cs35l56.o \ soc_sdw_cs42l42.o soc_sdw_cs42l43.o \ soc_sdw_cs_amp.o \ - soc_sdw_maxim.o + soc_sdw_maxim.o \ + soc_sdw_ti_amp.o obj-$(CONFIG_SND_SOC_SDW_UTILS) += snd-soc-sdw-utils.o diff --git a/sound/soc/sdw_utils/soc_sdw_ti_amp.c b/sound/soc/sdw_utils/soc_sdw_ti_amp.c new file mode 100644 index 000000000000..f0011360ae9b --- /dev/null +++ b/sound/soc/sdw_utils/soc_sdw_ti_amp.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2025 Texas Instruments Inc. + +/* + * soc_sdw_ti_amp - Helpers to handle TI's soundwire based codecs + */ + +#include +#include +#include +#include +#include +#include + +#define TIAMP_SPK_VOLUME_0DB 200 + +int asoc_sdw_ti_amp_initial_settings(struct snd_soc_card *card, + const char *name_prefix) +{ + char *volume_ctl_name; + int ret; + + volume_ctl_name = kasprintf(GFP_KERNEL, "%s Speaker Volume", + name_prefix); + if (!volume_ctl_name) + return -ENOMEM; + + ret = snd_soc_limit_volume(card, volume_ctl_name, + TIAMP_SPK_VOLUME_0DB); + if (ret) + dev_err(card->dev, + "%s update failed %d\n", + volume_ctl_name, ret); + + kfree(volume_ctl_name); + return 0; +} +EXPORT_SYMBOL_NS(asoc_sdw_ti_amp_initial_settings, "SND_SOC_SDW_UTILS"); + +int asoc_sdw_ti_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, + struct snd_soc_dai *dai) +{ + struct snd_soc_card *card = rtd->card; + char widget_name[16]; + char speaker[16]; + struct snd_soc_dapm_route route = {speaker, NULL, widget_name}; + struct snd_soc_dai *codec_dai; + const char *prefix; + int i, ret = 0; + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + if (!strstr(codec_dai->name, "tas2783")) + continue; + + prefix = codec_dai->component->name_prefix; + if (!strncmp(prefix, "tas2783-1", strlen("tas2783-1"))) { + strscpy(speaker, "Left Spk", sizeof(speaker)); + } else if (!strncmp(prefix, "tas2783-2", strlen("tas2783-2"))) { + strscpy(speaker, "Right Spk", sizeof(speaker)); + } else { + ret = -EINVAL; + dev_err(card->dev, "unhandled prefix %s", prefix); + break; + } + + snprintf(widget_name, sizeof(widget_name), "%s SPK", prefix); + ret = asoc_sdw_ti_amp_initial_settings(card, prefix); + if (ret) + return ret; + + ret = snd_soc_dapm_add_routes(&card->dapm, &route, 1); + if (ret) + return ret; + } + + return ret; +} +EXPORT_SYMBOL_NS(asoc_sdw_ti_spk_rtd_init, "SND_SOC_SDW_UTILS"); + +int asoc_sdw_ti_amp_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback) +{ + if (!playback) + return 0; + + info->amp_num++; + + return 0; +} +EXPORT_SYMBOL_NS(asoc_sdw_ti_amp_init, "SND_SOC_SDW_UTILS"); -- cgit v1.2.3 From ab91835e61ab56d3964f51480955c9661678c269 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 23 Sep 2025 14:03:25 +0100 Subject: ASoC: cs35l56: Set fw_regs table after getting REVID Defer setting the cs35l56_base.fw_regs pointer until after the REVID has been read in cs35l56_hw_init(). Also make the corresponding change to the cs35l56_hda drivers to prevent a build break. This is preparing for firmware registers that change address between revisions of the same device. Signed-off-by: Richard Fitzgerald Signed-off-by: Takashi Iwai --- include/sound/cs35l56.h | 3 -- sound/hda/codecs/side-codecs/cs35l56_hda.c | 1 + sound/hda/codecs/side-codecs/cs35l56_hda_i2c.c | 2 - sound/hda/codecs/side-codecs/cs35l56_hda_spi.c | 2 - sound/soc/codecs/cs35l56-i2c.c | 4 +- sound/soc/codecs/cs35l56-sdw.c | 4 +- sound/soc/codecs/cs35l56-shared.c | 59 +++++++++++++++----------- sound/soc/codecs/cs35l56-spi.c | 2 +- 8 files changed, 41 insertions(+), 36 deletions(-) (limited to 'include') diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h index 7c8bbe8ad1e2..20dc3ee6378d 100644 --- a/include/sound/cs35l56.h +++ b/include/sound/cs35l56.h @@ -337,9 +337,6 @@ extern const struct regmap_config cs35l56_regmap_sdw; extern const struct regmap_config cs35l63_regmap_i2c; extern const struct regmap_config cs35l63_regmap_sdw; -extern const struct cs35l56_fw_reg cs35l56_fw_reg; -extern const struct cs35l56_fw_reg cs35l63_fw_reg; - extern const struct cirrus_amp_cal_controls cs35l56_calibration_controls; extern const char * const cs35l56_tx_input_texts[CS35L56_NUM_INPUT_SRC]; diff --git a/sound/hda/codecs/side-codecs/cs35l56_hda.c b/sound/hda/codecs/side-codecs/cs35l56_hda.c index 36fa62a41984..5bb1c4ebeaf3 100644 --- a/sound/hda/codecs/side-codecs/cs35l56_hda.c +++ b/sound/hda/codecs/side-codecs/cs35l56_hda.c @@ -1049,6 +1049,7 @@ int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int hid, int id) goto err; } + cs35l56->base.type = hid & 0xff; cs35l56->base.cal_index = -1; cs35l56_init_cs_dsp(&cs35l56->base, &cs35l56->cs_dsp); diff --git a/sound/hda/codecs/side-codecs/cs35l56_hda_i2c.c b/sound/hda/codecs/side-codecs/cs35l56_hda_i2c.c index d10209e4eddd..1072f17385ac 100644 --- a/sound/hda/codecs/side-codecs/cs35l56_hda_i2c.c +++ b/sound/hda/codecs/side-codecs/cs35l56_hda_i2c.c @@ -27,8 +27,6 @@ static int cs35l56_hda_i2c_probe(struct i2c_client *clt) cs35l56->base.can_hibernate = true; #endif - cs35l56->base.fw_reg = &cs35l56_fw_reg; - cs35l56->base.regmap = devm_regmap_init_i2c(clt, &cs35l56_regmap_i2c); if (IS_ERR(cs35l56->base.regmap)) { ret = PTR_ERR(cs35l56->base.regmap); diff --git a/sound/hda/codecs/side-codecs/cs35l56_hda_spi.c b/sound/hda/codecs/side-codecs/cs35l56_hda_spi.c index f57533d3d728..f802c83c57b4 100644 --- a/sound/hda/codecs/side-codecs/cs35l56_hda_spi.c +++ b/sound/hda/codecs/side-codecs/cs35l56_hda_spi.c @@ -30,8 +30,6 @@ static int cs35l56_hda_spi_probe(struct spi_device *spi) cs35l56->base.can_hibernate = true; #endif - cs35l56->base.fw_reg = &cs35l56_fw_reg; - cs35l56->base.regmap = devm_regmap_init_spi(spi, &cs35l56_regmap_spi); if (IS_ERR(cs35l56->base.regmap)) { ret = PTR_ERR(cs35l56->base.regmap); diff --git a/sound/soc/codecs/cs35l56-i2c.c b/sound/soc/codecs/cs35l56-i2c.c index 073f1796ae29..0492ddc4102d 100644 --- a/sound/soc/codecs/cs35l56-i2c.c +++ b/sound/soc/codecs/cs35l56-i2c.c @@ -35,11 +35,11 @@ static int cs35l56_i2c_probe(struct i2c_client *client) switch (id) { case 0x3556: regmap_config = &cs35l56_regmap_i2c; - cs35l56->base.fw_reg = &cs35l56_fw_reg; + cs35l56->base.type = 0x56; break; case 0x3563: regmap_config = &cs35l63_regmap_i2c; - cs35l56->base.fw_reg = &cs35l63_fw_reg; + cs35l56->base.type = 0x63; break; default: return -ENODEV; diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c index 3905c9cb188a..42d24ac2977f 100644 --- a/sound/soc/codecs/cs35l56-sdw.c +++ b/sound/soc/codecs/cs35l56-sdw.c @@ -527,16 +527,16 @@ static int cs35l56_sdw_probe(struct sdw_slave *peripheral, const struct sdw_devi case 0x3556: case 0x3557: regmap_config = &cs35l56_regmap_sdw; - cs35l56->base.fw_reg = &cs35l56_fw_reg; break; case 0x3563: regmap_config = &cs35l63_regmap_sdw; - cs35l56->base.fw_reg = &cs35l63_fw_reg; break; default: return -ENODEV; } + cs35l56->base.type = ((unsigned int)id->driver_data) & 0xff; + cs35l56->base.regmap = devm_regmap_init(dev, &cs35l56_regmap_bus_sdw, peripheral, regmap_config); if (IS_ERR(cs35l56->base.regmap)) { diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index 95d018ecb953..03ea66f08787 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -309,6 +309,40 @@ static bool cs35l63_volatile_reg(struct device *dev, unsigned int reg) } } +static const struct cs35l56_fw_reg cs35l56_fw_reg = { + .fw_ver = CS35L56_DSP1_FW_VER, + .halo_state = CS35L56_DSP1_HALO_STATE, + .pm_cur_stat = CS35L56_DSP1_PM_CUR_STATE, + .prot_sts = CS35L56_PROTECTION_STATUS, + .transducer_actual_ps = CS35L56_TRANSDUCER_ACTUAL_PS, + .user_mute = CS35L56_MAIN_RENDER_USER_MUTE, + .user_volume = CS35L56_MAIN_RENDER_USER_VOLUME, + .posture_number = CS35L56_MAIN_POSTURE_NUMBER, +}; + +static const struct cs35l56_fw_reg cs35l63_fw_reg = { + .fw_ver = CS35L63_DSP1_FW_VER, + .halo_state = CS35L63_DSP1_HALO_STATE, + .pm_cur_stat = CS35L63_DSP1_PM_CUR_STATE, + .prot_sts = CS35L63_PROTECTION_STATUS, + .transducer_actual_ps = CS35L63_TRANSDUCER_ACTUAL_PS, + .user_mute = CS35L63_MAIN_RENDER_USER_MUTE, + .user_volume = CS35L63_MAIN_RENDER_USER_VOLUME, + .posture_number = CS35L63_MAIN_POSTURE_NUMBER, +}; + +static void cs35l56_set_fw_reg_table(struct cs35l56_base *cs35l56_base) +{ + switch (cs35l56_base->type) { + default: + cs35l56_base->fw_reg = &cs35l56_fw_reg; + break; + case 0x63: + cs35l56_base->fw_reg = &cs35l63_fw_reg; + break; + } +} + int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command) { unsigned int val; @@ -979,6 +1013,7 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base) return ret; } cs35l56_base->rev = revid & (CS35L56_AREVID_MASK | CS35L56_MTLREVID_MASK); + cs35l56_set_fw_reg_table(cs35l56_base); ret = cs35l56_wait_for_firmware_boot(cs35l56_base); if (ret) @@ -1280,30 +1315,6 @@ const struct regmap_config cs35l63_regmap_sdw = { }; EXPORT_SYMBOL_NS_GPL(cs35l63_regmap_sdw, "SND_SOC_CS35L56_SHARED"); -const struct cs35l56_fw_reg cs35l56_fw_reg = { - .fw_ver = CS35L56_DSP1_FW_VER, - .halo_state = CS35L56_DSP1_HALO_STATE, - .pm_cur_stat = CS35L56_DSP1_PM_CUR_STATE, - .prot_sts = CS35L56_PROTECTION_STATUS, - .transducer_actual_ps = CS35L56_TRANSDUCER_ACTUAL_PS, - .user_mute = CS35L56_MAIN_RENDER_USER_MUTE, - .user_volume = CS35L56_MAIN_RENDER_USER_VOLUME, - .posture_number = CS35L56_MAIN_POSTURE_NUMBER, -}; -EXPORT_SYMBOL_NS_GPL(cs35l56_fw_reg, "SND_SOC_CS35L56_SHARED"); - -const struct cs35l56_fw_reg cs35l63_fw_reg = { - .fw_ver = CS35L63_DSP1_FW_VER, - .halo_state = CS35L63_DSP1_HALO_STATE, - .pm_cur_stat = CS35L63_DSP1_PM_CUR_STATE, - .prot_sts = CS35L63_PROTECTION_STATUS, - .transducer_actual_ps = CS35L63_TRANSDUCER_ACTUAL_PS, - .user_mute = CS35L63_MAIN_RENDER_USER_MUTE, - .user_volume = CS35L63_MAIN_RENDER_USER_VOLUME, - .posture_number = CS35L63_MAIN_POSTURE_NUMBER, -}; -EXPORT_SYMBOL_NS_GPL(cs35l63_fw_reg, "SND_SOC_CS35L56_SHARED"); - MODULE_DESCRIPTION("ASoC CS35L56 Shared"); MODULE_AUTHOR("Richard Fitzgerald "); MODULE_AUTHOR("Simon Trimmer "); diff --git a/sound/soc/codecs/cs35l56-spi.c b/sound/soc/codecs/cs35l56-spi.c index c2ddee22cd23..9bc9b7c98390 100644 --- a/sound/soc/codecs/cs35l56-spi.c +++ b/sound/soc/codecs/cs35l56-spi.c @@ -26,7 +26,7 @@ static int cs35l56_spi_probe(struct spi_device *spi) spi_set_drvdata(spi, cs35l56); - cs35l56->base.fw_reg = &cs35l56_fw_reg; + cs35l56->base.type = 0x56; cs35l56->base.regmap = devm_regmap_init_spi(spi, regmap_config); if (IS_ERR(cs35l56->base.regmap)) { -- cgit v1.2.3 From 33da2d892b6241a3e71f96acdd0e64de5d70b7f3 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 23 Sep 2025 14:03:26 +0100 Subject: ASoC: cs35l56: Add support for CS35L56 B2 silicon This adds support for changed firmware addresses on the B2 revision of CS35L56 silicon. Signed-off-by: Richard Fitzgerald Signed-off-by: Takashi Iwai --- include/sound/cs35l56.h | 2 ++ sound/soc/codecs/cs35l56-shared.c | 40 +++++++++++++++++++++++++++++++++++---- 2 files changed, 38 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h index 20dc3ee6378d..ab044ce2aa8b 100644 --- a/include/sound/cs35l56.h +++ b/include/sound/cs35l56.h @@ -85,7 +85,9 @@ #define CS35L56_DSP1_XMEM_UNPACKED24_0 0x2800000 #define CS35L56_DSP1_FW_VER 0x2800010 #define CS35L56_DSP1_HALO_STATE 0x28021E0 +#define CS35L56_B2_DSP1_HALO_STATE 0x2803D20 #define CS35L56_DSP1_PM_CUR_STATE 0x2804308 +#define CS35L56_B2_DSP1_PM_CUR_STATE 0x2804678 #define CS35L56_DSP1_XMEM_UNPACKED24_8191 0x2807FFC #define CS35L56_DSP1_CORE_BASE 0x2B80000 #define CS35L56_DSP1_SCRATCH1 0x2B805C0 diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index 03ea66f08787..9e6b9ca2f354 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -320,6 +320,17 @@ static const struct cs35l56_fw_reg cs35l56_fw_reg = { .posture_number = CS35L56_MAIN_POSTURE_NUMBER, }; +static const struct cs35l56_fw_reg cs35l56_b2_fw_reg = { + .fw_ver = CS35L56_DSP1_FW_VER, + .halo_state = CS35L56_B2_DSP1_HALO_STATE, + .pm_cur_stat = CS35L56_B2_DSP1_PM_CUR_STATE, + .prot_sts = CS35L56_PROTECTION_STATUS, + .transducer_actual_ps = CS35L56_TRANSDUCER_ACTUAL_PS, + .user_mute = CS35L56_MAIN_RENDER_USER_MUTE, + .user_volume = CS35L56_MAIN_RENDER_USER_VOLUME, + .posture_number = CS35L56_MAIN_POSTURE_NUMBER, +}; + static const struct cs35l56_fw_reg cs35l63_fw_reg = { .fw_ver = CS35L63_DSP1_FW_VER, .halo_state = CS35L63_DSP1_HALO_STATE, @@ -335,7 +346,14 @@ static void cs35l56_set_fw_reg_table(struct cs35l56_base *cs35l56_base) { switch (cs35l56_base->type) { default: - cs35l56_base->fw_reg = &cs35l56_fw_reg; + switch (cs35l56_base->rev) { + case 0xb0: + cs35l56_base->fw_reg = &cs35l56_fw_reg; + break; + default: + cs35l56_base->fw_reg = &cs35l56_b2_fw_reg; + break; + } break; case 0x63: cs35l56_base->fw_reg = &cs35l63_fw_reg; @@ -502,6 +520,11 @@ static const struct reg_sequence cs35l56_system_reset_seq[] = { REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET), }; +static const struct reg_sequence cs35l56_b2_system_reset_seq[] = { + REG_SEQ0(CS35L56_B2_DSP1_HALO_STATE, 0), + REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET), +}; + static const struct reg_sequence cs35l63_system_reset_seq[] = { REG_SEQ0(CS35L63_DSP1_HALO_STATE, 0), REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET), @@ -524,9 +547,18 @@ void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire) case 0x54: case 0x56: case 0x57: - regmap_multi_reg_write_bypassed(cs35l56_base->regmap, - cs35l56_system_reset_seq, - ARRAY_SIZE(cs35l56_system_reset_seq)); + switch (cs35l56_base->rev) { + case 0xb0: + regmap_multi_reg_write_bypassed(cs35l56_base->regmap, + cs35l56_system_reset_seq, + ARRAY_SIZE(cs35l56_system_reset_seq)); + break; + default: + regmap_multi_reg_write_bypassed(cs35l56_base->regmap, + cs35l56_b2_system_reset_seq, + ARRAY_SIZE(cs35l56_b2_system_reset_seq)); + break; + } break; case 0x63: regmap_multi_reg_write_bypassed(cs35l56_base->regmap, -- cgit v1.2.3 From fa7d16734f9606c396681648618dd76a5af861e6 Mon Sep 17 00:00:00 2001 From: Kriish Sharma Date: Sat, 27 Sep 2025 14:27:08 +0000 Subject: ALSA: compress: document 'chan_map' member in snd_dec_opus When building kernel docs, the following warning appeared: WARNING: ./include/uapi/sound/compress_params.h:364 struct member 'chan_map' not described in 'snd_dec_opus' The inline struct 'snd_dec_opus_ch_map' inside 'snd_dec_opus' was not properly documented. This patch documents the 'chan_map' member and its fields (stream_count, coupled_count, channel_map), resolving the warning. Fixes: 5d36370f3431 ("ALSA: compress: add raw opus codec define and opus decoder structs") Suggested-by: Bagas Sanjaya Signed-off-by: Kriish Sharma Signed-off-by: Takashi Iwai --- include/uapi/sound/compress_params.h | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/include/uapi/sound/compress_params.h b/include/uapi/sound/compress_params.h index faf4fa911f7f..d7db6b4e1166 100644 --- a/include/uapi/sound/compress_params.h +++ b/include/uapi/sound/compress_params.h @@ -336,16 +336,14 @@ struct snd_dec_ape { * @mapping_family: Order and meaning of output channels. Only values 0 and 1 * are expected; values 2..255 are not recommended for playback. * - * Optional channel mapping table. Describes mapping of opus streams to decoded - * channels. - * @struct snd_dec_opus_ch_map - * @stream_count: Number of streams encoded in each Ogg packet. - * @coupled_count: Number of streams whose decoders are used for two - * channels. - * @channel_map: describes which decoded channel to be used for each one. - * See RFC doc for details. - * This supports only mapping families 0 and 1, therefore max - * number of channels is 8. + * @chan_map: Optional channel mapping table. Describes mapping of opus streams + * to decoded channels. Fields: + * @chan_map.stream_count: Number of streams encoded in each Ogg packet. + * @chan_map.coupled_count: Number of streams whose decoders are used + * for two channels. + * @chan_map.channel_map: Which decoded channel to be used for each one. + * Supports only mapping families 0 and 1, + * max number of channels is 8. * * These options were extracted from RFC7845 Section 5. */ -- cgit v1.2.3