sound fixes for 6.9-rc7

As usual in a late stage, we received a fair amount of fixes for ASoC,
 and it became bigger than wished.  But all fixes are rather device-
 specific, and they look pretty safe to apply.
 
 A major par of changes are series of fixes for ASoC meson and SOF
 drivers as well as for Realtek and Cirrus codecs.  In addition,
 recent emu10k1 regression fixes and usual HD-audio quirks are
 included.
 -----BEGIN PGP SIGNATURE-----
 
 iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmY0n6wOHHRpd2FpQHN1
 c2UuZGUACgkQLtJE4w1nLE8PqA/7BB6G1i3ARX7MusxZA/bqoEQ5nVhocs/WJGos
 WCUTc6GH9uWvpBE+dY3/9IQemnndb5LaKuIK8Bh1ooTdHiu431X4cXPqX5U2gvbW
 iHom2Mk7KFPVqQEzx0QV4i5gc68G3FMgwi2G6FMx4APaNn2XpyTweKoV9V8keBQq
 lpLQ5dxxeK4CJQFen5HOY0NqxtydSq4ee1wEK8UaxYWdI0U6EQ3aHqs+MvUytTvv
 zgfm0QUE1tWjpEg2NnVdsJsoJ7W8NQWJqhuELR+cZY2nE6c0yEZDSmVOcCe8SaDu
 GjsAQZ3RWIBtBnjeU9XYdtxOqviDAzxic0x0CQWS/WIk/AI4vLRBu8ke+0N92lrO
 XthqrbF+5Gf+SwGeh8UldInR/wFMnvatOhg91JGJfFFOq8lPSk6XG59CXc6o8Hqc
 G7fWxRkbPI93mSxmWdoOLfzoQLpCUw2hKt5CtKVpPs3Pw01lKUK5ypRMDxpr8yiv
 gJ8RpK9d1Rxvi6422B3f+/0uX/R2Lis1D28GzqJDAvR12GceJtX2Ngnto0xya3Hb
 n4nAUA2CP1OdaHX9652iC+7d7NI7RHFen1Pme/EvidH2aA93C5W6FzpcmI5J70AZ
 BCCaeHnAP4mLY2Xozi12RHb9+fBZ+OJ3nSg79EiTKyTzf11DqTZe1/QLg+gTl4Aa
 n4ZaTKY=
 =K8HF
 -----END PGP SIGNATURE-----

Merge tag 'sound-6.9-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound fixes from Takashi Iwai:
 "As usual in a late stage, we received a fair amount of fixes for ASoC,
  and it became bigger than wished. But all fixes are rather device-
  specific, and they look pretty safe to apply.

  A major par of changes are series of fixes for ASoC meson and SOF
  drivers as well as for Realtek and Cirrus codecs. In addition, recent
  emu10k1 regression fixes and usual HD-audio quirks are included"

* tag 'sound-6.9-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (46 commits)
  ALSA: hda/realtek: Fix build error without CONFIG_PM
  ALSA: hda/realtek: Fix conflicting PCI SSID 17aa:386f for Lenovo Legion models
  ALSA: hda/realtek - Set GPIO3 to default at S4 state for Thinkpad with ALC1318
  ALSA: hda: intel-sdw-acpi: fix usage of device_get_named_child_node()
  ALSA: hda: intel-dsp-config: harden I2C/I2S codec detection
  ASoC: cs35l56: fix usages of device_get_named_child_node()
  ASoC: da7219-aad: fix usage of device_get_named_child_node()
  ASoC: meson: cards: select SND_DYNAMIC_MINORS
  ASoC: meson: axg-tdm: add continuous clock support
  ASoC: meson: axg-tdm-interface: manage formatters in trigger
  ASoC: meson: axg-card: make links nonatomic
  ASoC: meson: axg-fifo: use threaded irq to check periods
  ALSA: hda/realtek: Fix mute led of HP Laptop 15-da3001TU
  ALSA: emu10k1: make E-MU FPGA writes potentially more reliable
  ALSA: emu10k1: fix E-MU dock initialization
  ALSA: emu10k1: use mutex for E-MU FPGA access locking
  ALSA: emu10k1: move the whole GPIO event handling to the workqueue
  ALSA: emu10k1: factor out snd_emu1010_load_dock_firmware()
  ALSA: emu10k1: fix E-MU card dock presence monitoring
  ASoC: rt715-sdca: volume step modification
  ...
This commit is contained in:
Linus Torvalds 2024-05-03 09:24:46 -07:00
commit 7dc78c7b44
44 changed files with 715 additions and 252 deletions

View File

@ -20,6 +20,11 @@ Optional properties:
a GPIO spec for the external headphone detect pin. If jd-mode = 0,
we will get the JD status by getting the value of hp-detect-gpios.
- cbj-sleeve-gpios:
a GPIO spec to control the external combo jack circuit to tie the sleeve/ring2
contacts to the ground or floating. It could avoid some electric noise from the
active speaker jacks.
- realtek,in2-differential
Boolean. Indicate MIC2 input are differential, rather than single-ended.
@ -68,6 +73,7 @@ codec: rt5650@1a {
compatible = "realtek,rt5650";
reg = <0x1a>;
hp-detect-gpios = <&gpio 19 0>;
cbj-sleeve-gpios = <&gpio 20 0>;
interrupt-parent = <&gpio>;
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
realtek,dmic-en = "true";

View File

@ -2838,6 +2838,43 @@ int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
}
EXPORT_SYMBOL_GPL(regmap_read);
/**
* regmap_read_bypassed() - Read a value from a single register direct
* from the device, bypassing the cache
*
* @map: Register map to read from
* @reg: Register to be read from
* @val: Pointer to store read value
*
* A value of zero will be returned on success, a negative errno will
* be returned in error cases.
*/
int regmap_read_bypassed(struct regmap *map, unsigned int reg, unsigned int *val)
{
int ret;
bool bypass, cache_only;
if (!IS_ALIGNED(reg, map->reg_stride))
return -EINVAL;
map->lock(map->lock_arg);
bypass = map->cache_bypass;
cache_only = map->cache_only;
map->cache_bypass = true;
map->cache_only = false;
ret = _regmap_read(map, reg, val);
map->cache_bypass = bypass;
map->cache_only = cache_only;
map->unlock(map->lock_arg);
return ret;
}
EXPORT_SYMBOL_GPL(regmap_read_bypassed);
/**
* regmap_raw_read() - Read raw data from the device
*

View File

@ -1230,6 +1230,7 @@ int regmap_multi_reg_write_bypassed(struct regmap *map,
int regmap_raw_write_async(struct regmap *map, unsigned int reg,
const void *val, size_t val_len);
int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val);
int regmap_read_bypassed(struct regmap *map, unsigned int reg, unsigned int *val);
int regmap_raw_read(struct regmap *map, unsigned int reg,
void *val, size_t val_len);
int regmap_noinc_read(struct regmap *map, unsigned int reg,
@ -1739,6 +1740,13 @@ static inline int regmap_read(struct regmap *map, unsigned int reg,
return -EINVAL;
}
static inline int regmap_read_bypassed(struct regmap *map, unsigned int reg,
unsigned int *val)
{
WARN_ONCE(1, "regmap API is disabled");
return -EINVAL;
}
static inline int regmap_raw_read(struct regmap *map, unsigned int reg,
void *val, size_t val_len)
{

View File

@ -267,6 +267,7 @@ struct cs35l56_base {
bool fw_patched;
bool secured;
bool can_hibernate;
bool fw_owns_asp1;
bool cal_data_valid;
s8 cal_index;
struct cirrus_amp_cal_data cal_data;
@ -283,6 +284,7 @@ extern const char * const cs35l56_tx_input_texts[CS35L56_NUM_INPUT_SRC];
extern const unsigned int cs35l56_tx_input_values[CS35L56_NUM_INPUT_SRC];
int cs35l56_set_patch(struct cs35l56_base *cs35l56_base);
int cs35l56_init_asp1_regs_for_driver_control(struct cs35l56_base *cs35l56_base);
int cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_base *cs35l56_base);
int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command);
int cs35l56_firmware_shutdown(struct cs35l56_base *cs35l56_base);

View File

@ -1684,8 +1684,8 @@ struct snd_emu1010 {
unsigned int clock_fallback;
unsigned int optical_in; /* 0:SPDIF, 1:ADAT */
unsigned int optical_out; /* 0:SPDIF, 1:ADAT */
struct work_struct firmware_work;
struct work_struct clock_work;
struct work_struct work;
struct mutex lock;
};
struct snd_emu10k1 {
@ -1834,6 +1834,9 @@ unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, unsigned int reg,
void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data);
int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, unsigned int data);
int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, u32 reg, u32 value);
static inline void snd_emu1010_fpga_lock(struct snd_emu10k1 *emu) { mutex_lock(&emu->emu1010.lock); };
static inline void snd_emu1010_fpga_unlock(struct snd_emu10k1 *emu) { mutex_unlock(&emu->emu1010.lock); };
void snd_emu1010_fpga_write_lock(struct snd_emu10k1 *emu, u32 reg, u32 value);
void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value);
void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value);
void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src);

View File

@ -557,9 +557,32 @@ static const struct config_entry *snd_intel_dsp_find_config
if (table->codec_hid) {
int i;
for (i = 0; i < table->codec_hid->num_codecs; i++)
if (acpi_dev_present(table->codec_hid->codecs[i], NULL, -1))
for (i = 0; i < table->codec_hid->num_codecs; i++) {
struct nhlt_acpi_table *nhlt;
bool ssp_found = false;
if (!acpi_dev_present(table->codec_hid->codecs[i], NULL, -1))
continue;
nhlt = intel_nhlt_init(&pci->dev);
if (!nhlt) {
dev_warn(&pci->dev, "%s: NHLT table not found, skipped HID %s\n",
__func__, table->codec_hid->codecs[i]);
continue;
}
if (intel_nhlt_has_endpoint_type(nhlt, NHLT_LINK_SSP) &&
intel_nhlt_ssp_endpoint_mask(nhlt, NHLT_DEVICE_I2S))
ssp_found = true;
intel_nhlt_free(nhlt);
if (ssp_found)
break;
dev_warn(&pci->dev, "%s: no valid SSP found for HID %s, skipped\n",
__func__, table->codec_hid->codecs[i]);
}
if (i == table->codec_hid->num_codecs)
continue;
}

View File

