Commit 645291cf authored by Bard Liao's avatar Bard Liao Committed by Vinod Koul
Browse files

Soundwire: stream: program BUSCLOCK_SCALE



We need to program bus clock scale to adjust the bus clock if current
bus clock doesn't fit the bandwidth.

Signed-off-by: default avatarBard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Link: https://lore.kernel.org/r/20241218080155.102405-8-yung-chuan.liao@linux.intel.com


Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent 8f4e3343
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -813,6 +813,16 @@ void sdw_extract_slave_id(struct sdw_bus *bus,
}
EXPORT_SYMBOL(sdw_extract_slave_id);

bool is_clock_scaling_supported_by_slave(struct sdw_slave *slave)
{
	/*
	 * Dynamic scaling is a defined by SDCA. However, some devices expose the class ID but
	 * can't support dynamic scaling. We might need a quirk to handle such devices.
	 */
	return slave->id.class_id;
}
EXPORT_SYMBOL(is_clock_scaling_supported_by_slave);

static int sdw_program_device_num(struct sdw_bus *bus, bool *programmed)
{
	u8 buf[SDW_NUM_DEV_ID_REGISTERS] = {0};
+36 −0
Original line number Diff line number Diff line
@@ -629,8 +629,44 @@ static int sdw_notify_config(struct sdw_master_runtime *m_rt)
static int sdw_program_params(struct sdw_bus *bus, bool prepare)
{
	struct sdw_master_runtime *m_rt;
	struct sdw_slave *slave;
	int ret = 0;
	u32 addr1;

	/* Check if all Peripherals comply with SDCA */
	list_for_each_entry(slave, &bus->slaves, node) {
		if (!slave->dev_num_sticky)
			continue;
		if (!is_clock_scaling_supported_by_slave(slave)) {
			dev_dbg(&slave->dev, "The Peripheral doesn't comply with SDCA\n");
			goto manager_runtime;
		}
	}

	if (bus->params.next_bank)
		addr1 = SDW_SCP_BUSCLOCK_SCALE_B1;
	else
		addr1 = SDW_SCP_BUSCLOCK_SCALE_B0;

	/* Program SDW_SCP_BUSCLOCK_SCALE if all Peripherals comply with SDCA */
	list_for_each_entry(slave, &bus->slaves, node) {
		int scale_index;
		u8 base;

		if (!slave->dev_num_sticky)
			continue;
		scale_index = sdw_slave_get_scale_index(slave, &base);
		if (scale_index < 0)
			return scale_index;

		ret = sdw_write_no_pm(slave, addr1, scale_index);
		if (ret < 0) {
			dev_err(&slave->dev, "SDW_SCP_BUSCLOCK_SCALE register write failed\n");
			return ret;
		}
	}

manager_runtime:
	list_for_each_entry(m_rt, &bus->m_rt_list, bus_node) {

		/*
+1 −0
Original line number Diff line number Diff line
@@ -1041,6 +1041,7 @@ int sdw_bus_exit_clk_stop(struct sdw_bus *bus);

int sdw_compare_devid(struct sdw_slave *slave, struct sdw_slave_id id);
void sdw_extract_slave_id(struct sdw_bus *bus, u64 addr, struct sdw_slave_id *id);
bool is_clock_scaling_supported_by_slave(struct sdw_slave *slave);

#if IS_ENABLED(CONFIG_SOUNDWIRE)