mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-28 16:52:18 +00:00
soundwire updates for 6.13
- 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 -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE+vs47OPLdNbVcHzyfBQHDyUjg0cFAmdEgiMACgkQfBQHDyUj g0dVBA/+MWwHs+Sl7LMSmkpGsfAsmSbD2il+v+9WcVnaQpl/dgv8EXPGbafBBgK/ AlVUvLCNdbwY93wCb/2xdGPOJS699D7AtdJnUEppcL2VsMtEbgQxyG0OSekRVH0c NxVLNPVLQFQnZayh7MNflQNVrXJyEqUJg8n0G9G1KT7jTeMavejYhqmhN7TKNtLD vJzF79QFC2n7+f7jK9+d2pJlhW5V3XUyQCRF6FipftKbuZN+ciVh9kjnAf1GjPsi qpv7kRZ3ttZiYW+/8FjJxqChnT10b/ahRDwJTXE+uGhqxHD9Cjo/GYrzUtQQbDR2 uvZ6+o0UxhN3HR5Dq09FJYPluHpt8S/s/wZ0dj+dXlvPR82qT6LA9LP16BFwYj3S 36/DpGwJBYg3tsmwECKbY08t3aI1d8nXNKG0tXbkEU3RUWVeOJOLAyXbwYQ9DRGN k3RbTTEZiw223FlgAk9dzCI6mMuekdh20UWVH7iZwUl8ZvJhWNdWiZOV4uaUcGZS fmJ6JE7cM1ntv5rXjKIhhnTnoL5Z+3es3PjLxj8PE7VNC8Dlln67FF1NuoDd0uF0 jWA13iNUOKgytsx2jxAxWnU8S3SAPjB1+GD65ovMxH+b9xtgwhtmCcpySJaG4/Pn P7F7dx1+bK8gbmc5xJf8ZddYeDF/Nb/493trk+Sf+zZSs+hevRY= =3Ob7 -----END PGP SIGNATURE----- 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 ...
This commit is contained in:
commit
9ad55a67a7
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -1377,6 +1377,31 @@ static void cdns_init_clock_ctrl(struct sdw_cdns *cdns)
|
||||
cdns_writel(cdns, CDNS_MCP_SSP_CTRL1, ssp_interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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[] = {
|
||||
|
@ -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;
|
||||
struct lock_class_key bus_lock_key;
|
||||
struct mutex bus_lock;
|
||||
struct list_head slaves;
|
||||
struct lock_class_key msg_lock_key;
|
||||
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_master_prop prop;
|
||||
void *vendor_specific_prop;
|
||||
int hw_sync_min_links;
|
||||
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 lock_class_key msg_lock_key;
|
||||
int (*compute_params)(struct sdw_bus *bus);
|
||||
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;
|
||||
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);
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user