@ -45,6 +45,8 @@ static bool is_link_enabled(struct fwnode_handle *fw_node, u8 idx)
"intel-quirk-mask",
&quirk_mask);
fwnode_handle_put(link);
if (quirk_mask & SDW_INTEL_QUIRK_MASK_BUS_DISABLE)
return false;

View File

@ -189,8 +189,7 @@ static int snd_emu10k1_suspend(struct device *dev)
emu->suspend = 1;
cancel_work_sync(&emu->emu1010.firmware_work);
cancel_work_sync(&emu->emu1010.clock_work);
cancel_work_sync(&emu->emu1010.work);
snd_ac97_suspend(emu->ac97);

View File

@ -732,69 +732,67 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, int dock,
return snd_emu1010_load_firmware_entry(emu, *fw);
}
static void emu1010_firmware_work(struct work_struct *work)
static void snd_emu1010_load_dock_firmware(struct snd_emu10k1 *emu)
{
struct snd_emu10k1 *emu;
u32 tmp, tmp2, reg;
u32 tmp, tmp2;
int err;
emu = container_of(work, struct snd_emu10k1,
emu1010.firmware_work);
if (emu->card->shutdown)
// The docking events clearly arrive prematurely - while the
// Dock's FPGA seems to be successfully programmed, the Dock
// fails to initialize subsequently if we don't give it some
// time to "warm up" here.
msleep(200);
dev_info(emu->card->dev, "emu1010: Loading Audio Dock Firmware\n");
/* Return to Audio Dock programming mode */
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG,
EMU_HANA_FPGA_CONFIG_AUDIODOCK);
err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw);
if (err < 0)
return;
#ifdef CONFIG_PM_SLEEP
if (emu->suspend)
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp);
dev_dbg(emu->card->dev, "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp);
if ((tmp & 0x1f) != 0x15) {
/* FPGA failed to be programmed */
dev_err(emu->card->dev,
"emu1010: Loading Audio Dock Firmware failed, reg = 0x%x\n",
tmp);
return;
#endif
}
dev_info(emu->card->dev, "emu1010: Audio Dock Firmware loaded\n");
snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp);
snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2);
dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2);
/* Allow DLL to settle, to sync clocking between 1010 and Dock */
msleep(10);
}
static void emu1010_dock_event(struct snd_emu10k1 *emu)
{
u32 reg;
snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg); /* OPTIONS: Which cards are attached to the EMU */
if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) {
/* Audio Dock attached */
/* Return to Audio Dock programming mode */
dev_info(emu->card->dev,
"emu1010: Loading Audio Dock Firmware\n");
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG,
EMU_HANA_FPGA_CONFIG_AUDIODOCK);
err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw);
if (err < 0)
return;
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp);
dev_info(emu->card->dev,
"emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp);
if ((tmp & 0x1f) != 0x15) {
/* FPGA failed to be programmed */
dev_info(emu->card->dev,
"emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n",
tmp);
return;
}
dev_info(emu->card->dev,
"emu1010: Audio Dock Firmware loaded\n");
snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp);
snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2);
dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2);
/* Sync clocking between 1010 and Dock */
/* Allow DLL to settle */
msleep(10);
snd_emu1010_load_dock_firmware(emu);
/* Unmute all. Default is muted after a firmware load */
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
} else if (!(reg & EMU_HANA_OPTION_DOCK_ONLINE)) {
/* Audio Dock removed */
dev_info(emu->card->dev, "emu1010: Audio Dock detached\n");
/* The hardware auto-mutes all, so we unmute again */
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
}
}
static void emu1010_clock_work(struct work_struct *work)
static void emu1010_clock_event(struct snd_emu10k1 *emu)
{
struct snd_emu10k1 *emu;
struct snd_ctl_elem_id id;
emu = container_of(work, struct snd_emu10k1,
emu1010.clock_work);
if (emu->card->shutdown)
return;
#ifdef CONFIG_PM_SLEEP
if (emu->suspend)
return;
#endif
spin_lock_irq(&emu->reg_lock);
// This is the only thing that can actually happen.
emu->emu1010.clock_source = emu->emu1010.clock_fallback;
@ -805,21 +803,44 @@ static void emu1010_clock_work(struct work_struct *work)
snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE, &id);
}
static void emu1010_interrupt(struct snd_emu10k1 *emu)
static void emu1010_work(struct work_struct *work)
{
struct snd_emu10k1 *emu;
u32 sts;
emu = container_of(work, struct snd_emu10k1, emu1010.work);
if (emu->card->shutdown)
return;
#ifdef CONFIG_PM_SLEEP
if (emu->suspend)
return;
#endif
snd_emu1010_fpga_lock(emu);
snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &sts);
if (sts & EMU_HANA_IRQ_DOCK_LOST) {
/* Audio Dock removed */
dev_info(emu->card->dev, "emu1010: Audio Dock detached\n");
/* The hardware auto-mutes all, so we unmute again */
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
} else if (sts & EMU_HANA_IRQ_DOCK) {
schedule_work(&emu->emu1010.firmware_work);
}
// The distinction of the IRQ status bits is unreliable,
// so we dispatch later based on option card status.
if (sts & (EMU_HANA_IRQ_DOCK | EMU_HANA_IRQ_DOCK_LOST))
emu1010_dock_event(emu);
if (sts & EMU_HANA_IRQ_WCLK_CHANGED)
schedule_work(&emu->emu1010.clock_work);
emu1010_clock_event(emu);
snd_emu1010_fpga_unlock(emu);
}
static void emu1010_interrupt(struct snd_emu10k1 *emu)
{
// We get an interrupt on each GPIO input pin change, but we
// care only about the ones triggered by the dedicated pin.
u16 sts = inw(emu->port + A_GPIO);
u16 bit = emu->card_capabilities->ca0108_chip ? 0x2000 : 0x8000;
if (!(sts & bit))
return;
schedule_work(&emu->emu1010.work);
}
/*
@ -841,6 +862,8 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
* Proper init follows in snd_emu10k1_init(). */
outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG);
snd_emu1010_fpga_lock(emu);
/* Disable 48Volt power to Audio Dock */
snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0);
@ -866,7 +889,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
err = snd_emu1010_load_firmware(emu, 0, &emu->firmware);
if (err < 0) {
dev_info(emu->card->dev, "emu1010: Loading Firmware failed\n");
return err;
goto fail;
}
/* ID, should read & 0x7f = 0x55 when FPGA programmed. */
@ -876,7 +899,8 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
dev_info(emu->card->dev,
"emu1010: Loading Hana Firmware file failed, reg = 0x%x\n",
reg);
return -ENODEV;
err = -ENODEV;
goto fail;
}
dev_info(emu->card->dev, "emu1010: Hana Firmware loaded\n");
@ -889,7 +913,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg);
dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg);
if (reg & EMU_HANA_OPTION_DOCK_OFFLINE)
schedule_work(&emu->emu1010.firmware_work);
snd_emu1010_load_dock_firmware(emu);
if (emu->card_capabilities->no_adat) {
emu->emu1010.optical_in = 0; /* IN_SPDIF */
emu->emu1010.optical_out = 0; /* OUT_SPDIF */
@ -936,7 +960,9 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
// so it is safe to simply enable the outputs.
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
return 0;
fail:
snd_emu1010_fpga_unlock(emu);
return err;
}
/*
* Create the EMU10K1 instance
@ -958,10 +984,10 @@ static void snd_emu10k1_free(struct snd_card *card)
}
if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) {
/* Disable 48Volt power to Audio Dock */
snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0);
snd_emu1010_fpga_write_lock(emu, EMU_HANA_DOCK_PWR, 0);
}
cancel_work_sync(&emu->emu1010.firmware_work);
cancel_work_sync(&emu->emu1010.clock_work);
cancel_work_sync(&emu->emu1010.work);
mutex_destroy(&emu->emu1010.lock);
release_firmware(emu->firmware);
release_firmware(emu->dock_fw);
snd_util_memhdr_free(emu->memhdr);
@ -1540,8 +1566,8 @@ int snd_emu10k1_create(struct snd_card *card,
emu->irq = -1;
emu->synth = NULL;
emu->get_synth_voice = NULL;
INIT_WORK(&emu->emu1010.firmware_work, emu1010_firmware_work);
INIT_WORK(&emu->emu1010.clock_work, emu1010_clock_work);
INIT_WORK(&emu->emu1010.work, emu1010_work);
mutex_init(&emu->emu1010.lock);
/* read revision & serial */
emu->revision = pci->revision;
pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);

View File

@ -661,7 +661,9 @@ static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol,
change = (emu->emu1010.output_source[channel] != val);
if (change) {
emu->emu1010.output_source[channel] = val;
snd_emu1010_fpga_lock(emu);
snd_emu1010_output_source_apply(emu, channel, val);
snd_emu1010_fpga_unlock(emu);
}
return change;
}
@ -705,7 +707,9 @@ static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
change = (emu->emu1010.input_source[channel] != val);
if (change) {
emu->emu1010.input_source[channel] = val;
snd_emu1010_fpga_lock(emu);
snd_emu1010_input_source_apply(emu, channel, val);
snd_emu1010_fpga_unlock(emu);
}
return change;
}
@ -774,7 +778,7 @@ static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct
cache = cache & ~mask;
change = (cache != emu->emu1010.adc_pads);
if (change) {
snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache );
snd_emu1010_fpga_write_lock(emu, EMU_HANA_ADC_PADS, cache );
emu->emu1010.adc_pads = cache;
}
@ -832,7 +836,7 @@ static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct
cache = cache & ~mask;
change = (cache != emu->emu1010.dac_pads);
if (change) {
snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, cache );
snd_emu1010_fpga_write_lock(emu, EMU_HANA_DAC_PADS, cache );
emu->emu1010.dac_pads = cache;
}
@ -980,6 +984,7 @@ static int snd_emu1010_clock_source_put(struct snd_kcontrol *kcontrol,
val = ucontrol->value.enumerated.item[0] ;
if (val >= emu_ci->num)
return -EINVAL;
snd_emu1010_fpga_lock(emu);
spin_lock_irq(&emu->reg_lock);
change = (emu->emu1010.clock_source != val);
if (change) {
@ -996,6 +1001,7 @@ static int snd_emu1010_clock_source_put(struct snd_kcontrol *kcontrol,
} else {
spin_unlock_irq(&emu->reg_lock);
}
snd_emu1010_fpga_unlock(emu);
return change;
}
@ -1041,7 +1047,7 @@ static int snd_emu1010_clock_fallback_put(struct snd_kcontrol *kcontrol,
change = (emu->emu1010.clock_fallback != val);
if (change) {
emu->emu1010.clock_fallback = val;
snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 1 - val);
snd_emu1010_fpga_write_lock(emu, EMU_HANA_DEFCLOCK, 1 - val);
}
return change;
}
@ -1093,7 +1099,7 @@ static int snd_emu1010_optical_out_put(struct snd_kcontrol *kcontrol,
emu->emu1010.optical_out = val;
tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : EMU_HANA_OPTICAL_IN_SPDIF) |
(emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : EMU_HANA_OPTICAL_OUT_SPDIF);
snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp);
snd_emu1010_fpga_write_lock(emu, EMU_HANA_OPTICAL_TYPE, tmp);
}
return change;
}
@ -1144,7 +1150,7 @@ static int snd_emu1010_optical_in_put(struct snd_kcontrol *kcontrol,
emu->emu1010.optical_in = val;
tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : EMU_HANA_OPTICAL_IN_SPDIF) |
(emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : EMU_HANA_OPTICAL_OUT_SPDIF);
snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp);
snd_emu1010_fpga_write_lock(emu, EMU_HANA_OPTICAL_TYPE, tmp);
}
return change;
}
@ -2323,7 +2329,9 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
for (i = 0; i < emu_ri->n_outs; i++)
emu->emu1010.output_source[i] =
emu1010_map_source(emu_ri, emu_ri->out_dflts[i]);
snd_emu1010_fpga_lock(emu);
snd_emu1010_apply_sources(emu);
snd_emu1010_fpga_unlock(emu);
kctl = emu->ctl_clock_source = snd_ctl_new1(&snd_emu1010_clock_source, emu);
err = snd_ctl_add(card, kctl);

