mirror of
https://github.com/torvalds/linux.git
synced 2026-01-25 07:47:50 +00:00
ASoC: SDCA: Add parsing for Control range structures
DisCo/SDCA contains small buffers of data that hold ranges of valid values for the various SDCA Controls. Add support for parsing these from ACPI. Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev> Link: https://patch.msgid.link/20250205113801.3699902-7-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
committed by
Mark Brown
parent
42b144cb6a
commit
64fb5af1d1
@@ -612,6 +612,18 @@ enum sdca_access_layer {
|
||||
SDCA_ACCESS_LAYER_EXTENSION = 1 << 5,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sdca_control_range - SDCA Control range table
|
||||
* @cols: Number of columns in the range table.
|
||||
* @rows: Number of rows in the range table.
|
||||
* @data: Array of values contained in the range table.
|
||||
*/
|
||||
struct sdca_control_range {
|
||||
unsigned int cols;
|
||||
unsigned int rows;
|
||||
u32 *data;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sdca_control - information for one SDCA Control
|
||||
* @label: Name for the Control, from SDCA Specification v1.0, section 7.1.7.
|
||||
@@ -622,6 +634,7 @@ enum sdca_access_layer {
|
||||
* Control.
|
||||
* @cn_list: A bitmask showing the valid Control Numbers within this Control,
|
||||
* Control Numbers typically represent channels.
|
||||
* @range: Buffer describing valid range of values for the Control.
|
||||
* @mode: Access mode of the Control.
|
||||
* @layers: Bitmask of access layers of the Control.
|
||||
* @deferrable: Indicates if the access to the Control can be deferred.
|
||||
@@ -637,6 +650,7 @@ struct sdca_control {
|
||||
int interrupt_position;
|
||||
u64 cn_list;
|
||||
|
||||
struct sdca_control_range range;
|
||||
enum sdca_access_mode mode;
|
||||
u8 layers;
|
||||
|
||||
|
||||
@@ -603,6 +603,44 @@ static unsigned int find_sdca_control_bits(const struct sdca_entity *entity,
|
||||
}
|
||||
}
|
||||
|
||||
static int find_sdca_control_range(struct device *dev,
|
||||
struct fwnode_handle *control_node,
|
||||
struct sdca_control_range *range)
|
||||
{
|
||||
u8 *range_list;
|
||||
int num_range;
|
||||
u16 *limits;
|
||||
int i;
|
||||
|
||||
num_range = fwnode_property_count_u8(control_node, "mipi-sdca-control-range");
|
||||
if (!num_range || num_range == -EINVAL)
|
||||
return 0;
|
||||
else if (num_range < 0)
|
||||
return num_range;
|
||||
|
||||
range_list = devm_kcalloc(dev, num_range, sizeof(*range_list), GFP_KERNEL);
|
||||
if (!range_list)
|
||||
return -ENOMEM;
|
||||
|
||||
fwnode_property_read_u8_array(control_node, "mipi-sdca-control-range",
|
||||
range_list, num_range);
|
||||
|
||||
limits = (u16 *)range_list;
|
||||
|
||||
range->cols = le16_to_cpu(limits[0]);
|
||||
range->rows = le16_to_cpu(limits[1]);
|
||||
range->data = (u32 *)&limits[2];
|
||||
|
||||
num_range = (num_range - (2 * sizeof(*limits))) / sizeof(*range->data);
|
||||
if (num_range != range->cols * range->rows)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < num_range; i++)
|
||||
range->data[i] = le32_to_cpu(range->data[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Add support for -cn- properties, allowing different channels to have
|
||||
* different defaults etc.
|
||||
@@ -678,6 +716,13 @@ static int find_sdca_entity_control(struct device *dev, struct sdca_entity *enti
|
||||
break;
|
||||
}
|
||||
|
||||
ret = find_sdca_control_range(dev, control_node, &control->range);
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: control %#x: range missing: %d\n",
|
||||
entity->label, control->sel, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = fwnode_property_read_u64(control_node, "mipi-sdca-control-cn-list",
|
||||
&control->cn_list);
|
||||
if (ret == -EINVAL) {
|
||||
|
||||
Reference in New Issue
Block a user