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

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
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -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>;
+17 −10
Original line number Diff line number Diff line
@@ -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);
		}
	}

+39 −3
Original line number Diff line number Diff line
@@ -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,
+8 −3
Original line number Diff line number Diff line
@@ -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);

+11 −11
Original line number Diff line number Diff line
@@ -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 */},
};

Loading