View File

@ -165,6 +165,8 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry,
u32 value2;
if (emu->card_capabilities->emu_model) {
snd_emu1010_fpga_lock(emu);
// This represents the S/PDIF lock status on 0404b, which is
// kinda weird and unhelpful, because monitoring it via IRQ is
// impractical (one gets an IRQ flood as long as it is desynced).
@ -197,6 +199,8 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry,
snd_iprintf(buffer, "\nS/PDIF mode: %s%s\n",
value & EMU_HANA_SPDIF_MODE_RX_PRO ? "professional" : "consumer",
value & EMU_HANA_SPDIF_MODE_RX_NOCOPY ? ", no copy" : "");
snd_emu1010_fpga_unlock(emu);
} else {
snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS);
snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS);
@ -458,6 +462,9 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry,
struct snd_emu10k1 *emu = entry->private_data;
u32 value;
int i;
snd_emu1010_fpga_lock(emu);
snd_iprintf(buffer, "EMU1010 Registers:\n\n");
for(i = 0; i < 0x40; i+=1) {
@ -496,6 +503,8 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry,
snd_emu_proc_emu1010_link_read(emu, buffer, 0x701);
}
}
snd_emu1010_fpga_unlock(emu);
}
static void snd_emu_proc_io_reg_read(struct snd_info_entry *entry,

View File

@ -285,24 +285,33 @@ static void snd_emu1010_fpga_write_locked(struct snd_emu10k1 *emu, u32 reg, u32
outw(value, emu->port + A_GPIO);
udelay(10);
outw(value | 0x80 , emu->port + A_GPIO); /* High bit clocks the value into the fpga. */
udelay(10);
}
void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value)
{
unsigned long flags;
spin_lock_irqsave(&emu->emu_lock, flags);
if (snd_BUG_ON(!mutex_is_locked(&emu->emu1010.lock)))
return;
snd_emu1010_fpga_write_locked(emu, reg, value);
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
static void snd_emu1010_fpga_read_locked(struct snd_emu10k1 *emu, u32 reg, u32 *value)
void snd_emu1010_fpga_write_lock(struct snd_emu10k1 *emu, u32 reg, u32 value)
{
snd_emu1010_fpga_lock(emu);
snd_emu1010_fpga_write_locked(emu, reg, value);
snd_emu1010_fpga_unlock(emu);
}
void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value)
{
// The higest input pin is used as the designated interrupt trigger,
// so it needs to be masked out.
// But note that any other input pin change will also cause an IRQ,
// so using this function often causes an IRQ as a side effect.
u32 mask = emu->card_capabilities->ca0108_chip ? 0x1f : 0x7f;
if (snd_BUG_ON(!mutex_is_locked(&emu->emu1010.lock)))
return;
if (snd_BUG_ON(reg > 0x3f))
return;
reg += 0x40; /* 0x40 upwards are registers. */
@ -313,47 +322,31 @@ static void snd_emu1010_fpga_read_locked(struct snd_emu10k1 *emu, u32 reg, u32 *
*value = ((inw(emu->port + A_GPIO) >> 8) & mask);
}
void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value)
{
unsigned long flags;
spin_lock_irqsave(&emu->emu_lock, flags);
snd_emu1010_fpga_read_locked(emu, reg, value);
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
/* Each Destination has one and only one Source,
* but one Source can feed any number of Destinations simultaneously.
*/
void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src)
{
unsigned long flags;
if (snd_BUG_ON(dst & ~0x71f))
return;
if (snd_BUG_ON(src & ~0x71f))
return;
spin_lock_irqsave(&emu->emu_lock, flags);
snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTHI, dst >> 8);
snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTLO, dst & 0x1f);
snd_emu1010_fpga_write_locked(emu, EMU_HANA_SRCHI, src >> 8);
snd_emu1010_fpga_write_locked(emu, EMU_HANA_SRCLO, src & 0x1f);
spin_unlock_irqrestore(&emu->emu_lock, flags);
snd_emu1010_fpga_write(emu, EMU_HANA_DESTHI, dst >> 8);
snd_emu1010_fpga_write(emu, EMU_HANA_DESTLO, dst & 0x1f);
snd_emu1010_fpga_write(emu, EMU_HANA_SRCHI, src >> 8);
snd_emu1010_fpga_write(emu, EMU_HANA_SRCLO, src & 0x1f);
}
u32 snd_emu1010_fpga_link_dst_src_read(struct snd_emu10k1 *emu, u32 dst)
{
unsigned long flags;
u32 hi, lo;
if (snd_BUG_ON(dst & ~0x71f))
return 0;
spin_lock_irqsave(&emu->emu_lock, flags);
snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTHI, dst >> 8);
snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTLO, dst & 0x1f);
snd_emu1010_fpga_read_locked(emu, EMU_HANA_SRCHI, &hi);
snd_emu1010_fpga_read_locked(emu, EMU_HANA_SRCLO, &lo);
spin_unlock_irqrestore(&emu->emu_lock, flags);
snd_emu1010_fpga_write(emu, EMU_HANA_DESTHI, dst >> 8);
snd_emu1010_fpga_write(emu, EMU_HANA_DESTLO, dst & 0x1f);
snd_emu1010_fpga_read(emu, EMU_HANA_SRCHI, &hi);
snd_emu1010_fpga_read(emu, EMU_HANA_SRCLO, &lo);
return (hi << 8) | lo;
}

View File

@ -644,6 +644,8 @@ static int cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56)
ret = cs35l56_wait_for_firmware_boot(&cs35l56->base);
if (ret)
goto err_powered_up;
regcache_cache_only(cs35l56->base.regmap, false);
}
/* Disable auto-hibernate so that runtime_pm has control */
@ -1002,6 +1004,8 @@ int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int hid, int id)
if (ret)
goto err;
regcache_cache_only(cs35l56->base.regmap, false);
ret = cs35l56_set_patch(&cs35l56->base);
if (ret)
goto err;

View File

