Skip to content

Commit

Permalink
soundwire: stream: reuse existing code for BPT stream
Browse files Browse the repository at this point in the history
DP0 (Data Port 0) is very similar to regular data ports, with minor
tweaks we can reuse the same code.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Liam Girdwood <liam.r.girdwood@intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Tested-by: shumingf@realtek.com
Link: https://lore.kernel.org/r/20250227140615.8147-7-yung-chuan.liao@linux.intel.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
  • Loading branch information
Pierre-Louis Bossart authored and Vinod Koul committed Mar 10, 2025
1 parent 00f5719 commit b422b72
Showing 1 changed file with 73 additions and 31 deletions.
104 changes: 73 additions & 31 deletions drivers/soundwire/stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,14 @@ static int _sdw_program_slave_port_params(struct sdw_bus *bus,
return ret;
}

/* Program DPN_BlockCtrl3 register */
ret = sdw_write_no_pm(slave, addr2, t_params->blk_pkg_mode);
if (ret < 0) {
dev_err(bus->dev, "DPN_BlockCtrl3 register write failed\n");
return ret;
/* DP0 does not implement BlockCtrl3 */
if (t_params->port_num) {
/* Program DPN_BlockCtrl3 register */
ret = sdw_write_no_pm(slave, addr2, t_params->blk_pkg_mode);
if (ret < 0) {
dev_err(bus->dev, "DPN_BlockCtrl3 register write failed\n");
return ret;
}
}

/*
Expand Down Expand Up @@ -131,18 +134,28 @@ static int sdw_program_slave_port_params(struct sdw_bus *bus,
struct sdw_port_params *p_params = &p_rt->port_params;
struct sdw_slave_prop *slave_prop = &s_rt->slave->prop;
u32 addr1, addr2, addr3, addr4, addr5, addr6;
struct sdw_dpn_prop *dpn_prop;
enum sdw_dpn_type port_type;
bool read_only_wordlength;
int ret;
u8 wbuf;

if (s_rt->slave->is_mockup_device)
return 0;

dpn_prop = sdw_get_slave_dpn_prop(s_rt->slave,
s_rt->direction,
t_params->port_num);
if (!dpn_prop)
return -EINVAL;
if (t_params->port_num) {
struct sdw_dpn_prop *dpn_prop;

dpn_prop = sdw_get_slave_dpn_prop(s_rt->slave, s_rt->direction,
t_params->port_num);
if (!dpn_prop)
return -EINVAL;

read_only_wordlength = dpn_prop->read_only_wordlength;
port_type = dpn_prop->type;
} else {
read_only_wordlength = false;
port_type = SDW_DPN_FULL;
}

addr1 = SDW_DPN_PORTCTRL(t_params->port_num);
addr2 = SDW_DPN_BLOCKCTRL1(t_params->port_num);
Expand Down Expand Up @@ -172,7 +185,7 @@ static int sdw_program_slave_port_params(struct sdw_bus *bus,
return ret;
}

if (!dpn_prop->read_only_wordlength) {
if (!read_only_wordlength) {
/* Program DPN_BlockCtrl1 register */
ret = sdw_write_no_pm(s_rt->slave, addr2, (p_params->bps - 1));
if (ret < 0) {
Expand Down Expand Up @@ -224,9 +237,9 @@ static int sdw_program_slave_port_params(struct sdw_bus *bus,
}
}

if (dpn_prop->type != SDW_DPN_SIMPLE) {
if (port_type != SDW_DPN_SIMPLE) {
ret = _sdw_program_slave_port_params(bus, s_rt->slave,
t_params, dpn_prop->type);
t_params, port_type);
if (ret < 0)
dev_err(&s_rt->slave->dev,
"Transport reg write failed for port: %d\n",
Expand Down Expand Up @@ -433,27 +446,45 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus,
struct completion *port_ready;
struct sdw_dpn_prop *dpn_prop;
struct sdw_prepare_ch prep_ch;
u32 imp_def_interrupts;
bool simple_ch_prep_sm;
u32 ch_prep_timeout;
bool intr = false;
int ret = 0, val;
u32 addr;

prep_ch.num = p_rt->num;
prep_ch.ch_mask = p_rt->ch_mask;

dpn_prop = sdw_get_slave_dpn_prop(s_rt->slave,
s_rt->direction,
prep_ch.num);
if (!dpn_prop) {
dev_err(bus->dev,
"Slave Port:%d properties not found\n", prep_ch.num);
return -EINVAL;
if (p_rt->num) {
dpn_prop = sdw_get_slave_dpn_prop(s_rt->slave, s_rt->direction, prep_ch.num);
if (!dpn_prop) {
dev_err(bus->dev,
"Slave Port:%d properties not found\n", prep_ch.num);
return -EINVAL;
}

imp_def_interrupts = dpn_prop->imp_def_interrupts;
simple_ch_prep_sm = dpn_prop->simple_ch_prep_sm;
ch_prep_timeout = dpn_prop->ch_prep_timeout;
} else {
struct sdw_dp0_prop *dp0_prop = s_rt->slave->prop.dp0_prop;

if (!dp0_prop) {
dev_err(bus->dev,
"Slave DP0 properties not found\n");
return -EINVAL;
}
imp_def_interrupts = dp0_prop->imp_def_interrupts;
simple_ch_prep_sm = dp0_prop->simple_ch_prep_sm;
ch_prep_timeout = dp0_prop->ch_prep_timeout;
}

prep_ch.prepare = prep;

prep_ch.bank = bus->params.next_bank;

if (dpn_prop->imp_def_interrupts || !dpn_prop->simple_ch_prep_sm ||
if (imp_def_interrupts || !simple_ch_prep_sm ||
bus->params.s_data_mode != SDW_PORT_DATA_MODE_NORMAL)
intr = true;

Expand All @@ -464,7 +495,7 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus,
*/
if (prep && intr) {
ret = sdw_configure_dpn_intr(s_rt->slave, p_rt->num, prep,
dpn_prop->imp_def_interrupts);
imp_def_interrupts);
if (ret < 0)
return ret;
}
Expand All @@ -473,7 +504,7 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus,
sdw_do_port_prep(s_rt, prep_ch, prep ? SDW_OPS_PORT_PRE_PREP : SDW_OPS_PORT_PRE_DEPREP);

/* Prepare Slave port implementing CP_SM */
if (!dpn_prop->simple_ch_prep_sm) {
if (!simple_ch_prep_sm) {
addr = SDW_DPN_PREPARECTRL(p_rt->num);

if (prep)
Expand All @@ -490,7 +521,7 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus,
/* Wait for completion on port ready */
port_ready = &s_rt->slave->port_ready[prep_ch.num];
wait_for_completion_timeout(port_ready,
msecs_to_jiffies(dpn_prop->ch_prep_timeout));
msecs_to_jiffies(ch_prep_timeout));

val = sdw_read_no_pm(s_rt->slave, SDW_DPN_PREPARESTATUS(p_rt->num));
if ((val < 0) || (val & p_rt->ch_mask)) {
Expand All @@ -507,7 +538,7 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus,
/* Disable interrupt after Port de-prepare */
if (!prep && intr)
ret = sdw_configure_dpn_intr(s_rt->slave, p_rt->num, prep,
dpn_prop->imp_def_interrupts);
imp_def_interrupts);

return ret;
}
Expand Down Expand Up @@ -1008,7 +1039,8 @@ static int sdw_slave_port_is_valid_range(struct device *dev, int num)

static int sdw_slave_port_config(struct sdw_slave *slave,
struct sdw_slave_runtime *s_rt,
const struct sdw_port_config *port_config)
const struct sdw_port_config *port_config,
bool is_bpt_stream)
{
struct sdw_port_runtime *p_rt;
int ret;
Expand All @@ -1020,9 +1052,13 @@ static int sdw_slave_port_config(struct sdw_slave *slave,
* TODO: Check valid port range as defined by DisCo/
* slave
*/
ret = sdw_slave_port_is_valid_range(&slave->dev, port_config[i].num);
if (ret < 0)
return ret;
if (!is_bpt_stream) {
ret = sdw_slave_port_is_valid_range(&slave->dev, port_config[i].num);
if (ret < 0)
return ret;
} else if (port_config[i].num) {
return -EINVAL;
}

ret = sdw_port_config(p_rt, port_config, i);
if (ret < 0)
Expand Down Expand Up @@ -1331,6 +1367,11 @@ struct sdw_dpn_prop *sdw_get_slave_dpn_prop(struct sdw_slave *slave,
u8 num_ports;
int i;

if (!port_num) {
dev_err(&slave->dev, "%s: port_num is zero\n", __func__);
return NULL;
}

if (direction == SDW_DATA_DIR_TX) {
num_ports = hweight32(slave->prop.source_ports);
dpn_prop = slave->prop.src_dpn_prop;
Expand Down Expand Up @@ -2116,7 +2157,8 @@ int sdw_stream_add_slave(struct sdw_slave *slave,
if (ret)
goto unlock;

ret = sdw_slave_port_config(slave, s_rt, port_config);
ret = sdw_slave_port_config(slave, s_rt, port_config,
stream->type == SDW_STREAM_BPT);
if (ret)
goto unlock;

Expand Down

0 comments on commit b422b72

Please sign in to comment.