in stream.c [420:505]
static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus,
struct sdw_slave_runtime *s_rt,
struct sdw_port_runtime *p_rt,
bool prep)
{
struct completion *port_ready;
struct sdw_dpn_prop *dpn_prop;
struct sdw_prepare_ch prep_ch;
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;
}
prep_ch.prepare = prep;
prep_ch.bank = bus->params.next_bank;
if (dpn_prop->imp_def_interrupts || !dpn_prop->simple_ch_prep_sm ||
bus->params.s_data_mode != SDW_PORT_DATA_MODE_NORMAL)
intr = true;
/*
* Enable interrupt before Port prepare.
* For Port de-prepare, it is assumed that port
* was prepared earlier
*/
if (prep && intr) {
ret = sdw_configure_dpn_intr(s_rt->slave, p_rt->num, prep,
dpn_prop->imp_def_interrupts);
if (ret < 0)
return ret;
}
/* Inform slave about the impending port prepare */
sdw_do_port_prep(s_rt, prep_ch, SDW_OPS_PORT_PRE_PREP);
/* Prepare Slave port implementing CP_SM */
if (!dpn_prop->simple_ch_prep_sm) {
addr = SDW_DPN_PREPARECTRL(p_rt->num);
if (prep)
ret = sdw_write(s_rt->slave, addr, p_rt->ch_mask);
else
ret = sdw_write(s_rt->slave, addr, 0x0);
if (ret < 0) {
dev_err(&s_rt->slave->dev,
"Slave prep_ctrl reg write failed\n");
return ret;
}
/* 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));
val = sdw_read(s_rt->slave, SDW_DPN_PREPARESTATUS(p_rt->num));
if ((val < 0) || (val & p_rt->ch_mask)) {
ret = (val < 0) ? val : -ETIMEDOUT;
dev_err(&s_rt->slave->dev,
"Chn prep failed for port %d: %d\n", prep_ch.num, ret);
return ret;
}
}
/* Inform slaves about ports prepared */
sdw_do_port_prep(s_rt, prep_ch, SDW_OPS_PORT_POST_PREP);
/* 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);
return ret;
}