Commit b422b723 authored by Pierre-Louis Bossart's avatar Pierre-Louis Bossart Committed by Vinod Koul
Browse files

soundwire: stream: reuse existing code for BPT stream



DP0 (Data Port 0) is very similar to regular data ports, with minor
tweaks we can reuse the same code.

Signed-off-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.dev>
Signed-off-by: default avatarBard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: default avatarPéter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: default avatarLiam Girdwood <liam.r.girdwood@intel.com>
Reviewed-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Tested-by: default avatar <shumingf@realtek.com>
Link: https://lore.kernel.org/r/20250227140615.8147-7-yung-chuan.liao@linux.intel.com


Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent 00f57195
Loading
Loading
Loading
Loading
+73 −31
Original line number Diff line number Diff line
@@ -88,12 +88,15 @@ static int _sdw_program_slave_port_params(struct sdw_bus *bus,
		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;
		}
	}

	/*
	 * Data ports are FULL, SIMPLE and REDUCED. This function handles
@@ -131,19 +134,29 @@ 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,
	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);

@@ -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) {
@@ -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",
@@ -433,6 +446,9 @@ 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;
@@ -440,20 +456,35 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus,
	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 (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;

@@ -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;
	}
@@ -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)
@@ -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)) {
@@ -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;
}
@@ -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;
@@ -1020,9 +1052,13 @@ static int sdw_slave_port_config(struct sdw_slave *slave,
		 * TODO: Check valid port range as defined by DisCo/
		 * slave
		 */
		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)
@@ -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;
@@ -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;