summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-11-27 22:38:09 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2024-11-27 22:38:09 +0100
commit9ad55a67a788c0806b0fe23be36fae6dbfbc3fc5 (patch)
tree1399c743936bfbdc0e5a7a9daa692d108614c5cd
parentMerge tag 'phy-for-6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/phy... (diff)
parentsoundwire: Minor formatting fixups in sdw.h header (diff)
downloadlinux-9ad55a67a788c0806b0fe23be36fae6dbfbc3fc5.tar.xz
linux-9ad55a67a788c0806b0fe23be36fae6dbfbc3fc5.zip
Merge tag 'soundwire-6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire
Pull soundwire updates from Vinod Koul: - structure optimization of few bus structures and header updates - support for 2.0 disco spec - amd driver updates for acp revision, refactoring code and support for acp6.3 - soft reset support for cadence driver * tag 'soundwire-6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire: (24 commits) soundwire: Minor formatting fixups in sdw.h header soundwire: Update the includes on the sdw.h header soundwire: cadence: clear MCP BLOCK_WAKEUP in init soundwire: cadence: add soft-reset on startup soundwire: intel_auxdevice: add kernel parameter for mclk divider soundwire: mipi-disco: add support for DP0/DPn 'lane-list' property soundwire: mipi-disco: add new properties from 2.0 spec soundwire: mipi-disco: add comment on DP0-supported property soundwire: mipi-disco: add support for peripheral channelprepare timeout soundwire: mipi_disco: add support for clock-scales property soundwire: mipi-disco: add error handling for property array read soundwire: mipi-disco: remove DPn audio-modes soundwire: optimize sdw_dpn_prop soundwire: optimize sdw_dp0_prop soundwire: optimize sdw_slave_prop soundwire: optimize sdw_bus structure soundwire: optimize sdw_master_prop soundwire: optimize sdw_stream_runtime memory layout soundwire: mipi_disco: add MIPI-specific property_read_bool() helpers soundwire: Correct some typos in comments ...
-rw-r--r--Documentation/admin-guide/kernel-parameters.rst1
-rw-r--r--Documentation/admin-guide/kernel-parameters.txt4
-rw-r--r--drivers/soundwire/amd_init.c1
-rw-r--r--drivers/soundwire/amd_manager.c99
-rw-r--r--drivers/soundwire/amd_manager.h16
-rw-r--r--drivers/soundwire/bus.c2
-rw-r--r--drivers/soundwire/cadence_master.c30
-rw-r--r--drivers/soundwire/cadence_master.h1
-rw-r--r--drivers/soundwire/intel_auxdevice.c12
-rw-r--r--drivers/soundwire/intel_bus_common.c6
-rw-r--r--drivers/soundwire/mipi_disco.c144
-rw-r--r--drivers/soundwire/qcom.c2
-rw-r--r--drivers/soundwire/sysfs_slave.c2
-rw-r--r--include/linux/soundwire/sdw.h241
-rw-r--r--include/linux/soundwire/sdw_amd.h6
-rw-r--r--sound/soc/amd/ps/acp63.h2
-rw-r--r--sound/soc/amd/ps/pci-ps.c2
-rw-r--r--sound/soc/sof/amd/acp.c1
18 files changed, 366 insertions, 206 deletions
diff --git a/Documentation/admin-guide/kernel-parameters.rst b/Documentation/admin-guide/kernel-parameters.rst
index 6247bbc9547c..59931f21c974 100644
--- a/Documentation/admin-guide/kernel-parameters.rst
+++ b/Documentation/admin-guide/kernel-parameters.rst
@@ -174,6 +174,7 @@ is applicable::
SCSI Appropriate SCSI support is enabled.
A lot of drivers have their options described inside
the Documentation/scsi/ sub-directory.
+ SDW SoundWire support is enabled.
SECURITY Different security models are enabled.
SELINUX SELinux support is enabled.
SERIAL Serial support is enabled.
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 14ebd1f4b45e..dc663c0ca670 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -6075,6 +6075,10 @@
non-zero "wait" parameter. See weight_single
and weight_many.
+ sdw_mclk_divider=[SDW]
+ Specify the MCLK divider for Intel SoundWire buses in
+ case the BIOS does not provide the clock rate properly.
+
skew_tick= [KNL,EARLY] Offset the periodic timer tick per cpu to mitigate
xtime_lock contention on larger systems, and/or RCU lock
contention on all systems with CONFIG_MAXSMP set.
diff --git a/drivers/soundwire/amd_init.c b/drivers/soundwire/amd_init.c
index 53d1d707ca1a..d11b60efda33 100644
--- a/drivers/soundwire/amd_init.c
+++ b/drivers/soundwire/amd_init.c
@@ -121,6 +121,7 @@ static struct sdw_amd_ctx *sdw_amd_probe_controller(struct sdw_amd_res *res)
sdw_pdata[index].instance = index;
sdw_pdata[index].acp_sdw_lock = res->acp_lock;
+ sdw_pdata[index].acp_rev = res->acp_rev;
pdevinfo[index].name = "amd_sdw_manager";
pdevinfo[index].id = index;
pdevinfo[index].parent = res->parent;
diff --git a/drivers/soundwire/amd_manager.c b/drivers/soundwire/amd_manager.c
index 0d01849c3586..5a4bfaef65fb 100644
--- a/drivers/soundwire/amd_manager.c
+++ b/drivers/soundwire/amd_manager.c
@@ -433,12 +433,18 @@ static int amd_sdw_port_params(struct sdw_bus *bus, struct sdw_port_params *p_pa
u32 frame_fmt_reg, dpn_frame_fmt;
dev_dbg(amd_manager->dev, "p_params->num:0x%x\n", p_params->num);
- switch (amd_manager->instance) {
- case ACP_SDW0:
- frame_fmt_reg = sdw0_manager_dp_reg[p_params->num].frame_fmt_reg;
- break;
- case ACP_SDW1:
- frame_fmt_reg = sdw1_manager_dp_reg[p_params->num].frame_fmt_reg;
+ switch (amd_manager->acp_rev) {
+ case ACP63_PCI_REV_ID:
+ switch (amd_manager->instance) {
+ case ACP_SDW0:
+ frame_fmt_reg = acp63_sdw0_dp_reg[p_params->num].frame_fmt_reg;
+ break;
+ case ACP_SDW1:
+ frame_fmt_reg = acp63_sdw1_dp_reg[p_params->num].frame_fmt_reg;
+ break;
+ default:
+ return -EINVAL;
+ }
break;
default:
return -EINVAL;
@@ -465,20 +471,28 @@ static int amd_sdw_transport_params(struct sdw_bus *bus,
u32 frame_fmt_reg, sample_int_reg, hctrl_dp0_reg;
u32 offset_reg, lane_ctrl_ch_en_reg;
- switch (amd_manager->instance) {
- case ACP_SDW0:
- frame_fmt_reg = sdw0_manager_dp_reg[params->port_num].frame_fmt_reg;
- sample_int_reg = sdw0_manager_dp_reg[params->port_num].sample_int_reg;
- hctrl_dp0_reg = sdw0_manager_dp_reg[params->port_num].hctrl_dp0_reg;
- offset_reg = sdw0_manager_dp_reg[params->port_num].offset_reg;
- lane_ctrl_ch_en_reg = sdw0_manager_dp_reg[params->port_num].lane_ctrl_ch_en_reg;
- break;
- case ACP_SDW1:
- frame_fmt_reg = sdw1_manager_dp_reg[params->port_num].frame_fmt_reg;
- sample_int_reg = sdw1_manager_dp_reg[params->port_num].sample_int_reg;
- hctrl_dp0_reg = sdw1_manager_dp_reg[params->port_num].hctrl_dp0_reg;
- offset_reg = sdw1_manager_dp_reg[params->port_num].offset_reg;
- lane_ctrl_ch_en_reg = sdw1_manager_dp_reg[params->port_num].lane_ctrl_ch_en_reg;
+ switch (amd_manager->acp_rev) {
+ case ACP63_PCI_REV_ID:
+ switch (amd_manager->instance) {
+ case ACP_SDW0:
+ frame_fmt_reg = acp63_sdw0_dp_reg[params->port_num].frame_fmt_reg;
+ sample_int_reg = acp63_sdw0_dp_reg[params->port_num].sample_int_reg;
+ hctrl_dp0_reg = acp63_sdw0_dp_reg[params->port_num].hctrl_dp0_reg;
+ offset_reg = acp63_sdw0_dp_reg[params->port_num].offset_reg;
+ lane_ctrl_ch_en_reg =
+ acp63_sdw0_dp_reg[params->port_num].lane_ctrl_ch_en_reg;
+ break;
+ case ACP_SDW1:
+ frame_fmt_reg = acp63_sdw1_dp_reg[params->port_num].frame_fmt_reg;
+ sample_int_reg = acp63_sdw1_dp_reg[params->port_num].sample_int_reg;
+ hctrl_dp0_reg = acp63_sdw1_dp_reg[params->port_num].hctrl_dp0_reg;
+ offset_reg = acp63_sdw1_dp_reg[params->port_num].offset_reg;
+ lane_ctrl_ch_en_reg =
+ acp63_sdw1_dp_reg[params->port_num].lane_ctrl_ch_en_reg;
+ break;
+ default:
+ return -EINVAL;
+ }
break;
default:
return -EINVAL;
@@ -520,12 +534,20 @@ static int amd_sdw_port_enable(struct sdw_bus *bus,
u32 dpn_ch_enable;
u32 lane_ctrl_ch_en_reg;
- switch (amd_manager->instance) {
- case ACP_SDW0:
- lane_ctrl_ch_en_reg = sdw0_manager_dp_reg[enable_ch->port_num].lane_ctrl_ch_en_reg;
- break;
- case ACP_SDW1:
- lane_ctrl_ch_en_reg = sdw1_manager_dp_reg[enable_ch->port_num].lane_ctrl_ch_en_reg;
+ switch (amd_manager->acp_rev) {
+ case ACP63_PCI_REV_ID:
+ switch (amd_manager->instance) {
+ case ACP_SDW0:
+ lane_ctrl_ch_en_reg =
+ acp63_sdw0_dp_reg[enable_ch->port_num].lane_ctrl_ch_en_reg;
+ break;
+ case ACP_SDW1:
+ lane_ctrl_ch_en_reg =
+ acp63_sdw1_dp_reg[enable_ch->port_num].lane_ctrl_ch_en_reg;
+ break;
+ default:
+ return -EINVAL;
+ }
break;
default:
return -EINVAL;
@@ -910,6 +932,7 @@ static int amd_sdw_manager_probe(struct platform_device *pdev)
amd_manager->mmio = amd_manager->acp_mmio +
(amd_manager->instance * SDW_MANAGER_REG_OFFSET);
amd_manager->acp_sdw_lock = pdata->acp_sdw_lock;
+ amd_manager->acp_rev = pdata->acp_rev;
amd_manager->cols_index = sdw_find_col_index(AMD_SDW_DEFAULT_COLUMNS);
amd_manager->rows_index = sdw_find_row_index(AMD_SDW_DEFAULT_ROWS);
amd_manager->dev = dev;
@@ -926,15 +949,21 @@ static int amd_sdw_manager_probe(struct platform_device *pdev)
* information.
*/
amd_manager->bus.controller_id = 0;
-
- switch (amd_manager->instance) {
- case ACP_SDW0:
- amd_manager->num_dout_ports = AMD_SDW0_MAX_TX_PORTS;
- amd_manager->num_din_ports = AMD_SDW0_MAX_RX_PORTS;
- break;
- case ACP_SDW1:
- amd_manager->num_dout_ports = AMD_SDW1_MAX_TX_PORTS;
- amd_manager->num_din_ports = AMD_SDW1_MAX_RX_PORTS;
+ dev_dbg(dev, "acp_rev:0x%x\n", amd_manager->acp_rev);
+ switch (amd_manager->acp_rev) {
+ case ACP63_PCI_REV_ID:
+ switch (amd_manager->instance) {
+ case ACP_SDW0:
+ amd_manager->num_dout_ports = AMD_ACP63_SDW0_MAX_TX_PORTS;
+ amd_manager->num_din_ports = AMD_ACP63_SDW0_MAX_RX_PORTS;
+ break;
+ case ACP_SDW1:
+ amd_manager->num_dout_ports = AMD_ACP63_SDW1_MAX_TX_PORTS;
+ amd_manager->num_din_ports = AMD_ACP63_SDW1_MAX_RX_PORTS;
+ break;
+ default:
+ return -EINVAL;
+ }
break;
default:
return -EINVAL;
diff --git a/drivers/soundwire/amd_manager.h b/drivers/soundwire/amd_manager.h
index 707065468e05..cc2170e4521e 100644
--- a/drivers/soundwire/amd_manager.h
+++ b/drivers/soundwire/amd_manager.h
@@ -155,12 +155,12 @@
#define AMD_SDW_IRQ_MASK_8TO11 0x000c7777
#define AMD_SDW_IRQ_ERROR_MASK 0xff
#define AMD_SDW_MAX_FREQ_NUM 1
-#define AMD_SDW0_MAX_TX_PORTS 3
-#define AMD_SDW0_MAX_RX_PORTS 3
-#define AMD_SDW1_MAX_TX_PORTS 1
-#define AMD_SDW1_MAX_RX_PORTS 1
-#define AMD_SDW0_MAX_DAI 6
-#define AMD_SDW1_MAX_DAI 2
+#define AMD_ACP63_SDW0_MAX_TX_PORTS 3
+#define AMD_ACP63_SDW0_MAX_RX_PORTS 3
+#define AMD_ACP63_SDW1_MAX_TX_PORTS 1
+#define AMD_ACP63_SDW1_MAX_RX_PORTS 1
+#define AMD_ACP63_SDW0_MAX_DAI 6
+#define AMD_ACP63_SDW1_MAX_DAI 2
#define AMD_SDW_SLAVE_0_ATTACHED 5
#define AMD_SDW_SSP_COUNTER_VAL 3
@@ -222,7 +222,7 @@ struct sdw_manager_dp_reg {
* in SoundWire DMA driver.
*/
-static struct sdw_manager_dp_reg sdw0_manager_dp_reg[AMD_SDW0_MAX_DAI] = {
+static struct sdw_manager_dp_reg acp63_sdw0_dp_reg[AMD_ACP63_SDW0_MAX_DAI] = {
{ACP_SW_AUDIO0_TX_FRAME_FORMAT, ACP_SW_AUDIO0_TX_SAMPLEINTERVAL, ACP_SW_AUDIO0_TX_HCTRL_DP0,
ACP_SW_AUDIO0_TX_OFFSET_DP0, ACP_SW_AUDIO0_TX_CHANNEL_ENABLE_DP0},
{ACP_SW_AUDIO1_TX_FRAME_FORMAT, ACP_SW_AUDIO1_TX_SAMPLEINTERVAL, ACP_SW_AUDIO1_TX_HCTRL,
@@ -237,7 +237,7 @@ static struct sdw_manager_dp_reg sdw0_manager_dp_reg[AMD_SDW0_MAX_DAI] = {
ACP_SW_AUDIO2_RX_OFFSET, ACP_SW_AUDIO2_RX_CHANNEL_ENABLE_DP0},
};
-static struct sdw_manager_dp_reg sdw1_manager_dp_reg[AMD_SDW1_MAX_DAI] = {
+static struct sdw_manager_dp_reg acp63_sdw1_dp_reg[AMD_ACP63_SDW1_MAX_DAI] = {
{ACP_SW_AUDIO1_TX_FRAME_FORMAT, ACP_SW_AUDIO1_TX_SAMPLEINTERVAL, ACP_SW_AUDIO1_TX_HCTRL,
ACP_SW_AUDIO1_TX_OFFSET, ACP_SW_AUDIO1_TX_CHANNEL_ENABLE_DP0},
{ACP_SW_AUDIO1_RX_FRAME_FORMAT, ACP_SW_AUDIO1_RX_SAMPLEINTERVAL, ACP_SW_AUDIO1_RX_HCTRL,
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c
index 263ca32f0c5c..d1dc62c34f1c 100644
--- a/drivers/soundwire/bus.c
+++ b/drivers/soundwire/bus.c
@@ -112,7 +112,7 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent,
/* Set higher order bits */
*bus->assigned = ~GENMASK(SDW_BROADCAST_DEV_NUM, SDW_ENUM_DEV_NUM);
- /* Set enumuration device number and broadcast device number */
+ /* Set enumeration device number and broadcast device number */
set_bit(SDW_ENUM_DEV_NUM, bus->assigned);
set_bit(SDW_BROADCAST_DEV_NUM, bus->assigned);
diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c
index 05652e983539..f367670ea991 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -1378,6 +1378,31 @@ static void cdns_init_clock_ctrl(struct sdw_cdns *cdns)
}
/**
+ * sdw_cdns_soft_reset() - Cadence soft-reset
+ * @cdns: Cadence instance
+ */
+int sdw_cdns_soft_reset(struct sdw_cdns *cdns)
+{
+ int ret;
+
+ cdns_updatel(cdns, CDNS_MCP_CONTROL, CDNS_MCP_CONTROL_SOFT_RST,
+ CDNS_MCP_CONTROL_SOFT_RST);
+
+ ret = cdns_config_update(cdns);
+ if (ret < 0) {
+ dev_err(cdns->dev, "%s: config update failed\n", __func__);
+ return ret;
+ }
+
+ ret = cdns_set_wait(cdns, CDNS_MCP_CONTROL, CDNS_MCP_CONTROL_SOFT_RST, 0);
+ if (ret < 0)
+ dev_err(cdns->dev, "%s: Soft Reset timed out\n", __func__);
+
+ return ret;
+}
+EXPORT_SYMBOL(sdw_cdns_soft_reset);
+
+/**
* sdw_cdns_init() - Cadence initialization
* @cdns: Cadence instance
*/
@@ -1400,6 +1425,11 @@ int sdw_cdns_init(struct sdw_cdns *cdns)
cdns_ip_updatel(cdns, CDNS_IP_MCP_CONTROL, CDNS_IP_MCP_CONTROL_CMD_ACCEPT,
CDNS_IP_MCP_CONTROL_CMD_ACCEPT);
+ /* disable wakeup */
+ cdns_ip_updatel(cdns, CDNS_IP_MCP_CONTROL,
+ CDNS_IP_MCP_CONTROL_BLOCK_WAKEUP,
+ 0);
+
/* Configure mcp config */
val = cdns_readl(cdns, CDNS_MCP_CONFIG);
diff --git a/drivers/soundwire/cadence_master.h b/drivers/soundwire/cadence_master.h
index e1d7969ba48a..c34fb050fe4f 100644
--- a/drivers/soundwire/cadence_master.h
+++ b/drivers/soundwire/cadence_master.h
@@ -168,6 +168,7 @@ int sdw_cdns_probe(struct sdw_cdns *cdns);
irqreturn_t sdw_cdns_irq(int irq, void *dev_id);
irqreturn_t sdw_cdns_thread(int irq, void *dev_id);
+int sdw_cdns_soft_reset(struct sdw_cdns *cdns);
int sdw_cdns_init(struct sdw_cdns *cdns);
int sdw_cdns_pdi_init(struct sdw_cdns *cdns,
struct sdw_cdns_stream_config config);
diff --git a/drivers/soundwire/intel_auxdevice.c b/drivers/soundwire/intel_auxdevice.c
index ae689d5d1ab9..599954d92752 100644
--- a/drivers/soundwire/intel_auxdevice.c
+++ b/drivers/soundwire/intel_auxdevice.c
@@ -41,6 +41,10 @@ static int md_flags;
module_param_named(sdw_md_flags, md_flags, int, 0444);
MODULE_PARM_DESC(sdw_md_flags, "SoundWire Intel Master device flags (0x0 all off)");
+static int mclk_divider;
+module_param_named(sdw_mclk_divider, mclk_divider, int, 0444);
+MODULE_PARM_DESC(sdw_mclk_divider, "SoundWire Intel mclk divider");
+
struct wake_capable_part {
const u16 mfg_id;
const u16 part_id;
@@ -142,8 +146,12 @@ static int sdw_master_read_intel_prop(struct sdw_bus *bus)
"intel-sdw-ip-clock",
&prop->mclk_freq);
- /* the values reported by BIOS are the 2x clock, not the bus clock */
- prop->mclk_freq /= 2;
+ if (mclk_divider)
+ /* use kernel parameter for BIOS or board work-arounds */
+ prop->mclk_freq /= mclk_divider;
+ else
+ /* the values reported by BIOS are the 2x clock, not the bus clock */
+ prop->mclk_freq /= 2;
fwnode_property_read_u32(link,
"intel-quirk-mask",
diff --git a/drivers/soundwire/intel_bus_common.c b/drivers/soundwire/intel_bus_common.c
index d3ff6c65b64c..ad1f8ebdbfc9 100644
--- a/drivers/soundwire/intel_bus_common.c
+++ b/drivers/soundwire/intel_bus_common.c
@@ -16,6 +16,12 @@ int intel_start_bus(struct sdw_intel *sdw)
struct sdw_bus *bus = &cdns->bus;
int ret;
+ ret = sdw_cdns_soft_reset(cdns);
+ if (ret < 0) {
+ dev_err(dev, "%s: unable to soft-reset Cadence IP: %d\n", __func__, ret);
+ return ret;
+ }
+
/*
* follow recommended programming flows to avoid timeouts when
* gsync is enabled
diff --git a/drivers/soundwire/mipi_disco.c b/drivers/soundwire/mipi_disco.c
index e5d9df26d4dc..9d59f486edbe 100644
--- a/drivers/soundwire/mipi_disco.c
+++ b/drivers/soundwire/mipi_disco.c
@@ -23,6 +23,26 @@
#include <linux/soundwire/sdw.h>
#include "bus.h"
+static bool mipi_fwnode_property_read_bool(const struct fwnode_handle *fwnode,
+ const char *propname)
+{
+ int ret;
+ u8 val;
+
+ if (!fwnode_property_present(fwnode, propname))
+ return false;
+ ret = fwnode_property_read_u8_array(fwnode, propname, &val, 1);
+ if (ret < 0)
+ return false;
+ return !!val;
+}
+
+static bool mipi_device_property_read_bool(const struct device *dev,
+ const char *propname)
+{
+ return mipi_fwnode_property_read_bool(dev_fwnode(dev), propname);
+}
+
/**
* sdw_master_read_prop() - Read Master properties
* @bus: SDW bus instance
@@ -31,8 +51,11 @@ int sdw_master_read_prop(struct sdw_bus *bus)
{
struct sdw_master_prop *prop = &bus->prop;
struct fwnode_handle *link;
+ const char *scales_prop;
char name[32];
- int nval, i;
+ int nval;
+ int ret;
+ int i;
device_property_read_u32(bus->dev,
"mipi-sdw-sw-interface-revision",
@@ -48,11 +71,11 @@ int sdw_master_read_prop(struct sdw_bus *bus)
return -EIO;
}
- if (fwnode_property_read_bool(link,
+ if (mipi_fwnode_property_read_bool(link,
"mipi-sdw-clock-stop-mode0-supported"))
prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE0);
- if (fwnode_property_read_bool(link,
+ if (mipi_fwnode_property_read_bool(link,
"mipi-sdw-clock-stop-mode1-supported"))
prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE1);
@@ -71,9 +94,11 @@ int sdw_master_read_prop(struct sdw_bus *bus)
return -ENOMEM;
}
- fwnode_property_read_u32_array(link,
+ ret = fwnode_property_read_u32_array(link,
"mipi-sdw-clock-frequencies-supported",
prop->clk_freq, prop->num_clk_freq);
+ if (ret < 0)
+ return ret;
}
/*
@@ -88,7 +113,12 @@ int sdw_master_read_prop(struct sdw_bus *bus)
}
}
- nval = fwnode_property_count_u32(link, "mipi-sdw-supported-clock-gears");
+ scales_prop = "mipi-sdw-supported-clock-scales";
+ nval = fwnode_property_count_u32(link, scales_prop);
+ if (nval == 0) {
+ scales_prop = "mipi-sdw-supported-clock-gears";
+ nval = fwnode_property_count_u32(link, scales_prop);
+ }
if (nval > 0) {
prop->num_clk_gears = nval;
prop->clk_gears = devm_kcalloc(bus->dev, prop->num_clk_gears,
@@ -99,10 +129,12 @@ int sdw_master_read_prop(struct sdw_bus *bus)
return -ENOMEM;
}
- fwnode_property_read_u32_array(link,
- "mipi-sdw-supported-clock-gears",
+ ret = fwnode_property_read_u32_array(link,
+ scales_prop,
prop->clk_gears,
prop->num_clk_gears);
+ if (ret < 0)
+ return ret;
}
fwnode_property_read_u32(link, "mipi-sdw-default-frame-rate",
@@ -114,7 +146,7 @@ int sdw_master_read_prop(struct sdw_bus *bus)
fwnode_property_read_u32(link, "mipi-sdw-default-frame-col-size",
&prop->default_col);
- prop->dynamic_frame = fwnode_property_read_bool(link,
+ prop->dynamic_frame = mipi_fwnode_property_read_bool(link,
"mipi-sdw-dynamic-frame-shape");
fwnode_property_read_u32(link, "mipi-sdw-command-error-threshold",
@@ -131,6 +163,7 @@ static int sdw_slave_read_dp0(struct sdw_slave *slave,
struct sdw_dp0_prop *dp0)
{
int nval;
+ int ret;
fwnode_property_read_u32(port, "mipi-sdw-port-max-wordlength",
&dp0->max_word);
@@ -148,20 +181,38 @@ static int sdw_slave_read_dp0(struct sdw_slave *slave,
if (!dp0->words)
return -ENOMEM;
- fwnode_property_read_u32_array(port,
+ ret = fwnode_property_read_u32_array(port,
"mipi-sdw-port-wordlength-configs",
dp0->words, dp0->num_words);
+ if (ret < 0)
+ return ret;
}
- dp0->BRA_flow_controlled = fwnode_property_read_bool(port,
+ dp0->BRA_flow_controlled = mipi_fwnode_property_read_bool(port,
"mipi-sdw-bra-flow-controlled");
- dp0->simple_ch_prep_sm = fwnode_property_read_bool(port,
+ dp0->simple_ch_prep_sm = mipi_fwnode_property_read_bool(port,
"mipi-sdw-simplified-channel-prepare-sm");
- dp0->imp_def_interrupts = fwnode_property_read_bool(port,
+ dp0->imp_def_interrupts = mipi_fwnode_property_read_bool(port,
"mipi-sdw-imp-def-dp0-interrupts-supported");
+ nval = fwnode_property_count_u32(port, "mipi-sdw-lane-list");
+ if (nval > 0) {
+ dp0->num_lanes = nval;
+ dp0->lane_list = devm_kcalloc(&slave->dev,
+ dp0->num_lanes, sizeof(*dp0->lane_list),
+ GFP_KERNEL);
+ if (!dp0->lane_list)
+ return -ENOMEM;
+
+ ret = fwnode_property_read_u32_array(port,
+ "mipi-sdw-lane-list",
+ dp0->lane_list, dp0->num_lanes);
+ if (ret < 0)
+ return ret;
+ }
+
return 0;
}
@@ -171,9 +222,10 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave,
{
struct fwnode_handle *node;
u32 bit, i = 0;
- int nval;
unsigned long addr;
char name[40];
+ int nval;
+ int ret;
addr = ports;
/* valid ports are 1 to 14 so apply mask */
@@ -208,9 +260,11 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave,
return -ENOMEM;
}
- fwnode_property_read_u32_array(node,
+ ret = fwnode_property_read_u32_array(node,
"mipi-sdw-port-wordlength-configs",
dpn[i].words, dpn[i].num_words);
+ if (ret < 0)
+ return ret;
}
fwnode_property_read_u32(node, "mipi-sdw-data-port-type",
@@ -220,7 +274,7 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave,
"mipi-sdw-max-grouping-supported",
&dpn[i].max_grouping);
- dpn[i].simple_ch_prep_sm = fwnode_property_read_bool(node,
+ dpn[i].simple_ch_prep_sm = mipi_fwnode_property_read_bool(node,
"mipi-sdw-simplified-channelprepare-sm");
fwnode_property_read_u32(node,
@@ -249,9 +303,11 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave,
return -ENOMEM;
}
- fwnode_property_read_u32_array(node,
+ ret = fwnode_property_read_u32_array(node,
"mipi-sdw-channel-number-list",
dpn[i].channels, dpn[i].num_channels);
+ if (ret < 0)
+ return ret;
}
nval = fwnode_property_count_u32(node, "mipi-sdw-channel-combination-list");
@@ -266,10 +322,12 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave,
return -ENOMEM;
}
- fwnode_property_read_u32_array(node,
+ ret = fwnode_property_read_u32_array(node,
"mipi-sdw-channel-combination-list",
dpn[i].ch_combinations,
dpn[i].num_ch_combinations);
+ if (ret < 0)
+ return ret;
}
fwnode_property_read_u32(node,
@@ -278,13 +336,27 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave,
fwnode_property_read_u32(node, "mipi-sdw-max-async-buffer",
&dpn[i].max_async_buffer);
- dpn[i].block_pack_mode = fwnode_property_read_bool(node,
+ dpn[i].block_pack_mode = mipi_fwnode_property_read_bool(node,
"mipi-sdw-block-packing-mode");
fwnode_property_read_u32(node, "mipi-sdw-port-encoding-type",
&dpn[i].port_encoding);
- /* TODO: Read audio mode */
+ nval = fwnode_property_count_u32(node, "mipi-sdw-lane-list");
+ if (nval > 0) {
+ dpn[i].num_lanes = nval;
+ dpn[i].lane_list = devm_kcalloc(&slave->dev,
+ dpn[i].num_lanes, sizeof(*dpn[i].lane_list),
+ GFP_KERNEL);
+ if (!dpn[i].lane_list)
+ return -ENOMEM;
+
+ ret = fwnode_property_read_u32_array(node,
+ "mipi-sdw-lane-list",
+ dpn[i].lane_list, dpn[i].num_lanes);
+ if (ret < 0)
+ return ret;
+ }
fwnode_handle_put(node);
@@ -304,42 +376,46 @@ int sdw_slave_read_prop(struct sdw_slave *slave)
struct device *dev = &slave->dev;
struct fwnode_handle *port;
int nval;
+ int ret;
device_property_read_u32(dev, "mipi-sdw-sw-interface-revision",
&prop->mipi_revision);
- prop->wake_capable = device_property_read_bool(dev,
+ prop->wake_capable = mipi_device_property_read_bool(dev,
"mipi-sdw-wake-up-unavailable");
prop->wake_capable = !prop->wake_capable;
- prop->test_mode_capable = device_property_read_bool(dev,
+ prop->test_mode_capable = mipi_device_property_read_bool(dev,
"mipi-sdw-test-mode-supported");
prop->clk_stop_mode1 = false;
- if (device_property_read_bool(dev,
+ if (mipi_device_property_read_bool(dev,
"mipi-sdw-clock-stop-mode1-supported"))
prop->clk_stop_mode1 = true;
- prop->simple_clk_stop_capable = device_property_read_bool(dev,
+ prop->simple_clk_stop_capable = mipi_device_property_read_bool(dev,
"mipi-sdw-simplified-clockstopprepare-sm-supported");
device_property_read_u32(dev, "mipi-sdw-clockstopprepare-timeout",
&prop->clk_stop_timeout);
- device_property_read_u32(dev, "mipi-sdw-slave-channelprepare-timeout",
- &prop->ch_prep_timeout);
+ ret = device_property_read_u32(dev, "mipi-sdw-peripheral-channelprepare-timeout",
+ &prop->ch_prep_timeout);
+ if (ret < 0)
+ device_property_read_u32(dev, "mipi-sdw-slave-channelprepare-timeout",
+ &prop->ch_prep_timeout);
device_property_read_u32(dev,
"mipi-sdw-clockstopprepare-hard-reset-behavior",
&prop->reset_behave);
- prop->high_PHY_capable = device_property_read_bool(dev,
+ prop->high_PHY_capable = mipi_device_property_read_bool(dev,
"mipi-sdw-highPHY-capable");
- prop->paging_support = device_property_read_bool(dev,
+ prop->paging_support = mipi_device_property_read_bool(dev,
"mipi-sdw-paging-support");
- prop->bank_delay_support = device_property_read_bool(dev,
+ prop->bank_delay_support = mipi_device_property_read_bool(dev,
"mipi-sdw-bank-delay-support");
device_property_read_u32(dev,
@@ -354,7 +430,17 @@ int sdw_slave_read_prop(struct sdw_slave *slave)
device_property_read_u32(dev, "mipi-sdw-sink-port-list",
&prop->sink_ports);
- /* Read dp0 properties */
+ device_property_read_u32(dev, "mipi-sdw-sdca-interrupt-register-list",
+ &prop->sdca_interrupt_register_list);
+
+ prop->commit_register_supported = mipi_device_property_read_bool(dev,
+ "mipi-sdw-commit-register-supported");
+
+ /*
+ * Read dp0 properties - we don't rely on the 'mipi-sdw-dp-0-supported'
+ * property since the 'mipi-sdw-dp0-subproperties' property is logically
+ * equivalent.
+ */
port = device_get_named_child_node(dev, "mipi-sdw-dp-0-subproperties");
if (!port) {
dev_dbg(dev, "DP0 node not found!!\n");
diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c
index aed57002fd0e..2b403b14066c 100644
--- a/drivers/soundwire/qcom.c
+++ b/drivers/soundwire/qcom.c
@@ -1173,7 +1173,7 @@ static int qcom_swrm_stream_alloc_ports(struct qcom_swrm_ctrl *ctrl,
else
sconfig.direction = SDW_DATA_DIR_RX;
- /* hw parameters wil be ignored as we only support PDM */
+ /* hw parameters will be ignored as we only support PDM */
sconfig.ch_count = 1;
sconfig.frame_rate = params_rate(params);
sconfig.type = stream->type;
diff --git a/drivers/soundwire/sysfs_slave.c b/drivers/soundwire/sysfs_slave.c
index f4259710dd0f..c5c22d1708ec 100644
--- a/drivers/soundwire/sysfs_slave.c
+++ b/drivers/soundwire/sysfs_slave.c
@@ -215,7 +215,7 @@ const struct attribute_group *sdw_attr_groups[] = {
/*
* the status is shown in capital letters for UNATTACHED and RESERVED
- * on purpose, to highligh users to the fact that these status values
+ * on purpose, to highlight users to the fact that these status values
* are not expected.
*/
static const char *const slave_status[] = {
diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h
index 49d690f3d29a..bd9836690da6 100644
--- a/include/linux/soundwire/sdw.h
+++ b/include/linux/soundwire/sdw.h
@@ -4,14 +4,21 @@
#ifndef __SOUNDWIRE_H
#define __SOUNDWIRE_H
+#include <linux/bitfield.h>
#include <linux/bug.h>
-#include <linux/lockdep_types.h>
+#include <linux/completion.h>
+#include <linux/device.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
+#include <linux/lockdep_types.h>
#include <linux/mod_devicetable.h>
-#include <linux/bitfield.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
#include <sound/sdca.h>
+struct dentry;
+struct fwnode_handle;
+
struct sdw_bus;
struct sdw_slave;
@@ -227,64 +234,36 @@ enum sdw_clk_stop_mode {
/**
* struct sdw_dp0_prop - DP0 properties
+ * @words: wordlengths supported
* @max_word: Maximum number of bits in a Payload Channel Sample, 1 to 64
* (inclusive)
* @min_word: Minimum number of bits in a Payload Channel Sample, 1 to 64
* (inclusive)
* @num_words: number of wordlengths supported
- * @words: wordlengths supported
+ * @ch_prep_timeout: Port-specific timeout value, in milliseconds
* @BRA_flow_controlled: Slave implementation results in an OK_NotReady
* response
* @simple_ch_prep_sm: If channel prepare sequence is required
- * @ch_prep_timeout: Port-specific timeout value, in milliseconds
* @imp_def_interrupts: If set, each bit corresponds to support for
* implementation-defined interrupts
+ * @num_lanes: array size of @lane_list
+ * @lane_list: indicates which Lanes can be used by DP0
*
* The wordlengths are specified by Spec as max, min AND number of
* discrete values, implementation can define based on the wordlengths they
* support
*/
struct sdw_dp0_prop {
+ u32 *words;
u32 max_word;
u32 min_word;
u32 num_words;
- u32 *words;
+ u32 ch_prep_timeout;
bool BRA_flow_controlled;
bool simple_ch_prep_sm;
- u32 ch_prep_timeout;
bool imp_def_interrupts;
-};
-
-/**
- * struct sdw_dpn_audio_mode - Audio mode properties for DPn
- * @bus_min_freq: Minimum bus frequency, in Hz
- * @bus_max_freq: Maximum bus frequency, in Hz
- * @bus_num_freq: Number of discrete frequencies supported
- * @bus_freq: Discrete bus frequencies, in Hz
- * @min_freq: Minimum sampling frequency, in Hz
- * @max_freq: Maximum sampling bus frequency, in Hz
- * @num_freq: Number of discrete sampling frequency supported
- * @freq: Discrete sampling frequencies, in Hz
- * @prep_ch_behave: Specifies the dependencies between Channel Prepare
- * sequence and bus clock configuration
- * If 0, Channel Prepare can happen at any Bus clock rate
- * If 1, Channel Prepare sequence shall happen only after Bus clock is
- * changed to a frequency supported by this mode or compatible modes
- * described by the next field
- * @glitchless: Bitmap describing possible glitchless transitions from this
- * Audio Mode to other Audio Modes
- */
-struct sdw_dpn_audio_mode {
- u32 bus_min_freq;
- u32 bus_max_freq;
- u32 bus_num_freq;
- u32 *bus_freq;
- u32 max_freq;
- u32 min_freq;
- u32 num_freq;
- u32 *freq;
- u32 prep_ch_behave;
- u32 glitchless;
+ int num_lanes;
+ u32 *lane_list;
};
/**
@@ -299,24 +278,25 @@ struct sdw_dpn_audio_mode {
* @type: Data port type. Full, Simplified or Reduced
* @max_grouping: Maximum number of samples that can be grouped together for
* a full data port
- * @simple_ch_prep_sm: If the port supports simplified channel prepare state
- * machine
* @ch_prep_timeout: Port-specific timeout value, in milliseconds
* @imp_def_interrupts: If set, each bit corresponds to support for
* implementation-defined interrupts
* @max_ch: Maximum channels supported
* @min_ch: Minimum channels supported
* @num_channels: Number of discrete channels supported
- * @channels: Discrete channels supported
* @num_ch_combinations: Number of channel combinations supported
+ * @channels: Discrete channels supported
* @ch_combinations: Channel combinations supported
+ * @lane_list: indicates which Lanes can be used by DPn
+ * @num_lanes: array size of @lane_list
* @modes: SDW mode supported
* @max_async_buffer: Number of samples that this port can buffer in
* asynchronous modes
+ * @port_encoding: Payload Channel Sample encoding schemes supported
* @block_pack_mode: Type of block port mode supported
* @read_only_wordlength: Read Only wordlength field in DPN_BlockCtrl1 register
- * @port_encoding: Payload Channel Sample encoding schemes supported
- * @audio_modes: Audio modes supported
+ * @simple_ch_prep_sm: If the port supports simplified channel prepare state
+ * machine
*/
struct sdw_dpn_prop {
u32 num;
@@ -326,25 +306,29 @@ struct sdw_dpn_prop {
u32 *words;
enum sdw_dpn_type type;
u32 max_grouping;
- bool simple_ch_prep_sm;
u32 ch_prep_timeout;
u32 imp_def_interrupts;
u32 max_ch;
u32 min_ch;
u32 num_channels;
- u32 *channels;
u32 num_ch_combinations;
+ u32 *channels;
u32 *ch_combinations;
+ u32 *lane_list;
+ int num_lanes;
u32 modes;
u32 max_async_buffer;
+ u32 port_encoding;
bool block_pack_mode;
bool read_only_wordlength;
- u32 port_encoding;
- struct sdw_dpn_audio_mode *audio_modes;
+ bool simple_ch_prep_sm;
};
/**
* struct sdw_slave_prop - SoundWire Slave properties
+ * @dp0_prop: Data Port 0 properties
+ * @src_dpn_prop: Source Data Port N properties
+ * @sink_dpn_prop: Sink Data Port N properties
* @mipi_revision: Spec version of the implementation
* @wake_capable: Wake-up events are supported
* @test_mode_capable: If test mode is supported
@@ -361,23 +345,26 @@ struct sdw_dpn_prop {
* SCP_AddrPage2
* @bank_delay_support: Slave implements bank delay/bridge support registers
* SCP_BankDelay and SCP_NextFrame
+ * @lane_control_support: Slave supports lane control
* @p15_behave: Slave behavior when the Master attempts a read to the Port15
* alias
- * @lane_control_support: Slave supports lane control
* @master_count: Number of Masters present on this Slave
* @source_ports: Bitmap identifying source ports
* @sink_ports: Bitmap identifying sink ports
- * @dp0_prop: Data Port 0 properties
- * @src_dpn_prop: Source Data Port N properties
- * @sink_dpn_prop: Sink Data Port N properties
- * @scp_int1_mask: SCP_INT1_MASK desired settings
* @quirks: bitmask identifying deltas from the MIPI specification
+ * @sdca_interrupt_register_list: indicates which sets of SDCA interrupt status
+ * and masks are supported
+ * @commit_register_supported: is PCP_Commit register supported
+ * @scp_int1_mask: SCP_INT1_MASK desired settings
* @clock_reg_supported: the Peripheral implements the clock base and scale
* registers introduced with the SoundWire 1.2 specification. SDCA devices
* do not need to set this boolean property as the registers are required.
* @use_domain_irq: call actual IRQ handler on slave, as well as callback
*/
struct sdw_slave_prop {
+ struct sdw_dp0_prop *dp0_prop;
+ struct sdw_dpn_prop *src_dpn_prop;
+ struct sdw_dpn_prop *sink_dpn_prop;
u32 mipi_revision;
bool wake_capable;
bool test_mode_capable;
@@ -389,16 +376,15 @@ struct sdw_slave_prop {
bool high_PHY_capable;
bool paging_support;
bool bank_delay_support;
- enum sdw_p15_behave p15_behave;
bool lane_control_support;
+ enum sdw_p15_behave p15_behave;
u32 master_count;
u32 source_ports;
u32 sink_ports;
- struct sdw_dp0_prop *dp0_prop;
- struct sdw_dpn_prop *src_dpn_prop;
- struct sdw_dpn_prop *sink_dpn_prop;
- u8 scp_int1_mask;
u32 quirks;
+ u32 sdca_interrupt_register_list;
+ u8 commit_register_supported;
+ u8 scp_int1_mask;
bool clock_reg_supported;
bool use_domain_irq;
};
@@ -407,13 +393,14 @@ struct sdw_slave_prop {
/**
* struct sdw_master_prop - Master properties
+ * @clk_gears: Clock gears supported
+ * @clk_freq: Clock frequencies supported, in Hz
+ * @quirks: bitmask identifying optional behavior beyond the scope of the MIPI specification
* @revision: MIPI spec version of the implementation
* @clk_stop_modes: Bitmap, bit N set when clock-stop-modeN supported
* @max_clk_freq: Maximum Bus clock frequency, in Hz
* @num_clk_gears: Number of clock gears supported
- * @clk_gears: Clock gears supported
* @num_clk_freq: Number of clock frequencies supported, in Hz
- * @clk_freq: Clock frequencies supported, in Hz
* @default_frame_rate: Controller default Frame rate, in Hz
* @default_row: Number of rows
* @default_col: Number of columns
@@ -422,24 +409,23 @@ struct sdw_slave_prop {
* command
* @mclk_freq: clock reference passed to SoundWire Master, in Hz.
* @hw_disabled: if true, the Master is not functional, typically due to pin-mux
- * @quirks: bitmask identifying optional behavior beyond the scope of the MIPI specification
*/
struct sdw_master_prop {
+ u32 *clk_gears;
+ u32 *clk_freq;
+ u64 quirks;
u32 revision;
u32 clk_stop_modes;
u32 max_clk_freq;
u32 num_clk_gears;
- u32 *clk_gears;
u32 num_clk_freq;
- u32 *clk_freq;
u32 default_frame_rate;
u32 default_row;
u32 default_col;
- bool dynamic_frame;
u32 err_threshold;
u32 mclk_freq;
+ bool dynamic_frame;
bool hw_disabled;
- u64 quirks;
};
/* Definitions for Master quirks */
@@ -631,7 +617,6 @@ struct sdw_slave_ops {
int (*clk_stop)(struct sdw_slave *slave,
enum sdw_clk_stop_mode mode,
enum sdw_clk_stop_type type);
-
};
/**
@@ -707,8 +692,7 @@ struct sdw_master_device {
container_of(d, struct sdw_master_device, dev)
struct sdw_driver {
- int (*probe)(struct sdw_slave *sdw,
- const struct sdw_device_id *id);
+ int (*probe)(struct sdw_slave *sdw, const struct sdw_device_id *id);
int (*remove)(struct sdw_slave *sdw);
void (*shutdown)(struct sdw_slave *sdw);
@@ -727,7 +711,7 @@ struct sdw_driver {
SDW_SLAVE_ENTRY_EXT((_mfg_id), (_part_id), 0, 0, (_drv_data))
int sdw_handle_slave_status(struct sdw_bus *bus,
- enum sdw_slave_status status[]);
+ enum sdw_slave_status status[]);
/*
* SDW master structures and APIs
@@ -809,29 +793,28 @@ struct sdw_enable_ch {
*/
struct sdw_master_port_ops {
int (*dpn_set_port_params)(struct sdw_bus *bus,
- struct sdw_port_params *port_params,
- unsigned int bank);
+ struct sdw_port_params *port_params,
+ unsigned int bank);
int (*dpn_set_port_transport_params)(struct sdw_bus *bus,
- struct sdw_transport_params *transport_params,
- enum sdw_reg_bank bank);
- int (*dpn_port_prep)(struct sdw_bus *bus,
- struct sdw_prepare_ch *prepare_ch);
+ struct sdw_transport_params *transport_params,
+ enum sdw_reg_bank bank);
+ int (*dpn_port_prep)(struct sdw_bus *bus, struct sdw_prepare_ch *prepare_ch);
int (*dpn_port_enable_ch)(struct sdw_bus *bus,
- struct sdw_enable_ch *enable_ch, unsigned int bank);
+ struct sdw_enable_ch *enable_ch, unsigned int bank);
};
struct sdw_msg;
/**
- * struct sdw_defer - SDW deffered message
- * @length: message length
+ * struct sdw_defer - SDW deferred message
* @complete: message completion
* @msg: SDW message
+ * @length: message length
*/
struct sdw_defer {
+ struct sdw_msg *msg;
int length;
struct completion complete;
- struct sdw_msg *msg;
};
/**
@@ -852,14 +835,11 @@ struct sdw_defer {
*/
struct sdw_master_ops {
int (*read_prop)(struct sdw_bus *bus);
- u64 (*override_adr)
- (struct sdw_bus *bus, u64 addr);
- enum sdw_command_response (*xfer_msg)
- (struct sdw_bus *bus, struct sdw_msg *msg);
- enum sdw_command_response (*xfer_msg_defer)
- (struct sdw_bus *bus);
+ u64 (*override_adr)(struct sdw_bus *bus, u64 addr);
+ enum sdw_command_response (*xfer_msg)(struct sdw_bus *bus, struct sdw_msg *msg);
+ enum sdw_command_response (*xfer_msg_defer)(struct sdw_bus *bus);
int (*set_bus_conf)(struct sdw_bus *bus,
- struct sdw_bus_params *params);
+ struct sdw_bus_params *params);
int (*pre_bank_switch)(struct sdw_bus *bus);
int (*post_bank_switch)(struct sdw_bus *bus);
u32 (*read_ping_status)(struct sdw_bus *bus);
@@ -874,68 +854,71 @@ struct sdw_master_ops {
* struct sdw_bus - SoundWire bus
* @dev: Shortcut to &bus->md->dev to avoid changing the entire code.
* @md: Master device
- * @controller_id: system-unique controller ID. If set to -1, the bus @id will be used.
- * @link_id: Link id number, can be 0 to N, unique for each Controller
- * @id: bus system-wide unique id
- * @slaves: list of Slaves on this bus
- * @assigned: Bitmap for Slave device numbers.
- * Bit set implies used number, bit clear implies unused number.
+ * @bus_lock_key: bus lock key associated to @bus_lock
* @bus_lock: bus lock
+ * @slaves: list of Slaves on this bus
+ * @msg_lock_key: message lock key associated to @msg_lock
* @msg_lock: message lock
- * @compute_params: points to Bus resource management implementation
- * @ops: Master callback ops
- * @port_ops: Master port callback ops
- * @params: Current bus parameters
- * @prop: Master properties
- * @vendor_specific_prop: pointer to non-standard properties
* @m_rt_list: List of Master instance of all stream(s) running on Bus. This
* is used to compute and program bus bandwidth, clock, frame shape,
* transport and port parameters
- * @debugfs: Bus debugfs
- * @domain: IRQ domain
* @defer_msg: Defer message
- * @clk_stop_timeout: Clock stop timeout computed
- * @bank_switch_timeout: Bank switch timeout computed
- * @multi_link: Store bus property that indicates if multi links
- * are supported. This flag is populated by drivers after reading
- * appropriate firmware (ACPI/DT).
+ * @params: Current bus parameters
+ * @stream_refcount: number of streams currently using this bus
+ * @ops: Master callback ops
+ * @port_ops: Master port callback ops
+ * @prop: Master properties
+ * @vendor_specific_prop: pointer to non-standard properties
* @hw_sync_min_links: Number of links used by a stream above which
* hardware-based synchronization is required. This value is only
* meaningful if multi_link is set. If set to 1, hardware-based
* synchronization will be used even if a stream only uses a single
* SoundWire segment.
- * @stream_refcount: number of streams currently using this bus
+ * @controller_id: system-unique controller ID. If set to -1, the bus @id will be used.
+ * @link_id: Link id number, can be 0 to N, unique for each Controller
+ * @id: bus system-wide unique id
+ * @compute_params: points to Bus resource management implementation
+ * @assigned: Bitmap for Slave device numbers.
+ * Bit set implies used number, bit clear implies unused number.
+ * @clk_stop_timeout: Clock stop timeout computed
+ * @bank_switch_timeout: Bank switch timeout computed
+ * @domain: IRQ domain
+ * @irq_chip: IRQ chip
+ * @debugfs: Bus debugfs (optional)
+ * @multi_link: Store bus property that indicates if multi links
+ * are supported. This flag is populated by drivers after reading
+ * appropriate firmware (ACPI/DT).
*/
struct sdw_bus {
struct device *dev;
struct sdw_master_device *md;
- int controller_id;
- unsigned int link_id;
- int id;
- struct list_head slaves;
- DECLARE_BITMAP(assigned, SDW_MAX_DEVICES);
- struct mutex bus_lock;
struct lock_class_key bus_lock_key;
- struct mutex msg_lock;
+ struct mutex bus_lock;
+ struct list_head slaves;
struct lock_class_key msg_lock_key;
- int (*compute_params)(struct sdw_bus *bus);
+ struct mutex msg_lock;
+ struct list_head m_rt_list;
+ struct sdw_defer defer_msg;
+ struct sdw_bus_params params;
+ int stream_refcount;
const struct sdw_master_ops *ops;
const struct sdw_master_port_ops *port_ops;
- struct sdw_bus_params params;
struct sdw_master_prop prop;
void *vendor_specific_prop;
- struct list_head m_rt_list;
+ int hw_sync_min_links;
+ int controller_id;
+ unsigned int link_id;
+ int id;
+ int (*compute_params)(struct sdw_bus *bus);
+ DECLARE_BITMAP(assigned, SDW_MAX_DEVICES);
+ unsigned int clk_stop_timeout;
+ u32 bank_switch_timeout;
+ struct irq_chip irq_chip;
+ struct irq_domain *domain;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs;
#endif
- struct irq_chip irq_chip;
- struct irq_domain *domain;
- struct sdw_defer defer_msg;
- unsigned int clk_stop_timeout;
- u32 bank_switch_timeout;
bool multi_link;
- int hw_sync_min_links;
- int stream_refcount;
};
int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent,
@@ -1013,18 +996,18 @@ struct sdw_stream_params {
* @params: Stream parameters
* @state: Current state of the stream
* @type: Stream type PCM or PDM
+ * @m_rt_count: Count of Master runtime(s) in this stream
* @master_list: List of Master runtime(s) in this stream.
* master_list can contain only one m_rt per Master instance
* for a stream
- * @m_rt_count: Count of Master runtime(s) in this stream
*/
struct sdw_stream_runtime {
const char *name;
struct sdw_stream_params params;
enum sdw_stream_state state;
enum sdw_stream_type type;
- struct list_head master_list;
int m_rt_count;
+ struct list_head master_list;
};
struct sdw_stream_runtime *sdw_alloc_stream(const char *stream_name);
@@ -1033,12 +1016,12 @@ void sdw_release_stream(struct sdw_stream_runtime *stream);
int sdw_compute_params(struct sdw_bus *bus);
int sdw_stream_add_master(struct sdw_bus *bus,
- struct sdw_stream_config *stream_config,
- const struct sdw_port_config *port_config,
- unsigned int num_ports,
- struct sdw_stream_runtime *stream);
+ struct sdw_stream_config *stream_config,
+ const struct sdw_port_config *port_config,
+ unsigned int num_ports,
+ struct sdw_stream_runtime *stream);
int sdw_stream_remove_master(struct sdw_bus *bus,
- struct sdw_stream_runtime *stream);
+ struct sdw_stream_runtime *stream);
int sdw_startup_stream(void *sdw_substream);
int sdw_prepare_stream(struct sdw_stream_runtime *stream);
int sdw_enable_stream(struct sdw_stream_runtime *stream);
diff --git a/include/linux/soundwire/sdw_amd.h b/include/linux/soundwire/sdw_amd.h
index 585b4c58a8a6..799f8578137b 100644
--- a/include/linux/soundwire/sdw_amd.h
+++ b/include/linux/soundwire/sdw_amd.h
@@ -27,9 +27,11 @@
#define ACP_SDW0 0
#define ACP_SDW1 1
#define AMD_SDW_MAX_MANAGER_COUNT 2
+#define ACP63_PCI_REV_ID 0x63
struct acp_sdw_pdata {
u16 instance;
+ u32 acp_rev;
/* mutex to protect acp common register access */
struct mutex *acp_sdw_lock;
};
@@ -66,6 +68,7 @@ struct sdw_amd_dai_runtime {
* @instance: SoundWire manager instance
* @quirks: SoundWire manager quirks
* @wake_en_mask: wake enable mask per SoundWire manager
+ * @acp_rev: acp pci device revision id
* @clk_stopped: flag set to true when clock is stopped
* @power_mode_mask: flag interprets amd SoundWire manager power mode
* @dai_runtime_array: dai runtime array
@@ -94,6 +97,7 @@ struct amd_sdw_manager {
u32 quirks;
u32 wake_en_mask;
u32 power_mode_mask;
+ u32 acp_rev;
bool clk_stopped;
struct sdw_amd_dai_runtime **dai_runtime_array;
@@ -131,6 +135,7 @@ struct sdw_amd_ctx {
* struct sdw_amd_res - Soundwire AMD global resource structure,
* typically populated by the DSP driver/Legacy driver
*
+ * @acp_rev: acp pci device revision id
* @addr: acp pci device resource start address
* @reg_range: ACP register range
* @link_mask: bit-wise mask listing links selected by the DSP driver/
@@ -143,6 +148,7 @@ struct sdw_amd_ctx {
* @acp_lock: mutex protecting acp common registers access
*/
struct sdw_amd_res {
+ u32 acp_rev;
u32 addr;
u32 reg_range;
u32 link_mask;
diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h
index 39208305dd6c..e54eabaa4d3e 100644
--- a/sound/soc/amd/ps/acp63.h
+++ b/sound/soc/amd/ps/acp63.h
@@ -231,6 +231,7 @@ struct sdw_dma_ring_buf_reg {
* @sdw_en_stat: flag set to true when any one of the SoundWire manager instance is enabled
* @addr: pci ioremap address
* @reg_range: ACP reigister range
+ * @acp_rev: ACP PCI revision id
* @sdw0-dma_intr_stat: DMA interrupt status array for SoundWire manager-SW0 instance
* @sdw_dma_intr_stat: DMA interrupt status array for SoundWire manager-SW1 instance
*/
@@ -254,6 +255,7 @@ struct acp63_dev_data {
bool sdw_en_stat;
u32 addr;
u32 reg_range;
+ u32 acp_rev;
u16 sdw0_dma_intr_stat[ACP63_SDW0_DMA_MAX_STREAMS];
u16 sdw1_dma_intr_stat[ACP63_SDW1_DMA_MAX_STREAMS];
};
diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c
index a7583844f5b4..aef73ec6f7ef 100644
--- a/sound/soc/amd/ps/pci-ps.c
+++ b/sound/soc/amd/ps/pci-ps.c
@@ -267,6 +267,7 @@ static int amd_sdw_probe(struct device *dev)
sdw_res.acp_lock = &acp_data->acp_lock;
sdw_res.count = acp_data->info.count;
sdw_res.mmio_base = acp_data->acp63_base;
+ sdw_res.acp_rev = acp_data->acp_rev;
sdw_res.link_mask = acp_data->info.link_mask;
ret = sdw_amd_probe(&sdw_res, &acp_data->sdw);
if (ret)
@@ -575,6 +576,7 @@ static int snd_acp63_probe(struct pci_dev *pci,
}
adata->addr = addr;
adata->reg_range = ACP63_REG_END - ACP63_REG_START;
+ adata->acp_rev = pci->revision;
pci_set_master(pci);
pci_set_drvdata(pci, adata);
mutex_init(&adata->acp_lock);
diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c
index 95d4762c9d93..f7814dadf3ba 100644
--- a/sound/soc/sof/amd/acp.c
+++ b/sound/soc/sof/amd/acp.c
@@ -693,6 +693,7 @@ static int amd_sof_sdw_probe(struct snd_sof_dev *sdev)
sdw_res.count = acp_data->info.count;
sdw_res.link_mask = acp_data->info.link_mask;
sdw_res.mmio_base = sdev->bar[ACP_DSP_BAR];
+ sdw_res.acp_rev = acp_data->pci_rev;
ret = sdw_amd_probe(&sdw_res, &acp_data->sdw);
if (ret)