Skip to content

Commit

Permalink
Merge remote-tracking branch 'soundwire/next' into sound/upstream-202…
Browse files Browse the repository at this point in the history
…41016
  • Loading branch information
bardliao committed Oct 16, 2024
2 parents bc3c608 + 830f1aa commit e36694b
Show file tree
Hide file tree
Showing 18 changed files with 340 additions and 181 deletions.
1 change: 1 addition & 0 deletions Documentation/admin-guide/kernel-parameters.rst
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,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.
Expand Down
4 changes: 4 additions & 0 deletions Documentation/admin-guide/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6060,6 +6060,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.
Expand Down
1 change: 1 addition & 0 deletions drivers/soundwire/amd_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
99 changes: 64 additions & 35 deletions drivers/soundwire/amd_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
16 changes: 8 additions & 8 deletions drivers/soundwire/amd_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion drivers/soundwire/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
30 changes: 30 additions & 0 deletions drivers/soundwire/cadence_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);

Expand Down
1 change: 1 addition & 0 deletions drivers/soundwire/cadence_master.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
12 changes: 10 additions & 2 deletions drivers/soundwire/intel_auxdevice.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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",
Expand Down
6 changes: 6 additions & 0 deletions drivers/soundwire/intel_bus_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit e36694b

Please sign in to comment.