soundwire updates for 5.19-rc1

- Support for v1.6.0 Qualcomm controllers
  - Bunch of pm updates by Intel for peripheral attachment and system pm
    etc
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+vs47OPLdNbVcHzyfBQHDyUjg0cFAmJ8/LIACgkQfBQHDyUj
 g0cg/BAAhpuUHSE+4Xzhgbb93o6AAKVLFnGXuDCUYHGTJ/TyFarq8msHrEF8oAqu
 l7SPJjfpga1KNG6BVla0fTIVepdEZegdf2EF7xjYeszg9TwLX7Ek8kaGk8HJ9pKO
 euuRfy1xdouGobrk/gfywKNCLZWM2sCFow7FkdOhlvrofkeqj89rvYPkGY/c1cbM
 Pmnjg22aYR+cqXJcuLZ8SpO2QljVo0UGkgrn3Uoo7Qjgk/xq7NaW0TyS23w5O4nz
 VrDnGoP/kpOVMdXkp6y4mKhAfCWMj655Kr6Ag9+gIysk/qL0QVCkVwZ38u6XVK9z
 duUmwIIYemGIh5qP1sbjhUJ6cmcSDLR9+u4QliFMJqpKko1njLx3omOUm2/GN+fJ
 Jm75BQ16D7yruYD4nQPUl7KIqh/PyQRe4ofCY29qrrmUnAZFBrkf+HMRG+6roKyf
 z9fyQl4QdabVFOsMFdMXsMFTkCw5OIWjpPy/qdozHiCkAQH0C/P3EQSVKQfan2eb
 blLVOdr7pMHsks6IoXjqLHBX7lYGlmp8S1Qmh+GiENv7Zpl2vQBLOc9K0/jdHcBU
 wVuHOd320HN5MoZx3kuyHI6uoEL43kSHv4itaHc41wijetdu/I41X+ns5onukk5O
 2NXmowoZAoCtriJT7EGhJNczFymu63VyQu3wFI0g2zg8i6S4bCk=
 =ZFFY
 -----END PGP SIGNATURE-----

Merge tag 'soundwire-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire into char-misc-next

Vinod writes:

soundwire updates for 5.19-rc1

 - Support for v1.6.0 Qualcomm controllers
 - Bunch of pm updates by Intel for peripheral attachment and system pm
   etc

* tag 'soundwire-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire:
  soundwire: qcom: adjust autoenumeration timeout
  soundwire: qcom: use pm_runtime_resume_and_get()
  soundwire: intel: use pm_runtime_resume_and_get()
  soundwire: cadence: use pm_runtime_resume_and_get()
  soundwire: bus: use pm_runtime_resume_and_get()
  soundwire: qcom: return error when pm_runtime_get_sync fails
  soundwire: bus: pm_runtime_request_resume on peripheral attachment
  soundwire: intel: disable WAKEEN in pm_runtime resume
  soundwire: intel: prevent pm_runtime resume prior to system suspend
  soundwire: cadence: recheck device0 attachment after status change
  dt-bindings: soundwire: qcom: Add bindings for audio clock reset control property
  soundwire: qcom: Add compatible name for v1.6.0
  soundwire: stream: Fix error return code in do_bank_switch()
  soundwire: qcom: fix an error message in swrm_wait_for_frame_gen_enabled()
This commit is contained in:
Greg Kroah-Hartman 2022-05-19 16:57:16 +02:00
commit fa5602c625
6 changed files with 90 additions and 27 deletions

View File

