Skip to content

Commit b9dd56e

Browse files
committed
Merge tag 'soundwire-6.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire
Pull soundwire updates from Vinod Koul: - cleanup and conversion for soundwire sysfs groups - intel support for ace2x bits, auxdevice pm improvements - qcom multi link device support * tag 'soundwire-6.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire: (33 commits) soundwire: intel_ace2.x: add support for DOAISE property soundwire: intel_ace2.x: add support for DODSE property soundwire: intel_ace2x: use DOAIS and DODS settings from firmware soundwire: intel_ace2x: cleanup DOAIS/DODS settings soundwire: intel_ace2x: simplify check_wake() soundwire: intel_ace2x: fix wakeup handling soundwire: intel_init: resume all devices on exit. soundwire: intel: export intel_resume_child_device soundwire: intel_auxdevice: use pm_runtime_resume() instead of pm_request_resume() ASoC: SOF: Intel: hda: disable SoundWire interrupt later soundwire: qcom: allow multi-link on newer devices soundwire: intel_ace2x: use legacy formula for intel_alh_id soundwire: reconcile dp0_prop and dpn_prop soundwire: intel_ace2x: set the clock source soundwire: intel_ace2.x: power-up first before setting SYNCPRD soundwire: intel_ace2x: move and extend clock selection soundwire: intel: add support for MeteorLake additional clocks soundwire: intel: add more values for SYNCPRD soundwire: bus: extend base clock checks to 96 MHz soundwire: cadence: show the bus frequency and frame shape ...
2 parents 8053d2f + a0df7e0 commit b9dd56e

20 files changed

+336
-159
lines changed

drivers/soundwire/amd_init.c

+16-20
Original file line numberDiff line numberDiff line change
@@ -17,42 +17,38 @@
1717

1818
#define ACP_PAD_PULLDOWN_CTRL 0x0001448
1919
#define ACP_SW_PAD_KEEPER_EN 0x0001454
20-
#define AMD_SDW_PAD_PULLDOWN_CTRL_ENABLE_MASK 0x7f9a
21-
#define AMD_SDW0_PAD_PULLDOWN_CTRL_ENABLE_MASK 0x7f9f
22-
#define AMD_SDW1_PAD_PULLDOWN_CTRL_ENABLE_MASK 0x7ffa
23-
#define AMD_SDW0_PAD_EN_MASK 1
24-
#define AMD_SDW1_PAD_EN_MASK 0x10
25-
#define AMD_SDW_PAD_EN_MASK (AMD_SDW0_PAD_EN_MASK | AMD_SDW1_PAD_EN_MASK)
20+
#define AMD_SDW0_PAD_CTRL_MASK 0x60
21+
#define AMD_SDW1_PAD_CTRL_MASK 5
22+
#define AMD_SDW_PAD_CTRL_MASK (AMD_SDW0_PAD_CTRL_MASK | AMD_SDW1_PAD_CTRL_MASK)
23+
#define AMD_SDW0_PAD_EN 1
24+
#define AMD_SDW1_PAD_EN 0x10
25+
#define AMD_SDW_PAD_EN (AMD_SDW0_PAD_EN | AMD_SDW1_PAD_EN)
2626

2727
static int amd_enable_sdw_pads(void __iomem *mmio, u32 link_mask, struct device *dev)
2828
{
29-
u32 val;
30-
u32 pad_keeper_en_mask, pad_pulldown_ctrl_mask;
29+
u32 pad_keeper_en, pad_pulldown_ctrl_mask;
3130

3231
switch (link_mask) {
3332
case 1:
34-
pad_keeper_en_mask = AMD_SDW0_PAD_EN_MASK;
35-
pad_pulldown_ctrl_mask = AMD_SDW0_PAD_PULLDOWN_CTRL_ENABLE_MASK;
33+
pad_keeper_en = AMD_SDW0_PAD_EN;
34+
pad_pulldown_ctrl_mask = AMD_SDW0_PAD_CTRL_MASK;
3635
break;
3736
case 2:
38-
pad_keeper_en_mask = AMD_SDW1_PAD_EN_MASK;
39-
pad_pulldown_ctrl_mask = AMD_SDW1_PAD_PULLDOWN_CTRL_ENABLE_MASK;
37+
pad_keeper_en = AMD_SDW1_PAD_EN;
38+
pad_pulldown_ctrl_mask = AMD_SDW1_PAD_CTRL_MASK;
4039
break;
4140
case 3:
42-
pad_keeper_en_mask = AMD_SDW_PAD_EN_MASK;
43-
pad_pulldown_ctrl_mask = AMD_SDW_PAD_PULLDOWN_CTRL_ENABLE_MASK;
41+
pad_keeper_en = AMD_SDW_PAD_EN;
42+
pad_pulldown_ctrl_mask = AMD_SDW_PAD_CTRL_MASK;
4443
break;
4544
default:
4645
dev_err(dev, "No SDW Links are enabled\n");
4746
return -ENODEV;
4847
}
4948

50-
val = readl(mmio + ACP_SW_PAD_KEEPER_EN);
51-
val |= pad_keeper_en_mask;
52-
writel(val, mmio + ACP_SW_PAD_KEEPER_EN);
53-
val = readl(mmio + ACP_PAD_PULLDOWN_CTRL);
54-
val &= pad_pulldown_ctrl_mask;
55-
writel(val, mmio + ACP_PAD_PULLDOWN_CTRL);
49+
amd_updatel(mmio, ACP_SW_PAD_KEEPER_EN, pad_keeper_en, pad_keeper_en);
50+
amd_updatel(mmio, ACP_PAD_PULLDOWN_CTRL, pad_pulldown_ctrl_mask, 0);
51+
5652
return 0;
5753
}
5854

drivers/soundwire/amd_init.h

+8
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,12 @@
1010

1111
int amd_sdw_manager_start(struct amd_sdw_manager *amd_manager);
1212

13+
static inline void amd_updatel(void __iomem *mmio, int offset, u32 mask, u32 val)
14+
{
15+
u32 tmp;
16+
17+
tmp = readl(mmio + offset);
18+
tmp = (tmp & ~mask) | val;
19+
writel(tmp, mmio + offset);
20+
}
1321
#endif

drivers/soundwire/amd_manager.c

+6-7
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,8 @@ static void amd_enable_sdw_interrupts(struct amd_sdw_manager *amd_manager)
8989
u32 val;
9090

9191
mutex_lock(amd_manager->acp_sdw_lock);
92-
val = readl(amd_manager->acp_mmio + ACP_EXTERNAL_INTR_CNTL(amd_manager->instance));
93-
val |= sdw_manager_reg_mask_array[amd_manager->instance];
94-
writel(val, amd_manager->acp_mmio + ACP_EXTERNAL_INTR_CNTL(amd_manager->instance));
92+
val = sdw_manager_reg_mask_array[amd_manager->instance];
93+
amd_updatel(amd_manager->acp_mmio, ACP_EXTERNAL_INTR_CNTL(amd_manager->instance), val, val);
9594
mutex_unlock(amd_manager->acp_sdw_lock);
9695

9796
writel(AMD_SDW_IRQ_MASK_0TO7, amd_manager->mmio +
@@ -103,12 +102,12 @@ static void amd_enable_sdw_interrupts(struct amd_sdw_manager *amd_manager)
103102

104103
static void amd_disable_sdw_interrupts(struct amd_sdw_manager *amd_manager)
105104
{
106-
u32 val;
105+
u32 irq_mask;
107106

108107
mutex_lock(amd_manager->acp_sdw_lock);
109-
val = readl(amd_manager->acp_mmio + ACP_EXTERNAL_INTR_CNTL(amd_manager->instance));
110-
val &= ~sdw_manager_reg_mask_array[amd_manager->instance];
111-
writel(val, amd_manager->acp_mmio + ACP_EXTERNAL_INTR_CNTL(amd_manager->instance));
108+
irq_mask = sdw_manager_reg_mask_array[amd_manager->instance];
109+
amd_updatel(amd_manager->acp_mmio, ACP_EXTERNAL_INTR_CNTL(amd_manager->instance),
110+
irq_mask, 0);
112111
mutex_unlock(amd_manager->acp_sdw_lock);
113112

114113
writel(0x00, amd_manager->mmio + ACP_SW_STATE_CHANGE_STATUS_MASK_0TO7);

drivers/soundwire/bus.c

+7-7
Original file line numberDiff line numberDiff line change
@@ -1312,18 +1312,18 @@ static int sdw_slave_set_frequency(struct sdw_slave *slave)
13121312
if (!(19200000 % mclk_freq)) {
13131313
mclk_freq = 19200000;
13141314
base = SDW_SCP_BASE_CLOCK_19200000_HZ;
1315-
} else if (!(24000000 % mclk_freq)) {
1316-
mclk_freq = 24000000;
1317-
base = SDW_SCP_BASE_CLOCK_24000000_HZ;
1318-
} else if (!(24576000 % mclk_freq)) {
1319-
mclk_freq = 24576000;
1320-
base = SDW_SCP_BASE_CLOCK_24576000_HZ;
13211315
} else if (!(22579200 % mclk_freq)) {
13221316
mclk_freq = 22579200;
13231317
base = SDW_SCP_BASE_CLOCK_22579200_HZ;
1318+
} else if (!(24576000 % mclk_freq)) {
1319+
mclk_freq = 24576000;
1320+
base = SDW_SCP_BASE_CLOCK_24576000_HZ;
13241321
} else if (!(32000000 % mclk_freq)) {
13251322
mclk_freq = 32000000;
13261323
base = SDW_SCP_BASE_CLOCK_32000000_HZ;
1324+
} else if (!(96000000 % mclk_freq)) {
1325+
mclk_freq = 24000000;
1326+
base = SDW_SCP_BASE_CLOCK_24000000_HZ;
13271327
} else {
13281328
dev_err(&slave->dev,
13291329
"Unsupported clock base, mclk %d\n",
@@ -1474,7 +1474,7 @@ static int sdw_handle_dp0_interrupt(struct sdw_slave *slave, u8 *slave_status)
14741474
}
14751475

14761476
do {
1477-
clear = status & ~SDW_DP0_INTERRUPTS;
1477+
clear = status & ~(SDW_DP0_INTERRUPTS | SDW_DP0_SDCA_CASCADE);
14781478

14791479
if (status & SDW_DP0_INT_TEST_FAIL) {
14801480
dev_err(&slave->dev, "Test fail for port 0\n");

drivers/soundwire/bus_type.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ static int sdw_drv_probe(struct device *dev)
126126
if (slave->prop.use_domain_irq)
127127
sdw_irq_create_mapping(slave);
128128

129-
/* init the sysfs as we have properties now */
130-
ret = sdw_slave_sysfs_init(slave);
129+
/* init the dynamic sysfs attributes we need */
130+
ret = sdw_slave_sysfs_dpn_init(slave);
131131
if (ret < 0)
132132
dev_warn(dev, "Slave sysfs init failed:%d\n", ret);
133133

@@ -221,6 +221,7 @@ int __sdw_register_driver(struct sdw_driver *drv, struct module *owner)
221221
drv->driver.probe = sdw_drv_probe;
222222
drv->driver.remove = sdw_drv_remove;
223223
drv->driver.shutdown = sdw_drv_shutdown;
224+
drv->driver.dev_groups = sdw_attr_groups;
224225

225226
return driver_register(&drv->driver);
226227
}

drivers/soundwire/cadence_master.c

+15-21
Original file line numberDiff line numberDiff line change
@@ -1236,7 +1236,7 @@ EXPORT_SYMBOL(sdw_cdns_enable_interrupt);
12361236

12371237
static int cdns_allocate_pdi(struct sdw_cdns *cdns,
12381238
struct sdw_cdns_pdi **stream,
1239-
u32 num, u32 pdi_offset)
1239+
u32 num)
12401240
{
12411241
struct sdw_cdns_pdi *pdi;
12421242
int i;
@@ -1249,7 +1249,7 @@ static int cdns_allocate_pdi(struct sdw_cdns *cdns,
12491249
return -ENOMEM;
12501250

12511251
for (i = 0; i < num; i++) {
1252-
pdi[i].num = i + pdi_offset;
1252+
pdi[i].num = i;
12531253
}
12541254

12551255
*stream = pdi;
@@ -1266,7 +1266,6 @@ int sdw_cdns_pdi_init(struct sdw_cdns *cdns,
12661266
struct sdw_cdns_stream_config config)
12671267
{
12681268
struct sdw_cdns_streams *stream;
1269-
int offset;
12701269
int ret;
12711270

12721271
cdns->pcm.num_bd = config.pcm_bd;
@@ -1277,24 +1276,15 @@ int sdw_cdns_pdi_init(struct sdw_cdns *cdns,
12771276
stream = &cdns->pcm;
12781277

12791278
/* we allocate PDI0 and PDI1 which are used for Bulk */
1280-
offset = 0;
1281-
1282-
ret = cdns_allocate_pdi(cdns, &stream->bd,
1283-
stream->num_bd, offset);
1279+
ret = cdns_allocate_pdi(cdns, &stream->bd, stream->num_bd);
12841280
if (ret)
12851281
return ret;
12861282

1287-
offset += stream->num_bd;
1288-
1289-
ret = cdns_allocate_pdi(cdns, &stream->in,
1290-
stream->num_in, offset);
1283+
ret = cdns_allocate_pdi(cdns, &stream->in, stream->num_in);
12911284
if (ret)
12921285
return ret;
12931286

1294-
offset += stream->num_in;
1295-
1296-
ret = cdns_allocate_pdi(cdns, &stream->out,
1297-
stream->num_out, offset);
1287+
ret = cdns_allocate_pdi(cdns, &stream->out, stream->num_out);
12981288
if (ret)
12991289
return ret;
13001290

@@ -1329,6 +1319,12 @@ static void cdns_init_clock_ctrl(struct sdw_cdns *cdns)
13291319
u32 ssp_interval;
13301320
int divider;
13311321

1322+
dev_dbg(cdns->dev, "mclk %d max %d row %d col %d\n",
1323+
prop->mclk_freq,
1324+
prop->max_clk_freq,
1325+
prop->default_row,
1326+
prop->default_col);
1327+
13321328
/* Set clock divider */
13331329
divider = (prop->mclk_freq / prop->max_clk_freq) - 1;
13341330

@@ -1802,7 +1798,6 @@ EXPORT_SYMBOL(cdns_set_sdw_stream);
18021798
* cdns_find_pdi() - Find a free PDI
18031799
*
18041800
* @cdns: Cadence instance
1805-
* @offset: Starting offset
18061801
* @num: Number of PDIs
18071802
* @pdi: PDI instances
18081803
* @dai_id: DAI id
@@ -1811,14 +1806,13 @@ EXPORT_SYMBOL(cdns_set_sdw_stream);
18111806
* expected to match, return NULL otherwise.
18121807
*/
18131808
static struct sdw_cdns_pdi *cdns_find_pdi(struct sdw_cdns *cdns,
1814-
unsigned int offset,
18151809
unsigned int num,
18161810
struct sdw_cdns_pdi *pdi,
18171811
int dai_id)
18181812
{
18191813
int i;
18201814

1821-
for (i = offset; i < offset + num; i++)
1815+
for (i = 0; i < num; i++)
18221816
if (pdi[i].num == dai_id)
18231817
return &pdi[i];
18241818

@@ -1872,15 +1866,15 @@ struct sdw_cdns_pdi *sdw_cdns_alloc_pdi(struct sdw_cdns *cdns,
18721866
struct sdw_cdns_pdi *pdi = NULL;
18731867

18741868
if (dir == SDW_DATA_DIR_RX)
1875-
pdi = cdns_find_pdi(cdns, 0, stream->num_in, stream->in,
1869+
pdi = cdns_find_pdi(cdns, stream->num_in, stream->in,
18761870
dai_id);
18771871
else
1878-
pdi = cdns_find_pdi(cdns, 0, stream->num_out, stream->out,
1872+
pdi = cdns_find_pdi(cdns, stream->num_out, stream->out,
18791873
dai_id);
18801874

18811875
/* check if we found a PDI, else find in bi-directional */
18821876
if (!pdi)
1883-
pdi = cdns_find_pdi(cdns, 2, stream->num_bd, stream->bd,
1877+
pdi = cdns_find_pdi(cdns, stream->num_bd, stream->bd,
18841878
dai_id);
18851879

18861880
if (pdi) {

drivers/soundwire/intel.c

+62-6
Original file line numberDiff line numberDiff line change
@@ -345,8 +345,10 @@ static int intel_link_power_up(struct sdw_intel *sdw)
345345
u32 spa_mask, cpa_mask;
346346
u32 link_control;
347347
int ret = 0;
348+
u32 clock_source;
348349
u32 syncprd;
349350
u32 sync_reg;
351+
bool lcap_mlcs;
350352

351353
mutex_lock(sdw->link_res->shim_lock);
352354

@@ -358,12 +360,35 @@ static int intel_link_power_up(struct sdw_intel *sdw)
358360
* is only dependent on the oscillator clock provided to
359361
* the IP, so adjust based on _DSD properties reported in DSDT
360362
* tables. The values reported are based on either 24MHz
361-
* (CNL/CML) or 38.4 MHz (ICL/TGL+).
363+
* (CNL/CML) or 38.4 MHz (ICL/TGL+). On MeteorLake additional
364+
* frequencies are available with the MLCS clock source selection.
362365
*/
363-
if (prop->mclk_freq % 6000000)
364-
syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_38_4;
365-
else
366-
syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_24;
366+
lcap_mlcs = intel_readl(shim, SDW_SHIM_LCAP) & SDW_SHIM_LCAP_MLCS_MASK;
367+
368+
if (prop->mclk_freq % 6000000) {
369+
if (prop->mclk_freq % 2400000) {
370+
if (lcap_mlcs) {
371+
syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_24_576;
372+
clock_source = SDW_SHIM_MLCS_CARDINAL_CLK;
373+
} else {
374+
dev_err(sdw->cdns.dev, "%s: invalid clock configuration, mclk %d lcap_mlcs %d\n",
375+
__func__, prop->mclk_freq, lcap_mlcs);
376+
ret = -EINVAL;
377+
goto out;
378+
}
379+
} else {
380+
syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_38_4;
381+
clock_source = SDW_SHIM_MLCS_XTAL_CLK;
382+
}
383+
} else {
384+
if (lcap_mlcs) {
385+
syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_96;
386+
clock_source = SDW_SHIM_MLCS_AUDIO_PLL_CLK;
387+
} else {
388+
syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_24;
389+
clock_source = SDW_SHIM_MLCS_XTAL_CLK;
390+
}
391+
}
367392

368393
if (!*shim_mask) {
369394
dev_dbg(sdw->cdns.dev, "powering up all links\n");
@@ -403,6 +428,13 @@ static int intel_link_power_up(struct sdw_intel *sdw)
403428
"Failed to set SHIM_SYNC: %d\n", ret);
404429
goto out;
405430
}
431+
432+
/* update link clock if needed */
433+
if (lcap_mlcs) {
434+
link_control = intel_readl(shim, SDW_SHIM_LCTL);
435+
u32p_replace_bits(&link_control, clock_source, SDW_SHIM_LCTL_MLCS_MASK);
436+
intel_writel(shim, SDW_SHIM_LCTL, link_control);
437+
}
406438
}
407439

408440
*shim_mask |= BIT(link_id);
@@ -668,6 +700,24 @@ static int intel_params_stream(struct sdw_intel *sdw,
668700
* DAI routines
669701
*/
670702

703+
static int intel_free_stream(struct sdw_intel *sdw,
704+
struct snd_pcm_substream *substream,
705+
struct snd_soc_dai *dai,
706+
int link_id)
707+
{
708+
struct sdw_intel_link_res *res = sdw->link_res;
709+
struct sdw_intel_stream_free_data free_data;
710+
711+
free_data.substream = substream;
712+
free_data.dai = dai;
713+
free_data.link_id = link_id;
714+
715+
if (res->ops && res->ops->free_stream && res->dev)
716+
return res->ops->free_stream(res->dev, &free_data);
717+
718+
return 0;
719+
}
720+
671721
static int intel_hw_params(struct snd_pcm_substream *substream,
672722
struct snd_pcm_hw_params *params,
673723
struct snd_soc_dai *dai)
@@ -799,6 +849,7 @@ static int
799849
intel_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
800850
{
801851
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
852+
struct sdw_intel *sdw = cdns_to_intel(cdns);
802853
struct sdw_cdns_dai_runtime *dai_runtime;
803854
int ret;
804855

@@ -819,6 +870,12 @@ intel_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
819870
return ret;
820871
}
821872

873+
ret = intel_free_stream(sdw, substream, dai, sdw->instance);
874+
if (ret < 0) {
875+
dev_err(dai->dev, "intel_free_stream: failed %d\n", ret);
876+
return ret;
877+
}
878+
822879
dai_runtime->pdi = NULL;
823880

824881
return 0;
@@ -1062,4 +1119,3 @@ const struct sdw_intel_hw_ops sdw_intel_cnl_hw_ops = {
10621119
.sync_check_cmdsync_unlocked = intel_check_cmdsync_unlocked,
10631120
};
10641121
EXPORT_SYMBOL_NS(sdw_intel_cnl_hw_ops, SOUNDWIRE_INTEL);
1065-

drivers/soundwire/intel.h

+7
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ struct sdw_intel {
5858
#endif
5959
};
6060

61+
struct sdw_intel_prop {
62+
u16 doaise;
63+
u16 doais;
64+
u16 dodse;
65+
u16 dods;
66+
};
67+
6168
enum intel_pdi_type {
6269
INTEL_PDI_IN = 0,
6370
INTEL_PDI_OUT = 1,

0 commit comments

Comments
 (0)