@ -920,6 +920,8 @@ static void alc_pre_init(struct hda_codec *codec)
((codec)->core.dev.power.power_state.event == PM_EVENT_RESUME)
#define is_s4_resume(codec) \
((codec)->core.dev.power.power_state.event == PM_EVENT_RESTORE)
#define is_s4_suspend(codec) \
((codec)->core.dev.power.power_state.event == PM_EVENT_FREEZE)
static int alc_init(struct hda_codec *codec)
{
@ -7183,6 +7185,46 @@ static void alc245_fixup_hp_spectre_x360_eu0xxx(struct hda_codec *codec,
alc245_fixup_hp_gpio_led(codec, fix, action);
}
/*
* ALC287 PCM hooks
*/
static void alc287_alc1318_playback_pcm_hook(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
struct snd_pcm_substream *substream,
int action)
{
alc_write_coef_idx(codec, 0x10, 0x8806); /* Change MLK to GPIO3 */
switch (action) {
case HDA_GEN_PCM_ACT_OPEN:
alc_write_coefex_idx(codec, 0x5a, 0x00, 0x954f); /* write gpio3 to high */
break;
case HDA_GEN_PCM_ACT_CLOSE:
alc_write_coefex_idx(codec, 0x5a, 0x00, 0x554f); /* write gpio3 as default value */
break;
}
}
static void __maybe_unused alc287_s4_power_gpio3_default(struct hda_codec *codec)
{
if (is_s4_suspend(codec)) {
alc_write_coef_idx(codec, 0x10, 0x8806); /* Change MLK to GPIO3 */
alc_write_coefex_idx(codec, 0x5a, 0x00, 0x554f); /* write gpio3 as default value */
}
}
static void alc287_fixup_lenovo_thinkpad_with_alc1318(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct alc_spec *spec = codec->spec;
if (action != HDA_FIXUP_ACT_PRE_PROBE)
return;
#ifdef CONFIG_PM
spec->power_hook = alc287_s4_power_gpio3_default;
#endif
spec->gen.pcm_playback_hook = alc287_alc1318_playback_pcm_hook;
}
enum {
ALC269_FIXUP_GPIO2,
@ -7426,6 +7468,7 @@ enum {
ALC287_FIXUP_YOGA7_14ITL_SPEAKERS,
ALC298_FIXUP_LENOVO_C940_DUET7,
ALC287_FIXUP_LENOVO_14IRP8_DUETITL,
ALC287_FIXUP_LENOVO_LEGION_7,
ALC287_FIXUP_13S_GEN2_SPEAKERS,
ALC256_FIXUP_SET_COEF_DEFAULTS,
ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
@ -7470,7 +7513,8 @@ enum {
ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC,
ALC285_FIXUP_ASUS_GA403U_I2C_SPEAKER2_TO_DAC1,
ALC285_FIXUP_ASUS_GU605_SPI_2_HEADSET_MIC,
ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1
ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1,
ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318,
};
/* A special fixup for Lenovo C940 and Yoga Duet 7;
@ -7510,6 +7554,23 @@ static void alc287_fixup_lenovo_14irp8_duetitl(struct hda_codec *codec,
__snd_hda_apply_fixup(codec, id, action, 0);
}
/* Another hilarious PCI SSID conflict with Lenovo Legion Pro 7 16ARX8H (with
* TAS2781 codec) and Legion 7i 16IAX7 (with CS35L41 codec);
* we apply a corresponding fixup depending on the codec SSID instead
*/
static void alc287_fixup_lenovo_legion_7(struct hda_codec *codec,
const struct hda_fixup *fix,
int action)
{
int id;
if (codec->core.subsystem_id == 0x17aa38a8)
id = ALC287_FIXUP_TAS2781_I2C; /* Legion Pro 7 16ARX8H */
else
id = ALC287_FIXUP_CS35L41_I2C_2; /* Legion 7i 16IAX7 */
__snd_hda_apply_fixup(codec, id, action, 0);
}
static const struct hda_fixup alc269_fixups[] = {
[ALC269_FIXUP_GPIO2] = {
.type = HDA_FIXUP_FUNC,
@ -9404,6 +9465,10 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc287_fixup_lenovo_14irp8_duetitl,
},
[ALC287_FIXUP_LENOVO_LEGION_7] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc287_fixup_lenovo_legion_7,
},
[ALC287_FIXUP_13S_GEN2_SPEAKERS] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
@ -9726,6 +9791,12 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC285_FIXUP_ASUS_GA403U,
},
[ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc287_fixup_lenovo_thinkpad_with_alc1318,
.chained = true,
.chain_id = ALC269_FIXUP_THINKPAD_ACPI
},
};
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@ -9937,6 +10008,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x860f, "HP ZBook 15 G6", ALC285_FIXUP_HP_GPIO_AMP_INIT),
SND_PCI_QUIRK(0x103c, 0x861f, "HP Elite Dragonfly G1", ALC285_FIXUP_HP_GPIO_AMP_INIT),
SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x86c1, "HP Laptop 15-da3001TU", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
SND_PCI_QUIRK(0x103c, 0x86c7, "HP Envy AiO 32", ALC274_FIXUP_HP_ENVY_GPIO),
SND_PCI_QUIRK(0x103c, 0x86e7, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
SND_PCI_QUIRK(0x103c, 0x86e8, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
@ -10393,6 +10465,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x2318, "Thinkpad Z13 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x2319, "Thinkpad Z16 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x231a, "Thinkpad Z16 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x231e, "Thinkpad", ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318),
SND_PCI_QUIRK(0x17aa, 0x231f, "Thinkpad", ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318),
SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
@ -10422,7 +10496,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6),
SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
SND_PCI_QUIRK(0x17aa, 0x386f, "Legion 7i 16IAX7", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x386f, "Legion Pro 7/7i", ALC287_FIXUP_LENOVO_LEGION_7),
SND_PCI_QUIRK(0x17aa, 0x3870, "Lenovo Yoga 7 14ARB7", ALC287_FIXUP_YOGA7_14ARB7_I2C),
SND_PCI_QUIRK(0x17aa, 0x3877, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x3878, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),

View File

@ -430,6 +430,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_BOARD_NAME, "MRID6"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "MDC"),
DMI_MATCH(DMI_BOARD_NAME, "Herbag_MDU"),
}
},
{
.driver_data = &acp6x_card,
.matches = {

View File

@ -1094,6 +1094,7 @@ static int cs35l41_handle_pdata(struct device *dev, struct cs35l41_hw_cfg *hw_cf
static int cs35l41_dsp_init(struct cs35l41_private *cs35l41)
{
struct wm_adsp *dsp;
uint32_t dsp1rx5_src;
int ret;
dsp = &cs35l41->dsp;
@ -1113,16 +1114,29 @@ static int cs35l41_dsp_init(struct cs35l41_private *cs35l41)
return ret;
}
ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX5_SRC,
CS35L41_INPUT_SRC_VPMON);
if (ret < 0) {
dev_err(cs35l41->dev, "Write INPUT_SRC_VPMON failed: %d\n", ret);
switch (cs35l41->hw_cfg.bst_type) {
case CS35L41_INT_BOOST:
case CS35L41_SHD_BOOST_ACTV:
dsp1rx5_src = CS35L41_INPUT_SRC_VPMON;
break;
case CS35L41_EXT_BOOST:
case CS35L41_SHD_BOOST_PASS:
dsp1rx5_src = CS35L41_INPUT_SRC_VBSTMON;
break;
default:
dev_err(cs35l41->dev, "wm_halo_init failed - Invalid Boost Type: %d\n",
cs35l41->hw_cfg.bst_type);
goto err_dsp;
}
ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX6_SRC,
CS35L41_INPUT_SRC_CLASSH);
ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX5_SRC, dsp1rx5_src);
if (ret < 0) {
dev_err(cs35l41->dev, "Write INPUT_SRC_CLASSH failed: %d\n", ret);
dev_err(cs35l41->dev, "Write DSP1RX5_SRC: %d failed: %d\n", dsp1rx5_src, ret);
goto err_dsp;
}
ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX6_SRC, CS35L41_INPUT_SRC_VBSTMON);
if (ret < 0) {
dev_err(cs35l41->dev, "Write CS35L41_INPUT_SRC_VBSTMON failed: %d\n", ret);
goto err_dsp;
}
ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX7_SRC,

View File