@ -162,6 +162,18 @@ board specific bus parameters.
or applicable for the respective data port.
More info in MIPI Alliance SoundWire 1.0 Specifications.
- reset:
Usage: optional
Value type: <prop-encoded-array>
Definition: Should specify the SoundWire audio CSR reset controller interface,
which is required for SoundWire version 1.6.0 and above.
- reset-names:
Usage: optional
Value type: <stringlist>
Definition: should be "swr_audio_cgcr" for SoundWire audio CSR reset
controller interface.
Note:
More Information on detail of encoding of these fields can be
found in MIPI Alliance SoundWire 1.0 Specifications.
@ -180,6 +192,8 @@ soundwire: soundwire@c85 {
interrupts = <20 IRQ_TYPE_EDGE_RISING>;
clocks = <&wcc>;
clock-names = "iface";
resets = <&lpass_audiocc LPASS_AUDIO_SWR_TX_CGCR>;
reset-names = "swr_audio_cgcr";
#sound-dai-cells = <1>;
qcom,dports-type = <0>;
qcom,dout-ports = <6>;

View File

@ -536,11 +536,9 @@ int sdw_nread(struct sdw_slave *slave, u32 addr, size_t count, u8 *val)
{
int ret;
ret = pm_runtime_get_sync(&slave->dev);
if (ret < 0 && ret != -EACCES) {
pm_runtime_put_noidle(&slave->dev);
ret = pm_runtime_resume_and_get(&slave->dev);
if (ret < 0 && ret != -EACCES)
return ret;
}
ret = sdw_nread_no_pm(slave, addr, count, val);
@ -562,11 +560,9 @@ int sdw_nwrite(struct sdw_slave *slave, u32 addr, size_t count, const u8 *val)
{
int ret;
ret = pm_runtime_get_sync(&slave->dev);
if (ret < 0 && ret != -EACCES) {
pm_runtime_put_noidle(&slave->dev);
ret = pm_runtime_resume_and_get(&slave->dev);
if (ret < 0 && ret != -EACCES)
return ret;
}
ret = sdw_nwrite_no_pm(slave, addr, count, val);
@ -1506,10 +1502,9 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)
sdw_modify_slave_status(slave, SDW_SLAVE_ALERT);
ret = pm_runtime_get_sync(&slave->dev);
ret = pm_runtime_resume_and_get(&slave->dev);
if (ret < 0 && ret != -EACCES) {
dev_err(&slave->dev, "Failed to resume device: %d\n", ret);
pm_runtime_put_noidle(&slave->dev);
return ret;
}
@ -1838,6 +1833,18 @@ int sdw_handle_slave_status(struct sdw_bus *bus,
__func__, slave->dev_num);
complete(&slave->initialization_complete);
/*
* If the manager became pm_runtime active, the peripherals will be
* restarted and attach, but their pm_runtime status may remain
* suspended. If the 'update_slave_status' callback initiates
* any sort of deferred processing, this processing would not be
* cancelled on pm_runtime suspend.
* To avoid such zombie states, we queue a request to resume.
* This would be a no-op in case the peripheral was being resumed
* by e.g. the ALSA/ASoC framework.
*/
pm_request_resume(&slave->dev);
}
}

View File

