Skip to content

Commit 6de6e7b

Browse files
committed
soundwire: bus: add CLOCK_STOP_MODE1 support back
CLOCK_STOP_MODE1 is used when the Peripheral might have entered a deeper power-saving mode that does not retain state while the Clock is stopped. It is useful when the device is more power consumption sensitive. Add it back to allow the Peripheral use CLOCK_STOP_MODE1. Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
1 parent 65fd664 commit 6de6e7b

File tree

2 files changed

+41
-10
lines changed
  • drivers/soundwire
  • include/linux/soundwire

2 files changed

+41
-10
lines changed

drivers/soundwire/bus.c

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,28 @@ static void sdw_modify_slave_status(struct sdw_slave *slave,
956956
mutex_unlock(&bus->bus_lock);
957957
}
958958

959+
static enum sdw_clk_stop_mode sdw_get_clk_stop_mode(struct sdw_slave *slave)
960+
{
961+
struct device *dev = &slave->dev;
962+
struct sdw_driver *drv = drv_to_sdw_driver(dev->driver);
963+
enum sdw_clk_stop_mode mode;
964+
965+
/*
966+
* Query for clock stop mode if Slave implements
967+
* ops->get_clk_stop_mode, else read from property.
968+
*/
969+
if (drv->ops && drv->ops->get_clk_stop_mode) {
970+
mode = drv->ops->get_clk_stop_mode(slave);
971+
} else {
972+
if (slave->prop.clk_stop_mode1)
973+
mode = SDW_CLK_STOP_MODE1;
974+
else
975+
mode = SDW_CLK_STOP_MODE0;
976+
}
977+
978+
return mode;
979+
}
980+
959981
static int sdw_slave_clk_stop_callback(struct sdw_slave *slave,
960982
enum sdw_clk_stop_mode mode,
961983
enum sdw_clk_stop_type type)
@@ -1054,6 +1076,7 @@ static int sdw_bus_wait_for_clk_prep_deprep(struct sdw_bus *bus, u16 dev_num, bo
10541076
*/
10551077
int sdw_bus_prep_clk_stop(struct sdw_bus *bus)
10561078
{
1079+
enum sdw_clk_stop_mode mode;
10571080
bool simple_clk_stop = true;
10581081
struct sdw_slave *slave;
10591082
bool is_slave = false;
@@ -1078,8 +1101,10 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus)
10781101
/* Identify if Slave(s) are available on Bus */
10791102
is_slave = true;
10801103

1081-
ret = sdw_slave_clk_stop_callback(slave,
1082-
SDW_CLK_STOP_MODE0,
1104+
mode = sdw_get_clk_stop_mode(slave);
1105+
slave->curr_clk_stop_mode = mode;
1106+
1107+
ret = sdw_slave_clk_stop_callback(slave, mode,
10831108
SDW_CLK_PRE_PREPARE);
10841109
if (ret < 0 && ret != -ENODATA) {
10851110
dev_err(&slave->dev, "clock stop pre-prepare cb failed:%d\n", ret);
@@ -1091,8 +1116,7 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus)
10911116
simple_clk_stop = false;
10921117

10931118
ret = sdw_slave_clk_stop_prepare(slave,
1094-
SDW_CLK_STOP_MODE0,
1095-
true);
1119+
mode, true);
10961120
if (ret < 0 && ret != -ENODATA) {
10971121
dev_err(&slave->dev, "clock stop prepare failed:%d\n", ret);
10981122
return ret;
@@ -1129,9 +1153,9 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus)
11291153
if (slave->status != SDW_SLAVE_ATTACHED &&
11301154
slave->status != SDW_SLAVE_ALERT)
11311155
continue;
1156+
mode = slave->curr_clk_stop_mode;
11321157

1133-
ret = sdw_slave_clk_stop_callback(slave,
1134-
SDW_CLK_STOP_MODE0,
1158+
ret = sdw_slave_clk_stop_callback(slave, mode,
11351159
SDW_CLK_POST_PREPARE);
11361160

11371161
if (ret < 0 && ret != -ENODATA) {
@@ -1183,6 +1207,7 @@ EXPORT_SYMBOL(sdw_bus_clk_stop);
11831207
*/
11841208
int sdw_bus_exit_clk_stop(struct sdw_bus *bus)
11851209
{
1210+
enum sdw_clk_stop_mode mode;
11861211
bool simple_clk_stop = true;
11871212
struct sdw_slave *slave;
11881213
bool is_slave = false;
@@ -1204,18 +1229,20 @@ int sdw_bus_exit_clk_stop(struct sdw_bus *bus)
12041229
/* Identify if Slave(s) are available on Bus */
12051230
is_slave = true;
12061231

1207-
ret = sdw_slave_clk_stop_callback(slave, SDW_CLK_STOP_MODE0,
1232+
mode = slave->curr_clk_stop_mode;
1233+
1234+
ret = sdw_slave_clk_stop_callback(slave, mode,
12081235
SDW_CLK_PRE_DEPREPARE);
12091236
if (ret < 0)
12101237
dev_warn(&slave->dev, "clock stop pre-deprepare cb failed:%d\n", ret);
12111238

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

1216-
ret = sdw_slave_clk_stop_prepare(slave, SDW_CLK_STOP_MODE0,
1244+
ret = sdw_slave_clk_stop_prepare(slave, mode,
12171245
false);
1218-
12191246
if (ret < 0)
12201247
dev_warn(&slave->dev, "clock stop deprepare failed:%d\n", ret);
12211248
}
@@ -1243,7 +1270,9 @@ int sdw_bus_exit_clk_stop(struct sdw_bus *bus)
12431270
slave->status != SDW_SLAVE_ALERT)
12441271
continue;
12451272

1246-
ret = sdw_slave_clk_stop_callback(slave, SDW_CLK_STOP_MODE0,
1273+
mode = slave->curr_clk_stop_mode;
1274+
1275+
ret = sdw_slave_clk_stop_callback(slave, mode,
12471276
SDW_CLK_POST_DEPREPARE);
12481277
if (ret < 0)
12491278
dev_warn(&slave->dev, "clock stop post-deprepare cb failed:%d\n", ret);

include/linux/soundwire/sdw.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,7 @@ struct sdw_slave_ops {
624624
int (*port_prep)(struct sdw_slave *slave,
625625
struct sdw_prepare_ch *prepare_ch,
626626
enum sdw_port_prep_ops pre_ops);
627+
int (*get_clk_stop_mode)(struct sdw_slave *slave);
627628
int (*clk_stop)(struct sdw_slave *slave,
628629
enum sdw_clk_stop_mode mode,
629630
enum sdw_clk_stop_type type);
@@ -676,6 +677,7 @@ struct sdw_slave {
676677
struct list_head node;
677678
struct completion port_ready[SDW_MAX_PORTS];
678679
unsigned int m_port_map[SDW_MAX_PORTS];
680+
enum sdw_clk_stop_mode curr_clk_stop_mode;
679681
u16 dev_num;
680682
u16 dev_num_sticky;
681683
bool probed;

0 commit comments

Comments
 (0)