@ -188,8 +188,6 @@ static void cs35l56_sdw_init(struct sdw_slave *peripheral)
goto out;
}
regcache_cache_only(cs35l56->base.regmap, false);
ret = cs35l56_init(cs35l56);
if (ret < 0) {
regcache_cache_only(cs35l56->base.regmap, true);

View File

@ -40,16 +40,11 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_set_patch, SND_SOC_CS35L56_SHARED);
static const struct reg_default cs35l56_reg_defaults[] = {
/* no defaults for OTP_MEM - first read populates cache */
{ CS35L56_ASP1_ENABLES1, 0x00000000 },
{ CS35L56_ASP1_CONTROL1, 0x00000028 },
{ CS35L56_ASP1_CONTROL2, 0x18180200 },
{ CS35L56_ASP1_CONTROL3, 0x00000002 },
{ CS35L56_ASP1_FRAME_CONTROL1, 0x03020100 },
{ CS35L56_ASP1_FRAME_CONTROL5, 0x00020100 },
{ CS35L56_ASP1_DATA_CONTROL1, 0x00000018 },
{ CS35L56_ASP1_DATA_CONTROL5, 0x00000018 },
/* no defaults for ASP1TX mixer */
/*
* No defaults for ASP1 control or ASP1TX mixer. See
* cs35l56_populate_asp1_register_defaults() and
* cs35l56_sync_asp1_mixer_widgets_with_firmware().
*/
{ CS35L56_SWIRE_DP3_CH1_INPUT, 0x00000018 },
{ CS35L56_SWIRE_DP3_CH2_INPUT, 0x00000019 },
@ -210,6 +205,36 @@ static bool cs35l56_volatile_reg(struct device *dev, unsigned int reg)
}
}
static const struct reg_sequence cs35l56_asp1_defaults[] = {
REG_SEQ0(CS35L56_ASP1_ENABLES1, 0x00000000),
REG_SEQ0(CS35L56_ASP1_CONTROL1, 0x00000028),
REG_SEQ0(CS35L56_ASP1_CONTROL2, 0x18180200),
REG_SEQ0(CS35L56_ASP1_CONTROL3, 0x00000002),
REG_SEQ0(CS35L56_ASP1_FRAME_CONTROL1, 0x03020100),
REG_SEQ0(CS35L56_ASP1_FRAME_CONTROL5, 0x00020100),
REG_SEQ0(CS35L56_ASP1_DATA_CONTROL1, 0x00000018),
REG_SEQ0(CS35L56_ASP1_DATA_CONTROL5, 0x00000018),
};
/*
* The firmware can have control of the ASP so we don't provide regmap
* with defaults for these registers, to prevent a regcache_sync() from
* overwriting the firmware settings. But if the machine driver hooks up
* the ASP it means the driver is taking control of the ASP, so then the
* registers are populated with the defaults.
*/
int cs35l56_init_asp1_regs_for_driver_control(struct cs35l56_base *cs35l56_base)
{
if (!cs35l56_base->fw_owns_asp1)
return 0;
cs35l56_base->fw_owns_asp1 = false;
return regmap_multi_reg_write(cs35l56_base->regmap, cs35l56_asp1_defaults,
ARRAY_SIZE(cs35l56_asp1_defaults));
}
EXPORT_SYMBOL_NS_GPL(cs35l56_init_asp1_regs_for_driver_control, SND_SOC_CS35L56_SHARED);
/*
* The firmware boot sequence can overwrite the ASP1 config registers so that
* they don't match regmap's view of their values. Rewrite the values from the
@ -217,19 +242,15 @@ static bool cs35l56_volatile_reg(struct device *dev, unsigned int reg)
*/
int cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_base *cs35l56_base)
{
struct reg_sequence asp1_regs[] = {
{ .reg = CS35L56_ASP1_ENABLES1 },
{ .reg = CS35L56_ASP1_CONTROL1 },
{ .reg = CS35L56_ASP1_CONTROL2 },
{ .reg = CS35L56_ASP1_CONTROL3 },
{ .reg = CS35L56_ASP1_FRAME_CONTROL1 },
{ .reg = CS35L56_ASP1_FRAME_CONTROL5 },
{ .reg = CS35L56_ASP1_DATA_CONTROL1 },
{ .reg = CS35L56_ASP1_DATA_CONTROL5 },
};
struct reg_sequence asp1_regs[ARRAY_SIZE(cs35l56_asp1_defaults)];
int i, ret;
/* Read values from regmap cache into a write sequence */
if (cs35l56_base->fw_owns_asp1)
return 0;
memcpy(asp1_regs, cs35l56_asp1_defaults, sizeof(asp1_regs));
/* Read current values from regmap cache into the write sequence */
for (i = 0; i < ARRAY_SIZE(asp1_regs); ++i) {
ret = regmap_read(cs35l56_base->regmap, asp1_regs[i].reg, &asp1_regs[i].def);
if (ret)
@ -307,10 +328,10 @@ int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base)
reg = CS35L56_DSP1_HALO_STATE;
/*
* This can't be a regmap_read_poll_timeout() because cs35l56 will NAK
* I2C until it has booted which would terminate the poll
* The regmap must remain in cache-only until the chip has
* booted, so use a bypassed read of the status register.
*/
poll_ret = read_poll_timeout(regmap_read, read_ret,
poll_ret = read_poll_timeout(regmap_read_bypassed, read_ret,
(val < 0xFFFF) && (val >= CS35L56_HALO_STATE_BOOT_DONE),
CS35L56_HALO_STATE_POLL_US,
CS35L56_HALO_STATE_TIMEOUT_US,
@ -362,7 +383,8 @@ void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire)
return;
cs35l56_wait_control_port_ready();
regcache_cache_only(cs35l56_base->regmap, false);
/* Leave in cache-only. This will be revoked when the chip has rebooted. */
}
EXPORT_SYMBOL_NS_GPL(cs35l56_system_reset, SND_SOC_CS35L56_SHARED);
@ -577,14 +599,14 @@ int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_sou
cs35l56_issue_wake_event(cs35l56_base);
out_sync:
regcache_cache_only(cs35l56_base->regmap, false);
ret = cs35l56_wait_for_firmware_boot(cs35l56_base);
if (ret) {
dev_err(cs35l56_base->dev, "Hibernate wake failed: %d\n", ret);
goto err;
}
regcache_cache_only(cs35l56_base->regmap, false);
ret = cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE);
if (ret)
goto err;
@ -684,7 +706,7 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_calibration_controls, SND_SOC_CS35L56_SHARED);
int cs35l56_get_calibration(struct cs35l56_base *cs35l56_base)
{
u64 silicon_uid;
u64 silicon_uid = 0;
int ret;
/* Driver can't apply calibration to a secured part, so skip */
@ -757,7 +779,7 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base)
* devices so the REVID needs to be determined before waiting for the
* firmware to boot.
*/
ret = regmap_read(cs35l56_base->regmap, CS35L56_REVID, &revid);
ret = regmap_read_bypassed(cs35l56_base->regmap, CS35L56_REVID, &revid);
if (ret < 0) {
dev_err(cs35l56_base->dev, "Get Revision ID failed\n");
return ret;
@ -768,7 +790,7 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base)
if (ret)
return ret;
ret = regmap_read(cs35l56_base->regmap, CS35L56_DEVID, &devid);
ret = regmap_read_bypassed(cs35l56_base->regmap, CS35L56_DEVID, &devid);
if (ret < 0) {
dev_err(cs35l56_base->dev, "Get Device ID failed\n");
return ret;
@ -787,6 +809,9 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base)
cs35l56_base->type = devid & 0xFF;
/* Silicon is now identified and booted so exit cache-only */
regcache_cache_only(cs35l56_base->regmap, false);
ret = regmap_read(cs35l56_base->regmap, CS35L56_DSP_RESTRICT_STS1, &secured);
if (ret) {
dev_err(cs35l56_base->dev, "Get Secure status failed\n");

View File

@ -454,9 +454,14 @@ static int cs35l56_asp_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int f
{
struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(codec_dai->component);
unsigned int val;
int ret;
dev_dbg(cs35l56->base.dev, "%s: %#x\n", __func__, fmt);
ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base);
if (ret)
return ret;
switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
case SND_SOC_DAIFMT_CBC_CFC:
break;
@ -530,6 +535,11 @@ static int cs35l56_asp_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx
unsigned int rx_mask, int slots, int slot_width)
{
struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component);
int ret;
ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base);
if (ret)
return ret;
if ((slots == 0) || (slot_width == 0)) {
dev_dbg(cs35l56->base.dev, "tdm config cleared\n");
@ -578,6 +588,11 @@ static int cs35l56_asp_dai_hw_params(struct snd_pcm_substream *substream,
struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component);
unsigned int rate = params_rate(params);
u8 asp_width, asp_wl;
int ret;
ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base);
if (ret)
return ret;
asp_wl = params_width(params);
if (cs35l56->asp_slot_width)
@ -634,7 +649,11 @@ static int cs35l56_asp_dai_set_sysclk(struct snd_soc_dai *dai,
int clk_id, unsigned int freq, int dir)
{
struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component);
int freq_id;
int freq_id, ret;
ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base);
if (ret)
return ret;
if (freq == 0) {
cs35l56->sysclk_set = false;
@ -1341,6 +1360,7 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5
"spk-id-gpios", ACPI_TYPE_PACKAGE, &obj);
if (ret) {
dev_dbg(cs35l56->base.dev, "Could not get spk-id-gpios package: %d\n", ret);
fwnode_handle_put(af01_fwnode);
return -ENOENT;
}
@ -1348,6 +1368,7 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5
if (obj->package.count != 4) {
dev_warn(cs35l56->base.dev, "Unexpected spk-id element count %d\n",
obj->package.count);
fwnode_handle_put(af01_fwnode);
return -ENOENT;
}
@ -1362,6 +1383,7 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5
*/
ret = acpi_dev_add_driver_gpios(adev, cs35l56_af01_spkid_gpios_mapping);
if (ret) {
fwnode_handle_put(af01_fwnode);
return dev_err_probe(cs35l56->base.dev, ret,
"Failed to add gpio mapping to AF01\n");
}
@ -1369,14 +1391,17 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5
ret = devm_add_action_or_reset(cs35l56->base.dev,
cs35l56_acpi_dev_release_driver_gpios,
adev);
if (ret)
if (ret) {
fwnode_handle_put(af01_fwnode);
return ret;
}
dev_dbg(cs35l56->base.dev, "Added spk-id-gpios mapping to AF01\n");
}
desc = fwnode_gpiod_get_index(af01_fwnode, "spk-id", 0, GPIOD_IN, NULL);
if (IS_ERR(desc)) {
fwnode_handle_put(af01_fwnode);
ret = PTR_ERR(desc);
return dev_err_probe(cs35l56->base.dev, ret, "Get GPIO from AF01 failed\n");
}
@ -1385,9 +1410,12 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5
gpiod_put(desc);
if (ret < 0) {
fwnode_handle_put(af01_fwnode);
dev_err_probe(cs35l56->base.dev, ret, "Error reading spk-id GPIO\n");
return ret;
}
}
fwnode_handle_put(af01_fwnode);
dev_info(cs35l56->base.dev, "Got spk-id from AF01\n");
@ -1403,6 +1431,9 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)
cs35l56->base.cal_index = -1;
cs35l56->speaker_id = -ENOENT;
/* Assume that the firmware owns ASP1 until we know different */
cs35l56->base.fw_owns_asp1 = true;
dev_set_drvdata(cs35l56->base.dev, cs35l56);
cs35l56_fill_supply_names(cs35l56->supplies);
@ -1531,6 +1562,8 @@ post_soft_reset:
return ret;
dev_dbg(cs35l56->base.dev, "Firmware rebooted after soft reset\n");
regcache_cache_only(cs35l56->base.regmap, false);
}
/* Disable auto-hibernate so that runtime_pm has control */

View File

@ -671,8 +671,10 @@ static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct device *dev)
return NULL;
aad_pdata = devm_kzalloc(dev, sizeof(*aad_pdata), GFP_KERNEL);
if (!aad_pdata)
if (!aad_pdata) {
fwnode_handle_put(aad_np);
return NULL;
}
aad_pdata->irq = i2c->irq;
@ -753,6 +755,8 @@ static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct device *dev)
else
aad_pdata->adc_1bit_rpt = DA7219_AAD_ADC_1BIT_RPT_1;
fwnode_handle_put(aad_np);
return aad_pdata;
}

View File

@ -444,6 +444,7 @@ struct rt5645_priv {
struct regmap *regmap;
struct i2c_client *i2c;
struct gpio_desc *gpiod_hp_det;
struct gpio_desc *gpiod_cbj_sleeve;
struct snd_soc_jack *hp_jack;
struct snd_soc_jack *mic_jack;
struct snd_soc_jack *btn_jack;
@ -3186,6 +3187,9 @@ static int rt5645_jack_detect(struct snd_soc_component *component, int jack_inse
regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL2,
RT5645_CBJ_MN_JD, 0);
if (rt5645->gpiod_cbj_sleeve)
gpiod_set_value(rt5645->gpiod_cbj_sleeve, 1);
msleep(600);
regmap_read(rt5645->regmap, RT5645_IN1_CTRL3, &val);
val &= 0x7;
@ -3202,6 +3206,8 @@ static int rt5645_jack_detect(struct snd_soc_component *component, int jack_inse
snd_soc_dapm_disable_pin(dapm, "Mic Det Power");
snd_soc_dapm_sync(dapm);
rt5645->jack_type = SND_JACK_HEADPHONE;
if (rt5645->gpiod_cbj_sleeve)
gpiod_set_value(rt5645->gpiod_cbj_sleeve, 0);
}
if (rt5645->pdata.level_trigger_irq)
regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2,
@ -3229,6 +3235,9 @@ static int rt5645_jack_detect(struct snd_soc_component *component, int jack_inse
if (rt5645->pdata.level_trigger_irq)
regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2,
RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV);
if (rt5645->gpiod_cbj_sleeve)
gpiod_set_value(rt5645->gpiod_cbj_sleeve, 0);
}
return rt5645->jack_type;
@ -4012,6 +4021,16 @@ static int rt5645_i2c_probe(struct i2c_client *i2c)
return ret;
}
rt5645->gpiod_cbj_sleeve = devm_gpiod_get_optional(&i2c->dev, "cbj-sleeve",
GPIOD_OUT_LOW);
if (IS_ERR(rt5645->gpiod_cbj_sleeve)) {
ret = PTR_ERR(rt5645->gpiod_cbj_sleeve);
dev_info(&i2c->dev, "failed to initialize gpiod, ret=%d\n", ret);
if (ret != -ENOENT)
return ret;
}
for (i = 0; i < ARRAY_SIZE(rt5645->supplies); i++)
rt5645->supplies[i].supply = rt5645_supply_names[i];
@ -4259,6 +4278,9 @@ static void rt5645_i2c_remove(struct i2c_client *i2c)
cancel_delayed_work_sync(&rt5645->jack_detect_work);
cancel_delayed_work_sync(&rt5645->rcclock_work);
if (rt5645->gpiod_cbj_sleeve)
gpiod_set_value(rt5645->gpiod_cbj_sleeve, 0);
regulator_bulk_disable(ARRAY_SIZE(rt5645->supplies), rt5645->supplies);
}
@ -4274,6 +4296,9 @@ static void rt5645_i2c_shutdown(struct i2c_client *i2c)
0);
msleep(20);
regmap_write(rt5645->regmap, RT5645_RESET, 0);
if (rt5645->gpiod_cbj_sleeve)
gpiod_set_value(rt5645->gpiod_cbj_sleeve, 0);
}
static int __maybe_unused rt5645_sys_suspend(struct device *dev)