@ -386,12 +386,11 @@ static int cdns_parity_error_injection(void *data, u64 value)
* Resume Master device. If this results in a bus reset, the
* Slave devices will re-attach and be re-enumerated.
*/
ret = pm_runtime_get_sync(bus->dev);
ret = pm_runtime_resume_and_get(bus->dev);
if (ret < 0 && ret != -EACCES) {
dev_err_ratelimited(cdns->dev,
"pm_runtime_get_sync failed in %s, ret %d\n",
"pm_runtime_resume_and_get failed in %s, ret %d\n",
__func__, ret);
pm_runtime_put_noidle(bus->dev);
return ret;
}
@ -959,6 +958,8 @@ static void cdns_update_slave_status_work(struct work_struct *work)
container_of(work, struct sdw_cdns, work);
u32 slave0, slave1;
u64 slave_intstat;
u32 device0_status;
int retry_count = 0;
slave0 = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT0);
slave1 = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT1);
@ -968,10 +969,45 @@ static void cdns_update_slave_status_work(struct work_struct *work)
dev_dbg_ratelimited(cdns->dev, "Slave status change: 0x%llx\n", slave_intstat);
update_status:
cdns_update_slave_status(cdns, slave_intstat);
cdns_writel(cdns, CDNS_MCP_SLAVE_INTSTAT0, slave0);
cdns_writel(cdns, CDNS_MCP_SLAVE_INTSTAT1, slave1);
/*
* When there is more than one peripheral per link, it's
* possible that a deviceB becomes attached after we deal with
* the attachment of deviceA. Since the hardware does a
* logical AND, the attachment of the second device does not
* change the status seen by the driver.
*
* In that case, clearing the registers above would result in
* the deviceB never being detected - until a change of status
* is observed on the bus.
*
* To avoid this race condition, re-check if any device0 needs
* attention with PING commands. There is no need to check for
* ALERTS since they are not allowed until a non-zero
* device_number is assigned.
*/
device0_status = cdns_readl(cdns, CDNS_MCP_SLAVE_STAT);
device0_status &= 3;
if (device0_status == SDW_SLAVE_ATTACHED) {
if (retry_count++ < SDW_MAX_DEVICES) {
dev_dbg_ratelimited(cdns->dev,
"Device0 detected after clearing status, iteration %d\n",
retry_count);
slave_intstat = CDNS_MCP_SLAVE_INTSTAT_ATTACHED;
goto update_status;
} else {
dev_err_ratelimited(cdns->dev,
"Device0 detected after %d iterations\n",
retry_count);
}
}
/* clear and unmask Slave interrupt now */
cdns_writel(cdns, CDNS_MCP_INTSTAT, CDNS_MCP_INT_SLAVE_MASK);
cdns_updatel(cdns, CDNS_MCP_INTMASK,

View File

@ -799,12 +799,11 @@ static int intel_startup(struct snd_pcm_substream *substream,
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
int ret;
ret = pm_runtime_get_sync(cdns->dev);
ret = pm_runtime_resume_and_get(cdns->dev);
if (ret < 0 && ret != -EACCES) {
dev_err_ratelimited(cdns->dev,
"pm_runtime_get_sync failed in %s, ret %d\n",
"pm_runtime_resume_and_get failed in %s, ret %d\n",
__func__, ret);
pm_runtime_put_noidle(cdns->dev);
return ret;
}
return 0;
@ -1293,6 +1292,9 @@ static int intel_link_probe(struct auxiliary_device *auxdev,
/* use generic bandwidth allocation algorithm */
sdw->cdns.bus.compute_params = sdw_compute_params;
/* avoid resuming from pm_runtime suspend if it's not required */
dev_pm_set_driver_flags(dev, DPM_FLAG_SMART_SUSPEND);
ret = sdw_bus_master_add(bus, dev, dev->fwnode);
if (ret) {
dev_err(dev, "sdw_bus_master_add fail: %d\n", ret);
@ -1828,6 +1830,9 @@ static int __maybe_unused intel_resume_runtime(struct device *dev)
return 0;
}
/* unconditionally disable WAKEEN interrupt */
intel_shim_wake(sdw, false);
link_flags = md_flags >> (bus->link_id * 8);
multi_link = !(link_flags & SDW_INTEL_MASTER_DISABLE_MULTI_LINK);

View File

@ -105,7 +105,7 @@
#define SWRM_SPECIAL_CMD_ID 0xF
#define MAX_FREQ_NUM 1
#define TIMEOUT_MS (2 * HZ)
#define TIMEOUT_MS 100
#define QCOM_SWRM_MAX_RD_LEN 0x1
#define QCOM_SDW_MAX_PORTS 14
#define DEFAULT_CLK_FREQ 9600000
@ -510,12 +510,12 @@ static irqreturn_t qcom_swrm_wake_irq_handler(int irq, void *dev_id)
struct qcom_swrm_ctrl *swrm = dev_id;
int ret;
ret = pm_runtime_get_sync(swrm->dev);
ret = pm_runtime_resume_and_get(swrm->dev);
if (ret < 0 && ret != -EACCES) {
dev_err_ratelimited(swrm->dev,
"pm_runtime_get_sync failed in %s, ret %d\n",
"pm_runtime_resume_and_get failed in %s, ret %d\n",
__func__, ret);
pm_runtime_put_noidle(swrm->dev);
return ret;
}
if (swrm->wake_irq > 0) {
@ -1058,12 +1058,11 @@ static int qcom_swrm_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *codec_dai;
int ret, i;
ret = pm_runtime_get_sync(ctrl->dev);
ret = pm_runtime_resume_and_get(ctrl->dev);
if (ret < 0 && ret != -EACCES) {
dev_err_ratelimited(ctrl->dev,
"pm_runtime_get_sync failed in %s, ret %d\n",
"pm_runtime_resume_and_get failed in %s, ret %d\n",
__func__, ret);
pm_runtime_put_noidle(ctrl->dev);
return ret;
}
@ -1252,12 +1251,12 @@ static int swrm_reg_show(struct seq_file *s_file, void *data)
struct qcom_swrm_ctrl *swrm = s_file->private;
int reg, reg_val, ret;
ret = pm_runtime_get_sync(swrm->dev);
ret = pm_runtime_resume_and_get(swrm->dev);
if (ret < 0 && ret != -EACCES) {
dev_err_ratelimited(swrm->dev,
"pm_runtime_get_sync failed in %s, ret %d\n",
"pm_runtime_resume_and_get failed in %s, ret %d\n",
__func__, ret);
pm_runtime_put_noidle(swrm->dev);
return ret;
}
for (reg = 0; reg <= SWR_MSTR_MAX_REG_ADDR; reg += 4) {
@ -1452,7 +1451,7 @@ static bool swrm_wait_for_frame_gen_enabled(struct qcom_swrm_ctrl *swrm)
} while (retry--);
dev_err(swrm->dev, "%s: link status not %s\n", __func__,
comp_sts && SWRM_FRM_GEN_ENABLED ? "connected" : "disconnected");
comp_sts & SWRM_FRM_GEN_ENABLED ? "connected" : "disconnected");
return false;
}
@ -1549,6 +1548,7 @@ static const struct dev_pm_ops swrm_dev_pm_ops = {
static const struct of_device_id qcom_swrm_of_match[] = {
{ .compatible = "qcom,soundwire-v1.3.0", .data = &swrm_v1_3_data },
{ .compatible = "qcom,soundwire-v1.5.1", .data = &swrm_v1_5_data },
{ .compatible = "qcom,soundwire-v1.6.0", .data = &swrm_v1_5_data },
{/* sentinel */},
};

View File

@ -822,6 +822,7 @@ static int do_bank_switch(struct sdw_stream_runtime *stream)
} else if (multi_link) {
dev_err(bus->dev,
"Post bank switch ops not implemented\n");
ret = -EINVAL;
goto error;
}