mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
soundwire updates for 6.10
- cleanup and conversion for soundwire sysfs groups - intel support for ace2x bits, auxdevice pm improvements - qcom multi link device support -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE+vs47OPLdNbVcHzyfBQHDyUjg0cFAmZMTBMACgkQfBQHDyUj g0cLwxAAs2BjcTzYcYX+bPQGBWb8Fvzm7/vKQrkPiZTVm0TtKL5EB2CBzqo+xhpf DIUNw9nNECswmS4X6J3vPZs4cYeIYgmrXXs0Wt+kB5YFsvYoM/aHNyxvwWheAcPg atzv4x0leYnmwD8rFwCER4jVNaUw54dy9L/SurCSxMEzpp48bkZyD4fAaAgO3I8x Ou0vZHEctev2s4cbSnnZhQnkcQdTfk2q93OrUtoWx0BaXA71HGds+tyJhM9iuih4 wpRvZvX7xYscohNEJxx0scks14dd8DvVklCWRc14mCYeUK32uX02cTUqDXZdr/SX Ljy/GjMKCcVlA75KIP47iqtsMZATqG/kJZQWps4lobJulinvkFaPO5BNZ1B0qpvm Y6zkMLQjF6YdP6DZnWvfp6+Zc8WOLnzDGiIhvnCL7YDMqVZwaJqurvVeTcX66K5l 1cB9BkgXamqS38aI4Zu/qr8vxVuhZK0Os/5/k2MJQhjzFb8tmK66oKEJ42kawK4X X1ZE4sUdsYbp3CR184FXXpzOeKsxjBiao2E8t1EEFgVPCvIFsa9TjjPWs+bGQ9jq iixdQXawzv1kwOuT5DzyDwRvwHe46o8zG5yR3kqu64EAzdcg8tspdtODsw2ZV1FJ EvALOC3bw6PJkOpurRFjijGrqFbWKSkgxOUkgR3GKExX/bd8NPQ= =H/AJ -----END PGP SIGNATURE----- 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 ...
This commit is contained in:
commit
b9dd56e813
@ -17,42 +17,38 @@
|
||||
|
||||
#define ACP_PAD_PULLDOWN_CTRL 0x0001448
|
||||
#define ACP_SW_PAD_KEEPER_EN 0x0001454
|
||||
#define AMD_SDW_PAD_PULLDOWN_CTRL_ENABLE_MASK 0x7f9a
|
||||
#define AMD_SDW0_PAD_PULLDOWN_CTRL_ENABLE_MASK 0x7f9f
|
||||
#define AMD_SDW1_PAD_PULLDOWN_CTRL_ENABLE_MASK 0x7ffa
|
||||
#define AMD_SDW0_PAD_EN_MASK 1
|
||||
#define AMD_SDW1_PAD_EN_MASK 0x10
|
||||
#define AMD_SDW_PAD_EN_MASK (AMD_SDW0_PAD_EN_MASK | AMD_SDW1_PAD_EN_MASK)
|
||||
#define AMD_SDW0_PAD_CTRL_MASK 0x60
|
||||
#define AMD_SDW1_PAD_CTRL_MASK 5
|
||||
#define AMD_SDW_PAD_CTRL_MASK (AMD_SDW0_PAD_CTRL_MASK | AMD_SDW1_PAD_CTRL_MASK)
|
||||
#define AMD_SDW0_PAD_EN 1
|
||||
#define AMD_SDW1_PAD_EN 0x10
|
||||
#define AMD_SDW_PAD_EN (AMD_SDW0_PAD_EN | AMD_SDW1_PAD_EN)
|
||||
|
||||
static int amd_enable_sdw_pads(void __iomem *mmio, u32 link_mask, struct device *dev)
|
||||
{
|
||||
u32 val;
|
||||
u32 pad_keeper_en_mask, pad_pulldown_ctrl_mask;
|
||||
u32 pad_keeper_en, pad_pulldown_ctrl_mask;
|
||||
|
||||
switch (link_mask) {
|
||||
case 1:
|
||||
pad_keeper_en_mask = AMD_SDW0_PAD_EN_MASK;
|
||||
pad_pulldown_ctrl_mask = AMD_SDW0_PAD_PULLDOWN_CTRL_ENABLE_MASK;
|
||||
pad_keeper_en = AMD_SDW0_PAD_EN;
|
||||
pad_pulldown_ctrl_mask = AMD_SDW0_PAD_CTRL_MASK;
|
||||
break;
|
||||
case 2:
|
||||
pad_keeper_en_mask = AMD_SDW1_PAD_EN_MASK;
|
||||
pad_pulldown_ctrl_mask = AMD_SDW1_PAD_PULLDOWN_CTRL_ENABLE_MASK;
|
||||
pad_keeper_en = AMD_SDW1_PAD_EN;
|
||||
pad_pulldown_ctrl_mask = AMD_SDW1_PAD_CTRL_MASK;
|
||||
break;
|
||||
case 3:
|
||||
pad_keeper_en_mask = AMD_SDW_PAD_EN_MASK;
|
||||
pad_pulldown_ctrl_mask = AMD_SDW_PAD_PULLDOWN_CTRL_ENABLE_MASK;
|
||||
pad_keeper_en = AMD_SDW_PAD_EN;
|
||||
pad_pulldown_ctrl_mask = AMD_SDW_PAD_CTRL_MASK;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "No SDW Links are enabled\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
val = readl(mmio + ACP_SW_PAD_KEEPER_EN);
|
||||
val |= pad_keeper_en_mask;
|
||||
writel(val, mmio + ACP_SW_PAD_KEEPER_EN);
|
||||
val = readl(mmio + ACP_PAD_PULLDOWN_CTRL);
|
||||
val &= pad_pulldown_ctrl_mask;
|
||||
writel(val, mmio + ACP_PAD_PULLDOWN_CTRL);
|
||||
amd_updatel(mmio, ACP_SW_PAD_KEEPER_EN, pad_keeper_en, pad_keeper_en);
|
||||
amd_updatel(mmio, ACP_PAD_PULLDOWN_CTRL, pad_pulldown_ctrl_mask, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -10,4 +10,12 @@
|
||||
|
||||
int amd_sdw_manager_start(struct amd_sdw_manager *amd_manager);
|
||||
|
||||
static inline void amd_updatel(void __iomem *mmio, int offset, u32 mask, u32 val)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
tmp = readl(mmio + offset);
|
||||
tmp = (tmp & ~mask) | val;
|
||||
writel(tmp, mmio + offset);
|
||||
}
|
||||
#endif
|
||||
|
@ -89,9 +89,8 @@ static void amd_enable_sdw_interrupts(struct amd_sdw_manager *amd_manager)
|
||||
u32 val;
|
||||
|
||||
mutex_lock(amd_manager->acp_sdw_lock);
|
||||
val = readl(amd_manager->acp_mmio + ACP_EXTERNAL_INTR_CNTL(amd_manager->instance));
|
||||
val |= sdw_manager_reg_mask_array[amd_manager->instance];
|
||||
writel(val, amd_manager->acp_mmio + ACP_EXTERNAL_INTR_CNTL(amd_manager->instance));
|
||||
val = sdw_manager_reg_mask_array[amd_manager->instance];
|
||||
amd_updatel(amd_manager->acp_mmio, ACP_EXTERNAL_INTR_CNTL(amd_manager->instance), val, val);
|
||||
mutex_unlock(amd_manager->acp_sdw_lock);
|
||||
|
||||
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)
|
||||
|
||||
static void amd_disable_sdw_interrupts(struct amd_sdw_manager *amd_manager)
|
||||
{
|
||||
u32 val;
|
||||
u32 irq_mask;
|
||||
|
||||
mutex_lock(amd_manager->acp_sdw_lock);
|
||||
val = readl(amd_manager->acp_mmio + ACP_EXTERNAL_INTR_CNTL(amd_manager->instance));
|
||||
val &= ~sdw_manager_reg_mask_array[amd_manager->instance];
|
||||
writel(val, amd_manager->acp_mmio + ACP_EXTERNAL_INTR_CNTL(amd_manager->instance));
|
||||
irq_mask = sdw_manager_reg_mask_array[amd_manager->instance];
|
||||
amd_updatel(amd_manager->acp_mmio, ACP_EXTERNAL_INTR_CNTL(amd_manager->instance),
|
||||
irq_mask, 0);
|
||||
mutex_unlock(amd_manager->acp_sdw_lock);
|
||||
|
||||
writel(0x00, amd_manager->mmio + ACP_SW_STATE_CHANGE_STATUS_MASK_0TO7);
|
||||
|
@ -1312,18 +1312,18 @@ static int sdw_slave_set_frequency(struct sdw_slave *slave)
|
||||
if (!(19200000 % mclk_freq)) {
|
||||
mclk_freq = 19200000;
|
||||
base = SDW_SCP_BASE_CLOCK_19200000_HZ;
|
||||
} else if (!(24000000 % mclk_freq)) {
|
||||
mclk_freq = 24000000;
|
||||
base = SDW_SCP_BASE_CLOCK_24000000_HZ;
|
||||
} else if (!(24576000 % mclk_freq)) {
|
||||
mclk_freq = 24576000;
|
||||
base = SDW_SCP_BASE_CLOCK_24576000_HZ;
|
||||
} else if (!(22579200 % mclk_freq)) {
|
||||
mclk_freq = 22579200;
|
||||
base = SDW_SCP_BASE_CLOCK_22579200_HZ;
|
||||
} else if (!(24576000 % mclk_freq)) {
|
||||
mclk_freq = 24576000;
|
||||
base = SDW_SCP_BASE_CLOCK_24576000_HZ;
|
||||
} else if (!(32000000 % mclk_freq)) {
|
||||
mclk_freq = 32000000;
|
||||
base = SDW_SCP_BASE_CLOCK_32000000_HZ;
|
||||
} else if (!(96000000 % mclk_freq)) {
|
||||
mclk_freq = 24000000;
|
||||
base = SDW_SCP_BASE_CLOCK_24000000_HZ;
|
||||
} else {
|
||||
dev_err(&slave->dev,
|
||||
"Unsupported clock base, mclk %d\n",
|
||||
@ -1474,7 +1474,7 @@ static int sdw_handle_dp0_interrupt(struct sdw_slave *slave, u8 *slave_status)
|
||||
}
|
||||
|
||||
do {
|
||||
clear = status & ~SDW_DP0_INTERRUPTS;
|
||||
clear = status & ~(SDW_DP0_INTERRUPTS | SDW_DP0_SDCA_CASCADE);
|
||||
|
||||
if (status & SDW_DP0_INT_TEST_FAIL) {
|
||||
dev_err(&slave->dev, "Test fail for port 0\n");
|
||||
|
@ -126,8 +126,8 @@ static int sdw_drv_probe(struct device *dev)
|
||||
if (slave->prop.use_domain_irq)
|
||||
sdw_irq_create_mapping(slave);
|
||||
|
||||
/* init the sysfs as we have properties now */
|
||||
ret = sdw_slave_sysfs_init(slave);
|
||||
/* init the dynamic sysfs attributes we need */
|
||||
ret = sdw_slave_sysfs_dpn_init(slave);
|
||||
if (ret < 0)
|
||||
dev_warn(dev, "Slave sysfs init failed:%d\n", ret);
|
||||
|
||||
@ -221,6 +221,7 @@ int __sdw_register_driver(struct sdw_driver *drv, struct module *owner)
|
||||
drv->driver.probe = sdw_drv_probe;
|
||||
drv->driver.remove = sdw_drv_remove;
|
||||
drv->driver.shutdown = sdw_drv_shutdown;
|
||||
drv->driver.dev_groups = sdw_attr_groups;
|
||||
|
||||
return driver_register(&drv->driver);
|
||||
}
|
||||
|
@ -1236,7 +1236,7 @@ EXPORT_SYMBOL(sdw_cdns_enable_interrupt);
|
||||
|
||||
static int cdns_allocate_pdi(struct sdw_cdns *cdns,
|
||||
struct sdw_cdns_pdi **stream,
|
||||
u32 num, u32 pdi_offset)
|
||||
u32 num)
|
||||
{
|
||||
struct sdw_cdns_pdi *pdi;
|
||||
int i;
|
||||
@ -1249,7 +1249,7 @@ static int cdns_allocate_pdi(struct sdw_cdns *cdns,
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
pdi[i].num = i + pdi_offset;
|
||||
pdi[i].num = i;
|
||||
}
|
||||
|
||||
*stream = pdi;
|
||||
@ -1266,7 +1266,6 @@ int sdw_cdns_pdi_init(struct sdw_cdns *cdns,
|
||||
struct sdw_cdns_stream_config config)
|
||||
{
|
||||
struct sdw_cdns_streams *stream;
|
||||
int offset;
|
||||
int ret;
|
||||
|
||||
cdns->pcm.num_bd = config.pcm_bd;
|
||||
@ -1277,24 +1276,15 @@ int sdw_cdns_pdi_init(struct sdw_cdns *cdns,
|
||||
stream = &cdns->pcm;
|
||||
|
||||
/* we allocate PDI0 and PDI1 which are used for Bulk */
|
||||
offset = 0;
|
||||
|
||||
ret = cdns_allocate_pdi(cdns, &stream->bd,
|
||||
stream->num_bd, offset);
|
||||
ret = cdns_allocate_pdi(cdns, &stream->bd, stream->num_bd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
offset += stream->num_bd;
|
||||
|
||||
ret = cdns_allocate_pdi(cdns, &stream->in,
|
||||
stream->num_in, offset);
|
||||
ret = cdns_allocate_pdi(cdns, &stream->in, stream->num_in);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
offset += stream->num_in;
|
||||
|
||||
ret = cdns_allocate_pdi(cdns, &stream->out,
|
||||
stream->num_out, offset);
|
||||
ret = cdns_allocate_pdi(cdns, &stream->out, stream->num_out);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -1329,6 +1319,12 @@ static void cdns_init_clock_ctrl(struct sdw_cdns *cdns)
|
||||
u32 ssp_interval;
|
||||
int divider;
|
||||
|
||||
dev_dbg(cdns->dev, "mclk %d max %d row %d col %d\n",
|
||||
prop->mclk_freq,
|
||||
prop->max_clk_freq,
|
||||
prop->default_row,
|
||||
prop->default_col);
|
||||
|
||||
/* Set clock divider */
|
||||
divider = (prop->mclk_freq / prop->max_clk_freq) - 1;
|
||||
|
||||
@ -1802,7 +1798,6 @@ EXPORT_SYMBOL(cdns_set_sdw_stream);
|
||||
* cdns_find_pdi() - Find a free PDI
|
||||
*
|
||||
* @cdns: Cadence instance
|
||||
* @offset: Starting offset
|
||||
* @num: Number of PDIs
|
||||
* @pdi: PDI instances
|
||||
* @dai_id: DAI id
|
||||
@ -1811,14 +1806,13 @@ EXPORT_SYMBOL(cdns_set_sdw_stream);
|
||||
* expected to match, return NULL otherwise.
|
||||
*/
|
||||
static struct sdw_cdns_pdi *cdns_find_pdi(struct sdw_cdns *cdns,
|
||||
unsigned int offset,
|
||||
unsigned int num,
|
||||
struct sdw_cdns_pdi *pdi,
|
||||
int dai_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = offset; i < offset + num; i++)
|
||||
for (i = 0; i < num; i++)
|
||||
if (pdi[i].num == dai_id)
|
||||
return &pdi[i];
|
||||
|
||||
@ -1872,15 +1866,15 @@ struct sdw_cdns_pdi *sdw_cdns_alloc_pdi(struct sdw_cdns *cdns,
|
||||
struct sdw_cdns_pdi *pdi = NULL;
|
||||
|
||||
if (dir == SDW_DATA_DIR_RX)
|
||||
pdi = cdns_find_pdi(cdns, 0, stream->num_in, stream->in,
|
||||
pdi = cdns_find_pdi(cdns, stream->num_in, stream->in,
|
||||
dai_id);
|
||||
else
|
||||
pdi = cdns_find_pdi(cdns, 0, stream->num_out, stream->out,
|
||||
pdi = cdns_find_pdi(cdns, stream->num_out, stream->out,
|
||||
dai_id);
|
||||
|
||||
/* check if we found a PDI, else find in bi-directional */
|
||||
if (!pdi)
|
||||
pdi = cdns_find_pdi(cdns, 2, stream->num_bd, stream->bd,
|
||||
pdi = cdns_find_pdi(cdns, stream->num_bd, stream->bd,
|
||||
dai_id);
|
||||
|
||||
if (pdi) {
|
||||
|
@ -345,8 +345,10 @@ static int intel_link_power_up(struct sdw_intel *sdw)
|
||||
u32 spa_mask, cpa_mask;
|
||||
u32 link_control;
|
||||
int ret = 0;
|
||||
u32 clock_source;
|
||||
u32 syncprd;
|
||||
u32 sync_reg;
|
||||
bool lcap_mlcs;
|
||||
|
||||
mutex_lock(sdw->link_res->shim_lock);
|
||||
|
||||
@ -358,12 +360,35 @@ static int intel_link_power_up(struct sdw_intel *sdw)
|
||||
* is only dependent on the oscillator clock provided to
|
||||
* the IP, so adjust based on _DSD properties reported in DSDT
|
||||
* tables. The values reported are based on either 24MHz
|
||||
* (CNL/CML) or 38.4 MHz (ICL/TGL+).
|
||||
* (CNL/CML) or 38.4 MHz (ICL/TGL+). On MeteorLake additional
|
||||
* frequencies are available with the MLCS clock source selection.
|
||||
*/
|
||||
if (prop->mclk_freq % 6000000)
|
||||
syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_38_4;
|
||||
else
|
||||
syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_24;
|
||||
lcap_mlcs = intel_readl(shim, SDW_SHIM_LCAP) & SDW_SHIM_LCAP_MLCS_MASK;
|
||||
|
||||
if (prop->mclk_freq % 6000000) {
|
||||
if (prop->mclk_freq % 2400000) {
|
||||
if (lcap_mlcs) {
|
||||
syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_24_576;
|
||||
clock_source = SDW_SHIM_MLCS_CARDINAL_CLK;
|
||||
} else {
|
||||
dev_err(sdw->cdns.dev, "%s: invalid clock configuration, mclk %d lcap_mlcs %d\n",
|
||||
__func__, prop->mclk_freq, lcap_mlcs);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_38_4;
|
||||
clock_source = SDW_SHIM_MLCS_XTAL_CLK;
|
||||
}
|
||||
} else {
|
||||
if (lcap_mlcs) {
|
||||
syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_96;
|
||||
clock_source = SDW_SHIM_MLCS_AUDIO_PLL_CLK;
|
||||
} else {
|
||||
syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_24;
|
||||
clock_source = SDW_SHIM_MLCS_XTAL_CLK;
|
||||
}
|
||||
}
|
||||
|
||||
if (!*shim_mask) {
|
||||
dev_dbg(sdw->cdns.dev, "powering up all links\n");
|
||||
@ -403,6 +428,13 @@ static int intel_link_power_up(struct sdw_intel *sdw)
|
||||
"Failed to set SHIM_SYNC: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* update link clock if needed */
|
||||
if (lcap_mlcs) {
|
||||
link_control = intel_readl(shim, SDW_SHIM_LCTL);
|
||||
u32p_replace_bits(&link_control, clock_source, SDW_SHIM_LCTL_MLCS_MASK);
|
||||
intel_writel(shim, SDW_SHIM_LCTL, link_control);
|
||||
}
|
||||
}
|
||||
|
||||
*shim_mask |= BIT(link_id);
|
||||
@ -668,6 +700,24 @@ static int intel_params_stream(struct sdw_intel *sdw,
|
||||
* DAI routines
|
||||
*/
|
||||
|
||||
static int intel_free_stream(struct sdw_intel *sdw,
|
||||
struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai,
|
||||
int link_id)
|
||||
{
|
||||
struct sdw_intel_link_res *res = sdw->link_res;
|
||||
struct sdw_intel_stream_free_data free_data;
|
||||
|
||||
free_data.substream = substream;
|
||||
free_data.dai = dai;
|
||||
free_data.link_id = link_id;
|
||||
|
||||
if (res->ops && res->ops->free_stream && res->dev)
|
||||
return res->ops->free_stream(res->dev, &free_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intel_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
@ -799,6 +849,7 @@ static int
|
||||
intel_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
|
||||
struct sdw_intel *sdw = cdns_to_intel(cdns);
|
||||
struct sdw_cdns_dai_runtime *dai_runtime;
|
||||
int ret;
|
||||
|
||||
@ -819,6 +870,12 @@ intel_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = intel_free_stream(sdw, substream, dai, sdw->instance);
|
||||
if (ret < 0) {
|
||||
dev_err(dai->dev, "intel_free_stream: failed %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dai_runtime->pdi = NULL;
|
||||
|
||||
return 0;
|
||||
@ -1062,4 +1119,3 @@ const struct sdw_intel_hw_ops sdw_intel_cnl_hw_ops = {
|
||||
.sync_check_cmdsync_unlocked = intel_check_cmdsync_unlocked,
|
||||
};
|
||||
EXPORT_SYMBOL_NS(sdw_intel_cnl_hw_ops, SOUNDWIRE_INTEL);
|
||||
|
||||
|
@ -58,6 +58,13 @@ struct sdw_intel {
|
||||
#endif
|
||||
};
|
||||
|
||||
struct sdw_intel_prop {
|
||||
u16 doaise;
|
||||
u16 doais;
|
||||
u16 dodse;
|
||||
u16 dods;
|
||||
};
|
||||
|
||||
enum intel_pdi_type {
|
||||
INTEL_PDI_IN = 0,
|
||||
INTEL_PDI_OUT = 1,
|
||||
|
@ -10,8 +10,10 @@
|
||||
#include <linux/soundwire/sdw_registers.h>
|
||||
#include <linux/soundwire/sdw.h>
|
||||
#include <linux/soundwire/sdw_intel.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/hdaudio.h>
|
||||
#include <sound/hda-mlink.h>
|
||||
#include <sound/hda_register.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include "cadence_master.h"
|
||||
#include "bus.h"
|
||||
#include "intel.h"
|
||||
@ -23,49 +25,86 @@
|
||||
static void intel_shim_vs_init(struct sdw_intel *sdw)
|
||||
{
|
||||
void __iomem *shim_vs = sdw->link_res->shim_vs;
|
||||
struct sdw_bus *bus = &sdw->cdns.bus;
|
||||
struct sdw_intel_prop *intel_prop;
|
||||
u16 doaise;
|
||||
u16 doais;
|
||||
u16 dodse;
|
||||
u16 dods;
|
||||
u16 act;
|
||||
|
||||
intel_prop = bus->vendor_specific_prop;
|
||||
doaise = intel_prop->doaise;
|
||||
doais = intel_prop->doais;
|
||||
dodse = intel_prop->dodse;
|
||||
dods = intel_prop->dods;
|
||||
|
||||
act = intel_readw(shim_vs, SDW_SHIM2_INTEL_VS_ACTMCTL);
|
||||
u16p_replace_bits(&act, 0x1, SDW_SHIM2_INTEL_VS_ACTMCTL_DOAIS);
|
||||
u16p_replace_bits(&act, doaise, SDW_SHIM2_INTEL_VS_ACTMCTL_DOAISE);
|
||||
u16p_replace_bits(&act, doais, SDW_SHIM2_INTEL_VS_ACTMCTL_DOAIS);
|
||||
u16p_replace_bits(&act, dodse, SDW_SHIM2_INTEL_VS_ACTMCTL_DODSE);
|
||||
u16p_replace_bits(&act, dods, SDW_SHIM2_INTEL_VS_ACTMCTL_DODS);
|
||||
act |= SDW_SHIM2_INTEL_VS_ACTMCTL_DACTQE;
|
||||
act |= SDW_SHIM2_INTEL_VS_ACTMCTL_DODS;
|
||||
intel_writew(shim_vs, SDW_SHIM2_INTEL_VS_ACTMCTL, act);
|
||||
usleep_range(10, 15);
|
||||
}
|
||||
|
||||
static void intel_shim_vs_set_clock_source(struct sdw_intel *sdw, u32 source)
|
||||
{
|
||||
void __iomem *shim_vs = sdw->link_res->shim_vs;
|
||||
u32 val;
|
||||
|
||||
val = intel_readl(shim_vs, SDW_SHIM2_INTEL_VS_LVSCTL);
|
||||
|
||||
u32p_replace_bits(&val, source, SDW_SHIM2_INTEL_VS_LVSCTL_MLCS);
|
||||
|
||||
intel_writel(shim_vs, SDW_SHIM2_INTEL_VS_LVSCTL, val);
|
||||
|
||||
dev_dbg(sdw->cdns.dev, "clock source %d LVSCTL %#x\n", source, val);
|
||||
}
|
||||
|
||||
static int intel_shim_check_wake(struct sdw_intel *sdw)
|
||||
{
|
||||
void __iomem *shim_vs;
|
||||
u16 wake_sts;
|
||||
/*
|
||||
* We follow the HDaudio example and resume unconditionally
|
||||
* without checking the WAKESTS bit for that specific link
|
||||
*/
|
||||
|
||||
shim_vs = sdw->link_res->shim_vs;
|
||||
wake_sts = intel_readw(shim_vs, SDW_SHIM2_INTEL_VS_WAKESTS);
|
||||
|
||||
return wake_sts & SDW_SHIM2_INTEL_VS_WAKEEN_PWS;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void intel_shim_wake(struct sdw_intel *sdw, bool wake_enable)
|
||||
{
|
||||
void __iomem *shim_vs = sdw->link_res->shim_vs;
|
||||
u16 lsdiid = 0;
|
||||
u16 wake_en;
|
||||
u16 wake_sts;
|
||||
int ret;
|
||||
|
||||
wake_en = intel_readw(shim_vs, SDW_SHIM2_INTEL_VS_WAKEEN);
|
||||
mutex_lock(sdw->link_res->shim_lock);
|
||||
|
||||
ret = hdac_bus_eml_sdw_get_lsdiid_unlocked(sdw->link_res->hbus, sdw->instance, &lsdiid);
|
||||
if (ret < 0)
|
||||
goto unlock;
|
||||
|
||||
wake_en = snd_hdac_chip_readw(sdw->link_res->hbus, WAKEEN);
|
||||
|
||||
if (wake_enable) {
|
||||
/* Enable the wakeup */
|
||||
wake_en |= SDW_SHIM2_INTEL_VS_WAKEEN_PWE;
|
||||
intel_writew(shim_vs, SDW_SHIM2_INTEL_VS_WAKEEN, wake_en);
|
||||
wake_en |= lsdiid;
|
||||
|
||||
snd_hdac_chip_writew(sdw->link_res->hbus, WAKEEN, wake_en);
|
||||
} else {
|
||||
/* Disable the wake up interrupt */
|
||||
wake_en &= ~SDW_SHIM2_INTEL_VS_WAKEEN_PWE;
|
||||
intel_writew(shim_vs, SDW_SHIM2_INTEL_VS_WAKEEN, wake_en);
|
||||
wake_en &= ~lsdiid;
|
||||
snd_hdac_chip_writew(sdw->link_res->hbus, WAKEEN, wake_en);
|
||||
|
||||
/* Clear wake status (W1C) */
|
||||
wake_sts = intel_readw(shim_vs, SDW_SHIM2_INTEL_VS_WAKESTS);
|
||||
wake_sts |= SDW_SHIM2_INTEL_VS_WAKEEN_PWS;
|
||||
intel_writew(shim_vs, SDW_SHIM2_INTEL_VS_WAKESTS, wake_sts);
|
||||
wake_sts = snd_hdac_chip_readw(sdw->link_res->hbus, STATESTS);
|
||||
wake_sts |= lsdiid;
|
||||
snd_hdac_chip_writew(sdw->link_res->hbus, STATESTS, wake_sts);
|
||||
}
|
||||
unlock:
|
||||
mutex_unlock(sdw->link_res->shim_lock);
|
||||
}
|
||||
|
||||
static int intel_link_power_up(struct sdw_intel *sdw)
|
||||
@ -74,28 +113,25 @@ static int intel_link_power_up(struct sdw_intel *sdw)
|
||||
struct sdw_master_prop *prop = &bus->prop;
|
||||
u32 *shim_mask = sdw->link_res->shim_mask;
|
||||
unsigned int link_id = sdw->instance;
|
||||
u32 clock_source;
|
||||
u32 syncprd;
|
||||
int ret;
|
||||
|
||||
mutex_lock(sdw->link_res->shim_lock);
|
||||
|
||||
if (!*shim_mask) {
|
||||
/* we first need to program the SyncPRD/CPU registers */
|
||||
dev_dbg(sdw->cdns.dev, "first link up, programming SYNCPRD\n");
|
||||
|
||||
if (prop->mclk_freq % 6000000)
|
||||
if (prop->mclk_freq % 6000000) {
|
||||
if (prop->mclk_freq % 2400000) {
|
||||
syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_24_576;
|
||||
clock_source = SDW_SHIM2_MLCS_CARDINAL_CLK;
|
||||
} else {
|
||||
syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_38_4;
|
||||
else
|
||||
syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_24;
|
||||
|
||||
ret = hdac_bus_eml_sdw_set_syncprd_unlocked(sdw->link_res->hbus, syncprd);
|
||||
if (ret < 0) {
|
||||
dev_err(sdw->cdns.dev, "%s: hdac_bus_eml_sdw_set_syncprd failed: %d\n",
|
||||
__func__, ret);
|
||||
goto out;
|
||||
clock_source = SDW_SHIM2_MLCS_XTAL_CLK;
|
||||
}
|
||||
} else {
|
||||
syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_96;
|
||||
clock_source = SDW_SHIM2_MLCS_AUDIO_PLL_CLK;
|
||||
}
|
||||
|
||||
mutex_lock(sdw->link_res->shim_lock);
|
||||
|
||||
ret = hdac_bus_eml_sdw_power_up_unlocked(sdw->link_res->hbus, link_id);
|
||||
if (ret < 0) {
|
||||
dev_err(sdw->cdns.dev, "%s: hdac_bus_eml_sdw_power_up failed: %d\n",
|
||||
@ -103,7 +139,19 @@ static int intel_link_power_up(struct sdw_intel *sdw)
|
||||
goto out;
|
||||
}
|
||||
|
||||
intel_shim_vs_set_clock_source(sdw, clock_source);
|
||||
|
||||
if (!*shim_mask) {
|
||||
/* we first need to program the SyncPRD/CPU registers */
|
||||
dev_dbg(sdw->cdns.dev, "first link up, programming SYNCPRD\n");
|
||||
|
||||
ret = hdac_bus_eml_sdw_set_syncprd_unlocked(sdw->link_res->hbus, syncprd);
|
||||
if (ret < 0) {
|
||||
dev_err(sdw->cdns.dev, "%s: hdac_bus_eml_sdw_set_syncprd failed: %d\n",
|
||||
__func__, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* SYNCPU will change once link is active */
|
||||
ret = hdac_bus_eml_sdw_wait_syncpu_unlocked(sdw->link_res->hbus);
|
||||
if (ret < 0) {
|
||||
@ -268,6 +316,11 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* use same definitions for alh_id as previous generations */
|
||||
pdi->intel_alh_id = (sdw->instance * 16) + pdi->num + 3;
|
||||
if (pdi->num >= 2)
|
||||
pdi->intel_alh_id += 2;
|
||||
|
||||
/* the SHIM will be configured in the callback functions */
|
||||
|
||||
sdw_cdns_config_stream(cdns, ch, dir, pdi);
|
||||
|
@ -122,6 +122,7 @@ static void generic_new_peripheral_assigned(struct sdw_bus *bus,
|
||||
static int sdw_master_read_intel_prop(struct sdw_bus *bus)
|
||||
{
|
||||
struct sdw_master_prop *prop = &bus->prop;
|
||||
struct sdw_intel_prop *intel_prop;
|
||||
struct fwnode_handle *link;
|
||||
char name[32];
|
||||
u32 quirk_mask;
|
||||
@ -153,6 +154,36 @@ static int sdw_master_read_intel_prop(struct sdw_bus *bus)
|
||||
prop->quirks = SDW_MASTER_QUIRKS_CLEAR_INITIAL_CLASH |
|
||||
SDW_MASTER_QUIRKS_CLEAR_INITIAL_PARITY;
|
||||
|
||||
intel_prop = devm_kzalloc(bus->dev, sizeof(*intel_prop), GFP_KERNEL);
|
||||
if (!intel_prop)
|
||||
return -ENOMEM;
|
||||
|
||||
/* initialize with hardware defaults, in case the properties are not found */
|
||||
intel_prop->doaise = 0x1;
|
||||
intel_prop->doais = 0x3;
|
||||
intel_prop->dodse = 0x0;
|
||||
intel_prop->dods = 0x1;
|
||||
|
||||
fwnode_property_read_u16(link,
|
||||
"intel-sdw-doaise",
|
||||
&intel_prop->doaise);
|
||||
fwnode_property_read_u16(link,
|
||||
"intel-sdw-doais",
|
||||
&intel_prop->doais);
|
||||
fwnode_property_read_u16(link,
|
||||
"intel-sdw-dodse",
|
||||
&intel_prop->dodse);
|
||||
fwnode_property_read_u16(link,
|
||||
"intel-sdw-dods",
|
||||
&intel_prop->dods);
|
||||
bus->vendor_specific_prop = intel_prop;
|
||||
|
||||
dev_dbg(bus->dev, "doaise %#x doais %#x dodse %#x dods %#x\n",
|
||||
intel_prop->doaise,
|
||||
intel_prop->doais,
|
||||
intel_prop->dodse,
|
||||
intel_prop->dods);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -440,7 +471,7 @@ int intel_link_process_wakeen_event(struct auxiliary_device *auxdev)
|
||||
* PM calls
|
||||
*/
|
||||
|
||||
static int intel_resume_child_device(struct device *dev, void *data)
|
||||
int intel_resume_child_device(struct device *dev, void *data)
|
||||
{
|
||||
int ret;
|
||||
struct sdw_slave *slave = dev_to_sdw_dev(dev);
|
||||
@ -454,9 +485,9 @@ static int intel_resume_child_device(struct device *dev, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = pm_request_resume(dev);
|
||||
ret = pm_runtime_resume(dev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: pm_request_resume failed: %d\n", __func__, ret);
|
||||
dev_err(dev, "%s: pm_runtime_resume failed: %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -499,9 +530,9 @@ static int __maybe_unused intel_pm_prepare(struct device *dev)
|
||||
* first resume the device for this link. This will also by construction
|
||||
* resume the PCI parent device.
|
||||
*/
|
||||
ret = pm_request_resume(dev);
|
||||
ret = pm_runtime_resume(dev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: pm_request_resume failed: %d\n", __func__, ret);
|
||||
dev_err(dev, "%s: pm_runtime_resume failed: %d\n", __func__, ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
int intel_link_startup(struct auxiliary_device *auxdev);
|
||||
int intel_link_process_wakeen_event(struct auxiliary_device *auxdev);
|
||||
int intel_resume_child_device(struct device *dev, void *data);
|
||||
|
||||
struct sdw_intel_link_dev {
|
||||
struct auxiliary_device auxdev;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/soundwire/sdw_intel.h>
|
||||
#include "cadence_master.h"
|
||||
#include "bus.h"
|
||||
#include "intel.h"
|
||||
#include "intel_auxdevice.h"
|
||||
|
||||
@ -356,6 +357,19 @@ EXPORT_SYMBOL_NS(sdw_intel_startup, SOUNDWIRE_INTEL_INIT);
|
||||
*/
|
||||
void sdw_intel_exit(struct sdw_intel_ctx *ctx)
|
||||
{
|
||||
struct sdw_intel_link_res *link;
|
||||
|
||||
/* we first resume links and devices and wait synchronously before the cleanup */
|
||||
list_for_each_entry(link, &ctx->link_list, list) {
|
||||
struct sdw_bus *bus = &link->cdns->bus;
|
||||
int ret;
|
||||
|
||||
ret = device_for_each_child(bus->dev, NULL, intel_resume_child_device);
|
||||
if (ret < 0)
|
||||
dev_err(bus->dev, "%s: intel_resume_child_device failed: %d\n",
|
||||
__func__, ret);
|
||||
}
|
||||
|
||||
sdw_intel_cleanup(ctx);
|
||||
kfree(ctx->ids);
|
||||
kfree(ctx->ldev);
|
||||
|
@ -905,6 +905,18 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_swrm_read_prop(struct sdw_bus *bus)
|
||||
{
|
||||
struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus);
|
||||
|
||||
if (ctrl->version >= SWRM_VERSION_2_0_0) {
|
||||
bus->multi_link = true;
|
||||
bus->hw_sync_min_links = 3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum sdw_command_response qcom_swrm_xfer_msg(struct sdw_bus *bus,
|
||||
struct sdw_msg *msg)
|
||||
{
|
||||
@ -1056,6 +1068,7 @@ static const struct sdw_master_port_ops qcom_swrm_port_ops = {
|
||||
};
|
||||
|
||||
static const struct sdw_master_ops qcom_swrm_ops = {
|
||||
.read_prop = qcom_swrm_read_prop,
|
||||
.xfer_msg = qcom_swrm_xfer_msg,
|
||||
.pre_bank_switch = qcom_swrm_pre_bank_switch,
|
||||
};
|
||||
@ -1173,6 +1186,15 @@ static int qcom_swrm_stream_alloc_ports(struct qcom_swrm_ctrl *ctrl,
|
||||
|
||||
mutex_lock(&ctrl->port_lock);
|
||||
list_for_each_entry(m_rt, &stream->master_list, stream_node) {
|
||||
/*
|
||||
* For streams with multiple masters:
|
||||
* Allocate ports only for devices connected to this master.
|
||||
* Such devices will have ports allocated by their own master
|
||||
* and its qcom_swrm_stream_alloc_ports() call.
|
||||
*/
|
||||
if (ctrl->bus.id != m_rt->bus->id)
|
||||
continue;
|
||||
|
||||
if (m_rt->direction == SDW_DATA_DIR_RX) {
|
||||
maxport = ctrl->num_dout_ports;
|
||||
port_mask = &ctrl->dout_port_mask;
|
||||
@ -1636,14 +1658,12 @@ err_init:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_swrm_remove(struct platform_device *pdev)
|
||||
static void qcom_swrm_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
sdw_bus_master_delete(&ctrl->bus);
|
||||
clk_disable_unprepare(ctrl->hclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused swrm_runtime_resume(struct device *dev)
|
||||
@ -1769,7 +1789,7 @@ MODULE_DEVICE_TABLE(of, qcom_swrm_of_match);
|
||||
|
||||
static struct platform_driver qcom_swrm_driver = {
|
||||
.probe = &qcom_swrm_probe,
|
||||
.remove = &qcom_swrm_remove,
|
||||
.remove_new = qcom_swrm_remove,
|
||||
.driver = {
|
||||
.name = "qcom-soundwire",
|
||||
.of_match_table = qcom_swrm_of_match,
|
||||
|
@ -11,8 +11,10 @@
|
||||
/* basic attributes to report status of Slave (attachment, dev_num) */
|
||||
extern const struct attribute_group *sdw_slave_status_attr_groups[];
|
||||
|
||||
/* attributes for all soundwire devices */
|
||||
extern const struct attribute_group *sdw_attr_groups[];
|
||||
|
||||
/* additional device-managed properties reported after driver probe */
|
||||
int sdw_slave_sysfs_init(struct sdw_slave *slave);
|
||||
int sdw_slave_sysfs_dpn_init(struct sdw_slave *slave);
|
||||
|
||||
#endif /* __SDW_SYSFS_LOCAL_H */
|
||||
|
@ -105,7 +105,10 @@ static struct attribute *slave_attrs[] = {
|
||||
&dev_attr_modalias.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(slave);
|
||||
|
||||
static const struct attribute_group slave_attr_group = {
|
||||
.attrs = slave_attrs,
|
||||
};
|
||||
|
||||
static struct attribute *slave_dev_attrs[] = {
|
||||
&dev_attr_mipi_revision.attr,
|
||||
@ -126,10 +129,6 @@ static struct attribute *slave_dev_attrs[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
/*
|
||||
* we don't use ATTRIBUTES_GROUP here since we want to add a subdirectory
|
||||
* for device-level properties
|
||||
*/
|
||||
static const struct attribute_group sdw_slave_dev_attr_group = {
|
||||
.attrs = slave_dev_attrs,
|
||||
.name = "dev-properties",
|
||||
@ -181,41 +180,38 @@ static struct attribute *dp0_attrs[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
/*
|
||||
* we don't use ATTRIBUTES_GROUP here since we want to add a subdirectory
|
||||
* for dp0-level properties
|
||||
*/
|
||||
static umode_t dp0_attr_visible(struct kobject *kobj, struct attribute *attr,
|
||||
int n)
|
||||
{
|
||||
struct sdw_slave *slave = dev_to_sdw_dev(kobj_to_dev(kobj));
|
||||
|
||||
if (slave->prop.dp0_prop)
|
||||
return attr->mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool dp0_group_visible(struct kobject *kobj)
|
||||
{
|
||||
struct sdw_slave *slave = dev_to_sdw_dev(kobj_to_dev(kobj));
|
||||
|
||||
if (slave->prop.dp0_prop)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
DEFINE_SYSFS_GROUP_VISIBLE(dp0);
|
||||
|
||||
static const struct attribute_group dp0_group = {
|
||||
.attrs = dp0_attrs,
|
||||
.is_visible = SYSFS_GROUP_VISIBLE(dp0),
|
||||
.name = "dp0",
|
||||
};
|
||||
|
||||
int sdw_slave_sysfs_init(struct sdw_slave *slave)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = devm_device_add_groups(&slave->dev, slave_groups);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = devm_device_add_group(&slave->dev, &sdw_slave_dev_attr_group);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (slave->prop.dp0_prop) {
|
||||
ret = devm_device_add_group(&slave->dev, &dp0_group);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (slave->prop.source_ports || slave->prop.sink_ports) {
|
||||
ret = sdw_slave_sysfs_dpn_init(slave);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
const struct attribute_group *sdw_attr_groups[] = {
|
||||
&slave_attr_group,
|
||||
&sdw_slave_dev_attr_group,
|
||||
&dp0_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/*
|
||||
* the status is shown in capital letters for UNATTACHED and RESERVED
|
||||
|
@ -283,6 +283,9 @@ int sdw_slave_sysfs_dpn_init(struct sdw_slave *slave)
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (!slave->prop.source_ports && !slave->prop.sink_ports)
|
||||
return 0;
|
||||
|
||||
mask = slave->prop.source_ports;
|
||||
for_each_set_bit(i, &mask, 32) {
|
||||
ret = add_all_attributes(&slave->dev, i, 1);
|
||||
|
@ -235,6 +235,7 @@ enum sdw_clk_stop_mode {
|
||||
* @BRA_flow_controlled: Slave implementation results in an OK_NotReady
|
||||
* response
|
||||
* @simple_ch_prep_sm: If channel prepare sequence is required
|
||||
* @ch_prep_timeout: Port-specific timeout value, in milliseconds
|
||||
* @imp_def_interrupts: If set, each bit corresponds to support for
|
||||
* implementation-defined interrupts
|
||||
*
|
||||
@ -249,6 +250,7 @@ struct sdw_dp0_prop {
|
||||
u32 *words;
|
||||
bool BRA_flow_controlled;
|
||||
bool simple_ch_prep_sm;
|
||||
u32 ch_prep_timeout;
|
||||
bool imp_def_interrupts;
|
||||
};
|
||||
|
||||
@ -542,21 +544,6 @@ enum sdw_reg_bank {
|
||||
SDW_BANK1,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sdw_bus_conf: Bus configuration
|
||||
*
|
||||
* @clk_freq: Clock frequency, in Hz
|
||||
* @num_rows: Number of rows in frame
|
||||
* @num_cols: Number of columns in frame
|
||||
* @bank: Next register bank
|
||||
*/
|
||||
struct sdw_bus_conf {
|
||||
unsigned int clk_freq;
|
||||
unsigned int num_rows;
|
||||
unsigned int num_cols;
|
||||
unsigned int bank;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sdw_prepare_ch: Prepare/De-prepare Data Port channel
|
||||
*
|
||||
@ -899,6 +886,7 @@ struct sdw_master_ops {
|
||||
* @port_ops: Master port callback ops
|
||||
* @params: Current bus parameters
|
||||
* @prop: Master properties
|
||||
* @vendor_specific_prop: pointer to non-standard properties
|
||||
* @m_rt_list: List of Master instance of all stream(s) running on Bus. This
|
||||
* is used to compute and program bus bandwidth, clock, frame shape,
|
||||
* transport and port parameters
|
||||
@ -933,6 +921,7 @@ struct sdw_bus {
|
||||
const struct sdw_master_port_ops *port_ops;
|
||||
struct sdw_bus_params params;
|
||||
struct sdw_master_prop prop;
|
||||
void *vendor_specific_prop;
|
||||
struct list_head m_rt_list;
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs;
|
||||
|
@ -22,6 +22,7 @@
|
||||
/* LCAP */
|
||||
#define SDW_SHIM_LCAP 0x0
|
||||
#define SDW_SHIM_LCAP_LCOUNT_MASK GENMASK(2, 0)
|
||||
#define SDW_SHIM_LCAP_MLCS_MASK BIT(8)
|
||||
|
||||
/* LCTL */
|
||||
#define SDW_SHIM_LCTL 0x4
|
||||
@ -30,12 +31,18 @@
|
||||
#define SDW_SHIM_LCTL_SPA_MASK GENMASK(3, 0)
|
||||
#define SDW_SHIM_LCTL_CPA BIT(8)
|
||||
#define SDW_SHIM_LCTL_CPA_MASK GENMASK(11, 8)
|
||||
#define SDW_SHIM_LCTL_MLCS_MASK GENMASK(29, 27)
|
||||
#define SDW_SHIM_MLCS_XTAL_CLK 0x0
|
||||
#define SDW_SHIM_MLCS_CARDINAL_CLK 0x1
|
||||
#define SDW_SHIM_MLCS_AUDIO_PLL_CLK 0x2
|
||||
|
||||
/* SYNC */
|
||||
#define SDW_SHIM_SYNC 0xC
|
||||
|
||||
#define SDW_SHIM_SYNC_SYNCPRD_VAL_24 (24000 / SDW_CADENCE_GSYNC_KHZ - 1)
|
||||
#define SDW_SHIM_SYNC_SYNCPRD_VAL_38_4 (38400 / SDW_CADENCE_GSYNC_KHZ - 1)
|
||||
#define SDW_SHIM_SYNC_SYNCPRD_VAL_24 (24000 / SDW_CADENCE_GSYNC_KHZ - 1)
|
||||
#define SDW_SHIM_SYNC_SYNCPRD_VAL_24_576 (24576 / SDW_CADENCE_GSYNC_KHZ - 1)
|
||||
#define SDW_SHIM_SYNC_SYNCPRD_VAL_38_4 (38400 / SDW_CADENCE_GSYNC_KHZ - 1)
|
||||
#define SDW_SHIM_SYNC_SYNCPRD_VAL_96 (96000 / SDW_CADENCE_GSYNC_KHZ - 1)
|
||||
#define SDW_SHIM_SYNC_SYNCPRD GENMASK(14, 0)
|
||||
#define SDW_SHIM_SYNC_SYNCCPU BIT(15)
|
||||
#define SDW_SHIM_SYNC_CMDSYNC_MASK GENMASK(19, 16)
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#define SDW_REG_NO_PAGE 0x00008000
|
||||
#define SDW_REG_OPTIONAL_PAGE 0x00010000
|
||||
#define SDW_REG_MAX 0x80000000
|
||||
#define SDW_REG_MAX 0x48000000
|
||||
|
||||
#define SDW_DPN_SIZE 0x100
|
||||
#define SDW_BANK1_OFFSET 0x10
|
||||
|
@ -246,12 +246,12 @@ static int hda_sdw_exit(struct snd_sof_dev *sdev)
|
||||
|
||||
hdev = sdev->pdata->hw_pdata;
|
||||
|
||||
hda_sdw_int_enable(sdev, false);
|
||||
|
||||
if (hdev->sdw)
|
||||
sdw_intel_exit(hdev->sdw);
|
||||
hdev->sdw = NULL;
|
||||
|
||||
hda_sdw_int_enable(sdev, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user