@@ -1361,6 +1361,7 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)
int port_num, stat, ret, count = 0;
unsigned long port;
bool slave_notify = false;
+ u8 sdca_cascade = 0;
u8 buf, buf2[2], _buf, _buf2[2];
sdw_modify_slave_status(slave, SDW_SLAVE_ALERT);
@@ -1388,6 +1389,16 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)
goto io_err;
}
+ if (slave->prop.is_sdca) {
+ ret = sdw_read(slave, SDW_DP0_INT);
+ if (ret < 0) {
+ dev_err(slave->bus->dev,
+ "SDW_DP0_INT read failed:%d\n", ret);
+ goto io_err;
+ }
+ sdca_cascade = ret & SDW_DP0_SDCA_CASCADE;
+ }
+
do {
/*
* Check parity, bus clash and Slave (impl defined)
@@ -1416,6 +1427,10 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)
slave_notify = true;
}
+ /* the SDCA interrupts are cleared in the codec driver .interrupt_callback() */
+ if (sdca_cascade)
+ slave_notify = true;
+
/* Check port 0 - 3 interrupts */
port = buf & SDW_SCP_INT1_PORT0_3;
@@ -1453,6 +1468,7 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)
/* Update the Slave driver */
if (slave_notify && slave->ops &&
slave->ops->interrupt_callback) {
+ slave_intr.sdca_cascade = sdca_cascade;
slave_intr.control_port = clear;
memcpy(slave_intr.port, &port_status,
sizeof(slave_intr.port));
@@ -1487,11 +1503,21 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)
goto io_err;
}
+ if (slave->prop.is_sdca) {
+ ret = sdw_read(slave, SDW_DP0_INT);
+ if (ret < 0) {
+ dev_err(slave->bus->dev,
+ "SDW_DP0_INT read failed:%d\n", ret);
+ goto io_err;
+ }
+ sdca_cascade = ret & SDW_DP0_SDCA_CASCADE;
+ }
+
/* Make sure no interrupts are pending */
buf &= _buf;
buf2[0] &= _buf2[0];
buf2[1] &= _buf2[1];
- stat = buf || buf2[0] || buf2[1];
+ stat = buf || buf2[0] || buf2[1] || sdca_cascade;
/*
* Exit loop if Slave is continuously in ALERT state even
@@ -355,6 +355,7 @@ struct sdw_dpn_prop {
* @dp0_prop: Data Port 0 properties
* @src_dpn_prop: Source Data Port N properties
* @sink_dpn_prop: Sink Data Port N properties
+ * @is_sdca: the Slave supports the SDCA specification
*/
struct sdw_slave_prop {
u32 mipi_revision;
@@ -376,6 +377,7 @@ struct sdw_slave_prop {
struct sdw_dp0_prop *dp0_prop;
struct sdw_dpn_prop *src_dpn_prop;
struct sdw_dpn_prop *sink_dpn_prop;
+ bool is_sdca;
};
/**
@@ -465,10 +467,12 @@ struct sdw_slave_id {
/**
* struct sdw_slave_intr_status - Slave interrupt status
+ * @sdca_cascade: set if the Slave device reports an SDCA interrupt
* @control_port: control port status
* @port: data port status
*/
struct sdw_slave_intr_status {
+ bool sdca_cascade;
u8 control_port;
u8 port[15];
};