Archived
linux Linux ptl 7.0.2 patch rebase (#83)
* linux-ptl: rebase patches for 7.0.2 * fix patch placement for 27
This commit is contained in:
-160
@@ -1,160 +0,0 @@
|
||||
From 917d5770485e4ccd73f1123e2032a220c021bb56 Mon Sep 17 00:00:00 2001
|
||||
From: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
|
||||
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 <krzysztof.kozlowski@oss.qualcomm.com>
|
||||
Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
|
||||
Link: https://patch.msgid.link/20251203-asoc-wrong-cleanup-h-continued-v1-3-5142be4874fb@oss.qualcomm.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
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
|
||||
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
From 04d5b8676de028c8dded6d174620f69656b6ddd2 Mon Sep 17 00:00:00 2001
|
||||
From: Marco Crivellari <marco.crivellari@suse.com>
|
||||
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 <tj@kernel.org>
|
||||
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
|
||||
Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
|
||||
Link: https://patch.msgid.link/20251230143429.179643-1-marco.crivellari@suse.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
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
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
From 4b55c8cdab4fbbf35fdb22e711a473c7c19b8c39 Mon Sep 17 00:00:00 2001
|
||||
From: Charles Keepax <ckeepax@opensource.cirrus.com>
|
||||
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 <ckeepax@opensource.cirrus.com>
|
||||
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
|
||||
Link: https://patch.msgid.link/20260109145206.3456151-2-ckeepax@opensource.cirrus.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
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
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
From 10bf875e22235547b28f5143566d154c665206cc Mon Sep 17 00:00:00 2001
|
||||
From: Charles Keepax <ckeepax@opensource.cirrus.com>
|
||||
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 <ckeepax@opensource.cirrus.com>
|
||||
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
|
||||
Link: https://patch.msgid.link/20260109145206.3456151-3-ckeepax@opensource.cirrus.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
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
|
||||
|
||||
-77
@@ -1,77 +0,0 @@
|
||||
From 914bb3e2ba56354fd66cbb130eb536513ae3e1ca Mon Sep 17 00:00:00 2001
|
||||
From: Charles Keepax <ckeepax@opensource.cirrus.com>
|
||||
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 <ckeepax@opensource.cirrus.com>
|
||||
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
|
||||
Link: https://patch.msgid.link/20260109145206.3456151-5-ckeepax@opensource.cirrus.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
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 <linux/auxiliary_bus.h>
|
||||
+#include <linux/cleanup.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pm.h>
|
||||
@@ -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
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
From 657e4d51de49864710a8b804c50e94e0e14ac63b Mon Sep 17 00:00:00 2001
|
||||
From: Charles Keepax <ckeepax@opensource.cirrus.com>
|
||||
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 <ckeepax@opensource.cirrus.com>
|
||||
Link: https://patch.msgid.link/20260115114607.271990-1-ckeepax@opensource.cirrus.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
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
|
||||
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
From b92178f5dd8fa8f70e26d4e2b055327842e58a74 Mon Sep 17 00:00:00 2001
|
||||
From: Charles Keepax <ckeepax@opensource.cirrus.com>
|
||||
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 <ckeepax@opensource.cirrus.com>
|
||||
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
|
||||
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 <broonie@kernel.org>
|
||||
---
|
||||
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
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
From c7da79578f653d5503f5faadcb887e4f8997c2b9 Mon Sep 17 00:00:00 2001
|
||||
From: Charles Keepax <ckeepax@opensource.cirrus.com>
|
||||
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 <ckeepax@opensource.cirrus.com>
|
||||
Link: https://patch.msgid.link/20260204125944.1134011-5-ckeepax@opensource.cirrus.com
|
||||
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
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
|
||||
|
||||
-160
@@ -1,160 +0,0 @@
|
||||
From a80d5cd47c6d2eb3890235a527ad41a73b28009e Mon Sep 17 00:00:00 2001
|
||||
From: Charles Keepax <ckeepax@opensource.cirrus.com>
|
||||
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 <ckeepax@opensource.cirrus.com>
|
||||
Link: https://patch.msgid.link/20260204125944.1134011-6-ckeepax@opensource.cirrus.com
|
||||
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
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
|
||||
|
||||
-90
@@ -1,90 +0,0 @@
|
||||
From 29408c08047402839d40cb03bf870efcf476c361 Mon Sep 17 00:00:00 2001
|
||||
From: Charles Keepax <ckeepax@opensource.cirrus.com>
|
||||
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 <ckeepax@opensource.cirrus.com>
|
||||
Link: https://patch.msgid.link/20260204125944.1134011-7-ckeepax@opensource.cirrus.com
|
||||
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
diff -ruN a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
|
||||
--- a/drivers/gpu/drm/i915/display/intel_psr.c 2026-04-06 23:05:21.088563236 -0700
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_psr.c 2026-04-06 23:05:32.080081783 -0700
|
||||
@@ -716,8 +716,14 @@
|
||||
--- a/drivers/gpu/drm/i915/display/intel_psr.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
|
||||
@@ -700,8 +700,14 @@
|
||||
* To support PSR version 02h and PSR version 03h without
|
||||
* Y-coordinate requirement panels we would need to enable
|
||||
* GTC first.
|
||||
@@ -10,10 +10,10 @@ diff -ruN a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/disp
|
||||
+ * support. Accept it without explicit Y-coordinate
|
||||
+ * requirement bit.
|
||||
*/
|
||||
- intel_dp->psr.sink_psr2_support = y_req &&
|
||||
+ intel_dp->psr.sink_psr2_support =
|
||||
+ (y_req || intel_dp->psr_dpcd[0] ==
|
||||
- connector->dp.psr_caps.su_support = y_req &&
|
||||
+ connector->dp.psr_caps.su_support =
|
||||
+ (y_req || connector->dp.psr_caps.dpcd[0] ==
|
||||
+ DP_PSR2_WITH_Y_COORD_ET_SUPPORTED) &&
|
||||
intel_alpm_aux_wake_supported(intel_dp);
|
||||
drm_dbg_kms(display->drm, "PSR2 %ssupported\n",
|
||||
intel_dp->psr.sink_psr2_support ? "" : "not ");
|
||||
connector->dp.psr_caps.su_support ? "" : "not ");
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Gaggery Tsai <gaggery.tsai@intel.com>
|
||||
Date: Tue, 28 Apr 2026 15:00:00 -0500
|
||||
Subject: [PATCH] drm/i915/alpm: limit Panel Replay ALPM programming to PR
|
||||
|
||||
Linux 7 already carries the Panel Replay/PSR selective-update
|
||||
granularity fixes from the old linux-ptl 0020 patch. Keep only the
|
||||
remaining ALPM fix: avoid programming PR-specific ALPM controls when
|
||||
Panel Replay is not active, and use the common helper for aux-less ALPM
|
||||
selection.
|
||||
|
||||
Signed-off-by: Gaggery Tsai <gaggery.tsai@intel.com>
|
||||
---
|
||||
drivers/gpu/drm/i915/display/intel_alpm.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c
|
||||
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
|
||||
@@ -317,7 +317,7 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp,
|
||||
ALPM_CTL_AUX_LESS_SLEEP_HOLD_TIME_50_SYMBOLS |
|
||||
ALPM_CTL_AUX_LESS_WAKE_TIME(crtc_state->alpm_state.aux_less_wake_lines);
|
||||
|
||||
- if (intel_dp->as_sdp_supported) {
|
||||
+ if (intel_dp->as_sdp_supported && crtc_state->has_panel_replay) {
|
||||
u32 pr_alpm_ctl = PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1;
|
||||
|
||||
if (crtc_state->link_off_after_as_sdp_when_pr_active)
|
||||
@@ -432,8 +432,8 @@ void intel_alpm_enable_sink(struct intel_dp *intel_dp,
|
||||
|
||||
val = DP_ALPM_ENABLE | DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE;
|
||||
|
||||
- if (crtc_state->has_panel_replay || (crtc_state->has_lobf &&
|
||||
- intel_alpm_aux_less_wake_supported(intel_dp)))
|
||||
+ if (intel_psr_needs_alpm_aux_less(intel_dp, crtc_state) ||
|
||||
+ (crtc_state->has_lobf && intel_alpm_aux_less_wake_supported(intel_dp)))
|
||||
val |= DP_ALPM_MODE_AUX_LESS;
|
||||
|
||||
drm_dp_dpcd_writeb(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG, val);
|
||||
@@ -1,56 +0,0 @@
|
||||
diff -ruN a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c
|
||||
--- a/drivers/gpu/drm/i915/display/intel_alpm.c 2026-04-06 22:15:28.734440462 -0700
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c 2026-04-06 22:16:30.831931436 -0700
|
||||
@@ -317,7 +317,7 @@
|
||||
ALPM_CTL_AUX_LESS_SLEEP_HOLD_TIME_50_SYMBOLS |
|
||||
ALPM_CTL_AUX_LESS_WAKE_TIME(crtc_state->alpm_state.aux_less_wake_lines);
|
||||
|
||||
- if (intel_dp->as_sdp_supported) {
|
||||
+ if (intel_dp->as_sdp_supported && crtc_state->has_panel_replay) {
|
||||
u32 pr_alpm_ctl = PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1;
|
||||
|
||||
if (intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_CAPABILITY)] &
|
||||
@@ -432,8 +432,8 @@
|
||||
|
||||
val = DP_ALPM_ENABLE | DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE;
|
||||
|
||||
- if (crtc_state->has_panel_replay || (crtc_state->has_lobf &&
|
||||
- intel_alpm_aux_less_wake_supported(intel_dp)))
|
||||
+ if (intel_psr_needs_alpm_aux_less(intel_dp, crtc_state) ||
|
||||
+ (crtc_state->has_lobf && intel_alpm_aux_less_wake_supported(intel_dp)))
|
||||
val |= DP_ALPM_MODE_AUX_LESS;
|
||||
|
||||
drm_dp_dpcd_writeb(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG, val);
|
||||
diff -ruN a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
|
||||
--- a/drivers/gpu/drm/i915/display/intel_psr.c 2026-04-06 22:15:28.733325868 -0700
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_psr.c 2026-04-06 23:05:46.639364241 -0700
|
||||
@@ -498,7 +498,8 @@
|
||||
{
|
||||
u8 su_capability = 0;
|
||||
|
||||
- if (intel_dp->psr.sink_panel_replay_su_support) {
|
||||
+ if (intel_dp->psr.sink_panel_replay_su_support &&
|
||||
+ panel_replay_global_enabled(intel_dp)) {
|
||||
if (drm_dp_dpcd_read_byte(&intel_dp->aux,
|
||||
DP_PANEL_REPLAY_CAP_CAPABILITY,
|
||||
&su_capability) < 0)
|
||||
@@ -513,7 +514,8 @@
|
||||
static unsigned int
|
||||
intel_dp_get_su_x_granularity_offset(struct intel_dp *intel_dp)
|
||||
{
|
||||
- return intel_dp->psr.sink_panel_replay_su_support ?
|
||||
+ return (intel_dp->psr.sink_panel_replay_su_support &&
|
||||
+ panel_replay_global_enabled(intel_dp)) ?
|
||||
DP_PANEL_REPLAY_CAP_X_GRANULARITY :
|
||||
DP_PSR2_SU_X_GRANULARITY;
|
||||
}
|
||||
@@ -521,7 +523,8 @@
|
||||
static unsigned int
|
||||
intel_dp_get_su_y_granularity_offset(struct intel_dp *intel_dp)
|
||||
{
|
||||
- return intel_dp->psr.sink_panel_replay_su_support ?
|
||||
+ return (intel_dp->psr.sink_panel_replay_su_support &&
|
||||
+ panel_replay_global_enabled(intel_dp)) ?
|
||||
DP_PANEL_REPLAY_CAP_Y_GRANULARITY :
|
||||
DP_PSR2_SU_Y_GRANULARITY;
|
||||
}
|
||||
@@ -21,7 +21,7 @@ Signed-off-by: Gaggery Tsai <gaggery.tsai@intel.com>
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
|
||||
--- a/drivers/gpu/drm/i915/display/intel_psr.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
|
||||
@@ -1712,12 +1712,6 @@ static bool _psr_compute_config(struct intel_dp *intel_dp,
|
||||
@@ -1708,13 +1708,7 @@ static bool _psr_compute_config(struct intel_dp *intel_dp,
|
||||
if (!CAN_PSR(intel_dp) || !display->params.enable_psr)
|
||||
return false;
|
||||
|
||||
@@ -31,6 +31,7 @@ diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/dis
|
||||
- if (crtc_state->vrr.enable)
|
||||
- return false;
|
||||
-
|
||||
entry_setup_frames = intel_psr_entry_setup_frames(intel_dp, adjusted_mode);
|
||||
entry_setup_frames = intel_psr_entry_setup_frames(intel_dp, conn_state, adjusted_mode);
|
||||
|
||||
if (entry_setup_frames >= 0) {
|
||||
intel_dp->psr.entry_setup_frames = entry_setup_frames;
|
||||
crtc_state->entry_setup_frames = entry_setup_frames;
|
||||
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
From: Gaggery Tsai <gaggery.tsai@intel.com>
|
||||
Date: Thu, 10 Apr 2026 00:00:00 -0700
|
||||
Subject: [PATCH] drm/i915/psr: handle Panel Replay full-line SU granularity
|
||||
|
||||
Panel Replay SU reports X granularity = 0xFFFF meaning full-line.
|
||||
Without this, psr2_granularity_check() rejects PR SU because
|
||||
2880 % 65535 != 0.
|
||||
|
||||
Signed-off-by: Gaggery Tsai <gaggery.tsai@intel.com>
|
||||
---
|
||||
drivers/gpu/drm/i915/display/intel_psr.c | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
|
||||
--- a/drivers/gpu/drm/i915/display/intel_psr.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
|
||||
@@ -1326,9 +1326,17 @@
|
||||
const int crtc_hdisplay = crtc_state->hw.adjusted_mode.crtc_hdisplay;
|
||||
const int crtc_vdisplay = crtc_state->hw.adjusted_mode.crtc_vdisplay;
|
||||
u16 y_granularity = 0;
|
||||
+ u16 w_granularity = intel_dp->psr.su_w_granularity;
|
||||
+
|
||||
+ /*
|
||||
+ * Panel Replay SU can report 0xFFFF meaning full-line granularity.
|
||||
+ * Substitute crtc_hdisplay so the modulo check passes.
|
||||
+ */
|
||||
+ if (w_granularity == 0xFFFF)
|
||||
+ w_granularity = crtc_hdisplay;
|
||||
|
||||
/* PSR2 HW only send full lines so we only need to validate the width */
|
||||
- if (crtc_hdisplay % intel_dp->psr.su_w_granularity)
|
||||
+ if (crtc_hdisplay % w_granularity)
|
||||
return false;
|
||||
|
||||
if (crtc_vdisplay % intel_dp->psr.su_y_granularity)
|
||||
+182
-44
@@ -1,21 +1,194 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Gaggery Tsai <gaggery.tsai@intel.com>
|
||||
Date: Thu, 10 Apr 2026 10:00:00 -0700
|
||||
Subject: [PATCH] drm/i915: send TRANS_PUSH Frame Change for Panel Replay cursor updates
|
||||
Date: Tue, 28 Apr 2026 16:10:00 -0500
|
||||
Subject: [PATCH] drm/i915: use TRANS_PUSH frame changes for PSR/Panel Replay
|
||||
|
||||
Panel Replay Selective Update requires a software-triggered Frame
|
||||
Change event via TRANS_PUSH to send dirty regions to the panel.
|
||||
Cursor updates (legacy_cursor_update) skip TRANS_PUSH_SEND, so the
|
||||
panel never receives cursor position changes under Panel Replay SU.
|
||||
Panel Replay Selective Update requires a software-triggered Frame Change
|
||||
event via TRANS_PUSH to send dirty regions to the panel. Cursor updates
|
||||
can skip the normal VRR push path, so the panel may not receive cursor
|
||||
position changes under Panel Replay SU.
|
||||
|
||||
Fix by sending TRANS_PUSH with LNL_TRANS_PUSH_PSR_PR_EN for cursor
|
||||
updates when Panel Replay is active.
|
||||
Backport the upstream TRANS_PUSH frame-change flow for display 20+:
|
||||
program the PSR/PR frame-change bit when PSR is enabled, skip the old
|
||||
CURSURFLIVE frame-change path on platforms using TRANS_PUSH, and send a
|
||||
push for legacy cursor updates when PSR/Panel Replay uses TRANS_PUSH.
|
||||
|
||||
Signed-off-by: Gaggery Tsai <gaggery.tsai@intel.com>
|
||||
---
|
||||
drivers/gpu/drm/i915/display/intel_crtc.c | 4 +++-
|
||||
drivers/gpu/drm/i915/display/intel_display_device.h | 1 +
|
||||
drivers/gpu/drm/i915/display/intel_psr.c | 20 +++++++++++++++++---
|
||||
drivers/gpu/drm/i915/display/intel_psr.h | 1 +
|
||||
drivers/gpu/drm/i915/display/intel_vrr.c | 35 +++++++++++++++++++++++++++++------
|
||||
drivers/gpu/drm/i915/display/intel_vrr.h | 1 +
|
||||
drivers/gpu/drm/i915/display/intel_vrr_regs.h | 1 +
|
||||
7 files changed, 53 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
|
||||
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
|
||||
@@ -747,7 +747,9 @@ void intel_pipe_update_end(struct intel_atomic_state *state,
|
||||
* push to affect the next frame instead of the current frame,
|
||||
* which would cause the next frame to terminate already at vmin
|
||||
* vblank start instead of vmax vblank start.
|
||||
*/
|
||||
- if (!state->base.legacy_cursor_update)
|
||||
+ if (!state->base.legacy_cursor_update ||
|
||||
+ (intel_psr_use_trans_push(new_crtc_state) &&
|
||||
+ !new_crtc_state->vrr.enable))
|
||||
intel_vrr_send_push(NULL, new_crtc_state);
|
||||
|
||||
local_irq_enable();
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h
|
||||
--- a/drivers/gpu/drm/i915/display/intel_display_device.h
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_display_device.h
|
||||
@@ -186,6 +186,7 @@ struct intel_display_platforms {
|
||||
#define HAS_PSR(__display) (DISPLAY_INFO(__display)->has_psr)
|
||||
#define HAS_PSR_HW_TRACKING(__display) (DISPLAY_INFO(__display)->has_psr_hw_tracking)
|
||||
#define HAS_PSR2_SEL_FETCH(__display) (DISPLAY_VER(__display) >= 12)
|
||||
+#define HAS_PSR_TRANS_PUSH_FRAME_CHANGE(__display) (DISPLAY_VER(__display) >= 20)
|
||||
#define HAS_SAGV(__display) (DISPLAY_VER(__display) >= 9 && \
|
||||
!(__display)->platform.broxton && !(__display)->platform.geminilake)
|
||||
#define HAS_TRANSCODER(__display, trans) ((DISPLAY_RUNTIME_INFO(__display)->cpu_transcoder_mask & \
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
|
||||
--- a/drivers/gpu/drm/i915/display/intel_psr.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
|
||||
@@ -2130,5 +2130,8 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
|
||||
|
||||
intel_alpm_configure(intel_dp, crtc_state);
|
||||
+
|
||||
+ if (HAS_PSR_TRANS_PUSH_FRAME_CHANGE(display))
|
||||
+ intel_vrr_psr_frame_change_enable(crtc_state);
|
||||
}
|
||||
|
||||
static bool psr_interrupt_error_check(struct intel_dp *intel_dp)
|
||||
@@ -2522,10 +2525,12 @@ void intel_psr_trigger_frame_change_event(struct intel_dsb *dsb,
|
||||
const struct intel_crtc_state *crtc_state =
|
||||
intel_pre_commit_crtc_state(state, crtc);
|
||||
struct intel_display *display = to_intel_display(crtc);
|
||||
|
||||
- if (crtc_state->has_psr)
|
||||
- intel_de_write_dsb(display, dsb,
|
||||
- CURSURFLIVE(display, crtc->pipe), 0);
|
||||
+ if (!crtc_state->has_psr || intel_psr_use_trans_push(crtc_state))
|
||||
+ return;
|
||||
+
|
||||
+ intel_de_write_dsb(display, dsb,
|
||||
+ CURSURFLIVE(display, crtc->pipe), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4615,3 +4620,10 @@ int intel_psr_min_guardband(struct intel_crtc_state *crtc_state)
|
||||
|
||||
return psr_min_guardband;
|
||||
}
|
||||
+
|
||||
+bool intel_psr_use_trans_push(const struct intel_crtc_state *crtc_state)
|
||||
+{
|
||||
+ struct intel_display *display = to_intel_display(crtc_state);
|
||||
+
|
||||
+ return HAS_PSR_TRANS_PUSH_FRAME_CHANGE(display) && crtc_state->has_psr;
|
||||
+}
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_psr.h b/drivers/gpu/drm/i915/display/intel_psr.h
|
||||
--- a/drivers/gpu/drm/i915/display/intel_psr.h
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_psr.h
|
||||
@@ -80,5 +80,6 @@ bool intel_psr_needs_alpm_aux_less(struct intel_dp *intel_dp,
|
||||
void intel_psr_compute_config_late(struct intel_dp *intel_dp,
|
||||
struct intel_crtc_state *crtc_state);
|
||||
int intel_psr_min_guardband(struct intel_crtc_state *crtc_state);
|
||||
+bool intel_psr_use_trans_push(const struct intel_crtc_state *crtc_state);
|
||||
|
||||
#endif /* __INTEL_PSR_H__ */
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
|
||||
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
|
||||
@@ -688,21 +688,40 @@ intel_vrr_dcb_reset(const struct intel_crtc_state *old_crtc_state,
|
||||
intel_de_write(display, PIPEDMC_DCB_BALANCE_RESET(pipe), 0);
|
||||
}
|
||||
|
||||
+static u32 trans_vrr_push(const struct intel_crtc_state *crtc_state,
|
||||
+ bool send_push)
|
||||
+{
|
||||
+ struct intel_display *display = to_intel_display(crtc_state);
|
||||
+ u32 trans_vrr_push = 0;
|
||||
+
|
||||
+ if (intel_vrr_always_use_vrr_tg(display) ||
|
||||
+ crtc_state->vrr.enable)
|
||||
+ trans_vrr_push |= TRANS_PUSH_EN;
|
||||
+
|
||||
+ if (send_push)
|
||||
+ trans_vrr_push |= TRANS_PUSH_SEND;
|
||||
+
|
||||
+ if (HAS_PSR_TRANS_PUSH_FRAME_CHANGE(display))
|
||||
+ trans_vrr_push |= LNL_TRANS_PUSH_PSR_PR_EN;
|
||||
+
|
||||
+ return trans_vrr_push;
|
||||
+}
|
||||
+
|
||||
void intel_vrr_send_push(struct intel_dsb *dsb,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc_state);
|
||||
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
|
||||
|
||||
- if (!crtc_state->vrr.enable)
|
||||
+ if (!crtc_state->vrr.enable && !intel_psr_use_trans_push(crtc_state))
|
||||
return;
|
||||
|
||||
if (dsb)
|
||||
intel_dsb_nonpost_start(dsb);
|
||||
|
||||
intel_de_write_dsb(display, dsb,
|
||||
TRANS_PUSH(display, cpu_transcoder),
|
||||
- TRANS_PUSH_EN | TRANS_PUSH_SEND);
|
||||
+ trans_vrr_push(crtc_state, true));
|
||||
|
||||
if (dsb)
|
||||
intel_dsb_nonpost_end(dsb);
|
||||
@@ -888,7 +907,8 @@ static void intel_vrr_tg_enable(const struct intel_crtc_state *crtc_state,
|
||||
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
|
||||
u32 vrr_ctl;
|
||||
|
||||
- intel_de_write(display, TRANS_PUSH(display, cpu_transcoder), TRANS_PUSH_EN);
|
||||
+ intel_de_write(display, TRANS_PUSH(display, cpu_transcoder),
|
||||
+ trans_vrr_push(crtc_state, false));
|
||||
|
||||
vrr_ctl = VRR_CTL_VRR_ENABLE | trans_vrr_ctl(crtc_state);
|
||||
|
||||
@@ -919,1 +939,2 @@ static void intel_vrr_tg_disable(const struct intel_crtc_state *old_crtc_state)
|
||||
- intel_de_write(display, TRANS_PUSH(display, cpu_transcoder), 0);
|
||||
+ intel_de_rmw(display, TRANS_PUSH(display, cpu_transcoder),
|
||||
+ TRANS_PUSH_EN, 0);
|
||||
@@ -970,6 +991,15 @@ void intel_vrr_transcoder_disable(const struct intel_crtc_state *old_crtc_state)
|
||||
intel_vrr_tg_disable(old_crtc_state);
|
||||
}
|
||||
|
||||
+void intel_vrr_psr_frame_change_enable(const struct intel_crtc_state *crtc_state)
|
||||
+{
|
||||
+ struct intel_display *display = to_intel_display(crtc_state);
|
||||
+ enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
|
||||
+
|
||||
+ intel_de_write(display, TRANS_PUSH(display, cpu_transcoder),
|
||||
+ trans_vrr_push(crtc_state, false));
|
||||
+}
|
||||
+
|
||||
bool intel_vrr_is_fixed_rr(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
return crtc_state->vrr.flipline &&
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.h b/drivers/gpu/drm/i915/display/intel_vrr.h
|
||||
--- a/drivers/gpu/drm/i915/display/intel_vrr.h
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_vrr.h
|
||||
@@ -30,5 +30,6 @@ void intel_vrr_dcb_increment_flip_count(struct intel_crtc_state *crtc_state,
|
||||
bool intel_vrr_is_push_sent(const struct intel_crtc_state *crtc_state);
|
||||
void intel_vrr_disable(const struct intel_crtc_state *old_crtc_state);
|
||||
+void intel_vrr_psr_frame_change_enable(const struct intel_crtc_state *crtc_state);
|
||||
void intel_vrr_get_config(struct intel_crtc_state *crtc_state);
|
||||
int intel_vrr_vmax_vtotal(const struct intel_crtc_state *crtc_state);
|
||||
int intel_vrr_vmin_vtotal(const struct intel_crtc_state *crtc_state);
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_vrr_regs.h b/drivers/gpu/drm/i915/display/intel_vrr_regs.h
|
||||
--- a/drivers/gpu/drm/i915/display/intel_vrr_regs.h
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_vrr_regs.h
|
||||
@@ -97,6 +97,7 @@
|
||||
@@ -163,6 +163,7 @@
|
||||
#define TRANS_PUSH(display, trans) _MMIO_TRANS2((display), (trans), _TRANS_PUSH_A)
|
||||
#define TRANS_PUSH_EN REG_BIT(31)
|
||||
#define TRANS_PUSH_SEND REG_BIT(30)
|
||||
@@ -23,38 +196,3 @@ diff --git a/drivers/gpu/drm/i915/display/intel_vrr_regs.h b/drivers/gpu/drm/i91
|
||||
|
||||
#define _TRANS_VRR_VSYNC_A 0x60078
|
||||
#define TRANS_VRR_VSYNC(display, trans) _MMIO_TRANS2((display), (trans), _TRANS_VRR_VSYNC_A)
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
|
||||
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
|
||||
@@ -732,7 +732,8 @@
|
||||
* which would cause the next frame to terminate already at vmin
|
||||
* vblank start instead of vmax vblank start.
|
||||
*/
|
||||
- if (!state->base.legacy_cursor_update)
|
||||
+ if (!state->base.legacy_cursor_update ||
|
||||
+ new_crtc_state->has_panel_replay)
|
||||
intel_vrr_send_push(NULL, new_crtc_state);
|
||||
|
||||
local_irq_enable();
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
|
||||
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
|
||||
@@ -597,7 +597,7 @@
|
||||
struct intel_display *display = to_intel_display(crtc_state);
|
||||
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
|
||||
|
||||
- if (!crtc_state->vrr.enable)
|
||||
+ if (!crtc_state->vrr.enable && !crtc_state->has_panel_replay)
|
||||
return;
|
||||
|
||||
if (dsb)
|
||||
@@ -605,7 +605,8 @@
|
||||
|
||||
intel_de_write_dsb(display, dsb,
|
||||
TRANS_PUSH(display, cpu_transcoder),
|
||||
- TRANS_PUSH_EN | TRANS_PUSH_SEND);
|
||||
+ TRANS_PUSH_EN | TRANS_PUSH_SEND |
|
||||
+ (crtc_state->has_panel_replay ? LNL_TRANS_PUSH_PSR_PR_EN : 0));
|
||||
|
||||
if (dsb)
|
||||
intel_dsb_nonpost_end(dsb);
|
||||
|
||||
@@ -61,19 +61,19 @@ Signed-off-by: Gaggery Tsai <gaggery.tsai@intel.com>
|
||||
enum fb_op_origin origin);
|
||||
--- a/drivers/gpu/drm/i915/display/intel_psr.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
|
||||
@@ -1217,6 +1217,8 @@ static void tgl_psr2_enable_dc3co(struct intel_dp *intel_dp)
|
||||
@@ -1189,6 +1189,8 @@ static void tgl_psr2_disable_dc3co(struct intel_dp *intel_dp)
|
||||
intel_display_power_set_target_dc_state(display, DC_STATE_EN_UPTO_DC6);
|
||||
psr2_program_idle_frames(intel_dp, psr_compute_idle_frames(intel_dp));
|
||||
}
|
||||
|
||||
+static void intel_psr_activate(struct intel_dp *intel_dp);
|
||||
+
|
||||
+static void intel_psr_activate(struct intel_dp *intel_dp);
|
||||
|
||||
static void tgl_dc3co_disable_work(struct work_struct *work)
|
||||
{
|
||||
struct intel_dp *intel_dp =
|
||||
@@ -1227,6 +1229,13 @@ static void tgl_dc3co_disable_work(struct work_struct *work)
|
||||
@@ -1203,6 +1205,13 @@ static void tgl_dc3co_disable_work(struct work_struct *work)
|
||||
if (delayed_work_pending(&intel_dp->psr.dc3co_work))
|
||||
goto unlock;
|
||||
|
||||
|
||||
+ /* Panel Replay ALPM cursor-lag workaround re-activation path. */
|
||||
+ if (intel_dp->psr.panel_replay_enabled &&
|
||||
+ intel_dp->psr.enabled && !intel_dp->psr.active) {
|
||||
@@ -84,7 +84,7 @@ Signed-off-by: Gaggery Tsai <gaggery.tsai@intel.com>
|
||||
tgl_psr2_disable_dc3co(intel_dp);
|
||||
unlock:
|
||||
mutex_unlock(&intel_dp->psr.lock);
|
||||
@@ -4593,2 +4593,29 @@ u8 intel_psr_needed_vblank_count_for_frontbuffer_flush(struct intel_display *dis
|
||||
@@ -4615,2 +4624,29 @@ int intel_psr_min_guardband(struct intel_crtc_state *crtc_state)
|
||||
return psr_min_guardband;
|
||||
}
|
||||
+
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
# Based on Arch Linux linux package by Jan Alexander Steffens (heftig)
|
||||
|
||||
pkgbase=linux-ptl
|
||||
pkgver=6.19.14.arch1
|
||||
pkgver=7.0.2.arch1
|
||||
pkgrel=1
|
||||
pkgdesc='Linux with Panther Lake hardware backports (SDCA audio, WiFi 7, PSR2, Panel Replay SU)'
|
||||
pkgdesc='Linux with Panther Lake hardware backports (SDCA audio, PSR2, Panel Replay SU)'
|
||||
url='https://github.com/archlinux/linux'
|
||||
arch=(
|
||||
x86_64
|
||||
@@ -30,21 +30,10 @@ _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
|
||||
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
|
||||
0019-drm-i915-psr-accept-early-transport-for-psr2.patch
|
||||
0020-drm-i915-psr-fix-su-granularity-source-for-psr2.patch
|
||||
0020-drm-i915-alpm-limit-pr-alpm-to-panel-replay.patch
|
||||
0022-drm-i915-psr-allow-psr-with-vrr-on-ptl.patch
|
||||
0026-drm-i915-psr-handle-Panel-Replay-full-line-SU-granul.patch
|
||||
0027-drm-i915-trans-push-frame-change-for-panel-replay.patch
|
||||
0028-drm-i915-psr-exit-Panel-Replay-for-ALPM-lag.patch
|
||||
0029-drm-edid-populate-monitor-range-from-displayid-adaptive-sync.patch
|
||||
@@ -55,23 +44,19 @@ validpgpkeys=(
|
||||
647F28654894E3BD457199BE38DBBDC86092693E # Greg Kroah-Hartman
|
||||
83BC8889351B5DEBBB68416EB8AC08600F108CDF # Jan Alexander Steffens (heftig)
|
||||
)
|
||||
b2sums=('64c2a0003d8080f268772d36923ff6ef8b2d55320ea08b77ad39384c98c9a5c1a8e71425470619aa3aa4dda8941f46aa9da364748cfa8fd9f8507a5ddd7ac03a'
|
||||
b2sums=('SKIP'
|
||||
'SKIP'
|
||||
'6536f9ccb408f89b0a6dc86fdbb09f4229e9e4ea5ed210d118484a18ca8a82a1e1060114877ce7286b721d59587a8a70b5ed4616c4ec4925b0bdf5b25227e6fe'
|
||||
'SKIP'
|
||||
'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP'
|
||||
'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP'
|
||||
'SKIP' 'SKIP')
|
||||
'SKIP'
|
||||
'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP')
|
||||
b2sums_x86_64=('9742088ab0381d8196046e42e8acb4ce01ea77461fada77dc90d197e859631e73b06ead4d512f15ab619b33ebad7bca58a10d4506d66916a99c40f9f52708a53')
|
||||
|
||||
# https://www.kernel.org/pub/linux/kernel/v6.x/sha256sums.asc
|
||||
sha256sums=('cde8bf6739be4a0777fedbbba5330b8188c55680c45a922a4dfa289cbec6f185'
|
||||
# https://www.kernel.org/pub/linux/kernel/v7.x/sha256sums.asc
|
||||
sha256sums=('53591a03294527a48ccb0b9e559e922df8a38554745a1206827ca751d2ca7662'
|
||||
'SKIP'
|
||||
'2ae741a9e5009d21e1bbbb7a9abeebcc39ec5cdb7cf4cdf52d616a57d262de96'
|
||||
'SKIP'
|
||||
'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP'
|
||||
'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP'
|
||||
'SKIP' 'SKIP')
|
||||
'SKIP'
|
||||
'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP')
|
||||
|
||||
export KBUILD_BUILD_HOST=archlinux
|
||||
export KBUILD_BUILD_USER=$pkgbase
|
||||
|
||||
Reference in New Issue
Block a user