ASoC: SDCA: add class_ops with populate_function

Add struct sdca_class_ops with a populate_function callback that lets
codec drivers supply the SDCA topology (entities, clusters,
init_table, ...) from static tables in place of sdca_parse_function()
on DT/non-DisCo platforms.  The callback is a pure data source and
performs no bus I/O.

Codec drivers embed sdca_class_drv in their own priv and register
their populate_function through class_ops passed to
sdca_class_probe().

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Link: https://patch.msgid.link/20260925161049.758913-5-srinivas.kandagatla@oss.qualcomm.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Srinivas Kandagatla 2026-09-25 17:10:45 +01:00 committed by Mark Brown
parent a60f1ac41f
commit 3273ec3e14
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
3 changed files with 33 additions and 4 deletions

View File

@ -19,6 +19,19 @@ struct regmap;
struct sdw_slave;
struct sdca_function_data;
/**
* struct sdca_class_ops - optional codec-provided class callbacks
* @populate_function: fill @function (entities, clusters, init_table, ...)
* from static tables in place of sdca_parse_function() on
* DT/non-DisCo platforms. Called once per SDCA function with
* @dev pointing at that function's device. Pure data source;
* performs no bus I/O. Return 0 on success or a negative errno.
*/
struct sdca_class_ops {
int (*populate_function)(struct device *dev,
struct sdca_function_data *function);
};
struct sdca_class_drv {
struct device *dev;
struct regmap *dev_regmap;
@ -26,6 +39,8 @@ struct sdca_class_drv {
struct sdca_interrupt_info *irq_info;
const struct sdca_class_ops *ops;
struct mutex regmap_lock;
/* Serialise function initialisations */
struct mutex init_lock;
@ -33,7 +48,9 @@ struct sdca_class_drv {
};
/* Library helpers used by codec-specific SDCA SoundWire drivers. */
int sdca_class_probe(struct sdw_slave *sdw, struct sdca_class_drv *drv);
int sdca_class_probe(struct sdw_slave *sdw,
struct sdca_class_drv *drv,
const struct sdca_class_ops *ops);
void sdca_class_remove(struct sdca_class_drv *drv);
/*

View File

@ -144,6 +144,8 @@ static void class_boot_work(struct work_struct *work)
* allocation and sets its own dev_set_drvdata() -- the framework
* does not touch drvdata. Typically embedded in the codec's own
* priv struct so codec drivers can keep per-slave state.
* @ops: optional codec-provided class callbacks (may be NULL for
* pure-generic SDCA parts that need no quirks)
*
* Codec-specific SoundWire drivers call this from their .probe after
* allocating a struct sdca_class_drv (usually embedded in their own
@ -151,7 +153,9 @@ static void class_boot_work(struct work_struct *work)
* sdca_class_drv fields, sets up the class regmap, and queues the
* deferred boot work.
*/
int sdca_class_probe(struct sdw_slave *sdw, struct sdca_class_drv *drv)
int sdca_class_probe(struct sdw_slave *sdw,
struct sdca_class_drv *drv,
const struct sdca_class_ops *ops)
{
struct device *dev = &sdw->dev;
struct regmap_config *dev_config;
@ -169,6 +173,7 @@ int sdca_class_probe(struct sdw_slave *sdw, struct sdca_class_drv *drv)
drv->dev = dev;
drv->sdw = sdw;
drv->ops = ops;
mutex_init(&drv->regmap_lock);
mutex_init(&drv->init_lock);
@ -213,7 +218,7 @@ static int class_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *id
dev_set_drvdata(&sdw->dev, drv);
return sdca_class_probe(sdw, drv);
return sdca_class_probe(sdw, drv, NULL);
}
/**

View File

@ -329,7 +329,14 @@ static int class_function_probe(struct auxiliary_device *auxdev,
drv->core = core;
drv->function = &sdev->function;
ret = sdca_parse_function(dev, drv->function);
if (core->ops && core->ops->populate_function) {
ret = core->ops->populate_function(dev, drv->function);
} else if (drv->function->desc->node) {
ret = sdca_parse_function(dev, drv->function);
} else {
dev_err(dev, "no firmware node and no populate_function hook\n");
return -ENOENT;
}
if (ret)
return ret;