Merge tag 'soundwire-6.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire

Pull soundwire updates from Vinod Koul:

 - SoundWire multi lane support to use multiple lanes if supported

 - Stream handling of DEPREPARED state

 - AMD wake register programming for power off mode

* tag 'soundwire-6.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire:
  soundwire: amd: clear wake enable register for power off mode
  soundwire: generic_bandwidth_allocation: count the bandwidth of active streams only
  SoundWire: pass stream to compute_params()
  soundwire: generic_bandwidth_allocation: add lane in sdw_group_params
  soundwire: generic_bandwidth_allocation: select data lane
  soundwire: generic_bandwidth_allocation: check required freq accurately
  soundwire: generic_bandwidth_allocation: correct clk_freq check in sdw_select_row_col
  Soundwire: generic_bandwidth_allocation: set frame shape on fly
  Soundwire: stream: program BUSCLOCK_SCALE
  Soundwire: add sdw_slave_get_scale_index helper
  soundwire: generic_bandwidth_allocation: skip DEPREPARED streams
  soundwire: stream: set DEPREPARED state earlier
  soundwire: add lane_used_bandwidth in struct sdw_bus
  soundwire: mipi_disco: read lane mapping properties from ACPI
  soundwire: add lane field in sdw_port_runtime
  soundwire: bus: Move irq mapping cleanup into devres
This commit is contained in:
Linus Torvalds
2025-01-29 14:38:19 -08:00
11 changed files with 513 additions and 163 deletions

View File

