Commit fa5602c6 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'soundwire-5.19-rc1' of...

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()
parents 46509e75 74da2724
...@@ -162,6 +162,18 @@ board specific bus parameters. ...@@ -162,6 +162,18 @@ board specific bus parameters.
or applicable for the respective data port. or applicable for the respective data port.
More info in MIPI Alliance SoundWire 1.0 Specifications. 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: Note:
More Information on detail of encoding of these fields can be More Information on detail of encoding of these fields can be
found in MIPI Alliance SoundWire 1.0 Specifications. found in MIPI Alliance SoundWire 1.0 Specifications.
...@@ -180,6 +192,8 @@ soundwire: soundwire@c85 { ...@@ -180,6 +192,8 @@ soundwire: soundwire@c85 {
interrupts = <20 IRQ_TYPE_EDGE_RISING>; interrupts = <20 IRQ_TYPE_EDGE_RISING>;
clocks = <&wcc>; clocks = <&wcc>;
clock-names = "iface"; clock-names = "iface";
resets = <&lpass_audiocc LPASS_AUDIO_SWR_TX_CGCR>;
reset-names = "swr_audio_cgcr";
#sound-dai-cells = <1>; #sound-dai-cells = <1>;
qcom,dports-type = <0>; qcom,dports-type = <0>;
qcom,dout-ports = <6>; qcom,dout-ports = <6>;
......
...@@ -536,11 +536,9 @@ int sdw_nread(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) ...@@ -536,11 +536,9 @@ int sdw_nread(struct sdw_slave *slave, u32 addr, size_t count, u8 *val)
{ {
int ret; int ret;
ret = pm_runtime_get_sync(&slave->dev); ret = pm_runtime_resume_and_get(&slave->dev);
if (ret < 0 && ret != -EACCES) { if (ret < 0 && ret != -EACCES)
pm_runtime_put_noidle(&slave->dev);
return ret; return ret;
}
ret = sdw_nread_no_pm(slave, addr, count, val); 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) ...@@ -562,11 +560,9 @@ int sdw_nwrite(struct sdw_slave *slave, u32 addr, size_t count, const u8 *val)
{ {
int ret; int ret;
ret = pm_runtime_get_sync(&slave->dev); ret = pm_runtime_resume_and_get(&slave->dev);
if (ret < 0 && ret != -EACCES) { if (ret < 0 && ret != -EACCES)
pm_runtime_put_noidle(&slave->dev);
return ret; return ret;
}
ret = sdw_nwrite_no_pm(slave, addr, count, val); ret = sdw_nwrite_no_pm(slave, addr, count, val);
...@@ -1506,10 +1502,9 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) ...@@ -1506,10 +1502,9 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)
sdw_modify_slave_status(slave, SDW_SLAVE_ALERT); 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) { if (ret < 0 && ret != -EACCES) {
dev_err(&slave->dev, "Failed to resume device: %d\n", ret); dev_err(&slave->dev, "Failed to resume device: %d\n", ret);
pm_runtime_put_noidle(&slave->dev);
return ret; return ret;
} }
...@@ -1838,6 +1833,18 @@ int sdw_handle_slave_status(struct sdw_bus *bus, ...@@ -1838,6 +1833,18 @@ int sdw_handle_slave_status(struct sdw_bus *bus,
__func__, slave->dev_num); __func__, slave->dev_num);
complete(&slave->initialization_complete); 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);
} }
} }
......
...@@ -386,12 +386,11 @@ static int cdns_parity_error_injection(void *data, u64 value) ...@@ -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 * Resume Master device. If this results in a bus reset, the
* Slave devices will re-attach and be re-enumerated. * 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) { if (ret < 0 && ret != -EACCES) {
dev_err_ratelimited(cdns->dev, 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); __func__, ret);
pm_runtime_put_noidle(bus->dev);
return ret; return ret;
} }
...@@ -959,6 +958,8 @@ static void cdns_update_slave_status_work(struct work_struct *work) ...@@ -959,6 +958,8 @@ static void cdns_update_slave_status_work(struct work_struct *work)
container_of(work, struct sdw_cdns, work); container_of(work, struct sdw_cdns, work);
u32 slave0, slave1; u32 slave0, slave1;
u64 slave_intstat; u64 slave_intstat;
u32 device0_status;
int retry_count = 0;
slave0 = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT0); slave0 = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT0);
slave1 = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT1); slave1 = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT1);
...@@ -968,10 +969,45 @@ static void cdns_update_slave_status_work(struct work_struct *work) ...@@ -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); dev_dbg_ratelimited(cdns->dev, "Slave status change: 0x%llx\n", slave_intstat);
update_status:
cdns_update_slave_status(cdns, slave_intstat); cdns_update_slave_status(cdns, slave_intstat);
cdns_writel(cdns, CDNS_MCP_SLAVE_INTSTAT0, slave0); cdns_writel(cdns, CDNS_MCP_SLAVE_INTSTAT0, slave0);
cdns_writel(cdns, CDNS_MCP_SLAVE_INTSTAT1, slave1); 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 */ /* clear and unmask Slave interrupt now */
cdns_writel(cdns, CDNS_MCP_INTSTAT, CDNS_MCP_INT_SLAVE_MASK); cdns_writel(cdns, CDNS_MCP_INTSTAT, CDNS_MCP_INT_SLAVE_MASK);
cdns_updatel(cdns, CDNS_MCP_INTMASK, cdns_updatel(cdns, CDNS_MCP_INTMASK,
......
...@@ -799,12 +799,11 @@ static int intel_startup(struct snd_pcm_substream *substream, ...@@ -799,12 +799,11 @@ static int intel_startup(struct snd_pcm_substream *substream,
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai); struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
int ret; int ret;
ret = pm_runtime_get_sync(cdns->dev); ret = pm_runtime_resume_and_get(cdns->dev);
if (ret < 0 && ret != -EACCES) { if (ret < 0 && ret != -EACCES) {
dev_err_ratelimited(cdns->dev, 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); __func__, ret);
pm_runtime_put_noidle(cdns->dev);
return ret; return ret;
} }
return 0; return 0;
...@@ -1293,6 +1292,9 @@ static int intel_link_probe(struct auxiliary_device *auxdev, ...@@ -1293,6 +1292,9 @@ static int intel_link_probe(struct auxiliary_device *auxdev,
/* use generic bandwidth allocation algorithm */ /* use generic bandwidth allocation algorithm */
sdw->cdns.bus.compute_params = sdw_compute_params; 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); ret = sdw_bus_master_add(bus, dev, dev->fwnode);
if (ret) { if (ret) {
dev_err(dev, "sdw_bus_master_add fail: %d\n", 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) ...@@ -1828,6 +1830,9 @@ static int __maybe_unused intel_resume_runtime(struct device *dev)
return 0; return 0;
} }
/* unconditionally disable WAKEEN interrupt */
intel_shim_wake(sdw, false);
link_flags = md_flags >> (bus->link_id * 8); link_flags = md_flags >> (bus->link_id * 8);
multi_link = !(link_flags & SDW_INTEL_MASTER_DISABLE_MULTI_LINK); multi_link = !(link_flags & SDW_INTEL_MASTER_DISABLE_MULTI_LINK);
......
...@@ -105,7 +105,7 @@ ...@@ -105,7 +105,7 @@
#define SWRM_SPECIAL_CMD_ID 0xF #define SWRM_SPECIAL_CMD_ID 0xF
#define MAX_FREQ_NUM 1 #define MAX_FREQ_NUM 1
#define TIMEOUT_MS (2 * HZ) #define TIMEOUT_MS 100
#define QCOM_SWRM_MAX_RD_LEN 0x1 #define QCOM_SWRM_MAX_RD_LEN 0x1
#define QCOM_SDW_MAX_PORTS 14 #define QCOM_SDW_MAX_PORTS 14
#define DEFAULT_CLK_FREQ 9600000 #define DEFAULT_CLK_FREQ 9600000
...@@ -510,12 +510,12 @@ static irqreturn_t qcom_swrm_wake_irq_handler(int irq, void *dev_id) ...@@ -510,12 +510,12 @@ static irqreturn_t qcom_swrm_wake_irq_handler(int irq, void *dev_id)
struct qcom_swrm_ctrl *swrm = dev_id; struct qcom_swrm_ctrl *swrm = dev_id;
int ret; int ret;
ret = pm_runtime_get_sync(swrm->dev); ret = pm_runtime_resume_and_get(swrm->dev);
if (ret < 0 && ret != -EACCES) { if (ret < 0 && ret != -EACCES) {
dev_err_ratelimited(swrm->dev, 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); __func__, ret);
pm_runtime_put_noidle(swrm->dev); return ret;
} }
if (swrm->wake_irq > 0) { if (swrm->wake_irq > 0) {
...@@ -1058,12 +1058,11 @@ static int qcom_swrm_startup(struct snd_pcm_substream *substream, ...@@ -1058,12 +1058,11 @@ static int qcom_swrm_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *codec_dai; struct snd_soc_dai *codec_dai;
int ret, i; int ret, i;
ret = pm_runtime_get_sync(ctrl->dev); ret = pm_runtime_resume_and_get(ctrl->dev);
if (ret < 0 && ret != -EACCES) { if (ret < 0 && ret != -EACCES) {
dev_err_ratelimited(ctrl->dev, 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); __func__, ret);
pm_runtime_put_noidle(ctrl->dev);
return ret; return ret;
} }
...@@ -1252,12 +1251,12 @@ static int swrm_reg_show(struct seq_file *s_file, void *data) ...@@ -1252,12 +1251,12 @@ static int swrm_reg_show(struct seq_file *s_file, void *data)
struct qcom_swrm_ctrl *swrm = s_file->private; struct qcom_swrm_ctrl *swrm = s_file->private;
int reg, reg_val, ret; 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) { if (ret < 0 && ret != -EACCES) {
dev_err_ratelimited(swrm->dev, 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); __func__, ret);
pm_runtime_put_noidle(swrm->dev); return ret;
} }
for (reg = 0; reg <= SWR_MSTR_MAX_REG_ADDR; reg += 4) { 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) ...@@ -1452,7 +1451,7 @@ static bool swrm_wait_for_frame_gen_enabled(struct qcom_swrm_ctrl *swrm)
} while (retry--); } while (retry--);
dev_err(swrm->dev, "%s: link status not %s\n", __func__, 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; return false;
} }
...@@ -1549,6 +1548,7 @@ static const struct dev_pm_ops swrm_dev_pm_ops = { ...@@ -1549,6 +1548,7 @@ static const struct dev_pm_ops swrm_dev_pm_ops = {
static const struct of_device_id qcom_swrm_of_match[] = { 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.3.0", .data = &swrm_v1_3_data },
{ .compatible = "qcom,soundwire-v1.5.1", .data = &swrm_v1_5_data }, { .compatible = "qcom,soundwire-v1.5.1", .data = &swrm_v1_5_data },
{ .compatible = "qcom,soundwire-v1.6.0", .data = &swrm_v1_5_data },
{/* sentinel */}, {/* sentinel */},
}; };
......
...@@ -822,6 +822,7 @@ static int do_bank_switch(struct sdw_stream_runtime *stream) ...@@ -822,6 +822,7 @@ static int do_bank_switch(struct sdw_stream_runtime *stream)
} else if (multi_link) { } else if (multi_link) {
dev_err(bus->dev, dev_err(bus->dev,
"Post bank switch ops not implemented\n"); "Post bank switch ops not implemented\n");
ret = -EINVAL;
goto error; goto error;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment