diff --git a/pkgbuilds/edge/linux-ptl-audio/0001-ASoC-SDCA-functions-Fix-confusing-cleanup.h-syntax.patch b/pkgbuilds/edge/linux-ptl-audio/0001-ASoC-SDCA-functions-Fix-confusing-cleanup.h-syntax.patch new file mode 100644 index 0000000..6a140ee --- /dev/null +++ b/pkgbuilds/edge/linux-ptl-audio/0001-ASoC-SDCA-functions-Fix-confusing-cleanup.h-syntax.patch @@ -0,0 +1,160 @@ +From 917d5770485e4ccd73f1123e2032a220c021bb56 Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Wed, 3 Dec 2025 17:12:40 +0100 +Subject: [PATCH 01/17] ASoC: SDCA: functions: Fix confusing cleanup.h syntax + +Initializing automatic __free variables to NULL without need (e.g. +branches with different allocations), followed by actual allocation is +in contrary to explicit coding rules guiding cleanup.h: + +"Given that the "__free(...) = NULL" pattern for variables defined at +the top of the function poses this potential interdependency problem the +recommendation is to always define and assign variables in one statement +and not group variable definitions at the top of the function when +__free() is used." + +Code does not have a bug, but is less readable and uses discouraged +coding practice, so fix that by moving declaration to the place of +assignment. + +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Charles Keepax +Link: https://patch.msgid.link/20251203-asoc-wrong-cleanup-h-continued-v1-3-5142be4874fb@oss.qualcomm.com +Signed-off-by: Mark Brown +--- + sound/soc/sdca/sdca_functions.c | 28 ++++++++++++++-------------- + 1 file changed, 14 insertions(+), 14 deletions(-) + +diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c +index e86004c9dea0..b26884fc2a98 100644 +--- a/sound/soc/sdca/sdca_functions.c ++++ b/sound/soc/sdca/sdca_functions.c +@@ -1180,7 +1180,6 @@ static int find_sdca_entity_pde(struct device *dev, + { + static const int mult_delay = 3; + struct sdca_entity_pde *power = &entity->pde; +- u32 *delay_list __free(kfree) = NULL; + struct sdca_pde_delay *delays; + int num_delays; + int i, j; +@@ -1201,7 +1200,8 @@ static int find_sdca_entity_pde(struct device *dev, + return -EINVAL; + } + +- delay_list = kcalloc(num_delays, sizeof(*delay_list), GFP_KERNEL); ++ u32 *delay_list __free(kfree) = kcalloc(num_delays, sizeof(*delay_list), ++ GFP_KERNEL); + if (!delay_list) + return -ENOMEM; + +@@ -1246,7 +1246,6 @@ static int find_sdca_entity_ge(struct device *dev, + struct sdca_entity *entity) + { + struct sdca_entity_ge *group = &entity->ge; +- u8 *affected_list __free(kfree) = NULL; + u8 *affected_iter; + int num_affected; + int i, j; +@@ -1265,7 +1264,8 @@ static int find_sdca_entity_ge(struct device *dev, + return -EINVAL; + } + +- affected_list = kcalloc(num_affected, sizeof(*affected_list), GFP_KERNEL); ++ u8 *affected_list __free(kfree) = kcalloc(num_affected, sizeof(*affected_list), ++ GFP_KERNEL); + if (!affected_list) + return -ENOMEM; + +@@ -1491,7 +1491,6 @@ static int find_sdca_entities(struct device *dev, struct sdw_slave *sdw, + struct fwnode_handle *function_node, + struct sdca_function_data *function) + { +- u32 *entity_list __free(kfree) = NULL; + struct sdca_entity *entities; + int num_entities; + int i, ret; +@@ -1513,7 +1512,8 @@ static int find_sdca_entities(struct device *dev, struct sdw_slave *sdw, + if (!entities) + return -ENOMEM; + +- entity_list = kcalloc(num_entities, sizeof(*entity_list), GFP_KERNEL); ++ u32 *entity_list __free(kfree) = kcalloc(num_entities, sizeof(*entity_list), ++ GFP_KERNEL); + if (!entity_list) + return -ENOMEM; + +@@ -1638,7 +1638,6 @@ static int find_sdca_entity_connection_pde(struct device *dev, + struct sdca_entity *entity) + { + struct sdca_entity_pde *power = &entity->pde; +- u32 *managed_list __free(kfree) = NULL; + struct sdca_entity **managed; + int num_managed; + int i; +@@ -1660,7 +1659,8 @@ static int find_sdca_entity_connection_pde(struct device *dev, + if (!managed) + return -ENOMEM; + +- managed_list = kcalloc(num_managed, sizeof(*managed_list), GFP_KERNEL); ++ u32 *managed_list __free(kfree) = kcalloc(num_managed, sizeof(*managed_list), ++ GFP_KERNEL); + if (!managed_list) + return -ENOMEM; + +@@ -1957,7 +1957,6 @@ static int find_sdca_clusters(struct device *dev, + struct fwnode_handle *function_node, + struct sdca_function_data *function) + { +- u32 *cluster_list __free(kfree) = NULL; + struct sdca_cluster *clusters; + int num_clusters; + int i, ret; +@@ -1978,7 +1977,8 @@ static int find_sdca_clusters(struct device *dev, + if (!clusters) + return -ENOMEM; + +- cluster_list = kcalloc(num_clusters, sizeof(*cluster_list), GFP_KERNEL); ++ u32 *cluster_list __free(kfree) = kcalloc(num_clusters, sizeof(*cluster_list), ++ GFP_KERNEL); + if (!cluster_list) + return -ENOMEM; + +@@ -2022,7 +2022,6 @@ static int find_sdca_filesets(struct device *dev, struct sdw_slave *sdw, + { + static const int mult_fileset = 3; + char fileset_name[SDCA_PROPERTY_LENGTH]; +- u32 *filesets_list __free(kfree) = NULL; + struct sdca_fdl_set *sets; + int num_sets; + int i, j; +@@ -2037,7 +2036,8 @@ static int find_sdca_filesets(struct device *dev, struct sdw_slave *sdw, + return num_sets; + } + +- filesets_list = kcalloc(num_sets, sizeof(u32), GFP_KERNEL); ++ u32 *filesets_list __free(kfree) = kcalloc(num_sets, sizeof(u32), ++ GFP_KERNEL); + if (!filesets_list) + return -ENOMEM; + +@@ -2049,7 +2049,6 @@ static int find_sdca_filesets(struct device *dev, struct sdw_slave *sdw, + return -ENOMEM; + + for (i = 0; i < num_sets; i++) { +- u32 *fileset_entries __free(kfree) = NULL; + struct sdca_fdl_set *set = &sets[i]; + struct sdca_fdl_file *files; + int num_files, num_entries; +@@ -2075,7 +2074,8 @@ static int find_sdca_filesets(struct device *dev, struct sdw_slave *sdw, + if (!files) + return -ENOMEM; + +- fileset_entries = kcalloc(num_entries, sizeof(u32), GFP_KERNEL); ++ u32 *fileset_entries __free(kfree) = kcalloc(num_entries, sizeof(u32), ++ GFP_KERNEL); + if (!fileset_entries) + return -ENOMEM; + +-- +2.43.0 + diff --git a/pkgbuilds/edge/linux-ptl-audio/0002-ASoC-SDCA-Add-ASoC-jack-hookup-in-class-driver.patch b/pkgbuilds/edge/linux-ptl-audio/0002-ASoC-SDCA-Add-ASoC-jack-hookup-in-class-driver.patch new file mode 100644 index 0000000..b6fe65d --- /dev/null +++ b/pkgbuilds/edge/linux-ptl-audio/0002-ASoC-SDCA-Add-ASoC-jack-hookup-in-class-driver.patch @@ -0,0 +1,57 @@ +From 09b0835977b5fa955e35147513ed770e6bf0229d Mon Sep 17 00:00:00 2001 +From: Charles Keepax +Date: Mon, 15 Dec 2025 15:36:49 +0000 +Subject: [PATCH 02/17] ASoC: SDCA: Add ASoC jack hookup in class driver + +Add the necessary calls to the class driver to connect the ASoC jack +from the machine driver. + +Signed-off-by: Charles Keepax +Link: https://patch.msgid.link/20251215153650.3913117-4-ckeepax@opensource.cirrus.com +Reviewed-by: Bard Liao +Signed-off-by: Mark Brown +--- + sound/soc/sdca/sdca_class_function.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/sound/soc/sdca/sdca_class_function.c b/sound/soc/sdca/sdca_class_function.c +index 0028482a1e75..416948cfb5cb 100644 +--- a/sound/soc/sdca/sdca_class_function.c ++++ b/sound/soc/sdca/sdca_class_function.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -195,6 +196,15 @@ static int class_function_component_probe(struct snd_soc_component *component) + return sdca_irq_populate(drv->function, component, core->irq_info); + } + ++static int class_function_set_jack(struct snd_soc_component *component, ++ struct snd_soc_jack *jack, void *d) ++{ ++ struct class_function_drv *drv = snd_soc_component_get_drvdata(component); ++ struct sdca_class_drv *core = drv->core; ++ ++ return sdca_jack_set_jack(core->irq_info, jack); ++} ++ + static const struct snd_soc_component_driver class_function_component_drv = { + .probe = class_function_component_probe, + .endianness = 1, +@@ -351,6 +361,9 @@ static int class_function_probe(struct auxiliary_device *auxdev, + return dev_err_probe(dev, PTR_ERR(drv->regmap), + "failed to create regmap"); + ++ if (desc->type == SDCA_FUNCTION_TYPE_UAJ) ++ cmp_drv->set_jack = class_function_set_jack; ++ + ret = sdca_asoc_populate_component(dev, drv->function, cmp_drv, + &dais, &num_dais, + &class_function_sdw_ops); +-- +2.43.0 + diff --git a/pkgbuilds/edge/linux-ptl-audio/0003-ASoC-SDCA-Replace-use-of-system_wq-with-system_dfl_w.patch b/pkgbuilds/edge/linux-ptl-audio/0003-ASoC-SDCA-Replace-use-of-system_wq-with-system_dfl_w.patch new file mode 100644 index 0000000..2797d82 --- /dev/null +++ b/pkgbuilds/edge/linux-ptl-audio/0003-ASoC-SDCA-Replace-use-of-system_wq-with-system_dfl_w.patch @@ -0,0 +1,52 @@ +From 04d5b8676de028c8dded6d174620f69656b6ddd2 Mon Sep 17 00:00:00 2001 +From: Marco Crivellari +Date: Tue, 30 Dec 2025 15:34:29 +0100 +Subject: [PATCH 03/17] ASoC: SDCA: Replace use of system_wq with system_dfl_wq + +This patch continues the effort to refactor workqueue APIs, which has begun +with the changes introducing new workqueues and a new alloc_workqueue flag: + + commit 128ea9f6ccfb ("workqueue: Add system_percpu_wq and system_dfl_wq") + commit 930c2ea566af ("workqueue: Add new WQ_PERCPU flag") + +The point of the refactoring is to eventually alter the default behavior of +workqueues to become unbound by default so that their workload placement is +optimized by the scheduler. + +Before that to happen after a careful review and conversion of each individual +case, workqueue users must be converted to the better named new workqueues with +no intended behaviour changes: + + system_wq -> system_percpu_wq + system_unbound_wq -> system_dfl_wq + +This specific workload has no benefits being per-cpu, so system_wq +has been replaced with system_dfl_wq (the unbound workqueue). + +This way the old obsolete workqueues (system_wq, system_unbound_wq) can be +removed in the future. + +Suggested-by: Tejun Heo +Signed-off-by: Marco Crivellari +Reviewed-by: Charles Keepax +Link: https://patch.msgid.link/20251230143429.179643-1-marco.crivellari@suse.com +Signed-off-by: Mark Brown +--- + sound/soc/sdca/sdca_ump.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/sdca/sdca_ump.c b/sound/soc/sdca/sdca_ump.c +index 8aba3ff16872..a86bb28c6d0a 100644 +--- a/sound/soc/sdca/sdca_ump.c ++++ b/sound/soc/sdca/sdca_ump.c +@@ -257,6 +257,6 @@ void sdca_ump_schedule_timeout(struct delayed_work *work, unsigned int timeout_u + if (!timeout_us) + return; + +- queue_delayed_work(system_wq, work, usecs_to_jiffies(timeout_us)); ++ queue_delayed_work(system_dfl_wq, work, usecs_to_jiffies(timeout_us)); + } + EXPORT_SYMBOL_NS_GPL(sdca_ump_schedule_timeout, "SND_SOC_SDCA"); +-- +2.43.0 + diff --git a/pkgbuilds/edge/linux-ptl-audio/0004-ASoC-SDCA-Add-SDCA-IRQ-enable-disable-helpers.patch b/pkgbuilds/edge/linux-ptl-audio/0004-ASoC-SDCA-Add-SDCA-IRQ-enable-disable-helpers.patch new file mode 100644 index 0000000..8b110ba --- /dev/null +++ b/pkgbuilds/edge/linux-ptl-audio/0004-ASoC-SDCA-Add-SDCA-IRQ-enable-disable-helpers.patch @@ -0,0 +1,120 @@ +From 4b55c8cdab4fbbf35fdb22e711a473c7c19b8c39 Mon Sep 17 00:00:00 2001 +From: Charles Keepax +Date: Fri, 9 Jan 2026 14:52:03 +0000 +Subject: [PATCH 04/17] ASoC: SDCA: Add SDCA IRQ enable/disable helpers + +Add helpers to enable and disable the SDCA IRQs by Function. These are +useful to sequence the powering down and up around system suspend. + +Signed-off-by: Charles Keepax +Reviewed-by: Pierre-Louis Bossart +Link: https://patch.msgid.link/20260109145206.3456151-2-ckeepax@opensource.cirrus.com +Signed-off-by: Mark Brown +--- + include/sound/sdca_interrupts.h | 7 +++ + sound/soc/sdca/sdca_interrupts.c | 76 ++++++++++++++++++++++++++++++++ + 2 files changed, 83 insertions(+) + +diff --git a/include/sound/sdca_interrupts.h b/include/sound/sdca_interrupts.h +index 8f13417d129a..9bcb5d8fd592 100644 +--- a/include/sound/sdca_interrupts.h ++++ b/include/sound/sdca_interrupts.h +@@ -84,4 +84,11 @@ int sdca_irq_populate(struct sdca_function_data *function, + struct sdca_interrupt_info *sdca_irq_allocate(struct device *dev, + struct regmap *regmap, int irq); + ++void sdca_irq_enable_early(struct sdca_function_data *function, ++ struct sdca_interrupt_info *info); ++void sdca_irq_enable(struct sdca_function_data *function, ++ struct sdca_interrupt_info *info); ++void sdca_irq_disable(struct sdca_function_data *function, ++ struct sdca_interrupt_info *info); ++ + #endif +diff --git a/sound/soc/sdca/sdca_interrupts.c b/sound/soc/sdca/sdca_interrupts.c +index ff3a7e405fdc..afef7bbf613c 100644 +--- a/sound/soc/sdca/sdca_interrupts.c ++++ b/sound/soc/sdca/sdca_interrupts.c +@@ -541,3 +541,79 @@ struct sdca_interrupt_info *sdca_irq_allocate(struct device *sdev, + return info; + } + EXPORT_SYMBOL_NS_GPL(sdca_irq_allocate, "SND_SOC_SDCA"); ++ ++static void irq_enable_flags(struct sdca_function_data *function, ++ struct sdca_interrupt_info *info, bool early) ++{ ++ struct sdca_interrupt *interrupt; ++ int i; ++ ++ for (i = 0; i < SDCA_MAX_INTERRUPTS; i++) { ++ interrupt = &info->irqs[i]; ++ ++ if (!interrupt || interrupt->function != function) ++ continue; ++ ++ switch (SDCA_CTL_TYPE(interrupt->entity->type, ++ interrupt->control->sel)) { ++ case SDCA_CTL_TYPE_S(XU, FDL_CURRENTOWNER): ++ if (early) ++ enable_irq(interrupt->irq); ++ break; ++ default: ++ if (!early) ++ enable_irq(interrupt->irq); ++ break; ++ } ++ } ++} ++ ++/** ++ * sdca_irq_enable_early - Re-enable early SDCA IRQs for a given function ++ * @function: Pointer to the SDCA Function. ++ * @info: Pointer to the SDCA interrupt info for this device. ++ * ++ * The early version of the IRQ enable allows enabling IRQs which may be ++ * necessary to bootstrap functionality for other IRQs, such as the FDL ++ * process. ++ */ ++void sdca_irq_enable_early(struct sdca_function_data *function, ++ struct sdca_interrupt_info *info) ++{ ++ irq_enable_flags(function, info, true); ++} ++EXPORT_SYMBOL_NS_GPL(sdca_irq_enable_early, "SND_SOC_SDCA"); ++ ++/** ++ * sdca_irq_enable - Re-enable SDCA IRQs for a given function ++ * @function: Pointer to the SDCA Function. ++ * @info: Pointer to the SDCA interrupt info for this device. ++ */ ++void sdca_irq_enable(struct sdca_function_data *function, ++ struct sdca_interrupt_info *info) ++{ ++ irq_enable_flags(function, info, false); ++} ++EXPORT_SYMBOL_NS_GPL(sdca_irq_enable, "SND_SOC_SDCA"); ++ ++/** ++ * sdca_irq_disable - Disable SDCA IRQs for a given function ++ * @function: Pointer to the SDCA Function. ++ * @info: Pointer to the SDCA interrupt info for this device. ++ */ ++void sdca_irq_disable(struct sdca_function_data *function, ++ struct sdca_interrupt_info *info) ++{ ++ struct sdca_interrupt *interrupt; ++ int i; ++ ++ for (i = 0; i < SDCA_MAX_INTERRUPTS; i++) { ++ interrupt = &info->irqs[i]; ++ ++ if (!interrupt || interrupt->function != function) ++ continue; ++ ++ disable_irq(interrupt->irq); ++ } ++} ++EXPORT_SYMBOL_NS_GPL(sdca_irq_disable, "SND_SOC_SDCA"); +-- +2.43.0 + diff --git a/pkgbuilds/edge/linux-ptl-audio/0005-ASoC-SDCA-Add-basic-system-suspend-support.patch b/pkgbuilds/edge/linux-ptl-audio/0005-ASoC-SDCA-Add-basic-system-suspend-support.patch new file mode 100644 index 0000000..41fa3f9 --- /dev/null +++ b/pkgbuilds/edge/linux-ptl-audio/0005-ASoC-SDCA-Add-basic-system-suspend-support.patch @@ -0,0 +1,149 @@ +From 10bf875e22235547b28f5143566d154c665206cc Mon Sep 17 00:00:00 2001 +From: Charles Keepax +Date: Fri, 9 Jan 2026 14:52:04 +0000 +Subject: [PATCH 05/17] ASoC: SDCA: Add basic system suspend support + +Add basic system suspend support. Disable the IRQs and force runtime +suspend, during system suspend, because the device will likely fully +power down during suspend. + +Signed-off-by: Charles Keepax +Reviewed-by: Pierre-Louis Bossart +Link: https://patch.msgid.link/20260109145206.3456151-3-ckeepax@opensource.cirrus.com +Signed-off-by: Mark Brown +--- + sound/soc/sdca/sdca_class.c | 33 ++++++++++++++++++ + sound/soc/sdca/sdca_class_function.c | 51 ++++++++++++++++++++++++++++ + 2 files changed, 84 insertions(+) + +diff --git a/sound/soc/sdca/sdca_class.c b/sound/soc/sdca/sdca_class.c +index 349d32933ba8..6d19a183683e 100644 +--- a/sound/soc/sdca/sdca_class.c ++++ b/sound/soc/sdca/sdca_class.c +@@ -238,6 +238,38 @@ static int class_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *id + return 0; + } + ++static int class_suspend(struct device *dev) ++{ ++ struct sdca_class_drv *drv = dev_get_drvdata(dev); ++ int ret; ++ ++ disable_irq(drv->sdw->irq); ++ ++ ret = pm_runtime_force_suspend(dev); ++ if (ret) { ++ dev_err(dev, "failed to force suspend: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int class_resume(struct device *dev) ++{ ++ struct sdca_class_drv *drv = dev_get_drvdata(dev); ++ int ret; ++ ++ ret = pm_runtime_force_resume(dev); ++ if (ret) { ++ dev_err(dev, "failed to force resume: %d\n", ret); ++ return ret; ++ } ++ ++ enable_irq(drv->sdw->irq); ++ ++ return 0; ++} ++ + static int class_runtime_suspend(struct device *dev) + { + struct sdca_class_drv *drv = dev_get_drvdata(dev); +@@ -278,6 +310,7 @@ static int class_runtime_resume(struct device *dev) + } + + static const struct dev_pm_ops class_pm_ops = { ++ SYSTEM_SLEEP_PM_OPS(class_suspend, class_resume) + RUNTIME_PM_OPS(class_runtime_suspend, class_runtime_resume, NULL) + }; + +diff --git a/sound/soc/sdca/sdca_class_function.c b/sound/soc/sdca/sdca_class_function.c +index 416948cfb5cb..7d0a6c0adbfb 100644 +--- a/sound/soc/sdca/sdca_class_function.c ++++ b/sound/soc/sdca/sdca_class_function.c +@@ -33,6 +33,7 @@ struct class_function_drv { + struct sdca_class_drv *core; + + struct sdca_function_data *function; ++ bool suspended; + }; + + static void class_function_regmap_lock(void *data) +@@ -417,6 +418,14 @@ static int class_function_runtime_resume(struct device *dev) + regcache_mark_dirty(drv->regmap); + regcache_cache_only(drv->regmap, false); + ++ if (drv->suspended) { ++ sdca_irq_enable_early(drv->function, drv->core->irq_info); ++ /* TODO: Add FDL process between early and late IRQs */ ++ sdca_irq_enable(drv->function, drv->core->irq_info); ++ ++ drv->suspended = false; ++ } ++ + ret = regcache_sync(drv->regmap); + if (ret) { + dev_err(drv->dev, "failed to restore register cache: %d\n", ret); +@@ -431,7 +440,49 @@ static int class_function_runtime_resume(struct device *dev) + return ret; + } + ++static int class_function_suspend(struct device *dev) ++{ ++ struct auxiliary_device *auxdev = to_auxiliary_dev(dev); ++ struct class_function_drv *drv = auxiliary_get_drvdata(auxdev); ++ int ret; ++ ++ drv->suspended = true; ++ ++ /* Ensure runtime resume runs on resume */ ++ ret = pm_runtime_resume_and_get(dev); ++ if (ret) { ++ dev_err(dev, "failed to resume for suspend: %d\n", ret); ++ return ret; ++ } ++ ++ sdca_irq_disable(drv->function, drv->core->irq_info); ++ ++ ret = pm_runtime_force_suspend(dev); ++ if (ret) { ++ dev_err(dev, "failed to force suspend: %d\n", ret); ++ return ret; ++ } ++ ++ pm_runtime_put_noidle(dev); ++ ++ return 0; ++} ++ ++static int class_function_resume(struct device *dev) ++{ ++ int ret; ++ ++ ret = pm_runtime_force_resume(dev); ++ if (ret) { ++ dev_err(dev, "failed to force resume: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ + static const struct dev_pm_ops class_function_pm_ops = { ++ SYSTEM_SLEEP_PM_OPS(class_function_suspend, class_function_resume) + RUNTIME_PM_OPS(class_function_runtime_suspend, + class_function_runtime_resume, NULL) + }; +-- +2.43.0 + diff --git a/pkgbuilds/edge/linux-ptl-audio/0007-ASoC-SDCA-Add-lock-to-serialise-the-Function-initial.patch b/pkgbuilds/edge/linux-ptl-audio/0007-ASoC-SDCA-Add-lock-to-serialise-the-Function-initial.patch new file mode 100644 index 0000000..cbb21ee --- /dev/null +++ b/pkgbuilds/edge/linux-ptl-audio/0007-ASoC-SDCA-Add-lock-to-serialise-the-Function-initial.patch @@ -0,0 +1,77 @@ +From 914bb3e2ba56354fd66cbb130eb536513ae3e1ca Mon Sep 17 00:00:00 2001 +From: Charles Keepax +Date: Fri, 9 Jan 2026 14:52:06 +0000 +Subject: [PATCH 07/17] ASoC: SDCA: Add lock to serialise the Function + initialisation + +To avoid issues on some devices serialise the boot of each SDCA Function +from the others. + +Signed-off-by: Charles Keepax +Reviewed-by: Pierre-Louis Bossart +Link: https://patch.msgid.link/20260109145206.3456151-5-ckeepax@opensource.cirrus.com +Signed-off-by: Mark Brown +--- + sound/soc/sdca/sdca_class.c | 1 + + sound/soc/sdca/sdca_class.h | 2 ++ + sound/soc/sdca/sdca_class_function.c | 5 +++++ + 3 files changed, 8 insertions(+) + +diff --git a/sound/soc/sdca/sdca_class.c b/sound/soc/sdca/sdca_class.c +index 6d19a183683e..918b638acb57 100644 +--- a/sound/soc/sdca/sdca_class.c ++++ b/sound/soc/sdca/sdca_class.c +@@ -205,6 +205,7 @@ static int class_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *id + drv->dev = dev; + drv->sdw = sdw; + mutex_init(&drv->regmap_lock); ++ mutex_init(&drv->init_lock); + + dev_set_drvdata(drv->dev, drv); + +diff --git a/sound/soc/sdca/sdca_class.h b/sound/soc/sdca/sdca_class.h +index bb4c9dd12429..6f24ea2bbd38 100644 +--- a/sound/soc/sdca/sdca_class.h ++++ b/sound/soc/sdca/sdca_class.h +@@ -28,6 +28,8 @@ struct sdca_class_drv { + struct sdca_interrupt_info *irq_info; + + struct mutex regmap_lock; ++ /* Serialise function initialisations */ ++ struct mutex init_lock; + struct work_struct boot_work; + struct completion device_attach; + +diff --git a/sound/soc/sdca/sdca_class_function.c b/sound/soc/sdca/sdca_class_function.c +index bbf486d9a3d0..0afa41c1ee93 100644 +--- a/sound/soc/sdca/sdca_class_function.c ++++ b/sound/soc/sdca/sdca_class_function.c +@@ -8,6 +8,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -244,6 +245,8 @@ static int class_function_boot(struct class_function_drv *drv) + unsigned int val; + int ret; + ++ guard(mutex)(&drv->core->init_lock); ++ + ret = regmap_read(drv->regmap, reg, &val); + if (ret < 0) { + dev_err(drv->dev, "failed to read function status: %d\n", ret); +@@ -418,6 +421,8 @@ static int class_function_runtime_resume(struct device *dev) + struct class_function_drv *drv = auxiliary_get_drvdata(auxdev); + int ret; + ++ guard(mutex)(&drv->core->init_lock); ++ + regcache_mark_dirty(drv->regmap); + regcache_cache_only(drv->regmap, false); + +-- +2.43.0 + diff --git a/pkgbuilds/edge/linux-ptl-audio/0008-ASoC-SDCA-Tidy-up-some-memory-allocations.patch b/pkgbuilds/edge/linux-ptl-audio/0008-ASoC-SDCA-Tidy-up-some-memory-allocations.patch new file mode 100644 index 0000000..16d5fb1 --- /dev/null +++ b/pkgbuilds/edge/linux-ptl-audio/0008-ASoC-SDCA-Tidy-up-some-memory-allocations.patch @@ -0,0 +1,65 @@ +From 657e4d51de49864710a8b804c50e94e0e14ac63b Mon Sep 17 00:00:00 2001 +From: Charles Keepax +Date: Thu, 15 Jan 2026 11:46:07 +0000 +Subject: [PATCH 08/17] ASoC: SDCA: Tidy up some memory allocations + +It is slightly better to deference the type being allocate for a sizeof +rather than manually using the type. Saves effort if types change in the +future. This results in no functional changes, just tidies up the style +of the code a little. + +Signed-off-by: Charles Keepax +Link: https://patch.msgid.link/20260115114607.271990-1-ckeepax@opensource.cirrus.com +Signed-off-by: Mark Brown +--- + sound/soc/sdca/sdca_fdl.c | 2 +- + sound/soc/sdca/sdca_functions.c | 6 +++--- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/sound/soc/sdca/sdca_fdl.c b/sound/soc/sdca/sdca_fdl.c +index 3180ebd07c40..8bee9f23c473 100644 +--- a/sound/soc/sdca/sdca_fdl.c ++++ b/sound/soc/sdca/sdca_fdl.c +@@ -487,7 +487,7 @@ int sdca_fdl_alloc_state(struct sdca_interrupt *interrupt) + struct device *dev = interrupt->dev; + struct fdl_state *fdl_state; + +- fdl_state = devm_kzalloc(dev, sizeof(struct fdl_state), GFP_KERNEL); ++ fdl_state = devm_kzalloc(dev, sizeof(*fdl_state), GFP_KERNEL); + if (!fdl_state) + return -ENOMEM; + +diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c +index b26884fc2a98..f97dde912d59 100644 +--- a/sound/soc/sdca/sdca_functions.c ++++ b/sound/soc/sdca/sdca_functions.c +@@ -948,7 +948,7 @@ static int find_sdca_entity_control(struct device *dev, struct sdca_entity *enti + } + + control->values = devm_kcalloc(dev, hweight64(control->cn_list), +- sizeof(int), GFP_KERNEL); ++ sizeof(*control->values), GFP_KERNEL); + if (!control->values) + return -ENOMEM; + +@@ -2044,7 +2044,7 @@ static int find_sdca_filesets(struct device *dev, struct sdw_slave *sdw, + fwnode_property_read_u32_array(function_node, "mipi-sdca-file-set-id-list", + filesets_list, num_sets); + +- sets = devm_kcalloc(dev, num_sets, sizeof(struct sdca_fdl_set), GFP_KERNEL); ++ sets = devm_kcalloc(dev, num_sets, sizeof(*sets), GFP_KERNEL); + if (!sets) + return -ENOMEM; + +@@ -2070,7 +2070,7 @@ static int find_sdca_filesets(struct device *dev, struct sdw_slave *sdw, + dev_dbg(dev, "fileset: %#x\n", filesets_list[i]); + + files = devm_kcalloc(dev, num_entries / mult_fileset, +- sizeof(struct sdca_fdl_file), GFP_KERNEL); ++ sizeof(*files), GFP_KERNEL); + if (!files) + return -ENOMEM; + +-- +2.43.0 + diff --git a/pkgbuilds/edge/linux-ptl-audio/0010-ASoC-SDCA-Add-NO_DIRECT_COMPLETE-flag-to-class-drive.patch b/pkgbuilds/edge/linux-ptl-audio/0010-ASoC-SDCA-Add-NO_DIRECT_COMPLETE-flag-to-class-drive.patch new file mode 100644 index 0000000..db1feb5 --- /dev/null +++ b/pkgbuilds/edge/linux-ptl-audio/0010-ASoC-SDCA-Add-NO_DIRECT_COMPLETE-flag-to-class-drive.patch @@ -0,0 +1,43 @@ +From b92178f5dd8fa8f70e26d4e2b055327842e58a74 Mon Sep 17 00:00:00 2001 +From: Charles Keepax +Date: Thu, 15 Jan 2026 13:17:26 +0000 +Subject: [PATCH 10/17] ASoC: SDCA: Add NO_DIRECT_COMPLETE flag to class driver + +The SDCA class driver currently expects the device will be fully powered +down on system suspend but not on runtime suspend. This is typically +required as when audio is not active (ie. runtime suspend) jack detect +is expected to still function, but when the whole system is hibernated +there is no need to recognise audio jack events. This means the class +driver needs to always be informed of a system suspend, so the direct +complete optimisation (where PM will skip calling system suspend if the +device is runtime suspended) is not appropriate for the SDCA class +driver. + +Add the NO_DIRECT_COMPLETE flag to prevent this optimisation from +running against this driver. + +Signed-off-by: Charles Keepax +Reviewed-by: Pierre-Louis Bossart +link: https://github.com/thesofproject/linux/blob/ec0e6c69113f4b342ee8eabec286dea33d98a7cc/drivers/soundwire/intel_auxdevice.c#L568 +Link: https://patch.msgid.link/20260115131727.373738-1-ckeepax@opensource.cirrus.com +Signed-off-by: Mark Brown +--- + sound/soc/sdca/sdca_class_function.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sound/soc/sdca/sdca_class_function.c b/sound/soc/sdca/sdca_class_function.c +index 0afa41c1ee93..98fd3fd1052b 100644 +--- a/sound/soc/sdca/sdca_class_function.c ++++ b/sound/soc/sdca/sdca_class_function.c +@@ -377,6 +377,8 @@ static int class_function_probe(struct auxiliary_device *auxdev, + if (ret) + return ret; + ++ dev_pm_set_driver_flags(dev, DPM_FLAG_NO_DIRECT_COMPLETE); ++ + pm_runtime_set_autosuspend_delay(dev, 200); + pm_runtime_use_autosuspend(dev); + pm_runtime_set_active(dev); +-- +2.43.0 + diff --git a/pkgbuilds/edge/linux-ptl-audio/0012-ASoC-SDCA-Rearrange-FDL-file-messages.patch b/pkgbuilds/edge/linux-ptl-audio/0012-ASoC-SDCA-Rearrange-FDL-file-messages.patch new file mode 100644 index 0000000..04bf77b --- /dev/null +++ b/pkgbuilds/edge/linux-ptl-audio/0012-ASoC-SDCA-Rearrange-FDL-file-messages.patch @@ -0,0 +1,61 @@ +From c7da79578f653d5503f5faadcb887e4f8997c2b9 Mon Sep 17 00:00:00 2001 +From: Charles Keepax +Date: Wed, 4 Feb 2026 12:59:41 +0000 +Subject: [PATCH 12/17] ASoC: SDCA: Rearrange FDL file messages + +It is helpful to have something in the log showing which firmware file +was loaded by the driver. Update the existing FDL disk file debug +statement to just note that a disk file rather than ACPI file was used, +and add a new info printk that prints out the details of the loaded file +regardless of where that file came from. Likewise, sometimes it is +useful to get a message if the file-sets list is missing, although this +isn't technically an error so make it a debug. + +Signed-off-by: Charles Keepax +Link: https://patch.msgid.link/20260204125944.1134011-5-ckeepax@opensource.cirrus.com +Reviewed-by: Pierre-Louis Bossart +Signed-off-by: Mark Brown +--- + sound/soc/sdca/sdca_fdl.c | 6 ++++-- + sound/soc/sdca/sdca_functions.c | 1 + + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/sdca/sdca_fdl.c b/sound/soc/sdca/sdca_fdl.c +index 8bee9f23c473..07892bc3a44e 100644 +--- a/sound/soc/sdca/sdca_fdl.c ++++ b/sound/soc/sdca/sdca_fdl.c +@@ -256,8 +256,7 @@ static int fdl_load_file(struct sdca_interrupt *interrupt, + tmp->file_length != firmware->size) { + dev_err(dev, "bad disk SWF size\n"); + } else if (!swf || swf->file_version <= tmp->file_version) { +- dev_dbg(dev, "using SWF from disk: %x-%x-%x\n", +- tmp->vendor_id, tmp->file_id, tmp->file_version); ++ dev_dbg(dev, "using SWF from disk\n"); + swf = tmp; + } + } +@@ -267,6 +266,9 @@ static int fdl_load_file(struct sdca_interrupt *interrupt, + return -ENOENT; + } + ++ dev_info(dev, "loading SWF: %x-%x-%x\n", ++ swf->vendor_id, swf->file_id, swf->file_version); ++ + ret = sdca_ump_write_message(dev, interrupt->device_regmap, + interrupt->function_regmap, + interrupt->function, interrupt->entity, +diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c +index f97dde912d59..f38791eab4f1 100644 +--- a/sound/soc/sdca/sdca_functions.c ++++ b/sound/soc/sdca/sdca_functions.c +@@ -2029,6 +2029,7 @@ static int find_sdca_filesets(struct device *dev, struct sdw_slave *sdw, + num_sets = fwnode_property_count_u32(function_node, + "mipi-sdca-file-set-id-list"); + if (num_sets == 0 || num_sets == -EINVAL) { ++ dev_dbg(dev, "%pfwP: file set id list missing\n", function_node); + return 0; + } else if (num_sets < 0) { + dev_err(dev, "%pfwP: failed to read file set list: %d\n", +-- +2.43.0 + diff --git a/pkgbuilds/edge/linux-ptl-audio/0013-ASoC-SDCA-Add-regmap-defaults-for-specification-defi.patch b/pkgbuilds/edge/linux-ptl-audio/0013-ASoC-SDCA-Add-regmap-defaults-for-specification-defi.patch new file mode 100644 index 0000000..206b171 --- /dev/null +++ b/pkgbuilds/edge/linux-ptl-audio/0013-ASoC-SDCA-Add-regmap-defaults-for-specification-defi.patch @@ -0,0 +1,160 @@ +From a80d5cd47c6d2eb3890235a527ad41a73b28009e Mon Sep 17 00:00:00 2001 +From: Charles Keepax +Date: Wed, 4 Feb 2026 12:59:42 +0000 +Subject: [PATCH 13/17] ASoC: SDCA: Add regmap defaults for specification + defined values + +Some of the SDCA Controls have a defined reset value in the +specification. Update the parsing to add these specification defined +values into the regmap defaults array. This will reduce the number of +registers that are synchronised on a cache sync. + +Signed-off-by: Charles Keepax +Link: https://patch.msgid.link/20260204125944.1134011-6-ckeepax@opensource.cirrus.com +Reviewed-by: Pierre-Louis Bossart +Signed-off-by: Mark Brown +--- + include/sound/sdca_function.h | 4 ++++ + sound/soc/sdca/sdca_functions.c | 36 +++++++++++++++++++++++++++++++++ + sound/soc/sdca/sdca_regmap.c | 14 ++++++++++--- + 3 files changed, 51 insertions(+), 3 deletions(-) + +diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h +index 6e9391b3816c..79bd5a7a0f88 100644 +--- a/include/sound/sdca_function.h ++++ b/include/sound/sdca_function.h +@@ -798,6 +798,7 @@ struct sdca_control_range { + * @sel: Identifier used for addressing. + * @nbits: Number of bits used in the Control. + * @values: Holds the Control value for constants and defaults. ++ * @reset: Defined reset value for the Control. + * @cn_list: A bitmask showing the valid Control Numbers within this Control, + * Control Numbers typically represent channels. + * @interrupt_position: SCDA interrupt line that will alert to changes on this +@@ -808,6 +809,7 @@ struct sdca_control_range { + * @layers: Bitmask of access layers of the Control. + * @deferrable: Indicates if the access to the Control can be deferred. + * @has_default: Indicates the Control has a default value to be written. ++ * @has_reset: Indicates the Control has a defined reset value. + * @has_fixed: Indicates the Control only supports a single value. + */ + struct sdca_control { +@@ -816,6 +818,7 @@ struct sdca_control { + + int nbits; + int *values; ++ int reset; + u64 cn_list; + int interrupt_position; + +@@ -827,6 +830,7 @@ struct sdca_control { + bool deferrable; + bool is_volatile; + bool has_default; ++ bool has_reset; + bool has_fixed; + }; + +diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c +index f38791eab4f1..95b67bb904c3 100644 +--- a/sound/soc/sdca/sdca_functions.c ++++ b/sound/soc/sdca/sdca_functions.c +@@ -911,6 +911,38 @@ static int find_sdca_control_value(struct device *dev, struct sdca_entity *entit + return 0; + } + ++static int find_sdca_control_reset(const struct sdca_entity *entity, ++ struct sdca_control *control) ++{ ++ switch (SDCA_CTL_TYPE(entity->type, control->sel)) { ++ case SDCA_CTL_TYPE_S(FU, AGC): ++ case SDCA_CTL_TYPE_S(FU, BASS_BOOST): ++ case SDCA_CTL_TYPE_S(FU, LOUDNESS): ++ case SDCA_CTL_TYPE_S(SMPU, TRIGGER_ENABLE): ++ case SDCA_CTL_TYPE_S(GE, SELECTED_MODE): ++ case SDCA_CTL_TYPE_S(TG, TONE_DIVIDER): ++ case SDCA_CTL_TYPE_S(ENTITY_0, COMMIT_GROUP_MASK): ++ control->has_reset = true; ++ control->reset = 0; ++ break; ++ case SDCA_CTL_TYPE_S(XU, BYPASS): ++ case SDCA_CTL_TYPE_S(MFPU, BYPASS): ++ case SDCA_CTL_TYPE_S(FU, MUTE): ++ case SDCA_CTL_TYPE_S(CX, CLOCK_SELECT): ++ control->has_reset = true; ++ control->reset = 1; ++ break; ++ case SDCA_CTL_TYPE_S(PDE, REQUESTED_PS): ++ control->has_reset = true; ++ control->reset = 3; ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ + static int find_sdca_entity_control(struct device *dev, struct sdca_entity *entity, + struct fwnode_handle *control_node, + struct sdca_control *control) +@@ -986,6 +1018,10 @@ static int find_sdca_entity_control(struct device *dev, struct sdca_entity *enti + + control->is_volatile = find_sdca_control_volatile(entity, control); + ++ ret = find_sdca_control_reset(entity, control); ++ if (ret) ++ return ret; ++ + ret = find_sdca_control_range(dev, control_node, &control->range); + if (ret) { + dev_err(dev, "%s: control %#x: range missing: %d\n", +diff --git a/sound/soc/sdca/sdca_regmap.c b/sound/soc/sdca/sdca_regmap.c +index 2cca9a9c71ea..4f8a685dc43d 100644 +--- a/sound/soc/sdca/sdca_regmap.c ++++ b/sound/soc/sdca/sdca_regmap.c +@@ -218,7 +218,8 @@ int sdca_regmap_count_constants(struct device *dev, + struct sdca_entity *entity = &function->entities[i]; + + for (j = 0; j < entity->num_controls; j++) { +- if (entity->controls[j].mode == SDCA_ACCESS_MODE_DC) ++ if (entity->controls[j].mode == SDCA_ACCESS_MODE_DC || ++ entity->controls[j].has_reset) + nconsts += hweight64(entity->controls[j].cn_list); + } + } +@@ -255,7 +256,8 @@ int sdca_regmap_populate_constants(struct device *dev, + struct sdca_control *control = &entity->controls[j]; + int cn; + +- if (control->mode != SDCA_ACCESS_MODE_DC) ++ if (control->mode != SDCA_ACCESS_MODE_DC && ++ !control->has_reset) + continue; + + l = 0; +@@ -264,7 +266,10 @@ int sdca_regmap_populate_constants(struct device *dev, + consts[k].reg = SDW_SDCA_CTL(function->desc->adr, + entity->id, + control->sel, cn); +- consts[k].def = control->values[l]; ++ if (control->mode == SDCA_ACCESS_MODE_DC) ++ consts[k].def = control->values[l]; ++ else ++ consts[k].def = control->reset; + k++; + l++; + } +@@ -306,6 +311,9 @@ static int populate_control_defaults(struct device *dev, struct regmap *regmap, + + i++; + } else if (!control->is_volatile) { ++ if (control->has_reset) ++ regcache_drop_region(regmap, reg, reg); ++ + ret = regmap_read(regmap, reg, &val); + if (ret) { + dev_err(dev, "Failed to read initial %#x: %d\n", +-- +2.43.0 + diff --git a/pkgbuilds/edge/linux-ptl-audio/0014-ASoC-SDCA-Limit-values-user-can-write-to-Selected-Mo.patch b/pkgbuilds/edge/linux-ptl-audio/0014-ASoC-SDCA-Limit-values-user-can-write-to-Selected-Mo.patch new file mode 100644 index 0000000..5e9fdac --- /dev/null +++ b/pkgbuilds/edge/linux-ptl-audio/0014-ASoC-SDCA-Limit-values-user-can-write-to-Selected-Mo.patch @@ -0,0 +1,90 @@ +From 29408c08047402839d40cb03bf870efcf476c361 Mon Sep 17 00:00:00 2001 +From: Charles Keepax +Date: Wed, 4 Feb 2026 12:59:43 +0000 +Subject: [PATCH 14/17] ASoC: SDCA: Limit values user can write to Selected + Mode + +Prevent the user from both updating the Selected Mode control +whilst the jack is not present, and from writing values that don't +correspond to a valid jack type (Unknown, in progress, etc.). + +Signed-off-by: Charles Keepax +Link: https://patch.msgid.link/20260204125944.1134011-7-ckeepax@opensource.cirrus.com +Reviewed-by: Pierre-Louis Bossart +Signed-off-by: Mark Brown +--- + sound/soc/sdca/sdca_asoc.c | 37 ++++++++++++++++++++++++++++++++++++- + sound/soc/sdca/sdca_jack.c | 2 +- + 2 files changed, 37 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/sdca/sdca_asoc.c b/sound/soc/sdca/sdca_asoc.c +index 9685281529e9..bb6e74e80a3e 100644 +--- a/sound/soc/sdca/sdca_asoc.c ++++ b/sound/soc/sdca/sdca_asoc.c +@@ -116,6 +116,41 @@ int sdca_asoc_count_component(struct device *dev, struct sdca_function_data *fun + } + EXPORT_SYMBOL_NS(sdca_asoc_count_component, "SND_SOC_SDCA"); + ++static int ge_put_enum_double(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol); ++ struct snd_soc_component *component = snd_soc_dapm_to_component(dapm); ++ struct device *dev = component->dev; ++ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; ++ unsigned int *item = ucontrol->value.enumerated.item; ++ unsigned int reg = e->reg; ++ int ret; ++ ++ reg &= ~SDW_SDCA_CTL_CSEL(0x3F); ++ reg |= SDW_SDCA_CTL_CSEL(SDCA_CTL_GE_DETECTED_MODE); ++ ++ ret = pm_runtime_resume_and_get(dev); ++ if (ret < 0) { ++ dev_err(dev, "failed to resume writing %s: %d\n", ++ kcontrol->id.name, ret); ++ return ret; ++ } ++ ++ ret = snd_soc_component_read(component, reg); ++ pm_runtime_put(dev); ++ if (ret < 0) ++ return ret; ++ else if (ret <= SDCA_DETECTED_MODE_DETECTION_IN_PROGRESS) ++ return -EBUSY; ++ ++ ret = snd_soc_enum_item_to_val(e, item[0]); ++ if (ret <= SDCA_DETECTED_MODE_DETECTION_IN_PROGRESS) ++ return -EINVAL; ++ ++ return snd_soc_dapm_put_enum_double(kcontrol, ucontrol); ++} ++ + static int entity_early_parse_ge(struct device *dev, + struct sdca_function_data *function, + struct sdca_entity *entity) +@@ -192,7 +227,7 @@ static int entity_early_parse_ge(struct device *dev, + kctl->name = control_name; + kctl->info = snd_soc_info_enum_double; + kctl->get = snd_soc_dapm_get_enum_double; +- kctl->put = snd_soc_dapm_put_enum_double; ++ kctl->put = ge_put_enum_double; + kctl->private_value = (unsigned long)soc_enum; + + entity->ge.kctl = kctl; +diff --git a/sound/soc/sdca/sdca_jack.c b/sound/soc/sdca/sdca_jack.c +index bfa621b744e1..605514f02045 100644 +--- a/sound/soc/sdca/sdca_jack.c ++++ b/sound/soc/sdca/sdca_jack.c +@@ -105,7 +105,7 @@ int sdca_jack_process(struct sdca_interrupt *interrupt) + + ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(soc_enum, val); + +- ret = kctl->put(kctl, ucontrol); ++ ret = snd_soc_dapm_put_enum_double(kctl, ucontrol); + if (ret < 0) { + dev_err(dev, "failed to update selected mode: %d\n", ret); + return ret; +-- +2.43.0 + diff --git a/pkgbuilds/edge/linux-ptl-audio/0017-ASoC-SDCA-Fix-NULL-pointer-dereference-in-sdca_jack_.patch b/pkgbuilds/edge/linux-ptl-audio/0017-ASoC-SDCA-Fix-NULL-pointer-dereference-in-sdca_jack_.patch new file mode 100644 index 0000000..5f61cab --- /dev/null +++ b/pkgbuilds/edge/linux-ptl-audio/0017-ASoC-SDCA-Fix-NULL-pointer-dereference-in-sdca_jack_.patch @@ -0,0 +1,43 @@ +From 849489b94fe35172a4fea6e09acabacd273d8993 Mon Sep 17 00:00:00 2001 +From: TsaiGaggery +Date: Wed, 11 Mar 2026 14:21:39 -0700 +Subject: [PATCH 17/17] ASoC: SDCA: Fix NULL pointer dereference in + sdca_jack_process() + +Add NULL guard for card and card->snd_card before dereferencing. +During card teardown, component->card can be NULL when an IRQ fires. +--- + sound/soc/sdca/sdca_jack.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/sdca/sdca_jack.c b/sound/soc/sdca/sdca_jack.c +index 605514f02045..04ff391aa7bc 100644 +--- a/sound/soc/sdca/sdca_jack.c ++++ b/sound/soc/sdca/sdca_jack.c +@@ -37,13 +37,21 @@ int sdca_jack_process(struct sdca_interrupt *interrupt) + struct device *dev = interrupt->dev; + struct snd_soc_component *component = interrupt->component; + struct snd_soc_card *card = component->card; +- struct rw_semaphore *rwsem = &card->snd_card->controls_rwsem; ++ struct rw_semaphore *rwsem; + struct jack_state *state = interrupt->priv; +- struct snd_kcontrol *kctl = state->kctl; ++ struct snd_kcontrol *kctl; + struct snd_ctl_elem_value *ucontrol __free(kfree) = NULL; + unsigned int reg, val; + int ret; + ++ if (!card || !card->snd_card) { ++ dev_dbg(dev, "card not yet bound, deferring jack event\n"); ++ return -ENODEV; ++ } ++ ++ rwsem = &card->snd_card->controls_rwsem; ++ kctl = state->kctl; ++ + guard(rwsem_write)(rwsem); + + if (!kctl) { +-- +2.43.0 + diff --git a/pkgbuilds/edge/linux-ptl-audio/PKGBUILD b/pkgbuilds/edge/linux-ptl-audio/PKGBUILD new file mode 100644 index 0000000..7ce53d2 --- /dev/null +++ b/pkgbuilds/edge/linux-ptl-audio/PKGBUILD @@ -0,0 +1,279 @@ +# Maintainer: Intel PTL Audio Enablement +# Based on Arch Linux linux package by Jan Alexander Steffens (heftig) + +pkgbase=linux-ptl-audio +pkgver=6.19.9.arch1 +pkgrel=1 +pkgdesc='Linux with Panther Lake SDCA audio backports' +url='https://github.com/archlinux/linux' +arch=( + x86_64 +) +license=(GPL-2.0-only) +makedepends=( + bc + cpio + gettext + libelf + pahole + perl + python + tar + xz +) +options=( + !debug + !strip +) +_srcname=linux-${pkgver%.*} +_srctag=v${pkgver%.*}-${pkgver##*.} +source=( + https://cdn.kernel.org/pub/linux/kernel/v${pkgver%%.*}.x/${_srcname}.tar.{xz,sign} + $url/releases/download/$_srctag/linux-$_srctag.patch.zst{,.sig} + 0001-ASoC-SDCA-functions-Fix-confusing-cleanup.h-syntax.patch + 0002-ASoC-SDCA-Add-ASoC-jack-hookup-in-class-driver.patch + 0003-ASoC-SDCA-Replace-use-of-system_wq-with-system_dfl_w.patch + 0004-ASoC-SDCA-Add-SDCA-IRQ-enable-disable-helpers.patch + 0005-ASoC-SDCA-Add-basic-system-suspend-support.patch + 0007-ASoC-SDCA-Add-lock-to-serialise-the-Function-initial.patch + 0008-ASoC-SDCA-Tidy-up-some-memory-allocations.patch + 0010-ASoC-SDCA-Add-NO_DIRECT_COMPLETE-flag-to-class-drive.patch + 0012-ASoC-SDCA-Rearrange-FDL-file-messages.patch + 0013-ASoC-SDCA-Add-regmap-defaults-for-specification-defi.patch + 0014-ASoC-SDCA-Limit-values-user-can-write-to-Selected-Mo.patch + 0017-ASoC-SDCA-Fix-NULL-pointer-dereference-in-sdca_jack_.patch +) +source_x86_64=(config.x86_64) +validpgpkeys=( + ABAF11C65A2970B130ABE3C479BE3E4300411886 # Linus Torvalds + 647F28654894E3BD457199BE38DBBDC86092693E # Greg Kroah-Hartman + 83BC8889351B5DEBBB68416EB8AC08600F108CDF # Jan Alexander Steffens (heftig) +) +b2sums=('6be41037c5b18e9a8d1c58fdd613e37bb5c841b7f43baf95516f3dda461adc6eb20da03e6a8892bd5b8410125ad42dae8ef4634a0eb95b84aaf3882a6ed00074' + 'SKIP' + 'edc6d11f32f16a53e520b53b52be690d192c0a64153419cbba65e4a2c0f426ce76ab2c10dbddd7f82f2c407c071039b05018796cf2b8ba501d46e3a259146ced' + 'SKIP' + 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' + 'SKIP' 'SKIP' 'SKIP' 'SKIP') +b2sums_x86_64=('cab93bd983d92e2fc6047bfaa3fc3b52fbd23272aef4aaa10500ac0ac26847c1bbdfdb13a6f64ad7689166109b99a078580bf43a02aaf9f2be0ae8885a87ffc8') + +# https://www.kernel.org/pub/linux/kernel/v6.x/sha256sums.asc +sha256sums=('c16068a3af12e3943dee3b1eef57ca70229c069128bfa1184fb3f48b219d55bf' + 'SKIP' + 'dacb94dc3be57fc442995a3d3d1519775d3f6877a4e2fec437223d95e318f04b' + 'SKIP' + 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' + 'SKIP' 'SKIP' 'SKIP' 'SKIP') + +export KBUILD_BUILD_HOST=archlinux +export KBUILD_BUILD_USER=$pkgbase +export KBUILD_BUILD_TIMESTAMP="$(date -Ru${SOURCE_DATE_EPOCH:+d @$SOURCE_DATE_EPOCH})" + +prepare() { + cd $_srcname + + echo "Setting version..." + echo "-$pkgrel" > localversion.10-pkgrel + echo "${pkgbase#linux}" > localversion.20-pkgname + + local src + for src in "${source[@]}"; do + src="${src%%::*}" + src="${src##*/}" + src="${src%.zst}" + [[ $src = *.patch ]] || continue + echo "Applying patch $src..." + patch -Np1 < "../$src" + done + + echo "Setting config..." + cp ../config.$CARCH .config + make olddefconfig + diff -u ../config.$CARCH .config || : + + make -s kernelrelease > version + echo "Prepared $pkgbase version $(