@@ -384,7 +384,7 @@ static u32 amd_sdw_read_ping_status(struct sdw_bus *bus)
return slave_stat;
}
static int amd_sdw_compute_params(struct sdw_bus *bus)
static int amd_sdw_compute_params(struct sdw_bus *bus, struct sdw_stream_runtime *stream)
{
struct sdw_transport_data t_data = {0};
struct sdw_master_runtime *m_rt;
@@ -410,7 +410,7 @@ static int amd_sdw_compute_params(struct sdw_bus *bus)
sdw_fill_xport_params(&p_rt->transport_params, p_rt->num,
false, SDW_BLK_GRP_CNT_1, sample_int,
port_bo, port_bo >> 8, hstart, hstop,
SDW_BLK_PKG_PER_PORT, 0x0);
SDW_BLK_PKG_PER_PORT, p_rt->lane);
sdw_fill_port_params(&p_rt->port_params,
p_rt->num, bps,
@@ -1190,6 +1190,7 @@ static int __maybe_unused amd_resume_runtime(struct device *dev)
if (amd_manager->power_mode_mask & AMD_SDW_CLK_STOP_MODE) {
return amd_sdw_clock_stop_exit(amd_manager);
} else if (amd_manager->power_mode_mask & AMD_SDW_POWER_OFF_MODE) {
writel(0x00, amd_manager->acp_mmio + ACP_SW_WAKE_EN(amd_manager->instance));
val = readl(amd_manager->mmio + ACP_SW_CLK_RESUME_CTRL);
if (val) {
val |= AMD_SDW_CLK_RESUME_REQ;

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};
@@ -1276,23 +1286,12 @@ int sdw_configure_dpn_intr(struct sdw_slave *slave,
return ret;
}
static int sdw_slave_set_frequency(struct sdw_slave *slave)
int sdw_slave_get_scale_index(struct sdw_slave *slave, u8 *base)
{
u32 mclk_freq = slave->bus->prop.mclk_freq;
u32 curr_freq = slave->bus->params.curr_dr_freq >> 1;
unsigned int scale;
u8 scale_index;
u8 base;
int ret;
/*
* frequency base and scale registers are required for SDCA
* devices. They may also be used for 1.2+/non-SDCA devices.
* Driver can set the property, we will need a DisCo property
* to discover this case from platform firmware.
*/
if (!slave->id.class_id && !slave->prop.clock_reg_supported)
return 0;
if (!mclk_freq) {
dev_err(&slave->dev,
@@ -1311,19 +1310,19 @@ static int sdw_slave_set_frequency(struct sdw_slave *slave)
*/
if (!(19200000 % mclk_freq)) {
mclk_freq = 19200000;
base = SDW_SCP_BASE_CLOCK_19200000_HZ;
*base = SDW_SCP_BASE_CLOCK_19200000_HZ;
} else if (!(22579200 % mclk_freq)) {
mclk_freq = 22579200;
base = SDW_SCP_BASE_CLOCK_22579200_HZ;
*base = SDW_SCP_BASE_CLOCK_22579200_HZ;
} else if (!(24576000 % mclk_freq)) {
mclk_freq = 24576000;
base = SDW_SCP_BASE_CLOCK_24576000_HZ;
*base = SDW_SCP_BASE_CLOCK_24576000_HZ;
} else if (!(32000000 % mclk_freq)) {
mclk_freq = 32000000;
base = SDW_SCP_BASE_CLOCK_32000000_HZ;
*base = SDW_SCP_BASE_CLOCK_32000000_HZ;
} else if (!(96000000 % mclk_freq)) {
mclk_freq = 24000000;
base = SDW_SCP_BASE_CLOCK_24000000_HZ;
*base = SDW_SCP_BASE_CLOCK_24000000_HZ;
} else {
dev_err(&slave->dev,
"Unsupported clock base, mclk %d\n",
@@ -1354,6 +1353,34 @@ static int sdw_slave_set_frequency(struct sdw_slave *slave)
}
scale_index++;
dev_dbg(&slave->dev,
"Configured bus base %d, scale %d, mclk %d, curr_freq %d\n",
*base, scale_index, mclk_freq, curr_freq);
return scale_index;
}
EXPORT_SYMBOL(sdw_slave_get_scale_index);
static int sdw_slave_set_frequency(struct sdw_slave *slave)
{
int scale_index;
u8 base;
int ret;
/*
* frequency base and scale registers are required for SDCA
* devices. They may also be used for 1.2+/non-SDCA devices.
* Driver can set the property directly, for now there's no
* DisCo property to discover support for the scaling registers
* from platform firmware.
*/
if (!slave->id.class_id && !slave->prop.clock_reg_supported)
return 0;
scale_index = sdw_slave_get_scale_index(slave, &base);
if (scale_index < 0)
return scale_index;
ret = sdw_write_no_pm(slave, SDW_SCP_BUS_CLOCK_BASE, base);
if (ret < 0) {
dev_err(&slave->dev,
@@ -1373,10 +1400,6 @@ static int sdw_slave_set_frequency(struct sdw_slave *slave)
dev_err(&slave->dev,
"SDW_SCP_BUSCLOCK_SCALE_B1 write failed:%d\n", ret);
dev_dbg(&slave->dev,
"Configured bus base %d, scale %d, mclk %d, curr_freq %d\n",
base, scale_index, mclk_freq, curr_freq);
return ret;
}

View File

@@ -90,6 +90,7 @@ int sdw_find_col_index(int col);
* @transport_params: Transport parameters
* @port_params: Port parameters
* @port_node: List node for Master or Slave port_list
* @lane: Which lane is used
*
* SoundWire spec has no mention of ports for Master interface but the
* concept is logically extended.
@@ -100,6 +101,7 @@ struct sdw_port_runtime {
struct sdw_transport_params transport_params;
struct sdw_port_params port_params;
struct list_head port_node;
unsigned int lane;
};
/**
@@ -149,6 +151,7 @@ struct sdw_transport_data {
int hstop;
int block_offset;
int sub_block_offset;
unsigned int lane;
};
struct sdw_dpn_prop *sdw_get_slave_dpn_prop(struct sdw_slave *slave,

View File

@@ -167,9 +167,6 @@ static int sdw_drv_remove(struct device *dev)
slave->probed = false;
if (slave->prop.use_domain_irq)
sdw_irq_dispose_mapping(slave);
mutex_unlock(&slave->sdw_dev_lock);
if (drv->remove)

File diff suppressed because it is too large Load Diff

View File

@@ -46,14 +46,18 @@ void sdw_irq_delete(struct sdw_bus *bus)
irq_domain_remove(bus->domain);
}
static void sdw_irq_dispose_mapping(void *data)
{
struct sdw_slave *slave = data;
irq_dispose_mapping(irq_find_mapping(slave->bus->domain, slave->dev_num));
}
void sdw_irq_create_mapping(struct sdw_slave *slave)
{
slave->irq = irq_create_mapping(slave->bus->domain, slave->dev_num);
if (!slave->irq)
dev_warn(&slave->dev, "Failed to map IRQ\n");
}
void sdw_irq_dispose_mapping(struct sdw_slave *slave)
{
irq_dispose_mapping(irq_find_mapping(slave->bus->domain, slave->dev_num));
devm_add_action_or_reset(&slave->dev, sdw_irq_dispose_mapping, slave);
}

View File

@@ -16,7 +16,6 @@ int sdw_irq_create(struct sdw_bus *bus,
struct fwnode_handle *fwnode);
void sdw_irq_delete(struct sdw_bus *bus);
void sdw_irq_create_mapping(struct sdw_slave *slave);
void sdw_irq_dispose_mapping(struct sdw_slave *slave);
#else /* CONFIG_IRQ_DOMAIN */
@@ -34,10 +33,6 @@ static inline void sdw_irq_create_mapping(struct sdw_slave *slave)
{
}
static inline void sdw_irq_dispose_mapping(struct sdw_slave *slave)
{
}
#endif /* CONFIG_IRQ_DOMAIN */
#endif /* __SDW_IRQ_H */

View File

@@ -366,6 +366,44 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave,
return 0;
}
/*
* In MIPI DisCo spec for SoundWire, lane mapping for a slave device is done with
* mipi-sdw-lane-x-mapping properties, where x is 1..7, and the values for those
* properties are mipi-sdw-manager-lane-x or mipi-sdw-peripheral-link-y, where x
* is an integer between 1 to 7 if the lane is connected to a manager lane, y is a
* character between A to E if the lane is connected to another peripheral lane.
*/
int sdw_slave_read_lane_mapping(struct sdw_slave *slave)
{
struct sdw_slave_prop *prop = &slave->prop;
struct device *dev = &slave->dev;
char prop_name[30];
const char *prop_val;
size_t len;
int ret, i;
u8 lane;
for (i = 0; i < SDW_MAX_LANES; i++) {
snprintf(prop_name, sizeof(prop_name), "mipi-sdw-lane-%d-mapping", i);
ret = device_property_read_string(dev, prop_name, &prop_val);
if (ret)
continue;
len = strlen(prop_val);
if (len < 1)
return -EINVAL;
/* The last character is enough to identify the connection */
ret = kstrtou8(&prop_val[len - 1], 10, &lane);
if (ret)
return ret;
if (in_range(lane, 1, SDW_MAX_LANES - 1))
prop->lane_maps[i] = lane;
}
return 0;
}
EXPORT_SYMBOL(sdw_slave_read_lane_mapping);
/**
* sdw_slave_read_prop() - Read Slave properties
* @slave: SDW Slave
@@ -486,6 +524,6 @@ int sdw_slave_read_prop(struct sdw_slave *slave)
sdw_slave_read_dpn(slave, prop->sink_dpn_prop, nval,
prop->sink_ports, "sink");
return 0;
return sdw_slave_read_lane_mapping(slave);
}
EXPORT_SYMBOL(sdw_slave_read_prop);

View File

@@ -1072,7 +1072,7 @@ static const struct sdw_master_ops qcom_swrm_ops = {
.pre_bank_switch = qcom_swrm_pre_bank_switch,
};
static int qcom_swrm_compute_params(struct sdw_bus *bus)
static int qcom_swrm_compute_params(struct sdw_bus *bus, struct sdw_stream_runtime *stream)
{
struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus);
struct sdw_master_runtime *m_rt;

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) {
/*
@@ -1383,7 +1419,7 @@ static int _sdw_prepare_stream(struct sdw_stream_runtime *stream,
/* Compute params */
if (bus->compute_params) {
ret = bus->compute_params(bus);
ret = bus->compute_params(bus, stream);
if (ret < 0) {
dev_err(bus->dev, "Compute params failed: %d\n",
ret);
@@ -1642,9 +1678,19 @@ EXPORT_SYMBOL(sdw_disable_stream);
static int _sdw_deprepare_stream(struct sdw_stream_runtime *stream)
{
struct sdw_master_runtime *m_rt;
struct sdw_port_runtime *p_rt;
unsigned int multi_lane_bandwidth;
unsigned int bandwidth;
struct sdw_bus *bus;
int state = stream->state;
int ret = 0;
/*
* first mark the state as DEPREPARED so that it is not taken into account
* for bit allocation
*/
stream->state = SDW_STREAM_DEPREPARED;
list_for_each_entry(m_rt, &stream->master_list, stream_node) {
bus = m_rt->bus;
/* De-prepare port(s) */
@@ -1652,19 +1698,34 @@ static int _sdw_deprepare_stream(struct sdw_stream_runtime *stream)
if (ret < 0) {
dev_err(bus->dev,
"De-prepare port(s) failed: %d\n", ret);
stream->state = state;
return ret;
}
multi_lane_bandwidth = 0;
list_for_each_entry(p_rt, &m_rt->port_list, port_node) {
if (!p_rt->lane)
continue;
bandwidth = m_rt->stream->params.rate * hweight32(p_rt->ch_mask) *
m_rt->stream->params.bps;
multi_lane_bandwidth += bandwidth;
bus->lane_used_bandwidth[p_rt->lane] -= bandwidth;
if (!bus->lane_used_bandwidth[p_rt->lane])
p_rt->lane = 0;
}
/* TODO: Update this during Device-Device support */
bus->params.bandwidth -= m_rt->stream->params.rate *
m_rt->ch_count * m_rt->stream->params.bps;
bandwidth = m_rt->stream->params.rate * m_rt->ch_count * m_rt->stream->params.bps;
bus->params.bandwidth -= bandwidth - multi_lane_bandwidth;
/* Compute params */
if (bus->compute_params) {
ret = bus->compute_params(bus);
ret = bus->compute_params(bus, stream);
if (ret < 0) {
dev_err(bus->dev, "Compute params failed: %d\n",
ret);
stream->state = state;
return ret;
}
}
@@ -1673,11 +1734,11 @@ static int _sdw_deprepare_stream(struct sdw_stream_runtime *stream)
ret = sdw_program_params(bus, false);
if (ret < 0) {
dev_err(bus->dev, "%s: Program params failed: %d\n", __func__, ret);
stream->state = state;
return ret;
}
}
stream->state = SDW_STREAM_DEPREPARED;
return do_bank_switch(stream);
}

View File

@@ -54,6 +54,8 @@ struct sdw_slave;
#define SDW_MAX_PORTS 15
#define SDW_VALID_PORT_RANGE(n) ((n) < SDW_MAX_PORTS && (n) >= 1)
#define SDW_MAX_LANES 8
enum {
SDW_PORT_DIRN_SINK = 0,
SDW_PORT_DIRN_SOURCE,
@@ -356,6 +358,7 @@ struct sdw_dpn_prop {
* and masks are supported
* @commit_register_supported: is PCP_Commit register supported
* @scp_int1_mask: SCP_INT1_MASK desired settings
* @lane_maps: Lane mapping for the slave, only valid if lane_control_support is set
* @clock_reg_supported: the Peripheral implements the clock base and scale
* registers introduced with the SoundWire 1.2 specification. SDCA devices
* do not need to set this boolean property as the registers are required.
@@ -385,6 +388,7 @@ struct sdw_slave_prop {
u32 sdca_interrupt_register_list;
u8 commit_register_supported;
u8 scp_int1_mask;
u8 lane_maps[SDW_MAX_LANES];
bool clock_reg_supported;
bool use_domain_irq;
};
@@ -450,6 +454,7 @@ struct sdw_master_prop {
int sdw_master_read_prop(struct sdw_bus *bus);
int sdw_slave_read_prop(struct sdw_slave *slave);
int sdw_slave_read_lane_mapping(struct sdw_slave *slave);
/*
* SDW Slave Structures and APIs
@@ -850,77 +855,6 @@ struct sdw_master_ops {
int dev_num);
};
/**
* struct sdw_bus - SoundWire bus
* @dev: Shortcut to &bus->md->dev to avoid changing the entire code.
* @md: Master device
* @bus_lock_key: bus lock key associated to @bus_lock
* @bus_lock: bus lock
* @slaves: list of Slaves on this bus
* @msg_lock_key: message lock key associated to @msg_lock
* @msg_lock: message lock
* @m_rt_list: List of Master instance of all stream(s) running on Bus. This
* is used to compute and program bus bandwidth, clock, frame shape,
* transport and port parameters
* @defer_msg: Defer message
* @params: Current bus parameters
* @stream_refcount: number of streams currently using this bus
* @ops: Master callback ops
* @port_ops: Master port callback ops
* @prop: Master properties
* @vendor_specific_prop: pointer to non-standard properties
* @hw_sync_min_links: Number of links used by a stream above which
* hardware-based synchronization is required. This value is only
* meaningful if multi_link is set. If set to 1, hardware-based
* synchronization will be used even if a stream only uses a single
* SoundWire segment.
* @controller_id: system-unique controller ID. If set to -1, the bus @id will be used.
* @link_id: Link id number, can be 0 to N, unique for each Controller
* @id: bus system-wide unique id
* @compute_params: points to Bus resource management implementation
* @assigned: Bitmap for Slave device numbers.
* Bit set implies used number, bit clear implies unused number.
* @clk_stop_timeout: Clock stop timeout computed
* @bank_switch_timeout: Bank switch timeout computed
* @domain: IRQ domain
* @irq_chip: IRQ chip
* @debugfs: Bus debugfs (optional)
* @multi_link: Store bus property that indicates if multi links
* are supported. This flag is populated by drivers after reading
* appropriate firmware (ACPI/DT).
*/
struct sdw_bus {
struct device *dev;
struct sdw_master_device *md;
struct lock_class_key bus_lock_key;
struct mutex bus_lock;
struct list_head slaves;
struct lock_class_key msg_lock_key;
struct mutex msg_lock;
struct list_head m_rt_list;
struct sdw_defer defer_msg;
struct sdw_bus_params params;
int stream_refcount;
const struct sdw_master_ops *ops;
const struct sdw_master_port_ops *port_ops;
struct sdw_master_prop prop;
void *vendor_specific_prop;
int hw_sync_min_links;
int controller_id;
unsigned int link_id;
int id;
int (*compute_params)(struct sdw_bus *bus);
DECLARE_BITMAP(assigned, SDW_MAX_DEVICES);
unsigned int clk_stop_timeout;
u32 bank_switch_timeout;
struct irq_chip irq_chip;
struct irq_domain *domain;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs;
#endif
bool multi_link;
};
int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent,
struct fwnode_handle *fwnode);
void sdw_bus_master_delete(struct sdw_bus *bus);
@@ -1010,10 +944,83 @@ struct sdw_stream_runtime {
struct list_head master_list;
};
/**
* struct sdw_bus - SoundWire bus
* @dev: Shortcut to &bus->md->dev to avoid changing the entire code.
* @md: Master device
* @bus_lock_key: bus lock key associated to @bus_lock
* @bus_lock: bus lock
* @slaves: list of Slaves on this bus
* @msg_lock_key: message lock key associated to @msg_lock
* @msg_lock: message lock
* @m_rt_list: List of Master instance of all stream(s) running on Bus. This
* is used to compute and program bus bandwidth, clock, frame shape,
* transport and port parameters
* @defer_msg: Defer message
* @params: Current bus parameters
* @stream_refcount: number of streams currently using this bus
* @ops: Master callback ops
* @port_ops: Master port callback ops
* @prop: Master properties
* @vendor_specific_prop: pointer to non-standard properties
* @hw_sync_min_links: Number of links used by a stream above which
* hardware-based synchronization is required. This value is only
* meaningful if multi_link is set. If set to 1, hardware-based
* synchronization will be used even if a stream only uses a single
* SoundWire segment.
* @controller_id: system-unique controller ID. If set to -1, the bus @id will be used.
* @link_id: Link id number, can be 0 to N, unique for each Controller
* @id: bus system-wide unique id
* @compute_params: points to Bus resource management implementation
* @assigned: Bitmap for Slave device numbers.
* Bit set implies used number, bit clear implies unused number.
* @clk_stop_timeout: Clock stop timeout computed
* @bank_switch_timeout: Bank switch timeout computed
* @domain: IRQ domain
* @irq_chip: IRQ chip
* @debugfs: Bus debugfs (optional)
* @multi_link: Store bus property that indicates if multi links
* are supported. This flag is populated by drivers after reading
* appropriate firmware (ACPI/DT).
* @lane_used_bandwidth: how much bandwidth in bits per second is used by each lane
*/
struct sdw_bus {
struct device *dev;
struct sdw_master_device *md;
struct lock_class_key bus_lock_key;
struct mutex bus_lock;
struct list_head slaves;
struct lock_class_key msg_lock_key;
struct mutex msg_lock;
struct list_head m_rt_list;
struct sdw_defer defer_msg;
struct sdw_bus_params params;
int stream_refcount;
const struct sdw_master_ops *ops;
const struct sdw_master_port_ops *port_ops;
struct sdw_master_prop prop;
void *vendor_specific_prop;
int hw_sync_min_links;
int controller_id;
unsigned int link_id;
int id;
int (*compute_params)(struct sdw_bus *bus, struct sdw_stream_runtime *stream);
DECLARE_BITMAP(assigned, SDW_MAX_DEVICES);
unsigned int clk_stop_timeout;
u32 bank_switch_timeout;
struct irq_chip irq_chip;
struct irq_domain *domain;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs;
#endif
bool multi_link;
unsigned int lane_used_bandwidth[SDW_MAX_LANES];
};
struct sdw_stream_runtime *sdw_alloc_stream(const char *stream_name);
void sdw_release_stream(struct sdw_stream_runtime *stream);
int sdw_compute_params(struct sdw_bus *bus);
int sdw_compute_params(struct sdw_bus *bus, struct sdw_stream_runtime *stream);
int sdw_stream_add_master(struct sdw_bus *bus,
struct sdw_stream_config *stream_config,
@@ -1034,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)
@@ -1045,6 +1053,8 @@ int sdw_stream_add_slave(struct sdw_slave *slave,
int sdw_stream_remove_slave(struct sdw_slave *slave,
struct sdw_stream_runtime *stream);
int sdw_slave_get_scale_index(struct sdw_slave *slave, u8 *base);
/* messaging and data APIs */
int sdw_read(struct sdw_slave *slave, u32 addr);
int sdw_write(struct sdw_slave *slave, u32 addr, u8 value);