On Thu, Jul 25, 2019 at 06:40:19PM -0500, Pierre-Louis Bossart wrote:
This algorithm computes bus parameters like clock frequency, frame shape and port transport parameters based on active stream(s) running on the bus.
This implementation is optimal for Intel platforms. Developers can also implement their own .compute_params() callback for specific resource management algorithm.
Credits: this patch is based on an earlier internal contribution by Vinod Koul, Sanyog Kale, Shreyas Nc and Hardik Shah. All hard-coded values were removed from the initial contribution to use BIOS information instead.
FIXME: remove checkpatch report WARNING: Reusing the krealloc arg is almost always a bug
group->rates = krealloc(group->rates,
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
drivers/soundwire/Makefile | 2 +- drivers/soundwire/algo_dynamic_allocation.c | 403 ++++++++++++++++++++ drivers/soundwire/bus.c | 3 + drivers/soundwire/bus.h | 46 ++- drivers/soundwire/stream.c | 20 + include/linux/soundwire/sdw.h | 5 + 6 files changed, 476 insertions(+), 3 deletions(-) create mode 100644 drivers/soundwire/algo_dynamic_allocation.c
diff --git a/drivers/soundwire/Makefile b/drivers/soundwire/Makefile index 88990cac48a7..f59a9d4a28fd 100644 --- a/drivers/soundwire/Makefile +++ b/drivers/soundwire/Makefile @@ -5,7 +5,7 @@
#Bus Objs soundwire-bus-objs := bus_type.o bus.o slave.o mipi_disco.o stream.o \
debugfs.o
debugfs.o algo_dynamic_allocation.o
obj-$(CONFIG_SOUNDWIRE_BUS) += soundwire-bus.o
diff --git a/drivers/soundwire/algo_dynamic_allocation.c b/drivers/soundwire/algo_dynamic_allocation.c new file mode 100644 index 000000000000..89edb39162b8 --- /dev/null +++ b/drivers/soundwire/algo_dynamic_allocation.c @@ -0,0 +1,403 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// Copyright(c) 2015-18 Intel Corporation.
+/*
- Bandwidth management algorithm based on 2^n gears
- */
+#include <linux/device.h> +#include <linux/mod_devicetable.h> +#include <linux/slab.h> +#include <linux/soundwire/sdw.h> +#include "bus.h"
+#define SDW_STRM_RATE_GROUPING 1
+struct sdw_group_params {
- unsigned int rate;
- int full_bw;
- int payload_bw;
- int hwidth;
+};
+struct sdw_group {
- unsigned int count;
- unsigned int max_size;
- unsigned int *rates;
+};
+struct sdw_transport_data {
- int hstart;
- int hstop;
- int block_offset;
- int sub_block_offset;
+};
+/**
- sdw_compute_port_params: Compute transport and port parameters
- @bus: SDW Bus instance
- */
+static int sdw_compute_port_params(struct sdw_bus *bus) +{
- struct sdw_group_params *params = NULL;
- struct sdw_group group;
- int ret;
- ret = sdw_get_group_count(bus, &group);
- if (ret < 0)
goto out;
- if (group.count == 0)
goto out;
- params = kcalloc(group.count, sizeof(*params), GFP_KERNEL);
- if (!params) {
ret = -ENOMEM;
goto out;
- }
- /* Compute transport parameters for grouped streams */
- ret = sdw_compute_group_params(bus, params,
&group.rates[0], group.count);
- if (ret < 0)
goto out;
- _sdw_compute_port_params(bus, params, group.count);
+out:
- kfree(params);
- kfree(group.rates);
- return ret;
+}
+static int sdw_select_row_col(struct sdw_bus *bus, int clk_freq) +{
- struct sdw_master_prop *prop = &bus->prop;
- int frame_int, frame_freq;
- int r, c;
- for (c = 0; c < SDW_FRAME_COLS; c++) {
for (r = 0; r < SDW_FRAME_ROWS; r++) {
if (sdw_rows[r] != prop->default_row ||
sdw_cols[c] != prop->default_col)
continue;
Are we only supporting default rows and cols?
frame_int = sdw_rows[r] * sdw_cols[c];
frame_freq = clk_freq / frame_int;
if ((clk_freq - (frame_freq * SDW_FRAME_CTRL_BITS)) <
bus->params.bandwidth)
continue;
bus->params.row = sdw_rows[r];
bus->params.col = sdw_cols[c];
return 0;
}
- }
- return -EINVAL;
+}
-- 2.20.1
--