Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 26 additions & 20 deletions drivers/soundwire/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -956,8 +956,22 @@ static void sdw_modify_slave_status(struct sdw_slave *slave,
mutex_unlock(&bus->bus_lock);
}

static enum sdw_clk_stop_mode sdw_get_clk_stop_mode(struct sdw_slave *slave)
{
struct device *dev = &slave->dev;
struct sdw_driver *drv = drv_to_sdw_driver(dev->driver);

/*
* Query for clock stop mode if Slave implements
* ops->get_clk_stop_mode, else read from property.
*/
if (drv->ops && drv->ops->get_clk_stop_mode)
return drv->ops->get_clk_stop_mode(slave);

return slave->prop.clk_stop_mode1 ? SDW_CLK_STOP_MODE1 : SDW_CLK_STOP_MODE0;
}

static int sdw_slave_clk_stop_callback(struct sdw_slave *slave,
enum sdw_clk_stop_mode mode,
enum sdw_clk_stop_type type)
{
int ret = 0;
Expand All @@ -969,7 +983,7 @@ static int sdw_slave_clk_stop_callback(struct sdw_slave *slave,
struct sdw_driver *drv = drv_to_sdw_driver(dev->driver);

if (drv->ops && drv->ops->clk_stop)
ret = drv->ops->clk_stop(slave, mode, type);
ret = drv->ops->clk_stop(slave, slave->clk_stop_mode, type);
}

mutex_unlock(&slave->sdw_dev_lock);
Expand All @@ -978,7 +992,6 @@ static int sdw_slave_clk_stop_callback(struct sdw_slave *slave,
}

static int sdw_slave_clk_stop_prepare(struct sdw_slave *slave,
enum sdw_clk_stop_mode mode,
bool prepare)
{
bool wake_en;
Expand All @@ -990,7 +1003,7 @@ static int sdw_slave_clk_stop_prepare(struct sdw_slave *slave,
if (prepare) {
val = SDW_SCP_SYSTEMCTRL_CLK_STP_PREP;

if (mode == SDW_CLK_STOP_MODE1)
if (slave->clk_stop_mode == SDW_CLK_STOP_MODE1)
val |= SDW_SCP_SYSTEMCTRL_CLK_STP_MODE1;

if (wake_en)
Expand Down Expand Up @@ -1078,9 +1091,9 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus)
/* Identify if Slave(s) are available on Bus */
is_slave = true;

ret = sdw_slave_clk_stop_callback(slave,
SDW_CLK_STOP_MODE0,
SDW_CLK_PRE_PREPARE);
slave->clk_stop_mode = sdw_get_clk_stop_mode(slave);

ret = sdw_slave_clk_stop_callback(slave, SDW_CLK_PRE_PREPARE);
if (ret < 0 && ret != -ENODATA) {
dev_err(&slave->dev, "clock stop pre-prepare cb failed:%d\n", ret);
return ret;
Expand All @@ -1090,9 +1103,7 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus)
if (!slave->prop.simple_clk_stop_capable) {
simple_clk_stop = false;

ret = sdw_slave_clk_stop_prepare(slave,
SDW_CLK_STOP_MODE0,
true);
ret = sdw_slave_clk_stop_prepare(slave, true);
if (ret < 0 && ret != -ENODATA) {
dev_err(&slave->dev, "clock stop prepare failed:%d\n", ret);
return ret;
Expand Down Expand Up @@ -1130,9 +1141,7 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus)
slave->status != SDW_SLAVE_ALERT)
continue;

ret = sdw_slave_clk_stop_callback(slave,
SDW_CLK_STOP_MODE0,
SDW_CLK_POST_PREPARE);
ret = sdw_slave_clk_stop_callback(slave, SDW_CLK_POST_PREPARE);

if (ret < 0 && ret != -ENODATA) {
dev_err(&slave->dev, "clock stop post-prepare cb failed:%d\n", ret);
Expand Down Expand Up @@ -1204,18 +1213,16 @@ int sdw_bus_exit_clk_stop(struct sdw_bus *bus)
/* Identify if Slave(s) are available on Bus */
is_slave = true;

ret = sdw_slave_clk_stop_callback(slave, SDW_CLK_STOP_MODE0,
SDW_CLK_PRE_DEPREPARE);
ret = sdw_slave_clk_stop_callback(slave, SDW_CLK_PRE_DEPREPARE);
if (ret < 0)
dev_warn(&slave->dev, "clock stop pre-deprepare cb failed:%d\n", ret);


/* Only de-prepare a Slave device if needed */
if (!slave->prop.simple_clk_stop_capable) {
simple_clk_stop = false;

ret = sdw_slave_clk_stop_prepare(slave, SDW_CLK_STOP_MODE0,
false);

ret = sdw_slave_clk_stop_prepare(slave, false);
if (ret < 0)
dev_warn(&slave->dev, "clock stop deprepare failed:%d\n", ret);
}
Expand Down Expand Up @@ -1243,8 +1250,7 @@ int sdw_bus_exit_clk_stop(struct sdw_bus *bus)
slave->status != SDW_SLAVE_ALERT)
continue;

ret = sdw_slave_clk_stop_callback(slave, SDW_CLK_STOP_MODE0,
SDW_CLK_POST_DEPREPARE);
ret = sdw_slave_clk_stop_callback(slave, SDW_CLK_POST_DEPREPARE);
if (ret < 0)
dev_warn(&slave->dev, "clock stop post-deprepare cb failed:%d\n", ret);
}
Expand Down
3 changes: 2 additions & 1 deletion drivers/soundwire/intel_auxdevice.c
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,8 @@ static int __maybe_unused intel_suspend(struct device *dev)
return 0;
}

ret = sdw_intel_stop_bus(sdw, false);
/* No need to keep the SoundWire clock active in system suspend */
ret = sdw_intel_stop_bus(sdw, true);
if (ret < 0) {
dev_err(dev, "%s: cannot stop bus: %d\n", __func__, ret);
return ret;
Expand Down
4 changes: 4 additions & 0 deletions include/linux/soundwire/sdw.h
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,7 @@ struct sdw_bus_params {
* @update_status: Update Slave status
* @bus_config: Update the bus config for Slave
* @port_prep: Prepare the port with parameters
* @get_clk_stop_mode: Get the clock stop mode of the Slave
* @clk_stop: handle imp-def sequences before and after prepare and de-prepare
*/
struct sdw_slave_ops {
Expand All @@ -624,6 +625,7 @@ struct sdw_slave_ops {
int (*port_prep)(struct sdw_slave *slave,
struct sdw_prepare_ch *prepare_ch,
enum sdw_port_prep_ops pre_ops);
enum sdw_clk_stop_mode (*get_clk_stop_mode)(struct sdw_slave *slave);
int (*clk_stop)(struct sdw_slave *slave,
enum sdw_clk_stop_mode mode,
enum sdw_clk_stop_type type);
Expand All @@ -642,6 +644,7 @@ struct sdw_slave_ops {
* @node: node for bus list
* @port_ready: Port ready completion flag for each Slave port
* @m_port_map: static Master port map for each Slave port
* @clk_stop_mode: The clock stop mode of the Slave
* @dev_num: Current Device Number, values can be 0 or dev_num_sticky
* @dev_num_sticky: one-time static Device Number assigned by Bus
* @probed: boolean tracking driver state
Expand Down Expand Up @@ -676,6 +679,7 @@ struct sdw_slave {
struct list_head node;
struct completion port_ready[SDW_MAX_PORTS];
unsigned int m_port_map[SDW_MAX_PORTS];
enum sdw_clk_stop_mode clk_stop_mode;
u16 dev_num;
u16 dev_num_sticky;
bool probed;
Expand Down
Loading