View File

@ -316,7 +316,7 @@ static int rt715_sdca_set_amp_gain_8ch_get(struct snd_kcontrol *kcontrol,
return 0;
}
static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -17625, 375, 0);
static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0);
static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0);
static int rt715_sdca_get_volsw(struct snd_kcontrol *kcontrol,
@ -477,7 +477,7 @@ static const struct snd_kcontrol_new rt715_sdca_snd_controls[] = {
RT715_SDCA_FU_VOL_CTRL, CH_01),
SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL,
RT715_SDCA_FU_VOL_CTRL, CH_02),
0x2f, 0x7f, 0,
0x2f, 0x3f, 0,
rt715_sdca_set_amp_gain_get, rt715_sdca_set_amp_gain_put,
in_vol_tlv),
RT715_SDCA_EXT_TLV("FU02 Capture Volume",
@ -485,13 +485,13 @@ static const struct snd_kcontrol_new rt715_sdca_snd_controls[] = {
RT715_SDCA_FU_VOL_CTRL, CH_01),
rt715_sdca_set_amp_gain_4ch_get,
rt715_sdca_set_amp_gain_4ch_put,
in_vol_tlv, 4, 0x7f),
in_vol_tlv, 4, 0x3f),
RT715_SDCA_EXT_TLV("FU06 Capture Volume",
SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL,
RT715_SDCA_FU_VOL_CTRL, CH_01),
rt715_sdca_set_amp_gain_4ch_get,
rt715_sdca_set_amp_gain_4ch_put,
in_vol_tlv, 4, 0x7f),
in_vol_tlv, 4, 0x3f),
/* MIC Boost Control */
RT715_SDCA_BOOST_EXT_TLV("FU0E Boost",
SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN,

View File

@ -111,6 +111,7 @@ static bool rt715_readable_register(struct device *dev, unsigned int reg)
case 0x839d:
case 0x83a7:
case 0x83a9:
case 0x752001:
case 0x752039:
return true;
default:

View File

@ -1330,7 +1330,7 @@ static struct snd_soc_dai_driver rt722_sdca_dai[] = {
.capture = {
.stream_name = "DP6 DMic Capture",
.channels_min = 1,
.channels_max = 2,
.channels_max = 4,
.rates = RT722_STEREO_RATES,
.formats = RT722_FORMATS,
},
@ -1439,9 +1439,12 @@ static void rt722_sdca_jack_preset(struct rt722_sdca_priv *rt722)
int loop_check, chk_cnt = 100, ret;
unsigned int calib_status = 0;
/* Read eFuse */
rt722_sdca_index_write(rt722, RT722_VENDOR_SPK_EFUSE, RT722_DC_CALIB_CTRL,
0x4808);
/* Config analog bias */
rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_ANALOG_BIAS_CTL3,
0xa081);
/* GE related settings */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_GE_RELATED_CTL2,
0xa009);
/* Button A, B, C, D bypass mode */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_UMP_HID_CTL4,
0xcf00);
@ -1475,9 +1478,6 @@ static void rt722_sdca_jack_preset(struct rt722_sdca_priv *rt722)
if ((calib_status & 0x0040) == 0x0)
break;
}
/* Release HP-JD, EN_CBJ_TIE_GL/R open, en_osw gating auto done bit */
rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_DIGITAL_MISC_CTRL4,
0x0010);
/* Set ADC09 power entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_ADC0A_08_PDE_FLOAT_CTL,
0x2a12);
@ -1490,8 +1490,21 @@ static void rt722_sdca_jack_preset(struct rt722_sdca_priv *rt722)
/* Set DAC03 and HP power entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_DAC03_HP_PDE_FLOAT_CTL,
0x4040);
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_ENT_FLOAT_CTRL_1,
0x4141);
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_FLOAT_CTRL_1,
0x0101);
/* Fine tune PDE40 latency */
regmap_write(rt722->regmap, 0x2f58, 0x07);
regmap_write(rt722->regmap, 0x2f03, 0x06);
/* MIC VRefo */
rt722_sdca_index_update_bits(rt722, RT722_VENDOR_REG,
RT722_COMBO_JACK_AUTO_CTL1, 0x0200, 0x0200);
rt722_sdca_index_update_bits(rt722, RT722_VENDOR_REG,
RT722_VREFO_GAT, 0x4000, 0x4000);
/* Release HP-JD, EN_CBJ_TIE_GL/R open, en_osw gating auto done bit */
rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_DIGITAL_MISC_CTRL4,
0x0010);
}
int rt722_sdca_io_init(struct device *dev, struct sdw_slave *slave)

View File

@ -69,6 +69,7 @@ struct rt722_sdca_dmic_kctrl_priv {
#define RT722_COMBO_JACK_AUTO_CTL2 0x46
#define RT722_COMBO_JACK_AUTO_CTL3 0x47
#define RT722_DIGITAL_MISC_CTRL4 0x4a
#define RT722_VREFO_GAT 0x63
#define RT722_FSM_CTL 0x67
#define RT722_SDCA_INTR_REC 0x82
#define RT722_SW_CONFIG1 0x8a
@ -127,6 +128,8 @@ struct rt722_sdca_dmic_kctrl_priv {
#define RT722_UMP_HID_CTL6 0x66
#define RT722_UMP_HID_CTL7 0x67
#define RT722_UMP_HID_CTL8 0x68
#define RT722_FLOAT_CTRL_1 0x70
#define RT722_ENT_FLOAT_CTRL_1 0x76
/* Parameter & Verb control 01 (0x1a)(NID:20h) */
#define RT722_HIDDEN_REG_SW_RESET (0x1 << 14)

View File

@ -1155,6 +1155,7 @@ static int wsa881x_probe(struct sdw_slave *pdev,
pdev->prop.sink_ports = GENMASK(WSA881X_MAX_SWR_PORTS, 0);
pdev->prop.sink_dpn_prop = wsa_sink_dpn_prop;
pdev->prop.scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY;
pdev->prop.clk_stop_mode1 = true;
gpiod_direction_output(wsa881x->sd_n, !wsa881x->sd_n_val);
wsa881x->regmap = devm_regmap_init_sdw(pdev, &wsa881x_regmap_config);

View File

@ -64,7 +64,7 @@ struct avs_icl_memwnd2_desc {
struct avs_icl_memwnd2 {
union {
struct avs_icl_memwnd2_desc slot_desc[AVS_ICL_MEMWND2_SLOTS_COUNT];
u8 rsvd[PAGE_SIZE];
u8 rsvd[SZ_4K];
};
u8 slot_array[AVS_ICL_MEMWND2_SLOTS_COUNT][PAGE_SIZE];
} __packed;

View File

@ -1582,6 +1582,8 @@ static int avs_widget_load(struct snd_soc_component *comp, int index,
if (!le32_to_cpu(dw->priv.size))
return 0;
w->no_wname_in_kcontrol_name = true;
if (w->ignore_suspend && !AVS_S0IX_SUPPORTED) {
dev_info_once(comp->dev, "Device does not support S0IX, check BIOS settings\n");
w->ignore_suspend = false;

View File

@ -636,17 +636,7 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_USE_AMCR0F28),
},
{
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"),
},
.driver_data = (void *)(BYT_RT5640_IN1_MAP |
BYT_RT5640_JD_SRC_JD2_IN4N |
BYT_RT5640_OVCD_TH_2000UA |
BYT_RT5640_OVCD_SF_0P75 |
BYT_RT5640_MCLK_EN),
},
{
/* Asus T100TAF, unlike other T100TA* models this one has a mono speaker */
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"),
@ -660,6 +650,18 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF2 |
BYT_RT5640_MCLK_EN),
},
{
/* Asus T100TA and T100TAM, must come after T100TAF (mono spk) match */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "T100TA"),
},
.driver_data = (void *)(BYT_RT5640_IN1_MAP |
BYT_RT5640_JD_SRC_JD2_IN4N |
BYT_RT5640_OVCD_TH_2000UA |
BYT_RT5640_OVCD_SF_0P75 |
BYT_RT5640_MCLK_EN),
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),

View File

@ -99,6 +99,7 @@ config SND_MESON_AXG_PDM
config SND_MESON_CARD_UTILS
tristate
select SND_DYNAMIC_MINORS
config SND_MESON_CODEC_GLUE
tristate

View File

@ -318,6 +318,7 @@ static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np,
dai_link->cpus = cpu;
dai_link->num_cpus = 1;
dai_link->nonatomic = true;
ret = meson_card_parse_dai(card, np, dai_link->cpus);
if (ret)

View File

