From: Greg Kroah-Hartman Date: Wed, 6 Nov 2024 08:07:22 +0000 (+0100) Subject: 6.6-stable patches X-Git-Tag: v4.19.323~20 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f0ba614bccc11f61bf555d4f0ea72e61388f9b1a;p=thirdparty%2Fkernel%2Fstable-queue.git 6.6-stable patches added patches: asoc-sof-ipc4-control-add-support-for-alsa-enum-control.patch asoc-sof-ipc4-control-add-support-for-alsa-switch-control.patch asoc-sof-ipc4-topology-add-definition-for-generic-switch-enum-control.patch drm-amd-display-add-null-checks-for-stream-and-plane-before-dereferencing.patch --- diff --git a/queue-6.6/asoc-sof-ipc4-control-add-support-for-alsa-enum-control.patch b/queue-6.6/asoc-sof-ipc4-control-add-support-for-alsa-enum-control.patch new file mode 100644 index 00000000000..816ee229f0b --- /dev/null +++ b/queue-6.6/asoc-sof-ipc4-control-add-support-for-alsa-enum-control.patch @@ -0,0 +1,159 @@ +From 07a866a41982c896dc46476f57d209a200602946 Mon Sep 17 00:00:00 2001 +From: Peter Ujfalusi +Date: Tue, 19 Sep 2023 13:31:15 +0300 +Subject: ASoC: SOF: ipc4-control: Add support for ALSA enum control + +From: Peter Ujfalusi + +commit 07a866a41982c896dc46476f57d209a200602946 upstream. + +Enum controls use generic param_id and a generic struct where the data +is passed to the firmware. + +Signed-off-by: Peter Ujfalusi +Reviewed-by: Bard Liao +Reviewed-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20230919103115.30783-4-peter.ujfalusi@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + sound/soc/sof/ipc4-control.c | 64 ++++++++++++++++++++++++++++++++++++++++++ + sound/soc/sof/ipc4-topology.c | 33 +++++++++++++++++++++ + 2 files changed, 97 insertions(+) + +--- a/sound/soc/sof/ipc4-control.c ++++ b/sound/soc/sof/ipc4-control.c +@@ -297,6 +297,63 @@ static int sof_ipc4_switch_get(struct sn + return 0; + } + ++static bool sof_ipc4_enum_put(struct snd_sof_control *scontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; ++ struct snd_soc_component *scomp = scontrol->scomp; ++ struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); ++ struct snd_sof_widget *swidget; ++ bool widget_found = false; ++ bool change = false; ++ unsigned int i; ++ u32 value; ++ int ret; ++ ++ /* update each channel */ ++ for (i = 0; i < scontrol->num_channels; i++) { ++ value = ucontrol->value.enumerated.item[i]; ++ change = change || (value != cdata->chanv[i].value); ++ cdata->chanv[i].channel = i; ++ cdata->chanv[i].value = value; ++ } ++ ++ if (!pm_runtime_active(scomp->dev)) ++ return change; ++ ++ /* find widget associated with the control */ ++ list_for_each_entry(swidget, &sdev->widget_list, list) { ++ if (swidget->comp_id == scontrol->comp_id) { ++ widget_found = true; ++ break; ++ } ++ } ++ ++ if (!widget_found) { ++ dev_err(scomp->dev, "Failed to find widget for kcontrol %s\n", scontrol->name); ++ return false; ++ } ++ ++ ret = sof_ipc4_set_generic_control_data(sdev, swidget, scontrol, true); ++ if (ret < 0) ++ return false; ++ ++ return change; ++} ++ ++static int sof_ipc4_enum_get(struct snd_sof_control *scontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; ++ unsigned int i; ++ ++ /* read back each channel */ ++ for (i = 0; i < scontrol->num_channels; i++) ++ ucontrol->value.enumerated.item[i] = cdata->chanv[i].value; ++ ++ return 0; ++} ++ + static int sof_ipc4_set_get_bytes_data(struct snd_sof_dev *sdev, + struct snd_sof_control *scontrol, + bool set, bool lock) +@@ -562,6 +619,11 @@ static int sof_ipc4_widget_kcontrol_setu + ret = sof_ipc4_set_get_bytes_data(sdev, scontrol, + true, false); + break; ++ case SND_SOC_TPLG_CTL_ENUM: ++ case SND_SOC_TPLG_CTL_ENUM_VALUE: ++ ret = sof_ipc4_set_generic_control_data(sdev, swidget, ++ scontrol, false); ++ break; + default: + break; + } +@@ -605,6 +667,8 @@ const struct sof_ipc_tplg_control_ops tp + .volume_get = sof_ipc4_volume_get, + .switch_put = sof_ipc4_switch_put, + .switch_get = sof_ipc4_switch_get, ++ .enum_put = sof_ipc4_enum_put, ++ .enum_get = sof_ipc4_enum_get, + .bytes_put = sof_ipc4_bytes_put, + .bytes_get = sof_ipc4_bytes_get, + .bytes_ext_put = sof_ipc4_bytes_ext_put, +--- a/sound/soc/sof/ipc4-topology.c ++++ b/sound/soc/sof/ipc4-topology.c +@@ -2148,6 +2148,36 @@ static int sof_ipc4_control_load_volume( + return 0; + } + ++static int sof_ipc4_control_load_enum(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) ++{ ++ struct sof_ipc4_control_data *control_data; ++ struct sof_ipc4_msg *msg; ++ int i; ++ ++ scontrol->size = struct_size(control_data, chanv, scontrol->num_channels); ++ ++ /* scontrol->ipc_control_data will be freed in sof_control_unload */ ++ scontrol->ipc_control_data = kzalloc(scontrol->size, GFP_KERNEL); ++ if (!scontrol->ipc_control_data) ++ return -ENOMEM; ++ ++ control_data = scontrol->ipc_control_data; ++ control_data->index = scontrol->index; ++ ++ msg = &control_data->msg; ++ msg->primary = SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_MOD_LARGE_CONFIG_SET); ++ msg->primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); ++ msg->primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG); ++ ++ msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_ENUM_CONTROL_PARAM_ID); ++ ++ /* Default, initial value for enums: first enum entry is selected (0) */ ++ for (i = 0; i < scontrol->num_channels; i++) ++ control_data->chanv[i].channel = i; ++ ++ return 0; ++} ++ + static int sof_ipc4_control_load_bytes(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) + { + struct sof_ipc4_control_data *control_data; +@@ -2222,6 +2252,9 @@ static int sof_ipc4_control_setup(struct + return sof_ipc4_control_load_volume(sdev, scontrol); + case SND_SOC_TPLG_CTL_BYTES: + return sof_ipc4_control_load_bytes(sdev, scontrol); ++ case SND_SOC_TPLG_CTL_ENUM: ++ case SND_SOC_TPLG_CTL_ENUM_VALUE: ++ return sof_ipc4_control_load_enum(sdev, scontrol); + default: + break; + } diff --git a/queue-6.6/asoc-sof-ipc4-control-add-support-for-alsa-switch-control.patch b/queue-6.6/asoc-sof-ipc4-control-add-support-for-alsa-switch-control.patch new file mode 100644 index 00000000000..898177721b5 --- /dev/null +++ b/queue-6.6/asoc-sof-ipc4-control-add-support-for-alsa-switch-control.patch @@ -0,0 +1,193 @@ +From 4a2fd607b7ca6128ee3532161505da7624197f55 Mon Sep 17 00:00:00 2001 +From: Peter Ujfalusi +Date: Tue, 19 Sep 2023 13:31:14 +0300 +Subject: ASoC: SOF: ipc4-control: Add support for ALSA switch control + +From: Peter Ujfalusi + +commit 4a2fd607b7ca6128ee3532161505da7624197f55 upstream. + +Volume controls with a max value of 1 are switches. +Switch controls use generic param_id and a generic struct where the data +is passed to the firmware. + +Signed-off-by: Peter Ujfalusi +Reviewed-by: Bard Liao +Reviewed-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20230919103115.30783-3-peter.ujfalusi@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + sound/soc/sof/ipc4-control.c | 111 +++++++++++++++++++++++++++++++++++++++++- + sound/soc/sof/ipc4-topology.c | 16 ++++-- + 2 files changed, 122 insertions(+), 5 deletions(-) + +--- a/sound/soc/sof/ipc4-control.c ++++ b/sound/soc/sof/ipc4-control.c +@@ -201,6 +201,102 @@ static int sof_ipc4_volume_get(struct sn + return 0; + } + ++static int ++sof_ipc4_set_generic_control_data(struct snd_sof_dev *sdev, ++ struct snd_sof_widget *swidget, ++ struct snd_sof_control *scontrol, bool lock) ++{ ++ struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; ++ struct sof_ipc4_control_msg_payload *data; ++ struct sof_ipc4_msg *msg = &cdata->msg; ++ size_t data_size; ++ unsigned int i; ++ int ret; ++ ++ data_size = struct_size(data, chanv, scontrol->num_channels); ++ data = kzalloc(data_size, GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ data->id = cdata->index; ++ data->num_elems = scontrol->num_channels; ++ for (i = 0; i < scontrol->num_channels; i++) { ++ data->chanv[i].channel = cdata->chanv[i].channel; ++ data->chanv[i].value = cdata->chanv[i].value; ++ } ++ ++ msg->data_ptr = data; ++ msg->data_size = data_size; ++ ++ ret = sof_ipc4_set_get_kcontrol_data(scontrol, true, lock); ++ msg->data_ptr = NULL; ++ msg->data_size = 0; ++ if (ret < 0) ++ dev_err(sdev->dev, "Failed to set control update for %s\n", ++ scontrol->name); ++ ++ kfree(data); ++ ++ return ret; ++} ++ ++static bool sof_ipc4_switch_put(struct snd_sof_control *scontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; ++ struct snd_soc_component *scomp = scontrol->scomp; ++ struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); ++ struct snd_sof_widget *swidget; ++ bool widget_found = false; ++ bool change = false; ++ unsigned int i; ++ u32 value; ++ int ret; ++ ++ /* update each channel */ ++ for (i = 0; i < scontrol->num_channels; i++) { ++ value = ucontrol->value.integer.value[i]; ++ change = change || (value != cdata->chanv[i].value); ++ cdata->chanv[i].channel = i; ++ cdata->chanv[i].value = value; ++ } ++ ++ if (!pm_runtime_active(scomp->dev)) ++ return change; ++ ++ /* find widget associated with the control */ ++ list_for_each_entry(swidget, &sdev->widget_list, list) { ++ if (swidget->comp_id == scontrol->comp_id) { ++ widget_found = true; ++ break; ++ } ++ } ++ ++ if (!widget_found) { ++ dev_err(scomp->dev, "Failed to find widget for kcontrol %s\n", scontrol->name); ++ return false; ++ } ++ ++ ret = sof_ipc4_set_generic_control_data(sdev, swidget, scontrol, true); ++ if (ret < 0) ++ return false; ++ ++ return change; ++} ++ ++static int sof_ipc4_switch_get(struct snd_sof_control *scontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; ++ unsigned int i; ++ ++ /* read back each channel */ ++ for (i = 0; i < scontrol->num_channels; i++) ++ ucontrol->value.integer.value[i] = cdata->chanv[i].value; ++ ++ return 0; ++} ++ + static int sof_ipc4_set_get_bytes_data(struct snd_sof_dev *sdev, + struct snd_sof_control *scontrol, + bool set, bool lock) +@@ -438,6 +534,16 @@ static int sof_ipc4_bytes_ext_volatile_g + return _sof_ipc4_bytes_ext_get(scontrol, binary_data, size, true); + } + ++static int ++sof_ipc4_volsw_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, ++ struct snd_sof_control *scontrol) ++{ ++ if (scontrol->max == 1) ++ return sof_ipc4_set_generic_control_data(sdev, swidget, scontrol, false); ++ ++ return sof_ipc4_set_volume_data(sdev, swidget, scontrol, false); ++} ++ + /* set up all controls for the widget */ + static int sof_ipc4_widget_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) + { +@@ -450,8 +556,7 @@ static int sof_ipc4_widget_kcontrol_setu + case SND_SOC_TPLG_CTL_VOLSW: + case SND_SOC_TPLG_CTL_VOLSW_SX: + case SND_SOC_TPLG_CTL_VOLSW_XR_SX: +- ret = sof_ipc4_set_volume_data(sdev, swidget, +- scontrol, false); ++ ret = sof_ipc4_volsw_setup(sdev, swidget, scontrol); + break; + case SND_SOC_TPLG_CTL_BYTES: + ret = sof_ipc4_set_get_bytes_data(sdev, scontrol, +@@ -498,6 +603,8 @@ sof_ipc4_set_up_volume_table(struct snd_ + const struct sof_ipc_tplg_control_ops tplg_ipc4_control_ops = { + .volume_put = sof_ipc4_volume_put, + .volume_get = sof_ipc4_volume_get, ++ .switch_put = sof_ipc4_switch_put, ++ .switch_get = sof_ipc4_switch_get, + .bytes_put = sof_ipc4_bytes_put, + .bytes_get = sof_ipc4_bytes_get, + .bytes_ext_put = sof_ipc4_bytes_ext_put, +--- a/sound/soc/sof/ipc4-topology.c ++++ b/sound/soc/sof/ipc4-topology.c +@@ -2127,12 +2127,22 @@ static int sof_ipc4_control_load_volume( + msg->primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); + msg->primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG); + +- msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_GAIN_PARAM_ID); ++ /* volume controls with range 0-1 (off/on) are switch controls */ ++ if (scontrol->max == 1) ++ msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_SWITCH_CONTROL_PARAM_ID); ++ else ++ msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_GAIN_PARAM_ID); + +- /* set default volume values to 0dB in control */ + for (i = 0; i < scontrol->num_channels; i++) { + control_data->chanv[i].channel = i; +- control_data->chanv[i].value = SOF_IPC4_VOL_ZERO_DB; ++ /* ++ * Default, initial values: ++ * - 0dB for volume controls ++ * - off (0) for switch controls - value already zero after ++ * memory allocation ++ */ ++ if (scontrol->max > 1) ++ control_data->chanv[i].value = SOF_IPC4_VOL_ZERO_DB; + } + + return 0; diff --git a/queue-6.6/asoc-sof-ipc4-topology-add-definition-for-generic-switch-enum-control.patch b/queue-6.6/asoc-sof-ipc4-topology-add-definition-for-generic-switch-enum-control.patch new file mode 100644 index 00000000000..4b651bfa530 --- /dev/null +++ b/queue-6.6/asoc-sof-ipc4-topology-add-definition-for-generic-switch-enum-control.patch @@ -0,0 +1,66 @@ +From 060a07cd9bc69eba2da33ed96b1fa69ead60bab1 Mon Sep 17 00:00:00 2001 +From: Peter Ujfalusi +Date: Tue, 19 Sep 2023 13:31:13 +0300 +Subject: ASoC: SOF: ipc4-topology: Add definition for generic switch/enum control + +From: Peter Ujfalusi + +commit 060a07cd9bc69eba2da33ed96b1fa69ead60bab1 upstream. + +Currently IPC4 has no notion of a switch or enum type of control which is +a generic concept in ALSA. + +The generic support for these control types will be as follows: +- large config is used to send the channel-value par array +- param_id of a SWITCH type is 200 +- param_id of an ENUM type is 201 + +Each module need to support a switch or/and enum must handle these +universal param_ids. +The message payload is described by struct sof_ipc4_control_msg_payload. + +Signed-off-by: Peter Ujfalusi +Reviewed-by: Bard Liao +Reviewed-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20230919103115.30783-2-peter.ujfalusi@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + sound/soc/sof/ipc4-topology.h | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +--- a/sound/soc/sof/ipc4-topology.h ++++ b/sound/soc/sof/ipc4-topology.h +@@ -319,7 +319,7 @@ struct sof_ipc4_copier { + /** + * struct sof_ipc4_ctrl_value_chan: generic channel mapped value data + * @channel: Channel ID +- * @value: gain value ++ * @value: Value associated with @channel + */ + struct sof_ipc4_ctrl_value_chan { + u32 channel; +@@ -343,6 +343,23 @@ struct sof_ipc4_control_data { + }; + }; + ++#define SOF_IPC4_SWITCH_CONTROL_PARAM_ID 200 ++#define SOF_IPC4_ENUM_CONTROL_PARAM_ID 201 ++ ++/** ++ * struct sof_ipc4_control_msg_payload - IPC payload for kcontrol parameters ++ * @id: unique id of the control ++ * @num_elems: Number of elements in the chanv array ++ * @reserved: reserved for future use, must be set to 0 ++ * @chanv: channel ID and value array ++ */ ++struct sof_ipc4_control_msg_payload { ++ uint16_t id; ++ uint16_t num_elems; ++ uint32_t reserved[4]; ++ DECLARE_FLEX_ARRAY(struct sof_ipc4_ctrl_value_chan, chanv); ++} __packed; ++ + /** + * struct sof_ipc4_gain_params - IPC gain parameters + * @channels: Channels diff --git a/queue-6.6/drm-amd-display-add-null-checks-for-stream-and-plane-before-dereferencing.patch b/queue-6.6/drm-amd-display-add-null-checks-for-stream-and-plane-before-dereferencing.patch new file mode 100644 index 00000000000..213d36febba --- /dev/null +++ b/queue-6.6/drm-amd-display-add-null-checks-for-stream-and-plane-before-dereferencing.patch @@ -0,0 +1,53 @@ +From 15c2990e0f0108b9c3752d7072a97d45d4283aea Mon Sep 17 00:00:00 2001 +From: Srinivasan Shanmugam +Date: Mon, 27 May 2024 20:15:21 +0530 +Subject: drm/amd/display: Add null checks for 'stream' and 'plane' before dereferencing + +From: Srinivasan Shanmugam + +commit 15c2990e0f0108b9c3752d7072a97d45d4283aea upstream. + +This commit adds null checks for the 'stream' and 'plane' variables in +the dcn30_apply_idle_power_optimizations function. These variables were +previously assumed to be null at line 922, but they were used later in +the code without checking if they were null. This could potentially lead +to a null pointer dereference, which would cause a crash. + +The null checks ensure that 'stream' and 'plane' are not null before +they are used, preventing potential crashes. + +Fixes the below static smatch checker: +drivers/gpu/drm/amd/amdgpu/../display/dc/hwss/dcn30/dcn30_hwseq.c:938 dcn30_apply_idle_power_optimizations() error: we previously assumed 'stream' could be null (see line 922) +drivers/gpu/drm/amd/amdgpu/../display/dc/hwss/dcn30/dcn30_hwseq.c:940 dcn30_apply_idle_power_optimizations() error: we previously assumed 'plane' could be null (see line 922) + +Cc: Tom Chung +Cc: Nicholas Kazlauskas +Cc: Bhawanpreet Lakha +Cc: Rodrigo Siqueira +Cc: Roman Li +Cc: Hersen Wu +Cc: Alex Hung +Cc: Aurabindo Pillai +Cc: Harry Wentland +Signed-off-by: Srinivasan Shanmugam +Reviewed-by: Aurabindo Pillai +Signed-off-by: Alex Deucher +[Xiangyu: Modified file path to backport this commit] +Signed-off-by: Xiangyu Chen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +@@ -735,6 +735,9 @@ bool dcn30_apply_idle_power_optimization + stream = dc->current_state->streams[0]; + plane = (stream ? dc->current_state->stream_status[0].plane_states[0] : NULL); + ++ if (!stream || !plane) ++ return false; ++ + if (stream && plane) { + cursor_cache_enable = stream->cursor_position.enable && + plane->address.grph.cursor_cache_addr.quad_part; diff --git a/queue-6.6/series b/queue-6.6/series index c4e930aebb2..5532a3ee91c 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -144,3 +144,7 @@ mm-huge_memory-add-vma_thp_disabled-and-thp_disabled_by_hw.patch mm-don-t-install-pmd-mappings-when-thps-are-disabled-by-the-hw-process-vma.patch mtd-spi-nor-winbond-fix-w25q128-regression.patch sunrpc-remove-bug_on-call-sites.patch +asoc-sof-ipc4-topology-add-definition-for-generic-switch-enum-control.patch +asoc-sof-ipc4-control-add-support-for-alsa-switch-control.patch +asoc-sof-ipc4-control-add-support-for-alsa-enum-control.patch +drm-amd-display-add-null-checks-for-stream-and-plane-before-dereferencing.patch