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: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Link: https://lore.kernel.org/r/20241218080155.102405-8-yung-chuan.liao@linux.intel.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
Bard Liao 2024-12-18 16:01:48 +08:00 committed by Vinod Koul
parent 8f4e3343ed
commit 645291cfe5
3 changed files with 47 additions and 0 deletions

View file

@ -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};

View file

@ -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) {
/*

View file

@ -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)