@ -204,18 +204,26 @@ static irqreturn_t axg_fifo_pcm_irq_block(int irq, void *dev_id)
unsigned int status;
regmap_read(fifo->map, FIFO_STATUS1, &status);
status = FIELD_GET(STATUS1_INT_STS, status);
if (status & FIFO_INT_COUNT_REPEAT)
snd_pcm_period_elapsed(ss);
else
dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n",
status);
/* Ack irqs */
axg_fifo_ack_irq(fifo, status);
return IRQ_RETVAL(status);
/* Use the thread to call period elapsed on nonatomic links */
if (status & FIFO_INT_COUNT_REPEAT)
return IRQ_WAKE_THREAD;
dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n",
status);
return IRQ_NONE;
}
static irqreturn_t axg_fifo_pcm_irq_block_thread(int irq, void *dev_id)
{
struct snd_pcm_substream *ss = dev_id;
snd_pcm_period_elapsed(ss);
return IRQ_HANDLED;
}
int axg_fifo_pcm_open(struct snd_soc_component *component,
@ -243,8 +251,9 @@ int axg_fifo_pcm_open(struct snd_soc_component *component,
if (ret)
return ret;
ret = request_irq(fifo->irq, axg_fifo_pcm_irq_block, 0,
dev_name(dev), ss);
ret = request_threaded_irq(fifo->irq, axg_fifo_pcm_irq_block,
axg_fifo_pcm_irq_block_thread,
IRQF_ONESHOT, dev_name(dev), ss);
if (ret)
return ret;

View File

@ -392,6 +392,46 @@ void axg_tdm_stream_free(struct axg_tdm_stream *ts)
}
EXPORT_SYMBOL_GPL(axg_tdm_stream_free);
int axg_tdm_stream_set_cont_clocks(struct axg_tdm_stream *ts,
unsigned int fmt)
{
int ret = 0;
if (fmt & SND_SOC_DAIFMT_CONT) {
/* Clock are already enabled - skipping */
if (ts->clk_enabled)
return 0;
ret = clk_prepare_enable(ts->iface->mclk);
if (ret)
return ret;
ret = clk_prepare_enable(ts->iface->sclk);
if (ret)
goto err_sclk;
ret = clk_prepare_enable(ts->iface->lrclk);
if (ret)
goto err_lrclk;
ts->clk_enabled = true;
return 0;
}
/* Clocks are already disabled - skipping */
if (!ts->clk_enabled)
return 0;
clk_disable_unprepare(ts->iface->lrclk);
err_lrclk:
clk_disable_unprepare(ts->iface->sclk);
err_sclk:
clk_disable_unprepare(ts->iface->mclk);
ts->clk_enabled = false;
return ret;
}
EXPORT_SYMBOL_GPL(axg_tdm_stream_set_cont_clocks);
MODULE_DESCRIPTION("Amlogic AXG TDM formatter driver");
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
MODULE_LICENSE("GPL v2");

View File

@ -309,6 +309,7 @@ static int axg_tdm_iface_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct axg_tdm_iface *iface = snd_soc_dai_get_drvdata(dai);
struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream);
int ret;
switch (iface->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@ -346,7 +347,11 @@ static int axg_tdm_iface_hw_params(struct snd_pcm_substream *substream,
return ret;
}
return 0;
ret = axg_tdm_stream_set_cont_clocks(ts, iface->fmt);
if (ret)
dev_err(dai->dev, "failed to apply continuous clock setting\n");
return ret;
}
static int axg_tdm_iface_hw_free(struct snd_pcm_substream *substream,
@ -354,19 +359,32 @@ static int axg_tdm_iface_hw_free(struct snd_pcm_substream *substream,
{
struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream);
/* Stop all attached formatters */
axg_tdm_stream_stop(ts);
return 0;
return axg_tdm_stream_set_cont_clocks(ts, 0);
}
static int axg_tdm_iface_prepare(struct snd_pcm_substream *substream,
static int axg_tdm_iface_trigger(struct snd_pcm_substream *substream,
int cmd,
struct snd_soc_dai *dai)
{
struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream);
struct axg_tdm_stream *ts =
snd_soc_dai_get_dma_data(dai, substream);
/* Force all attached formatters to update */
return axg_tdm_stream_reset(ts);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
axg_tdm_stream_start(ts);
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_STOP:
axg_tdm_stream_stop(ts);
break;
default:
return -EINVAL;
}
return 0;
}
static int axg_tdm_iface_remove_dai(struct snd_soc_dai *dai)
@ -412,8 +430,8 @@ static const struct snd_soc_dai_ops axg_tdm_iface_ops = {
.set_fmt = axg_tdm_iface_set_fmt,
.startup = axg_tdm_iface_startup,
.hw_params = axg_tdm_iface_hw_params,
.prepare = axg_tdm_iface_prepare,
.hw_free = axg_tdm_iface_hw_free,
.trigger = axg_tdm_iface_trigger,
};
/* TDM Backend DAIs */

View File

