mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 17:25:38 +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.
|
SCSI Appropriate SCSI support is enabled.
|
||||||
A lot of drivers have their options described inside
|
A lot of drivers have their options described inside
|
||||||
the Documentation/scsi/ sub-directory.
|
the Documentation/scsi/ sub-directory.
|
||||||
|
SDW SoundWire support is enabled.
|
||||||
SECURITY Different security models are enabled.
|
SECURITY Different security models are enabled.
|
||||||
SELINUX SELinux support is enabled.
|
SELINUX SELinux support is enabled.
|
||||||
SERIAL Serial support is enabled.
|
SERIAL Serial support is enabled.
|
||||||
|
@ -6075,6 +6075,10 @@
|
|||||||
non-zero "wait" parameter. See weight_single
|
non-zero "wait" parameter. See weight_single
|
||||||
and weight_many.
|
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
|
skew_tick= [KNL,EARLY] Offset the periodic timer tick per cpu to mitigate
|
||||||
xtime_lock contention on larger systems, and/or RCU lock
|
xtime_lock contention on larger systems, and/or RCU lock
|
||||||
contention on all systems with CONFIG_MAXSMP set.
|
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].instance = index;
|
||||||
sdw_pdata[index].acp_sdw_lock = res->acp_lock;
|
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].name = "amd_sdw_manager";
|
||||||
pdevinfo[index].id = index;
|
pdevinfo[index].id = index;
|
||||||
pdevinfo[index].parent = res->parent;
|
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;
|
u32 frame_fmt_reg, dpn_frame_fmt;
|
||||||
|
|
||||||
dev_dbg(amd_manager->dev, "p_params->num:0x%x\n", p_params->num);
|
dev_dbg(amd_manager->dev, "p_params->num:0x%x\n", p_params->num);
|
||||||
switch (amd_manager->instance) {
|
switch (amd_manager->acp_rev) {
|
||||||
case ACP_SDW0:
|
case ACP63_PCI_REV_ID:
|
||||||
frame_fmt_reg = sdw0_manager_dp_reg[p_params->num].frame_fmt_reg;
|
switch (amd_manager->instance) {
|
||||||
break;
|
case ACP_SDW0:
|
||||||
case ACP_SDW1:
|
frame_fmt_reg = acp63_sdw0_dp_reg[p_params->num].frame_fmt_reg;
|
||||||
frame_fmt_reg = sdw1_manager_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;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
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 frame_fmt_reg, sample_int_reg, hctrl_dp0_reg;
|
||||||
u32 offset_reg, lane_ctrl_ch_en_reg;
|
u32 offset_reg, lane_ctrl_ch_en_reg;
|
||||||
|
|
||||||
switch (amd_manager->instance) {
|
switch (amd_manager->acp_rev) {
|
||||||
case ACP_SDW0:
|
case ACP63_PCI_REV_ID:
|
||||||
frame_fmt_reg = sdw0_manager_dp_reg[params->port_num].frame_fmt_reg;
|
switch (amd_manager->instance) {
|
||||||
sample_int_reg = sdw0_manager_dp_reg[params->port_num].sample_int_reg;
|
case ACP_SDW0:
|
||||||
hctrl_dp0_reg = sdw0_manager_dp_reg[params->port_num].hctrl_dp0_reg;
|
frame_fmt_reg = acp63_sdw0_dp_reg[params->port_num].frame_fmt_reg;
|
||||||
offset_reg = sdw0_manager_dp_reg[params->port_num].offset_reg;
|
sample_int_reg = acp63_sdw0_dp_reg[params->port_num].sample_int_reg;
|
||||||
lane_ctrl_ch_en_reg = sdw0_manager_dp_reg[params->port_num].lane_ctrl_ch_en_reg;
|
hctrl_dp0_reg = acp63_sdw0_dp_reg[params->port_num].hctrl_dp0_reg;
|
||||||
break;
|
offset_reg = acp63_sdw0_dp_reg[params->port_num].offset_reg;
|
||||||
case ACP_SDW1:
|
lane_ctrl_ch_en_reg =
|
||||||
frame_fmt_reg = sdw1_manager_dp_reg[params->port_num].frame_fmt_reg;
|
acp63_sdw0_dp_reg[params->port_num].lane_ctrl_ch_en_reg;
|
||||||
sample_int_reg = sdw1_manager_dp_reg[params->port_num].sample_int_reg;
|
break;
|
||||||
hctrl_dp0_reg = sdw1_manager_dp_reg[params->port_num].hctrl_dp0_reg;
|
case ACP_SDW1:
|
||||||
offset_reg = sdw1_manager_dp_reg[params->port_num].offset_reg;
|
frame_fmt_reg = acp63_sdw1_dp_reg[params->port_num].frame_fmt_reg;
|
||||||
lane_ctrl_ch_en_reg = sdw1_manager_dp_reg[params->port_num].lane_ctrl_ch_en_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;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -520,12 +534,20 @@ static int amd_sdw_port_enable(struct sdw_bus *bus,
|
|||||||
u32 dpn_ch_enable;
|
u32 dpn_ch_enable;
|
||||||
u32 lane_ctrl_ch_en_reg;
|
u32 lane_ctrl_ch_en_reg;
|
||||||
|
|
||||||
switch (amd_manager->instance) {
|
switch (amd_manager->acp_rev) {
|
||||||
case ACP_SDW0:
|
case ACP63_PCI_REV_ID:
|
||||||
lane_ctrl_ch_en_reg = sdw0_manager_dp_reg[enable_ch->port_num].lane_ctrl_ch_en_reg;
|
switch (amd_manager->instance) {
|
||||||
break;
|
case ACP_SDW0:
|
||||||
case ACP_SDW1:
|
lane_ctrl_ch_en_reg =
|
||||||
lane_ctrl_ch_en_reg = sdw1_manager_dp_reg[enable_ch->port_num].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;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
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->mmio = amd_manager->acp_mmio +
|
||||||
(amd_manager->instance * SDW_MANAGER_REG_OFFSET);
|
(amd_manager->instance * SDW_MANAGER_REG_OFFSET);
|
||||||
amd_manager->acp_sdw_lock = pdata->acp_sdw_lock;
|
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->cols_index = sdw_find_col_index(AMD_SDW_DEFAULT_COLUMNS);
|
||||||
amd_manager->rows_index = sdw_find_row_index(AMD_SDW_DEFAULT_ROWS);
|
amd_manager->rows_index = sdw_find_row_index(AMD_SDW_DEFAULT_ROWS);
|
||||||
amd_manager->dev = dev;
|
amd_manager->dev = dev;
|
||||||
@ -926,15 +949,21 @@ static int amd_sdw_manager_probe(struct platform_device *pdev)
|
|||||||
* information.
|
* information.
|
||||||
*/
|
*/
|
||||||
amd_manager->bus.controller_id = 0;
|
amd_manager->bus.controller_id = 0;
|
||||||
|
dev_dbg(dev, "acp_rev:0x%x\n", amd_manager->acp_rev);
|
||||||
switch (amd_manager->instance) {
|
switch (amd_manager->acp_rev) {
|
||||||
case ACP_SDW0:
|
case ACP63_PCI_REV_ID:
|
||||||
amd_manager->num_dout_ports = AMD_SDW0_MAX_TX_PORTS;
|
switch (amd_manager->instance) {
|
||||||
amd_manager->num_din_ports = AMD_SDW0_MAX_RX_PORTS;
|
case ACP_SDW0:
|
||||||
break;
|
amd_manager->num_dout_ports = AMD_ACP63_SDW0_MAX_TX_PORTS;
|
||||||
case ACP_SDW1:
|
amd_manager->num_din_ports = AMD_ACP63_SDW0_MAX_RX_PORTS;
|
||||||
amd_manager->num_dout_ports = AMD_SDW1_MAX_TX_PORTS;
|
break;
|
||||||
amd_manager->num_din_ports = AMD_SDW1_MAX_RX_PORTS;
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -155,12 +155,12 @@
|
|||||||
#define AMD_SDW_IRQ_MASK_8TO11 0x000c7777
|
#define AMD_SDW_IRQ_MASK_8TO11 0x000c7777
|
||||||
#define AMD_SDW_IRQ_ERROR_MASK 0xff
|
#define AMD_SDW_IRQ_ERROR_MASK 0xff
|
||||||
#define AMD_SDW_MAX_FREQ_NUM 1
|
#define AMD_SDW_MAX_FREQ_NUM 1
|
||||||
#define AMD_SDW0_MAX_TX_PORTS 3
|
#define AMD_ACP63_SDW0_MAX_TX_PORTS 3
|
||||||
#define AMD_SDW0_MAX_RX_PORTS 3
|
#define AMD_ACP63_SDW0_MAX_RX_PORTS 3
|
||||||
#define AMD_SDW1_MAX_TX_PORTS 1
|
#define AMD_ACP63_SDW1_MAX_TX_PORTS 1
|
||||||
#define AMD_SDW1_MAX_RX_PORTS 1
|
#define AMD_ACP63_SDW1_MAX_RX_PORTS 1
|
||||||
#define AMD_SDW0_MAX_DAI 6
|
#define AMD_ACP63_SDW0_MAX_DAI 6
|
||||||
#define AMD_SDW1_MAX_DAI 2
|
#define AMD_ACP63_SDW1_MAX_DAI 2
|
||||||
#define AMD_SDW_SLAVE_0_ATTACHED 5
|
#define AMD_SDW_SLAVE_0_ATTACHED 5
|
||||||
#define AMD_SDW_SSP_COUNTER_VAL 3
|
#define AMD_SDW_SSP_COUNTER_VAL 3
|
||||||
|
|
||||||
@ -222,7 +222,7 @@ struct sdw_manager_dp_reg {
|
|||||||
* in SoundWire DMA driver.
|
* 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_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_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,
|
{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},
|
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_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_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,
|
{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 */
|
/* Set higher order bits */
|
||||||
*bus->assigned = ~GENMASK(SDW_BROADCAST_DEV_NUM, SDW_ENUM_DEV_NUM);
|
*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_ENUM_DEV_NUM, bus->assigned);
|
||||||
set_bit(SDW_BROADCAST_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);
|
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
|
* sdw_cdns_init() - Cadence initialization
|
||||||
* @cdns: Cadence instance
|
* @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_updatel(cdns, CDNS_IP_MCP_CONTROL, CDNS_IP_MCP_CONTROL_CMD_ACCEPT,
|
||||||
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 */
|
/* Configure mcp config */
|
||||||
val = cdns_readl(cdns, CDNS_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_irq(int irq, void *dev_id);
|
||||||
irqreturn_t sdw_cdns_thread(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_init(struct sdw_cdns *cdns);
|
||||||
int sdw_cdns_pdi_init(struct sdw_cdns *cdns,
|
int sdw_cdns_pdi_init(struct sdw_cdns *cdns,
|
||||||
struct sdw_cdns_stream_config config);
|
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_param_named(sdw_md_flags, md_flags, int, 0444);
|
||||||
MODULE_PARM_DESC(sdw_md_flags, "SoundWire Intel Master device flags (0x0 all off)");
|
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 {
|
struct wake_capable_part {
|
||||||
const u16 mfg_id;
|
const u16 mfg_id;
|
||||||
const u16 part_id;
|
const u16 part_id;
|
||||||
@ -142,8 +146,12 @@ static int sdw_master_read_intel_prop(struct sdw_bus *bus)
|
|||||||
"intel-sdw-ip-clock",
|
"intel-sdw-ip-clock",
|
||||||
&prop->mclk_freq);
|
&prop->mclk_freq);
|
||||||
|
|
||||||
/* the values reported by BIOS are the 2x clock, not the bus clock */
|
if (mclk_divider)
|
||||||
prop->mclk_freq /= 2;
|
/* 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,
|
fwnode_property_read_u32(link,
|
||||||
"intel-quirk-mask",
|
"intel-quirk-mask",
|
||||||
|
@ -16,6 +16,12 @@ int intel_start_bus(struct sdw_intel *sdw)
|
|||||||
struct sdw_bus *bus = &cdns->bus;
|
struct sdw_bus *bus = &cdns->bus;
|
||||||
int ret;
|
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
|
* follow recommended programming flows to avoid timeouts when
|
||||||
* gsync is enabled
|
* gsync is enabled
|
||||||
|
@ -23,6 +23,26 @@
|
|||||||
#include <linux/soundwire/sdw.h>
|
#include <linux/soundwire/sdw.h>
|
||||||
#include "bus.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
|
* sdw_master_read_prop() - Read Master properties
|
||||||
* @bus: SDW bus instance
|
* @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 sdw_master_prop *prop = &bus->prop;
|
||||||
struct fwnode_handle *link;
|
struct fwnode_handle *link;
|
||||||
|
const char *scales_prop;
|
||||||
char name[32];
|
char name[32];
|
||||||
int nval, i;
|
int nval;
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
device_property_read_u32(bus->dev,
|
device_property_read_u32(bus->dev,
|
||||||
"mipi-sdw-sw-interface-revision",
|
"mipi-sdw-sw-interface-revision",
|
||||||
@ -48,11 +71,11 @@ int sdw_master_read_prop(struct sdw_bus *bus)
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fwnode_property_read_bool(link,
|
if (mipi_fwnode_property_read_bool(link,
|
||||||
"mipi-sdw-clock-stop-mode0-supported"))
|
"mipi-sdw-clock-stop-mode0-supported"))
|
||||||
prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE0);
|
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"))
|
"mipi-sdw-clock-stop-mode1-supported"))
|
||||||
prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE1);
|
prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE1);
|
||||||
|
|
||||||
@ -71,9 +94,11 @@ int sdw_master_read_prop(struct sdw_bus *bus)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
fwnode_property_read_u32_array(link,
|
ret = fwnode_property_read_u32_array(link,
|
||||||
"mipi-sdw-clock-frequencies-supported",
|
"mipi-sdw-clock-frequencies-supported",
|
||||||
prop->clk_freq, prop->num_clk_freq);
|
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) {
|
if (nval > 0) {
|
||||||
prop->num_clk_gears = nval;
|
prop->num_clk_gears = nval;
|
||||||
prop->clk_gears = devm_kcalloc(bus->dev, prop->num_clk_gears,
|
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;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
fwnode_property_read_u32_array(link,
|
ret = fwnode_property_read_u32_array(link,
|
||||||
"mipi-sdw-supported-clock-gears",
|
scales_prop,
|
||||||
prop->clk_gears,
|
prop->clk_gears,
|
||||||
prop->num_clk_gears);
|
prop->num_clk_gears);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
fwnode_property_read_u32(link, "mipi-sdw-default-frame-rate",
|
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",
|
fwnode_property_read_u32(link, "mipi-sdw-default-frame-col-size",
|
||||||
&prop->default_col);
|
&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");
|
"mipi-sdw-dynamic-frame-shape");
|
||||||
|
|
||||||
fwnode_property_read_u32(link, "mipi-sdw-command-error-threshold",
|
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)
|
struct sdw_dp0_prop *dp0)
|
||||||
{
|
{
|
||||||
int nval;
|
int nval;
|
||||||
|
int ret;
|
||||||
|
|
||||||
fwnode_property_read_u32(port, "mipi-sdw-port-max-wordlength",
|
fwnode_property_read_u32(port, "mipi-sdw-port-max-wordlength",
|
||||||
&dp0->max_word);
|
&dp0->max_word);
|
||||||
@ -148,20 +181,38 @@ static int sdw_slave_read_dp0(struct sdw_slave *slave,
|
|||||||
if (!dp0->words)
|
if (!dp0->words)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
fwnode_property_read_u32_array(port,
|
ret = fwnode_property_read_u32_array(port,
|
||||||
"mipi-sdw-port-wordlength-configs",
|
"mipi-sdw-port-wordlength-configs",
|
||||||
dp0->words, dp0->num_words);
|
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");
|
"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");
|
"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");
|
"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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,9 +222,10 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave,
|
|||||||
{
|
{
|
||||||
struct fwnode_handle *node;
|
struct fwnode_handle *node;
|
||||||
u32 bit, i = 0;
|
u32 bit, i = 0;
|
||||||
int nval;
|
|
||||||
unsigned long addr;
|
unsigned long addr;
|
||||||
char name[40];
|
char name[40];
|
||||||
|
int nval;
|
||||||
|
int ret;
|
||||||
|
|
||||||
addr = ports;
|
addr = ports;
|
||||||
/* valid ports are 1 to 14 so apply mask */
|
/* 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;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
fwnode_property_read_u32_array(node,
|
ret = fwnode_property_read_u32_array(node,
|
||||||
"mipi-sdw-port-wordlength-configs",
|
"mipi-sdw-port-wordlength-configs",
|
||||||
dpn[i].words, dpn[i].num_words);
|
dpn[i].words, dpn[i].num_words);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
fwnode_property_read_u32(node, "mipi-sdw-data-port-type",
|
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",
|
"mipi-sdw-max-grouping-supported",
|
||||||
&dpn[i].max_grouping);
|
&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");
|
"mipi-sdw-simplified-channelprepare-sm");
|
||||||
|
|
||||||
fwnode_property_read_u32(node,
|
fwnode_property_read_u32(node,
|
||||||
@ -249,9 +303,11 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave,
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
fwnode_property_read_u32_array(node,
|
ret = fwnode_property_read_u32_array(node,
|
||||||
"mipi-sdw-channel-number-list",
|
"mipi-sdw-channel-number-list",
|
||||||
dpn[i].channels, dpn[i].num_channels);
|
dpn[i].channels, dpn[i].num_channels);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
nval = fwnode_property_count_u32(node, "mipi-sdw-channel-combination-list");
|
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;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
fwnode_property_read_u32_array(node,
|
ret = fwnode_property_read_u32_array(node,
|
||||||
"mipi-sdw-channel-combination-list",
|
"mipi-sdw-channel-combination-list",
|
||||||
dpn[i].ch_combinations,
|
dpn[i].ch_combinations,
|
||||||
dpn[i].num_ch_combinations);
|
dpn[i].num_ch_combinations);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
fwnode_property_read_u32(node,
|
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",
|
fwnode_property_read_u32(node, "mipi-sdw-max-async-buffer",
|
||||||
&dpn[i].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");
|
"mipi-sdw-block-packing-mode");
|
||||||
|
|
||||||
fwnode_property_read_u32(node, "mipi-sdw-port-encoding-type",
|
fwnode_property_read_u32(node, "mipi-sdw-port-encoding-type",
|
||||||
&dpn[i].port_encoding);
|
&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);
|
fwnode_handle_put(node);
|
||||||
|
|
||||||
@ -304,42 +376,46 @@ int sdw_slave_read_prop(struct sdw_slave *slave)
|
|||||||
struct device *dev = &slave->dev;
|
struct device *dev = &slave->dev;
|
||||||
struct fwnode_handle *port;
|
struct fwnode_handle *port;
|
||||||
int nval;
|
int nval;
|
||||||
|
int ret;
|
||||||
|
|
||||||
device_property_read_u32(dev, "mipi-sdw-sw-interface-revision",
|
device_property_read_u32(dev, "mipi-sdw-sw-interface-revision",
|
||||||
&prop->mipi_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");
|
"mipi-sdw-wake-up-unavailable");
|
||||||
prop->wake_capable = !prop->wake_capable;
|
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");
|
"mipi-sdw-test-mode-supported");
|
||||||
|
|
||||||
prop->clk_stop_mode1 = false;
|
prop->clk_stop_mode1 = false;
|
||||||
if (device_property_read_bool(dev,
|
if (mipi_device_property_read_bool(dev,
|
||||||
"mipi-sdw-clock-stop-mode1-supported"))
|
"mipi-sdw-clock-stop-mode1-supported"))
|
||||||
prop->clk_stop_mode1 = true;
|
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");
|
"mipi-sdw-simplified-clockstopprepare-sm-supported");
|
||||||
|
|
||||||
device_property_read_u32(dev, "mipi-sdw-clockstopprepare-timeout",
|
device_property_read_u32(dev, "mipi-sdw-clockstopprepare-timeout",
|
||||||
&prop->clk_stop_timeout);
|
&prop->clk_stop_timeout);
|
||||||
|
|
||||||
device_property_read_u32(dev, "mipi-sdw-slave-channelprepare-timeout",
|
ret = device_property_read_u32(dev, "mipi-sdw-peripheral-channelprepare-timeout",
|
||||||
&prop->ch_prep_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,
|
device_property_read_u32(dev,
|
||||||
"mipi-sdw-clockstopprepare-hard-reset-behavior",
|
"mipi-sdw-clockstopprepare-hard-reset-behavior",
|
||||||
&prop->reset_behave);
|
&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");
|
"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");
|
"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");
|
"mipi-sdw-bank-delay-support");
|
||||||
|
|
||||||
device_property_read_u32(dev,
|
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",
|
device_property_read_u32(dev, "mipi-sdw-sink-port-list",
|
||||||
&prop->sink_ports);
|
&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");
|
port = device_get_named_child_node(dev, "mipi-sdw-dp-0-subproperties");
|
||||||
if (!port) {
|
if (!port) {
|
||||||
dev_dbg(dev, "DP0 node not found!!\n");
|
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
|
else
|
||||||
sconfig.direction = SDW_DATA_DIR_RX;
|
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.ch_count = 1;
|
||||||
sconfig.frame_rate = params_rate(params);
|
sconfig.frame_rate = params_rate(params);
|
||||||
sconfig.type = stream->type;
|
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
|
* 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.
|
* are not expected.
|
||||||
*/
|
*/
|
||||||
static const char *const slave_status[] = {
|
static const char *const slave_status[] = {
|
||||||
|
@ -4,14 +4,21 @@
|
|||||||
#ifndef __SOUNDWIRE_H
|
#ifndef __SOUNDWIRE_H
|
||||||
#define __SOUNDWIRE_H
|
#define __SOUNDWIRE_H
|
||||||
|
|
||||||
|
#include <linux/bitfield.h>
|
||||||
#include <linux/bug.h>
|
#include <linux/bug.h>
|
||||||
#include <linux/lockdep_types.h>
|
#include <linux/completion.h>
|
||||||
|
#include <linux/device.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/irqdomain.h>
|
#include <linux/irqdomain.h>
|
||||||
|
#include <linux/lockdep_types.h>
|
||||||
#include <linux/mod_devicetable.h>
|
#include <linux/mod_devicetable.h>
|
||||||
#include <linux/bitfield.h>
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/types.h>
|
||||||
#include <sound/sdca.h>
|
#include <sound/sdca.h>
|
||||||
|
|
||||||
|
struct dentry;
|
||||||
|
struct fwnode_handle;
|
||||||
|
|
||||||
struct sdw_bus;
|
struct sdw_bus;
|
||||||
struct sdw_slave;
|
struct sdw_slave;
|
||||||
|
|
||||||
@ -227,64 +234,36 @@ enum sdw_clk_stop_mode {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* struct sdw_dp0_prop - DP0 properties
|
* struct sdw_dp0_prop - DP0 properties
|
||||||
|
* @words: wordlengths supported
|
||||||
* @max_word: Maximum number of bits in a Payload Channel Sample, 1 to 64
|
* @max_word: Maximum number of bits in a Payload Channel Sample, 1 to 64
|
||||||
* (inclusive)
|
* (inclusive)
|
||||||
* @min_word: Minimum number of bits in a Payload Channel Sample, 1 to 64
|
* @min_word: Minimum number of bits in a Payload Channel Sample, 1 to 64
|
||||||
* (inclusive)
|
* (inclusive)
|
||||||
* @num_words: number of wordlengths supported
|
* @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
|
* @BRA_flow_controlled: Slave implementation results in an OK_NotReady
|
||||||
* response
|
* response
|
||||||
* @simple_ch_prep_sm: If channel prepare sequence is required
|
* @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
|
* @imp_def_interrupts: If set, each bit corresponds to support for
|
||||||
* implementation-defined interrupts
|
* 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
|
* The wordlengths are specified by Spec as max, min AND number of
|
||||||
* discrete values, implementation can define based on the wordlengths they
|
* discrete values, implementation can define based on the wordlengths they
|
||||||
* support
|
* support
|
||||||
*/
|
*/
|
||||||
struct sdw_dp0_prop {
|
struct sdw_dp0_prop {
|
||||||
|
u32 *words;
|
||||||
u32 max_word;
|
u32 max_word;
|
||||||
u32 min_word;
|
u32 min_word;
|
||||||
u32 num_words;
|
u32 num_words;
|
||||||
u32 *words;
|
u32 ch_prep_timeout;
|
||||||
bool BRA_flow_controlled;
|
bool BRA_flow_controlled;
|
||||||
bool simple_ch_prep_sm;
|
bool simple_ch_prep_sm;
|
||||||
u32 ch_prep_timeout;
|
|
||||||
bool imp_def_interrupts;
|
bool imp_def_interrupts;
|
||||||
};
|
int num_lanes;
|
||||||
|
u32 *lane_list;
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -299,24 +278,25 @@ struct sdw_dpn_audio_mode {
|
|||||||
* @type: Data port type. Full, Simplified or Reduced
|
* @type: Data port type. Full, Simplified or Reduced
|
||||||
* @max_grouping: Maximum number of samples that can be grouped together for
|
* @max_grouping: Maximum number of samples that can be grouped together for
|
||||||
* a full data port
|
* 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
|
* @ch_prep_timeout: Port-specific timeout value, in milliseconds
|
||||||
* @imp_def_interrupts: If set, each bit corresponds to support for
|
* @imp_def_interrupts: If set, each bit corresponds to support for
|
||||||
* implementation-defined interrupts
|
* implementation-defined interrupts
|
||||||
* @max_ch: Maximum channels supported
|
* @max_ch: Maximum channels supported
|
||||||
* @min_ch: Minimum channels supported
|
* @min_ch: Minimum channels supported
|
||||||
* @num_channels: Number of discrete channels supported
|
* @num_channels: Number of discrete channels supported
|
||||||
* @channels: Discrete channels supported
|
|
||||||
* @num_ch_combinations: Number of channel combinations supported
|
* @num_ch_combinations: Number of channel combinations supported
|
||||||
|
* @channels: Discrete channels supported
|
||||||
* @ch_combinations: Channel combinations 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
|
* @modes: SDW mode supported
|
||||||
* @max_async_buffer: Number of samples that this port can buffer in
|
* @max_async_buffer: Number of samples that this port can buffer in
|
||||||
* asynchronous modes
|
* asynchronous modes
|
||||||
|
* @port_encoding: Payload Channel Sample encoding schemes supported
|
||||||
* @block_pack_mode: Type of block port mode supported
|
* @block_pack_mode: Type of block port mode supported
|
||||||
* @read_only_wordlength: Read Only wordlength field in DPN_BlockCtrl1 register
|
* @read_only_wordlength: Read Only wordlength field in DPN_BlockCtrl1 register
|
||||||
* @port_encoding: Payload Channel Sample encoding schemes supported
|
* @simple_ch_prep_sm: If the port supports simplified channel prepare state
|
||||||
* @audio_modes: Audio modes supported
|
* machine
|
||||||
*/
|
*/
|
||||||
struct sdw_dpn_prop {
|
struct sdw_dpn_prop {
|
||||||
u32 num;
|
u32 num;
|
||||||
@ -326,25 +306,29 @@ struct sdw_dpn_prop {
|
|||||||
u32 *words;
|
u32 *words;
|
||||||
enum sdw_dpn_type type;
|
enum sdw_dpn_type type;
|
||||||
u32 max_grouping;
|
u32 max_grouping;
|
||||||
bool simple_ch_prep_sm;
|
|
||||||
u32 ch_prep_timeout;
|
u32 ch_prep_timeout;
|
||||||
u32 imp_def_interrupts;
|
u32 imp_def_interrupts;
|
||||||
u32 max_ch;
|
u32 max_ch;
|
||||||
u32 min_ch;
|
u32 min_ch;
|
||||||
u32 num_channels;
|
u32 num_channels;
|
||||||
u32 *channels;
|
|
||||||
u32 num_ch_combinations;
|
u32 num_ch_combinations;
|
||||||
|
u32 *channels;
|
||||||
u32 *ch_combinations;
|
u32 *ch_combinations;
|
||||||
|
u32 *lane_list;
|
||||||
|
int num_lanes;
|
||||||
u32 modes;
|
u32 modes;
|
||||||
u32 max_async_buffer;
|
u32 max_async_buffer;
|
||||||
|
u32 port_encoding;
|
||||||
bool block_pack_mode;
|
bool block_pack_mode;
|
||||||
bool read_only_wordlength;
|
bool read_only_wordlength;
|
||||||
u32 port_encoding;
|
bool simple_ch_prep_sm;
|
||||||
struct sdw_dpn_audio_mode *audio_modes;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct sdw_slave_prop - SoundWire Slave properties
|
* 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
|
* @mipi_revision: Spec version of the implementation
|
||||||
* @wake_capable: Wake-up events are supported
|
* @wake_capable: Wake-up events are supported
|
||||||
* @test_mode_capable: If test mode is supported
|
* @test_mode_capable: If test mode is supported
|
||||||
@ -361,23 +345,26 @@ struct sdw_dpn_prop {
|
|||||||
* SCP_AddrPage2
|
* SCP_AddrPage2
|
||||||
* @bank_delay_support: Slave implements bank delay/bridge support registers
|
* @bank_delay_support: Slave implements bank delay/bridge support registers
|
||||||
* SCP_BankDelay and SCP_NextFrame
|
* 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
|
* @p15_behave: Slave behavior when the Master attempts a read to the Port15
|
||||||
* alias
|
* alias
|
||||||
* @lane_control_support: Slave supports lane control
|
|
||||||
* @master_count: Number of Masters present on this Slave
|
* @master_count: Number of Masters present on this Slave
|
||||||
* @source_ports: Bitmap identifying source ports
|
* @source_ports: Bitmap identifying source ports
|
||||||
* @sink_ports: Bitmap identifying sink 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
|
* @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
|
* @clock_reg_supported: the Peripheral implements the clock base and scale
|
||||||
* registers introduced with the SoundWire 1.2 specification. SDCA devices
|
* registers introduced with the SoundWire 1.2 specification. SDCA devices
|
||||||
* do not need to set this boolean property as the registers are required.
|
* 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
|
* @use_domain_irq: call actual IRQ handler on slave, as well as callback
|
||||||
*/
|
*/
|
||||||
struct sdw_slave_prop {
|
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;
|
u32 mipi_revision;
|
||||||
bool wake_capable;
|
bool wake_capable;
|
||||||
bool test_mode_capable;
|
bool test_mode_capable;
|
||||||
@ -389,16 +376,15 @@ struct sdw_slave_prop {
|
|||||||
bool high_PHY_capable;
|
bool high_PHY_capable;
|
||||||
bool paging_support;
|
bool paging_support;
|
||||||
bool bank_delay_support;
|
bool bank_delay_support;
|
||||||
enum sdw_p15_behave p15_behave;
|
|
||||||
bool lane_control_support;
|
bool lane_control_support;
|
||||||
|
enum sdw_p15_behave p15_behave;
|
||||||
u32 master_count;
|
u32 master_count;
|
||||||
u32 source_ports;
|
u32 source_ports;
|
||||||
u32 sink_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 quirks;
|
||||||
|
u32 sdca_interrupt_register_list;
|
||||||
|
u8 commit_register_supported;
|
||||||
|
u8 scp_int1_mask;
|
||||||
bool clock_reg_supported;
|
bool clock_reg_supported;
|
||||||
bool use_domain_irq;
|
bool use_domain_irq;
|
||||||
};
|
};
|
||||||
@ -407,13 +393,14 @@ struct sdw_slave_prop {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* struct sdw_master_prop - Master properties
|
* 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
|
* @revision: MIPI spec version of the implementation
|
||||||
* @clk_stop_modes: Bitmap, bit N set when clock-stop-modeN supported
|
* @clk_stop_modes: Bitmap, bit N set when clock-stop-modeN supported
|
||||||
* @max_clk_freq: Maximum Bus clock frequency, in Hz
|
* @max_clk_freq: Maximum Bus clock frequency, in Hz
|
||||||
* @num_clk_gears: Number of clock gears supported
|
* @num_clk_gears: Number of clock gears supported
|
||||||
* @clk_gears: Clock gears supported
|
|
||||||
* @num_clk_freq: Number of clock frequencies supported, in Hz
|
* @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_frame_rate: Controller default Frame rate, in Hz
|
||||||
* @default_row: Number of rows
|
* @default_row: Number of rows
|
||||||
* @default_col: Number of columns
|
* @default_col: Number of columns
|
||||||
@ -422,24 +409,23 @@ struct sdw_slave_prop {
|
|||||||
* command
|
* command
|
||||||
* @mclk_freq: clock reference passed to SoundWire Master, in Hz.
|
* @mclk_freq: clock reference passed to SoundWire Master, in Hz.
|
||||||
* @hw_disabled: if true, the Master is not functional, typically due to pin-mux
|
* @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 {
|
struct sdw_master_prop {
|
||||||
|
u32 *clk_gears;
|
||||||
|
u32 *clk_freq;
|
||||||
|
u64 quirks;
|
||||||
u32 revision;
|
u32 revision;
|
||||||
u32 clk_stop_modes;
|
u32 clk_stop_modes;
|
||||||
u32 max_clk_freq;
|
u32 max_clk_freq;
|
||||||
u32 num_clk_gears;
|
u32 num_clk_gears;
|
||||||
u32 *clk_gears;
|
|
||||||
u32 num_clk_freq;
|
u32 num_clk_freq;
|
||||||
u32 *clk_freq;
|
|
||||||
u32 default_frame_rate;
|
u32 default_frame_rate;
|
||||||
u32 default_row;
|
u32 default_row;
|
||||||
u32 default_col;
|
u32 default_col;
|
||||||
bool dynamic_frame;
|
|
||||||
u32 err_threshold;
|
u32 err_threshold;
|
||||||
u32 mclk_freq;
|
u32 mclk_freq;
|
||||||
|
bool dynamic_frame;
|
||||||
bool hw_disabled;
|
bool hw_disabled;
|
||||||
u64 quirks;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Definitions for Master quirks */
|
/* Definitions for Master quirks */
|
||||||
@ -631,7 +617,6 @@ struct sdw_slave_ops {
|
|||||||
int (*clk_stop)(struct sdw_slave *slave,
|
int (*clk_stop)(struct sdw_slave *slave,
|
||||||
enum sdw_clk_stop_mode mode,
|
enum sdw_clk_stop_mode mode,
|
||||||
enum sdw_clk_stop_type type);
|
enum sdw_clk_stop_type type);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -707,8 +692,7 @@ struct sdw_master_device {
|
|||||||
container_of(d, struct sdw_master_device, dev)
|
container_of(d, struct sdw_master_device, dev)
|
||||||
|
|
||||||
struct sdw_driver {
|
struct sdw_driver {
|
||||||
int (*probe)(struct sdw_slave *sdw,
|
int (*probe)(struct sdw_slave *sdw, const struct sdw_device_id *id);
|
||||||
const struct sdw_device_id *id);
|
|
||||||
int (*remove)(struct sdw_slave *sdw);
|
int (*remove)(struct sdw_slave *sdw);
|
||||||
void (*shutdown)(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))
|
SDW_SLAVE_ENTRY_EXT((_mfg_id), (_part_id), 0, 0, (_drv_data))
|
||||||
|
|
||||||
int sdw_handle_slave_status(struct sdw_bus *bus,
|
int sdw_handle_slave_status(struct sdw_bus *bus,
|
||||||
enum sdw_slave_status status[]);
|
enum sdw_slave_status status[]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SDW master structures and APIs
|
* SDW master structures and APIs
|
||||||
@ -809,29 +793,28 @@ struct sdw_enable_ch {
|
|||||||
*/
|
*/
|
||||||
struct sdw_master_port_ops {
|
struct sdw_master_port_ops {
|
||||||
int (*dpn_set_port_params)(struct sdw_bus *bus,
|
int (*dpn_set_port_params)(struct sdw_bus *bus,
|
||||||
struct sdw_port_params *port_params,
|
struct sdw_port_params *port_params,
|
||||||
unsigned int bank);
|
unsigned int bank);
|
||||||
int (*dpn_set_port_transport_params)(struct sdw_bus *bus,
|
int (*dpn_set_port_transport_params)(struct sdw_bus *bus,
|
||||||
struct sdw_transport_params *transport_params,
|
struct sdw_transport_params *transport_params,
|
||||||
enum sdw_reg_bank bank);
|
enum sdw_reg_bank bank);
|
||||||
int (*dpn_port_prep)(struct sdw_bus *bus,
|
int (*dpn_port_prep)(struct sdw_bus *bus, struct sdw_prepare_ch *prepare_ch);
|
||||||
struct sdw_prepare_ch *prepare_ch);
|
|
||||||
int (*dpn_port_enable_ch)(struct sdw_bus *bus,
|
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_msg;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct sdw_defer - SDW deffered message
|
* struct sdw_defer - SDW deferred message
|
||||||
* @length: message length
|
|
||||||
* @complete: message completion
|
* @complete: message completion
|
||||||
* @msg: SDW message
|
* @msg: SDW message
|
||||||
|
* @length: message length
|
||||||
*/
|
*/
|
||||||
struct sdw_defer {
|
struct sdw_defer {
|
||||||
|
struct sdw_msg *msg;
|
||||||
int length;
|
int length;
|
||||||
struct completion complete;
|
struct completion complete;
|
||||||
struct sdw_msg *msg;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -852,14 +835,11 @@ struct sdw_defer {
|
|||||||
*/
|
*/
|
||||||
struct sdw_master_ops {
|
struct sdw_master_ops {
|
||||||
int (*read_prop)(struct sdw_bus *bus);
|
int (*read_prop)(struct sdw_bus *bus);
|
||||||
u64 (*override_adr)
|
u64 (*override_adr)(struct sdw_bus *bus, u64 addr);
|
||||||
(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)
|
enum sdw_command_response (*xfer_msg_defer)(struct sdw_bus *bus);
|
||||||
(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,
|
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 (*pre_bank_switch)(struct sdw_bus *bus);
|
||||||
int (*post_bank_switch)(struct sdw_bus *bus);
|
int (*post_bank_switch)(struct sdw_bus *bus);
|
||||||
u32 (*read_ping_status)(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
|
* struct sdw_bus - SoundWire bus
|
||||||
* @dev: Shortcut to &bus->md->dev to avoid changing the entire code.
|
* @dev: Shortcut to &bus->md->dev to avoid changing the entire code.
|
||||||
* @md: Master device
|
* @md: Master device
|
||||||
* @controller_id: system-unique controller ID. If set to -1, the bus @id will be used.
|
* @bus_lock_key: bus lock key associated to @bus_lock
|
||||||
* @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: 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
|
* @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
|
* @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,
|
* is used to compute and program bus bandwidth, clock, frame shape,
|
||||||
* transport and port parameters
|
* transport and port parameters
|
||||||
* @debugfs: Bus debugfs
|
|
||||||
* @domain: IRQ domain
|
|
||||||
* @defer_msg: Defer message
|
* @defer_msg: Defer message
|
||||||
* @clk_stop_timeout: Clock stop timeout computed
|
* @params: Current bus parameters
|
||||||
* @bank_switch_timeout: Bank switch timeout computed
|
* @stream_refcount: number of streams currently using this bus
|
||||||
* @multi_link: Store bus property that indicates if multi links
|
* @ops: Master callback ops
|
||||||
* are supported. This flag is populated by drivers after reading
|
* @port_ops: Master port callback ops
|
||||||
* appropriate firmware (ACPI/DT).
|
* @prop: Master properties
|
||||||
|
* @vendor_specific_prop: pointer to non-standard properties
|
||||||
* @hw_sync_min_links: Number of links used by a stream above which
|
* @hw_sync_min_links: Number of links used by a stream above which
|
||||||
* hardware-based synchronization is required. This value is only
|
* hardware-based synchronization is required. This value is only
|
||||||
* meaningful if multi_link is set. If set to 1, hardware-based
|
* meaningful if multi_link is set. If set to 1, hardware-based
|
||||||
* synchronization will be used even if a stream only uses a single
|
* synchronization will be used even if a stream only uses a single
|
||||||
* SoundWire segment.
|
* 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 sdw_bus {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct sdw_master_device *md;
|
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;
|
int controller_id;
|
||||||
unsigned int link_id;
|
unsigned int link_id;
|
||||||
int 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);
|
int (*compute_params)(struct sdw_bus *bus);
|
||||||
const struct sdw_master_ops *ops;
|
DECLARE_BITMAP(assigned, SDW_MAX_DEVICES);
|
||||||
const struct sdw_master_port_ops *port_ops;
|
unsigned int clk_stop_timeout;
|
||||||
struct sdw_bus_params params;
|
u32 bank_switch_timeout;
|
||||||
struct sdw_master_prop prop;
|
struct irq_chip irq_chip;
|
||||||
void *vendor_specific_prop;
|
struct irq_domain *domain;
|
||||||
struct list_head m_rt_list;
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
struct dentry *debugfs;
|
struct dentry *debugfs;
|
||||||
#endif
|
#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;
|
bool multi_link;
|
||||||
int hw_sync_min_links;
|
|
||||||
int stream_refcount;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent,
|
int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent,
|
||||||
@ -1013,18 +996,18 @@ struct sdw_stream_params {
|
|||||||
* @params: Stream parameters
|
* @params: Stream parameters
|
||||||
* @state: Current state of the stream
|
* @state: Current state of the stream
|
||||||
* @type: Stream type PCM or PDM
|
* @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: List of Master runtime(s) in this stream.
|
||||||
* master_list can contain only one m_rt per Master instance
|
* master_list can contain only one m_rt per Master instance
|
||||||
* for a stream
|
* for a stream
|
||||||
* @m_rt_count: Count of Master runtime(s) in this stream
|
|
||||||
*/
|
*/
|
||||||
struct sdw_stream_runtime {
|
struct sdw_stream_runtime {
|
||||||
const char *name;
|
const char *name;
|
||||||
struct sdw_stream_params params;
|
struct sdw_stream_params params;
|
||||||
enum sdw_stream_state state;
|
enum sdw_stream_state state;
|
||||||
enum sdw_stream_type type;
|
enum sdw_stream_type type;
|
||||||
struct list_head master_list;
|
|
||||||
int m_rt_count;
|
int m_rt_count;
|
||||||
|
struct list_head master_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sdw_stream_runtime *sdw_alloc_stream(const char *stream_name);
|
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_compute_params(struct sdw_bus *bus);
|
||||||
|
|
||||||
int sdw_stream_add_master(struct sdw_bus *bus,
|
int sdw_stream_add_master(struct sdw_bus *bus,
|
||||||
struct sdw_stream_config *stream_config,
|
struct sdw_stream_config *stream_config,
|
||||||
const struct sdw_port_config *port_config,
|
const struct sdw_port_config *port_config,
|
||||||
unsigned int num_ports,
|
unsigned int num_ports,
|
||||||
struct sdw_stream_runtime *stream);
|
struct sdw_stream_runtime *stream);
|
||||||
int sdw_stream_remove_master(struct sdw_bus *bus,
|
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_startup_stream(void *sdw_substream);
|
||||||
int sdw_prepare_stream(struct sdw_stream_runtime *stream);
|
int sdw_prepare_stream(struct sdw_stream_runtime *stream);
|
||||||
int sdw_enable_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_SDW0 0
|
||||||
#define ACP_SDW1 1
|
#define ACP_SDW1 1
|
||||||
#define AMD_SDW_MAX_MANAGER_COUNT 2
|
#define AMD_SDW_MAX_MANAGER_COUNT 2
|
||||||
|
#define ACP63_PCI_REV_ID 0x63
|
||||||
|
|
||||||
struct acp_sdw_pdata {
|
struct acp_sdw_pdata {
|
||||||
u16 instance;
|
u16 instance;
|
||||||
|
u32 acp_rev;
|
||||||
/* mutex to protect acp common register access */
|
/* mutex to protect acp common register access */
|
||||||
struct mutex *acp_sdw_lock;
|
struct mutex *acp_sdw_lock;
|
||||||
};
|
};
|
||||||
@ -66,6 +68,7 @@ struct sdw_amd_dai_runtime {
|
|||||||
* @instance: SoundWire manager instance
|
* @instance: SoundWire manager instance
|
||||||
* @quirks: SoundWire manager quirks
|
* @quirks: SoundWire manager quirks
|
||||||
* @wake_en_mask: wake enable mask per SoundWire manager
|
* @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
|
* @clk_stopped: flag set to true when clock is stopped
|
||||||
* @power_mode_mask: flag interprets amd SoundWire manager power mode
|
* @power_mode_mask: flag interprets amd SoundWire manager power mode
|
||||||
* @dai_runtime_array: dai runtime array
|
* @dai_runtime_array: dai runtime array
|
||||||
@ -94,6 +97,7 @@ struct amd_sdw_manager {
|
|||||||
u32 quirks;
|
u32 quirks;
|
||||||
u32 wake_en_mask;
|
u32 wake_en_mask;
|
||||||
u32 power_mode_mask;
|
u32 power_mode_mask;
|
||||||
|
u32 acp_rev;
|
||||||
bool clk_stopped;
|
bool clk_stopped;
|
||||||
|
|
||||||
struct sdw_amd_dai_runtime **dai_runtime_array;
|
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,
|
* struct sdw_amd_res - Soundwire AMD global resource structure,
|
||||||
* typically populated by the DSP driver/Legacy driver
|
* typically populated by the DSP driver/Legacy driver
|
||||||
*
|
*
|
||||||
|
* @acp_rev: acp pci device revision id
|
||||||
* @addr: acp pci device resource start address
|
* @addr: acp pci device resource start address
|
||||||
* @reg_range: ACP register range
|
* @reg_range: ACP register range
|
||||||
* @link_mask: bit-wise mask listing links selected by the DSP driver/
|
* @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
|
* @acp_lock: mutex protecting acp common registers access
|
||||||
*/
|
*/
|
||||||
struct sdw_amd_res {
|
struct sdw_amd_res {
|
||||||
|
u32 acp_rev;
|
||||||
u32 addr;
|
u32 addr;
|
||||||
u32 reg_range;
|
u32 reg_range;
|
||||||
u32 link_mask;
|
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
|
* @sdw_en_stat: flag set to true when any one of the SoundWire manager instance is enabled
|
||||||
* @addr: pci ioremap address
|
* @addr: pci ioremap address
|
||||||
* @reg_range: ACP reigister range
|
* @reg_range: ACP reigister range
|
||||||
|
* @acp_rev: ACP PCI revision id
|
||||||
* @sdw0-dma_intr_stat: DMA interrupt status array for SoundWire manager-SW0 instance
|
* @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
|
* @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;
|
bool sdw_en_stat;
|
||||||
u32 addr;
|
u32 addr;
|
||||||
u32 reg_range;
|
u32 reg_range;
|
||||||
|
u32 acp_rev;
|
||||||
u16 sdw0_dma_intr_stat[ACP63_SDW0_DMA_MAX_STREAMS];
|
u16 sdw0_dma_intr_stat[ACP63_SDW0_DMA_MAX_STREAMS];
|
||||||
u16 sdw1_dma_intr_stat[ACP63_SDW1_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.acp_lock = &acp_data->acp_lock;
|
||||||
sdw_res.count = acp_data->info.count;
|
sdw_res.count = acp_data->info.count;
|
||||||
sdw_res.mmio_base = acp_data->acp63_base;
|
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;
|
sdw_res.link_mask = acp_data->info.link_mask;
|
||||||
ret = sdw_amd_probe(&sdw_res, &acp_data->sdw);
|
ret = sdw_amd_probe(&sdw_res, &acp_data->sdw);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -575,6 +576,7 @@ static int snd_acp63_probe(struct pci_dev *pci,
|
|||||||
}
|
}
|
||||||
adata->addr = addr;
|
adata->addr = addr;
|
||||||
adata->reg_range = ACP63_REG_END - ACP63_REG_START;
|
adata->reg_range = ACP63_REG_END - ACP63_REG_START;
|
||||||
|
adata->acp_rev = pci->revision;
|
||||||
pci_set_master(pci);
|
pci_set_master(pci);
|
||||||
pci_set_drvdata(pci, adata);
|
pci_set_drvdata(pci, adata);
|
||||||
mutex_init(&adata->acp_lock);
|
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.count = acp_data->info.count;
|
||||||
sdw_res.link_mask = acp_data->info.link_mask;
|
sdw_res.link_mask = acp_data->info.link_mask;
|
||||||
sdw_res.mmio_base = sdev->bar[ACP_DSP_BAR];
|
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);
|
ret = sdw_amd_probe(&sdw_res, &acp_data->sdw);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
Loading…
Reference in New Issue
Block a user