@ -58,12 +58,17 @@ struct axg_tdm_stream {
unsigned int physical_width;
u32 *mask;
bool ready;
/* For continuous clock tracking */
bool clk_enabled;
};
struct axg_tdm_stream *axg_tdm_stream_alloc(struct axg_tdm_iface *iface);
void axg_tdm_stream_free(struct axg_tdm_stream *ts);
int axg_tdm_stream_start(struct axg_tdm_stream *ts);
void axg_tdm_stream_stop(struct axg_tdm_stream *ts);
int axg_tdm_stream_set_cont_clocks(struct axg_tdm_stream *ts,
unsigned int fmt);
static inline int axg_tdm_stream_reset(struct axg_tdm_stream *ts)
{

View File

@ -350,7 +350,9 @@ static int sof_init_environment(struct snd_sof_dev *sdev)
}
ret = sof_select_ipc_and_paths(sdev);
if (!ret && plat_data->ipc_type != base_profile->ipc_type) {
if (ret) {
goto err_machine_check;
} else if (plat_data->ipc_type != base_profile->ipc_type) {
/* IPC type changed, re-initialize the ops */
sof_ops_free(sdev);

View File

@ -330,14 +330,32 @@ EXPORT_SYMBOL_GPL(snd_sof_dbg_memory_info_init);
int snd_sof_dbg_init(struct snd_sof_dev *sdev)
{
struct snd_sof_pdata *plat_data = sdev->pdata;
struct snd_sof_dsp_ops *ops = sof_ops(sdev);
const struct snd_sof_debugfs_map *map;
struct dentry *fw_profile;
int i;
int err;
/* use "sof" as top level debugFS dir */
sdev->debugfs_root = debugfs_create_dir("sof", NULL);
/* expose firmware/topology prefix/names for test purposes */
fw_profile = debugfs_create_dir("fw_profile", sdev->debugfs_root);
debugfs_create_str("fw_path", 0444, fw_profile,
(char **)&plat_data->fw_filename_prefix);
debugfs_create_str("fw_lib_path", 0444, fw_profile,
(char **)&plat_data->fw_lib_prefix);
debugfs_create_str("tplg_path", 0444, fw_profile,
(char **)&plat_data->tplg_filename_prefix);
debugfs_create_str("fw_name", 0444, fw_profile,
(char **)&plat_data->fw_filename);
debugfs_create_str("tplg_name", 0444, fw_profile,
(char **)&plat_data->tplg_filename);
debugfs_create_u32("ipc_type", 0444, fw_profile,
(u32 *)&plat_data->ipc_type);
/* init dfsentry list */
INIT_LIST_HEAD(&sdev->dfsentry_list);

View File

@ -35,6 +35,9 @@ static const struct sof_dev_desc lnl_desc = {
.default_fw_path = {
[SOF_IPC_TYPE_4] = "intel/sof-ipc4/lnl",
},
.default_lib_path = {
[SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/lnl",
},
.default_tplg_path = {
[SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg",
},

View File

@ -434,4 +434,5 @@ const struct sof_ipc_pcm_ops ipc3_pcm_ops = {
.trigger = sof_ipc3_pcm_trigger,
.dai_link_fixup = sof_ipc3_pcm_dai_link_fixup,
.reset_hw_params_during_stop = true,
.d0i3_supported_in_s0ix = true,
};

View File

@ -37,6 +37,25 @@ struct sof_ipc4_timestamp_info {
snd_pcm_sframes_t delay;
};
/**
* struct sof_ipc4_pcm_stream_priv - IPC4 specific private data
* @time_info: pointer to time info struct if it is supported, otherwise NULL
* @chain_dma_allocated: indicates the ChainDMA allocation state
*/
struct sof_ipc4_pcm_stream_priv {
struct sof_ipc4_timestamp_info *time_info;
bool chain_dma_allocated;
};
static inline struct sof_ipc4_timestamp_info *
sof_ipc4_sps_to_time_info(struct snd_sof_pcm_stream *sps)
{
struct sof_ipc4_pcm_stream_priv *stream_priv = sps->private;
return stream_priv->time_info;
}
static int sof_ipc4_set_multi_pipeline_state(struct snd_sof_dev *sdev, u32 state,
struct ipc4_pipeline_set_state_data *trigger_list)
{
@ -253,14 +272,17 @@ sof_ipc4_update_pipeline_state(struct snd_sof_dev *sdev, int state, int cmd,
*/
static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev,
int direction,
struct snd_sof_pcm *spcm, int direction,
struct snd_sof_pcm_stream_pipeline_list *pipeline_list,
int state, int cmd)
{
struct sof_ipc4_fw_data *ipc4_data = sdev->private;
struct sof_ipc4_pcm_stream_priv *stream_priv;
bool allocate, enable, set_fifo_size;
struct sof_ipc4_msg msg = {{ 0 }};
int i;
int ret, i;
stream_priv = spcm->stream[direction].private;
switch (state) {
case SOF_IPC4_PIPE_RUNNING: /* Allocate and start chained dma */
@ -281,6 +303,11 @@ static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev,
set_fifo_size = false;
break;
case SOF_IPC4_PIPE_RESET: /* Disable and free chained DMA. */
/* ChainDMA can only be reset if it has been allocated */
if (!stream_priv->chain_dma_allocated)
return 0;
allocate = false;
enable = false;
set_fifo_size = false;
@ -338,7 +365,12 @@ static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev,
if (enable)
msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_ENABLE_MASK;
return sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0);
ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0);
/* Update the ChainDMA allocation state */
if (!ret)
stream_priv->chain_dma_allocated = allocate;
return ret;
}
static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
@ -378,7 +410,7 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
* trigger function that handles the rest for the substream.
*/
if (pipeline->use_chain_dma)
return sof_ipc4_chain_dma_trigger(sdev, substream->stream,
return sof_ipc4_chain_dma_trigger(sdev, spcm, substream->stream,
pipeline_list, state, cmd);
/* allocate memory for the pipeline data */
@ -452,7 +484,7 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
* Invalidate the stream_start_offset to make sure that it is
* going to be updated if the stream resumes
*/
time_info = spcm->stream[substream->stream].private;
time_info = sof_ipc4_sps_to_time_info(&spcm->stream[substream->stream]);
if (time_info)
time_info->stream_start_offset = SOF_IPC4_INVALID_STREAM_POSITION;
@ -706,12 +738,16 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
static void sof_ipc4_pcm_free(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm)
{
struct snd_sof_pcm_stream_pipeline_list *pipeline_list;
struct sof_ipc4_pcm_stream_priv *stream_priv;
int stream;
for_each_pcm_streams(stream) {
pipeline_list = &spcm->stream[stream].pipeline_list;
kfree(pipeline_list->pipelines);
pipeline_list->pipelines = NULL;
stream_priv = spcm->stream[stream].private;
kfree(stream_priv->time_info);
kfree(spcm->stream[stream].private);
spcm->stream[stream].private = NULL;
}
@ -721,7 +757,8 @@ static int sof_ipc4_pcm_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm
{
struct snd_sof_pcm_stream_pipeline_list *pipeline_list;
struct sof_ipc4_fw_data *ipc4_data = sdev->private;
struct sof_ipc4_timestamp_info *stream_info;
struct sof_ipc4_pcm_stream_priv *stream_priv;
struct sof_ipc4_timestamp_info *time_info;
bool support_info = true;
u32 abi_version;
u32 abi_offset;
@ -749,33 +786,41 @@ static int sof_ipc4_pcm_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm
return -ENOMEM;
}
if (!support_info)
continue;
stream_info = kzalloc(sizeof(*stream_info), GFP_KERNEL);
if (!stream_info) {
stream_priv = kzalloc(sizeof(*stream_priv), GFP_KERNEL);
if (!stream_priv) {
sof_ipc4_pcm_free(sdev, spcm);
return -ENOMEM;
}
spcm->stream[stream].private = stream_info;
spcm->stream[stream].private = stream_priv;
if (!support_info)
continue;
time_info = kzalloc(sizeof(*time_info), GFP_KERNEL);
if (!time_info) {
sof_ipc4_pcm_free(sdev, spcm);
return -ENOMEM;
}
stream_priv->time_info = time_info;
}
return 0;
}
static void sof_ipc4_build_time_info(struct snd_sof_dev *sdev, struct snd_sof_pcm_stream *spcm)
static void sof_ipc4_build_time_info(struct snd_sof_dev *sdev, struct snd_sof_pcm_stream *sps)
{
struct sof_ipc4_copier *host_copier = NULL;
struct sof_ipc4_copier *dai_copier = NULL;
struct sof_ipc4_llp_reading_slot llp_slot;
struct sof_ipc4_timestamp_info *info;
struct sof_ipc4_timestamp_info *time_info;
struct snd_soc_dapm_widget *widget;
struct snd_sof_dai *dai;
int i;
/* find host & dai to locate info in memory window */
for_each_dapm_widgets(spcm->list, i, widget) {
for_each_dapm_widgets(sps->list, i, widget) {
struct snd_sof_widget *swidget = widget->dobj.private;
if (!swidget)
@ -795,44 +840,44 @@ static void sof_ipc4_build_time_info(struct snd_sof_dev *sdev, struct snd_sof_pc
return;
}
info = spcm->private;
info->host_copier = host_copier;
info->dai_copier = dai_copier;
info->llp_offset = offsetof(struct sof_ipc4_fw_registers, llp_gpdma_reading_slots) +
sdev->fw_info_box.offset;
time_info = sof_ipc4_sps_to_time_info(sps);
time_info->host_copier = host_copier;
time_info->dai_copier = dai_copier;
time_info->llp_offset = offsetof(struct sof_ipc4_fw_registers,
llp_gpdma_reading_slots) + sdev->fw_info_box.offset;
/* find llp slot used by current dai */
for (i = 0; i < SOF_IPC4_MAX_LLP_GPDMA_READING_SLOTS; i++) {
sof_mailbox_read(sdev, info->llp_offset, &llp_slot, sizeof(llp_slot));
sof_mailbox_read(sdev, time_info->llp_offset, &llp_slot, sizeof(llp_slot));
if (llp_slot.node_id == dai_copier->data.gtw_cfg.node_id)
break;
info->llp_offset += sizeof(llp_slot);
time_info->llp_offset += sizeof(llp_slot);
}
if (i < SOF_IPC4_MAX_LLP_GPDMA_READING_SLOTS)
return;
/* if no llp gpdma slot is used, check aggregated sdw slot */
info->llp_offset = offsetof(struct sof_ipc4_fw_registers, llp_sndw_reading_slots) +
sdev->fw_info_box.offset;
time_info->llp_offset = offsetof(struct sof_ipc4_fw_registers,
llp_sndw_reading_slots) + sdev->fw_info_box.offset;
for (i = 0; i < SOF_IPC4_MAX_LLP_SNDW_READING_SLOTS; i++) {
sof_mailbox_read(sdev, info->llp_offset, &llp_slot, sizeof(llp_slot));
sof_mailbox_read(sdev, time_info->llp_offset, &llp_slot, sizeof(llp_slot));
if (llp_slot.node_id == dai_copier->data.gtw_cfg.node_id)
break;
info->llp_offset += sizeof(llp_slot);
time_info->llp_offset += sizeof(llp_slot);
}
if (i < SOF_IPC4_MAX_LLP_SNDW_READING_SLOTS)
return;
/* check EVAD slot */
info->llp_offset = offsetof(struct sof_ipc4_fw_registers, llp_evad_reading_slot) +
sdev->fw_info_box.offset;
sof_mailbox_read(sdev, info->llp_offset, &llp_slot, sizeof(llp_slot));
time_info->llp_offset = offsetof(struct sof_ipc4_fw_registers,
llp_evad_reading_slot) + sdev->fw_info_box.offset;
sof_mailbox_read(sdev, time_info->llp_offset, &llp_slot, sizeof(llp_slot));
if (llp_slot.node_id != dai_copier->data.gtw_cfg.node_id)
info->llp_offset = 0;
time_info->llp_offset = 0;
}
static int sof_ipc4_pcm_hw_params(struct snd_soc_component *component,
@ -849,7 +894,7 @@ static int sof_ipc4_pcm_hw_params(struct snd_soc_component *component,
if (!spcm)
return -EINVAL;
time_info = spcm->stream[substream->stream].private;
time_info = sof_ipc4_sps_to_time_info(&spcm->stream[substream->stream]);
/* delay calculation is not supported by current fw_reg ABI */
if (!time_info)
return 0;
@ -864,7 +909,7 @@ static int sof_ipc4_pcm_hw_params(struct snd_soc_component *component,
static int sof_ipc4_get_stream_start_offset(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream,
struct snd_sof_pcm_stream *stream,
struct snd_sof_pcm_stream *sps,
struct sof_ipc4_timestamp_info *time_info)
{
struct sof_ipc4_copier *host_copier = time_info->host_copier;
@ -918,7 +963,7 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
struct sof_ipc4_timestamp_info *time_info;
struct sof_ipc4_llp_reading_slot llp;
snd_pcm_uframes_t head_cnt, tail_cnt;
struct snd_sof_pcm_stream *stream;
struct snd_sof_pcm_stream *sps;
u64 dai_cnt, host_cnt, host_ptr;
struct snd_sof_pcm *spcm;
int ret;
@ -927,8 +972,8 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
if (!spcm)
return -EOPNOTSUPP;
stream = &spcm->stream[substream->stream];
time_info = stream->private;
sps = &spcm->stream[substream->stream];
time_info = sof_ipc4_sps_to_time_info(sps);
if (!time_info)
return -EOPNOTSUPP;
@ -938,7 +983,7 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
* the statistics is complete. And it will not change after the first initiailization.
*/
if (time_info->stream_start_offset == SOF_IPC4_INVALID_STREAM_POSITION) {
ret = sof_ipc4_get_stream_start_offset(sdev, substream, stream, time_info);
ret = sof_ipc4_get_stream_start_offset(sdev, substream, sps, time_info);
if (ret < 0)
return -EOPNOTSUPP;
}
@ -1030,15 +1075,13 @@ static snd_pcm_sframes_t sof_ipc4_pcm_delay(struct snd_soc_component *component,
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct sof_ipc4_timestamp_info *time_info;
struct snd_sof_pcm_stream *stream;
struct snd_sof_pcm *spcm;
spcm = snd_sof_find_spcm_dai(component, rtd);
if (!spcm)
return 0;
stream = &spcm->stream[substream->stream];
time_info = stream->private;
time_info = sof_ipc4_sps_to_time_info(&spcm->stream[substream->stream]);
/*
* Report the stored delay value calculated in the pointer callback.
* In the unlikely event that the calculation was skipped/aborted, the

View File

@ -325,14 +325,13 @@ static int sof_pcm_trigger(struct snd_soc_component *component,
ipc_first = true;
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
if (sdev->system_suspend_target == SOF_SUSPEND_S0IX &&
/*
* If DSP D0I3 is allowed during S0iX, set the suspend_ignored flag for
* D0I3-compatible streams to keep the firmware pipeline running
*/
if (pcm_ops && pcm_ops->d0i3_supported_in_s0ix &&
sdev->system_suspend_target == SOF_SUSPEND_S0IX &&
spcm->stream[substream->stream].d0i3_compatible) {
/*
* trap the event, not sending trigger stop to
* prevent the FW pipelines from being stopped,
* and mark the flag to ignore the upcoming DAPM
* PM events.
*/
spcm->stream[substream->stream].suspend_ignored = true;
return 0;
}

View File

@ -116,6 +116,7 @@ struct snd_sof_dai_config_data {
* triggers. The FW keeps the host DMA running in this case and
* therefore the host must do the same and should stop the DMA during
* hw_free.
* @d0i3_supported_in_s0ix: Allow DSP D0I3 during S0iX
*/
struct sof_ipc_pcm_ops {
int (*hw_params)(struct snd_soc_component *component, struct snd_pcm_substream *substream,
@ -135,6 +136,7 @@ struct sof_ipc_pcm_ops {
bool reset_hw_params_during_stop;
bool ipc_first_on_start;
bool platform_stop_during_hw_free;
bool d0i3_supported_in_s0ix;
};
/**

View File

@ -1,8 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
//
// tegra186_dspk.c - Tegra186 DSPK driver
//
// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
@ -241,14 +240,14 @@ static int tegra186_dspk_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
cif_conf.client_bits = TEGRA_ACIF_BITS_24;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
cif_conf.client_bits = TEGRA_ACIF_BITS_16;
break;
case SNDRV_PCM_FORMAT_S32_LE:
cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
cif_conf.client_bits = TEGRA_ACIF_BITS_24;
break;
default:
dev_err(dev, "unsupported format!\n");

View File

@ -2417,12 +2417,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
mcasp_reparent_fck(pdev);
ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component,
&davinci_mcasp_dai[mcasp->op_mode], 1);
if (ret != 0)
goto err;
ret = davinci_mcasp_get_dma_type(mcasp);
switch (ret) {
case PCM_EDMA:
@ -2449,6 +2443,12 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
goto err;
}
ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component,
&davinci_mcasp_dai[mcasp->op_mode], 1);
if (ret != 0)
goto err;
no_audio:
ret = davinci_mcasp_init_gpiochip(mcasp);
if (ret) {