Commit 5414aea7 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull sound fixes from Takashi Iwai:
 "Apparently there were so many kids wishing bug fixes that made Santa
  busy; here we have lots of fixes although it's a bit late. But all
  changes are device-specific, hence it should be relatively safe to
  apply.

  Most of changes are for Cirrus codecs (for both ASoC and HD-audio),
  while the remaining are fixes for TI codecs, HD-audio and USB-audio
  quirks"

* tag 'sound-6.7-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (24 commits)
  ALSA: hda: cs35l41: Only add SPI CS GPIO if SPI is enabled in kernel
  ALSA: hda: cs35l41: Do not allow uninitialised variables to be freed
  ASoC: fsl_sai: Fix channel swap issue on i.MX8MP
  ASoC: hdmi-codec: fix missing report for jack initial status
  ALSA: hda/realtek: Add quirks for ASUS Zenbook 2023 Models
  ALSA: hda: cs35l41: Support additional ASUS Zenbook 2023 Models
  ALSA: hda/realtek: Add quirks for ASUS Zenbook 2022 Models
  ALSA: hda: cs35l41: Support additional ASUS Zenbook 2022 Models
  ALSA: hda/realtek: Add quirks for ASUS ROG 2023 models
  ALSA: hda: cs35l41: Support additional ASUS ROG 2023 models
  ALSA: hda: cs35l41: Add config table to support many laptops without _DSD
  ASoC: Intel: bytcr_rt5640: Add new swapped-speakers quirk
  ASoC: Intel: bytcr_rt5640: Add quirk for the Medion Lifetab S10346
  kselftest: alsa: fixed a print formatting warning
  ALSA: usb-audio: Increase delay in MOTU M quirk
  ASoC: tas2781: check the validity of prm_no/cfg_no
  ALSA: hda/tas2781: select program 0, conf 0 by default
  ALSA: hda/realtek: Add quirk for ASUS ROG GV302XA
  ASoC: cs42l43: Don't enable bias sense during type detect
  ASoC: Intel: soc-acpi-intel-mtl-match: Change CS35L56 prefixes to AMPn
  ...
parents 2618280d 916d0517
...@@ -1826,6 +1826,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i ...@@ -1826,6 +1826,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type)) if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0); gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
gpiod_put(cs35l41->reset_gpio); gpiod_put(cs35l41->reset_gpio);
gpiod_put(cs35l41->cs_gpio);
acpi_dev_put(cs35l41->dacpi); acpi_dev_put(cs35l41->dacpi);
kfree(cs35l41->acpi_subsystem_id); kfree(cs35l41->acpi_subsystem_id);
...@@ -1853,6 +1854,7 @@ void cs35l41_hda_remove(struct device *dev) ...@@ -1853,6 +1854,7 @@ void cs35l41_hda_remove(struct device *dev)
if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type)) if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0); gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
gpiod_put(cs35l41->reset_gpio); gpiod_put(cs35l41->reset_gpio);
gpiod_put(cs35l41->cs_gpio);
kfree(cs35l41->acpi_subsystem_id); kfree(cs35l41->acpi_subsystem_id);
} }
EXPORT_SYMBOL_NS_GPL(cs35l41_hda_remove, SND_HDA_SCODEC_CS35L41); EXPORT_SYMBOL_NS_GPL(cs35l41_hda_remove, SND_HDA_SCODEC_CS35L41);
......
...@@ -35,8 +35,8 @@ struct cs35l41_amp_efi_data { ...@@ -35,8 +35,8 @@ struct cs35l41_amp_efi_data {
} __packed; } __packed;
enum cs35l41_hda_spk_pos { enum cs35l41_hda_spk_pos {
CS35l41_LEFT, CS35L41_LEFT,
CS35l41_RIGHT, CS35L41_RIGHT,
}; };
enum cs35l41_hda_gpio_function { enum cs35l41_hda_gpio_function {
...@@ -50,6 +50,7 @@ struct cs35l41_hda { ...@@ -50,6 +50,7 @@ struct cs35l41_hda {
struct device *dev; struct device *dev;
struct regmap *regmap; struct regmap *regmap;
struct gpio_desc *reset_gpio; struct gpio_desc *reset_gpio;
struct gpio_desc *cs_gpio;
struct cs35l41_hw_cfg hw_cfg; struct cs35l41_hw_cfg hw_cfg;
struct hda_codec *codec; struct hda_codec *codec;
......
...@@ -6,9 +6,303 @@ ...@@ -6,9 +6,303 @@
// //
// Author: Stefan Binding <sbinding@opensource.cirrus.com> // Author: Stefan Binding <sbinding@opensource.cirrus.com>
#include <linux/acpi.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/string.h> #include <linux/string.h>
#include "cs35l41_hda_property.h" #include "cs35l41_hda_property.h"
#include <linux/spi/spi.h>
#define MAX_AMPS 4
struct cs35l41_config {
const char *ssid;
enum {
SPI,
I2C
} bus;
int num_amps;
enum {
INTERNAL,
EXTERNAL
} boost_type;
u8 channel[MAX_AMPS];
int reset_gpio_index; /* -1 if no reset gpio */
int spkid_gpio_index; /* -1 if no spkid gpio */
int cs_gpio_index; /* -1 if no cs gpio, or cs-gpios already exists, max num amps == 2 */
int boost_ind_nanohenry; /* Required if boost_type == Internal */
int boost_peak_milliamp; /* Required if boost_type == Internal */
int boost_cap_microfarad; /* Required if boost_type == Internal */
};
static const struct cs35l41_config cs35l41_config_table[] = {
/*
* Device 103C89C6 does have _DSD, however it is setup to use the wrong boost type.
* We can override the _DSD to correct the boost type here.
* Since this laptop has valid ACPI, we do not need to handle cs-gpios, since that already exists
* in the ACPI. The Reset GPIO is also valid, so we can use the Reset defined in _DSD.
*/
{ "103C89C6", SPI, 2, INTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, 0, 0 }, -1, -1, -1, 1000, 4500, 24 },
{ "104312AF", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
{ "10431433", I2C, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
{ "10431463", I2C, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
{ "10431473", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 1000, 4500, 24 },
{ "10431483", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 1000, 4500, 24 },
{ "10431493", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
{ "104314D3", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
{ "104314E3", I2C, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
{ "10431503", I2C, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
{ "10431533", I2C, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
{ "10431573", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
{ "10431663", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 1000, 4500, 24 },
{ "104316D3", SPI, 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
{ "104316F3", SPI, 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
{ "104317F3", I2C, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
{ "10431863", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
{ "104318D3", I2C, 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
{ "10431C9F", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
{ "10431CAF", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
{ "10431CCF", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
{ "10431CDF", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
{ "10431CEF", SPI, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
{ "10431D1F", I2C, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
{ "10431DA2", SPI, 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
{ "10431E02", SPI, 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
{ "10431EE2", I2C, 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
{ "10431F12", I2C, 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
{ "10431F1F", SPI, 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 0, 0, 0 },
{ "10431F62", SPI, 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
{}
};
static int cs35l41_add_gpios(struct cs35l41_hda *cs35l41, struct device *physdev, int reset_gpio,
int spkid_gpio, int cs_gpio_index, int num_amps)
{
struct acpi_gpio_mapping *gpio_mapping = NULL;
struct acpi_gpio_params *reset_gpio_params = NULL;
struct acpi_gpio_params *spkid_gpio_params = NULL;
struct acpi_gpio_params *cs_gpio_params = NULL;
unsigned int num_entries = 0;
unsigned int reset_index, spkid_index, csgpio_index;
int i;
/*
* GPIO Mapping only needs to be done once, since it would be available for subsequent amps
*/
if (cs35l41->dacpi->driver_gpios)
return 0;
if (reset_gpio >= 0) {
reset_index = num_entries;
num_entries++;
}
if (spkid_gpio >= 0) {
spkid_index = num_entries;
num_entries++;
}
if ((cs_gpio_index >= 0) && (num_amps == 2)) {
csgpio_index = num_entries;
num_entries++;
}
if (!num_entries)
return 0;
/* must include termination entry */
num_entries++;
gpio_mapping = devm_kcalloc(physdev, num_entries, sizeof(struct acpi_gpio_mapping),
GFP_KERNEL);
if (!gpio_mapping)
goto err;
if (reset_gpio >= 0) {
gpio_mapping[reset_index].name = "reset-gpios";
reset_gpio_params = devm_kcalloc(physdev, num_amps, sizeof(struct acpi_gpio_params),
GFP_KERNEL);
if (!reset_gpio_params)
goto err;
for (i = 0; i < num_amps; i++)
reset_gpio_params[i].crs_entry_index = reset_gpio;
gpio_mapping[reset_index].data = reset_gpio_params;
gpio_mapping[reset_index].size = num_amps;
}
if (spkid_gpio >= 0) {
gpio_mapping[spkid_index].name = "spk-id-gpios";
spkid_gpio_params = devm_kcalloc(physdev, num_amps, sizeof(struct acpi_gpio_params),
GFP_KERNEL);
if (!spkid_gpio_params)
goto err;
for (i = 0; i < num_amps; i++)
spkid_gpio_params[i].crs_entry_index = spkid_gpio;
gpio_mapping[spkid_index].data = spkid_gpio_params;
gpio_mapping[spkid_index].size = num_amps;
}
if ((cs_gpio_index >= 0) && (num_amps == 2)) {
gpio_mapping[csgpio_index].name = "cs-gpios";
/* only one GPIO CS is supported without using _DSD, obtained using index 0 */
cs_gpio_params = devm_kzalloc(physdev, sizeof(struct acpi_gpio_params), GFP_KERNEL);
if (!cs_gpio_params)
goto err;
cs_gpio_params->crs_entry_index = cs_gpio_index;
gpio_mapping[csgpio_index].data = cs_gpio_params;
gpio_mapping[csgpio_index].size = 1;
}
return devm_acpi_dev_add_driver_gpios(physdev, gpio_mapping);
err:
devm_kfree(physdev, gpio_mapping);
devm_kfree(physdev, reset_gpio_params);
devm_kfree(physdev, spkid_gpio_params);
devm_kfree(physdev, cs_gpio_params);
return -ENOMEM;
}
static int generic_dsd_config(struct cs35l41_hda *cs35l41, struct device *physdev, int id,
const char *hid)
{
struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;
const struct cs35l41_config *cfg;
struct gpio_desc *cs_gpiod;
struct spi_device *spi;
bool dsd_found;
int ret;
for (cfg = cs35l41_config_table; cfg->ssid; cfg++) {
if (!strcasecmp(cfg->ssid, cs35l41->acpi_subsystem_id))
break;
}
if (!cfg->ssid)
return -ENOENT;
if (!cs35l41->dacpi || cs35l41->dacpi != ACPI_COMPANION(physdev)) {
dev_err(cs35l41->dev, "ACPI Device does not match, cannot override _DSD.\n");
return -ENODEV;
}
dev_info(cs35l41->dev, "Adding DSD properties for %s\n", cs35l41->acpi_subsystem_id);
dsd_found = acpi_dev_has_props(cs35l41->dacpi);
if (!dsd_found) {
ret = cs35l41_add_gpios(cs35l41, physdev, cfg->reset_gpio_index,
cfg->spkid_gpio_index, cfg->cs_gpio_index,
cfg->num_amps);
if (ret) {
dev_err(cs35l41->dev, "Error adding GPIO mapping: %d\n", ret);
return ret;
}
} else if (cfg->reset_gpio_index >= 0 || cfg->spkid_gpio_index >= 0) {
dev_warn(cs35l41->dev, "Cannot add Reset/Speaker ID/SPI CS GPIO Mapping, "
"_DSD already exists.\n");
}
if (cfg->bus == SPI) {
cs35l41->index = id;
#if IS_ENABLED(CONFIG_SPI)
/*
* Manually set the Chip Select for the second amp <cs_gpio_index> in the node.
* This is only supported for systems with 2 amps, since we cannot expand the
* default number of chip selects without using cs-gpios
* The CS GPIO must be set high prior to communicating with the first amp (which
* uses a native chip select), to ensure the second amp does not clash with the
* first.
*/
if (cfg->cs_gpio_index >= 0) {
spi = to_spi_device(cs35l41->dev);
if (cfg->num_amps != 2) {
dev_warn(cs35l41->dev,
"Cannot update SPI CS, Number of Amps (%d) != 2\n",
cfg->num_amps);
} else if (dsd_found) {
dev_warn(cs35l41->dev,
"Cannot update SPI CS, _DSD already exists.\n");
} else {
/*
* This is obtained using driver_gpios, since only one GPIO for CS
* exists, this can be obtained using index 0.
*/
cs_gpiod = gpiod_get_index(physdev, "cs", 0, GPIOD_OUT_LOW);
if (IS_ERR(cs_gpiod)) {
dev_err(cs35l41->dev,
"Unable to get Chip Select GPIO descriptor\n");
return PTR_ERR(cs_gpiod);
}
if (id == 1) {
spi_set_csgpiod(spi, 0, cs_gpiod);
cs35l41->cs_gpio = cs_gpiod;
} else {
gpiod_set_value_cansleep(cs_gpiod, true);
gpiod_put(cs_gpiod);
}
spi_setup(spi);
}
}
#endif
} else {
if (cfg->num_amps > 2)
/*
* i2c addresses for 3/4 amps are used in order: 0x40, 0x41, 0x42, 0x43,
* subtracting 0x40 would give zero-based index
*/
cs35l41->index = id - 0x40;
else
/* i2c addr 0x40 for first amp (always), 0x41/0x42 for 2nd amp */
cs35l41->index = id == 0x40 ? 0 : 1;
}
if (cfg->num_amps == 3)
/* 3 amps means a center channel, so no duplicate channels */
cs35l41->channel_index = 0;
else
/*
* if 4 amps, there are duplicate channels, so they need different indexes
* if 2 amps, no duplicate channels, channel_index would be 0
*/
cs35l41->channel_index = cs35l41->index / 2;
cs35l41->reset_gpio = fwnode_gpiod_get_index(acpi_fwnode_handle(cs35l41->dacpi), "reset",
cs35l41->index, GPIOD_OUT_LOW,
"cs35l41-reset");
cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, cs35l41->index, cfg->num_amps, -1);
hw_cfg->spk_pos = cfg->channel[cs35l41->index];
if (cfg->boost_type == INTERNAL) {
hw_cfg->bst_type = CS35L41_INT_BOOST;
hw_cfg->bst_ind = cfg->boost_ind_nanohenry;
hw_cfg->bst_ipk = cfg->boost_peak_milliamp;
hw_cfg->bst_cap = cfg->boost_cap_microfarad;
hw_cfg->gpio1.func = CS35L41_NOT_USED;
hw_cfg->gpio1.valid = true;
} else {
hw_cfg->bst_type = CS35L41_EXT_BOOST;
hw_cfg->bst_ind = -1;
hw_cfg->bst_ipk = -1;
hw_cfg->bst_cap = -1;
hw_cfg->gpio1.func = CS35l41_VSPK_SWITCH;
hw_cfg->gpio1.valid = true;
}
hw_cfg->gpio2.func = CS35L41_INTERRUPT;
hw_cfg->gpio2.valid = true;
hw_cfg->valid = true;
return 0;
}
/* /*
* Device CLSA010(0/1) doesn't have _DSD so a gpiod_get by the label reset won't work. * Device CLSA010(0/1) doesn't have _DSD so a gpiod_get by the label reset won't work.
...@@ -43,44 +337,6 @@ static int lenovo_legion_no_acpi(struct cs35l41_hda *cs35l41, struct device *phy ...@@ -43,44 +337,6 @@ static int lenovo_legion_no_acpi(struct cs35l41_hda *cs35l41, struct device *phy
return 0; return 0;
} }
/*
* Device 103C89C6 does have _DSD, however it is setup to use the wrong boost type.
* We can override the _DSD to correct the boost type here.
* Since this laptop has valid ACPI, we do not need to handle cs-gpios, since that already exists
* in the ACPI.
*/
static int hp_vision_acpi_fix(struct cs35l41_hda *cs35l41, struct device *physdev, int id,
const char *hid)
{
struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;
dev_info(cs35l41->dev, "Adding DSD properties for %s\n", cs35l41->acpi_subsystem_id);
cs35l41->index = id;
cs35l41->channel_index = 0;
/*
* This system has _DSD, it just contains an error, so we can still get the reset using
* the "reset" label.
*/
cs35l41->reset_gpio = fwnode_gpiod_get_index(acpi_fwnode_handle(cs35l41->dacpi), "reset",
cs35l41->index, GPIOD_OUT_LOW,
"cs35l41-reset");
cs35l41->speaker_id = -ENOENT;
hw_cfg->spk_pos = cs35l41->index ? 0 : 1; // right:left
hw_cfg->gpio1.func = CS35L41_NOT_USED;
hw_cfg->gpio1.valid = true;
hw_cfg->gpio2.func = CS35L41_INTERRUPT;
hw_cfg->gpio2.valid = true;
hw_cfg->bst_type = CS35L41_INT_BOOST;
hw_cfg->bst_ind = 1000;
hw_cfg->bst_ipk = 4500;
hw_cfg->bst_cap = 24;
hw_cfg->valid = true;
return 0;
}
struct cs35l41_prop_model { struct cs35l41_prop_model {
const char *hid; const char *hid;
const char *ssid; const char *ssid;
...@@ -91,7 +347,36 @@ struct cs35l41_prop_model { ...@@ -91,7 +347,36 @@ struct cs35l41_prop_model {
static const struct cs35l41_prop_model cs35l41_prop_model_table[] = { static const struct cs35l41_prop_model cs35l41_prop_model_table[] = {
{ "CLSA0100", NULL, lenovo_legion_no_acpi }, { "CLSA0100", NULL, lenovo_legion_no_acpi },
{ "CLSA0101", NULL, lenovo_legion_no_acpi }, { "CLSA0101", NULL, lenovo_legion_no_acpi },
{ "CSC3551", "103C89C6", hp_vision_acpi_fix }, { "CSC3551", "103C89C6", generic_dsd_config },
{ "CSC3551", "104312AF", generic_dsd_config },
{ "CSC3551", "10431433", generic_dsd_config },
{ "CSC3551", "10431463", generic_dsd_config },
{ "CSC3551", "10431473", generic_dsd_config },
{ "CSC3551", "10431483", generic_dsd_config },
{ "CSC3551", "10431493", generic_dsd_config },
{ "CSC3551", "104314D3", generic_dsd_config },
{ "CSC3551", "104314E3", generic_dsd_config },
{ "CSC3551", "10431503", generic_dsd_config },
{ "CSC3551", "10431533", generic_dsd_config },
{ "CSC3551", "10431573", generic_dsd_config },
{ "CSC3551", "10431663", generic_dsd_config },
{ "CSC3551", "104316D3", generic_dsd_config },
{ "CSC3551", "104316F3", generic_dsd_config },
{ "CSC3551", "104317F3", generic_dsd_config },
{ "CSC3551", "10431863", generic_dsd_config },
{ "CSC3551", "104318D3", generic_dsd_config },
{ "CSC3551", "10431C9F", generic_dsd_config },
{ "CSC3551", "10431CAF", generic_dsd_config },
{ "CSC3551", "10431CCF", generic_dsd_config },
{ "CSC3551", "10431CDF", generic_dsd_config },
{ "CSC3551", "10431CEF", generic_dsd_config },
{ "CSC3551", "10431D1F", generic_dsd_config },
{ "CSC3551", "10431DA2", generic_dsd_config },
{ "CSC3551", "10431E02", generic_dsd_config },
{ "CSC3551", "10431EE2", generic_dsd_config },
{ "CSC3551", "10431F12", generic_dsd_config },
{ "CSC3551", "10431F1F", generic_dsd_config },
{ "CSC3551", "10431F62", generic_dsd_config },
{} {}
}; };
...@@ -104,7 +389,7 @@ int cs35l41_add_dsd_properties(struct cs35l41_hda *cs35l41, struct device *physd ...@@ -104,7 +389,7 @@ int cs35l41_add_dsd_properties(struct cs35l41_hda *cs35l41, struct device *physd
if (!strcmp(model->hid, hid) && if (!strcmp(model->hid, hid) &&
(!model->ssid || (!model->ssid ||
(cs35l41->acpi_subsystem_id && (cs35l41->acpi_subsystem_id &&
!strcmp(model->ssid, cs35l41->acpi_subsystem_id)))) !strcasecmp(model->ssid, cs35l41->acpi_subsystem_id))))
return model->add_prop(cs35l41, physdev, id, hid); return model->add_prop(cs35l41, physdev, id, hid);
} }
......
...@@ -9948,21 +9948,28 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { ...@@ -9948,21 +9948,28 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1313, "Asus K42JZ", ALC269VB_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x1313, "Asus K42JZ", ALC269VB_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC),
SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK), SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK),
SND_PCI_QUIRK(0x1043, 0x1433, "ASUS GX650P", ALC285_FIXUP_ASUS_I2C_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x1433, "ASUS GX650PY/PZ/PV/PU/PYV/PZV/PIV/PVV", ALC285_FIXUP_ASUS_I2C_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x1463, "Asus GA402X", ALC285_FIXUP_ASUS_I2C_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x1463, "Asus GA402X/GA402N", ALC285_FIXUP_ASUS_I2C_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x1473, "ASUS GU604V", ALC285_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x1473, "ASUS GU604VI/VC/VE/VG/VJ/VQ/VU/VV/VY/VZ", ALC285_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x1483, "ASUS GU603V", ALC285_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x1483, "ASUS GU603VQ/VU/VV/VJ/VI", ALC285_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x1493, "ASUS GV601V", ALC285_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x1493, "ASUS GV601VV/VU/VJ/VQ/VI", ALC285_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G614JY/JZ/JG", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS G513PI/PU/PV", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1043, 0x1503, "ASUS G733PY/PZ/PZV/PYV", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A), SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A),
SND_PCI_QUIRK(0x1043, 0x1573, "ASUS GZ301V", ALC285_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x1533, "ASUS GV302XA/XJ/XQ/XU/XV/XI", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1043, 0x1573, "ASUS GZ301VV/VQ/VU/VJ/VA/VC/VE/VVC/VQC/VUC/VJC/VEC/VCC", ALC285_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK), SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK),
SND_PCI_QUIRK(0x1043, 0x1663, "ASUS GU603ZV", ALC285_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x1663, "ASUS GU603ZI/ZJ/ZQ/ZU/ZV", ALC285_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x1683, "ASUS UM3402YAR", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x1043, 0x1683, "ASUS UM3402YAR", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1043, 0x16b2, "ASUS GU603", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x16b2, "ASUS GU603", ALC289_FIXUP_ASUS_GA401),
SND_PCI_QUIRK(0x1043, 0x16d3, "ASUS UX5304VA", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS UX7602VI/BZ", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1740, "ASUS UX430UA", ALC295_FIXUP_ASUS_DACS), SND_PCI_QUIRK(0x1043, 0x1740, "ASUS UX430UA", ALC295_FIXUP_ASUS_DACS),
SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK), SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK),
SND_PCI_QUIRK(0x1043, 0x17f3, "ROG Ally RC71L_RC71L", ALC294_FIXUP_ASUS_ALLY), SND_PCI_QUIRK(0x1043, 0x17f3, "ROG Ally NR2301L/X", ALC294_FIXUP_ASUS_ALLY),
SND_PCI_QUIRK(0x1043, 0x1863, "ASUS UX6404VI/VV", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS), SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS),
SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS UM3504DA", ALC294_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS UM3504DA", ALC294_FIXUP_CS35L41_I2C_2),
...@@ -9987,23 +9994,30 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { ...@@ -9987,23 +9994,30 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1c43, "ASUS UX8406MA", ALC245_FIXUP_CS35L41_SPI_2), SND_PCI_QUIRK(0x1043, 0x1c43, "ASUS UX8406MA", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1c62, "ASUS GU603", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x1c62, "ASUS GU603", ALC289_FIXUP_ASUS_GA401),
SND_PCI_QUIRK(0x1043, 0x1c92, "ASUS ROG Strix G15", ALC285_FIXUP_ASUS_G533Z_PINS), SND_PCI_QUIRK(0x1043, 0x1c92, "ASUS ROG Strix G15", ALC285_FIXUP_ASUS_G533Z_PINS),
SND_PCI_QUIRK(0x1043, 0x1c9f, "ASUS G614JI", ALC285_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x1c9f, "ASUS G614JU/JV/JI", ALC285_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x1caf, "ASUS G634JYR/JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS), SND_PCI_QUIRK(0x1043, 0x1caf, "ASUS G634JY/JZ/JI/JG", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC),
SND_PCI_QUIRK(0x1043, 0x1d1f, "ASUS ROG Strix G17 2023 (G713PV)", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x1043, 0x1ccf, "ASUS G814JU/JV/JI", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1cdf, "ASUS G814JY/JZ/JG", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1cef, "ASUS G834JY/JZ/JI/JG", ALC285_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x1d1f, "ASUS G713PI/PU/PV/PVN", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401),
SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE), SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE),
SND_PCI_QUIRK(0x1043, 0x1da2, "ASUS UP6502ZA/ZD", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402ZA", ALC245_FIXUP_CS35L41_SPI_2), SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402ZA", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS UX3402VA", ALC245_FIXUP_CS35L41_SPI_2), SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS UX3402VA", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1f62, "ASUS UX7602ZM", ALC245_FIXUP_CS35L41_SPI_2), SND_PCI_QUIRK(0x1043, 0x1f62, "ASUS UX7602ZM", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502), SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502),
SND_PCI_QUIRK(0x1043, 0x1e12, "ASUS UM3402", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x1043, 0x1e12, "ASUS UM6702RA/RC", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS), SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS),
SND_PCI_QUIRK(0x1043, 0x1e5e, "ASUS ROG Strix G513", ALC294_FIXUP_ASUS_G513_PINS), SND_PCI_QUIRK(0x1043, 0x1e5e, "ASUS ROG Strix G513", ALC294_FIXUP_ASUS_G513_PINS),
SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401),
SND_PCI_QUIRK(0x1043, 0x1ee2, "ASUS UM3402", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1043, 0x1c52, "ASUS Zephyrus G15 2022", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x1c52, "ASUS Zephyrus G15 2022", ALC289_FIXUP_ASUS_GA401),
SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401),
SND_PCI_QUIRK(0x1043, 0x1f12, "ASUS UM5302", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x1043, 0x1f12, "ASUS UM5302", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1043, 0x1f1f, "ASUS H7604JI/JV/J3D", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1f62, "ASUS UX7602ZM", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1f92, "ASUS ROG Flow X16", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x1f92, "ASUS ROG Flow X16", ALC289_FIXUP_ASUS_GA401),
SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2), SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2),
SND_PCI_QUIRK(0x1043, 0x3a20, "ASUS G614JZR", ALC245_FIXUP_CS35L41_SPI_2), SND_PCI_QUIRK(0x1043, 0x3a20, "ASUS G614JZR", ALC245_FIXUP_CS35L41_SPI_2),
......
...@@ -543,6 +543,10 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context) ...@@ -543,6 +543,10 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK; tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK;
tasdevice_prmg_load(tas_priv, 0); tasdevice_prmg_load(tas_priv, 0);
if (tas_priv->fmw->nr_programs > 0)
tas_priv->cur_prog = 0;
if (tas_priv->fmw->nr_configurations > 0)
tas_priv->cur_conf = 0;
/* If calibrated data occurs error, dsp will still works with default /* If calibrated data occurs error, dsp will still works with default
* calibrated data inside algo. * calibrated data inside algo.
......
...@@ -62,7 +62,7 @@ static struct i2c_driver cs35l45_i2c_driver = { ...@@ -62,7 +62,7 @@ static struct i2c_driver cs35l45_i2c_driver = {
.driver = { .driver = {
.name = "cs35l45", .name = "cs35l45",
.of_match_table = cs35l45_of_match, .of_match_table = cs35l45_of_match,
.pm = &cs35l45_pm_ops, .pm = pm_ptr(&cs35l45_pm_ops),
}, },
.id_table = cs35l45_id_i2c, .id_table = cs35l45_id_i2c,
.probe = cs35l45_i2c_probe, .probe = cs35l45_i2c_probe,
......
...@@ -64,7 +64,7 @@ static struct spi_driver cs35l45_spi_driver = { ...@@ -64,7 +64,7 @@ static struct spi_driver cs35l45_spi_driver = {
.driver = { .driver = {
.name = "cs35l45", .name = "cs35l45",
.of_match_table = cs35l45_of_match, .of_match_table = cs35l45_of_match,
.pm = &cs35l45_pm_ops, .pm = pm_ptr(&cs35l45_pm_ops),
}, },
.id_table = cs35l45_id_spi, .id_table = cs35l45_id_spi,
.probe = cs35l45_spi_probe, .probe = cs35l45_spi_probe,
......
...@@ -947,6 +947,8 @@ static int cs35l45_enter_hibernate(struct cs35l45_private *cs35l45) ...@@ -947,6 +947,8 @@ static int cs35l45_enter_hibernate(struct cs35l45_private *cs35l45)
cs35l45_setup_hibernate(cs35l45); cs35l45_setup_hibernate(cs35l45);
regmap_set_bits(cs35l45->regmap, CS35L45_IRQ1_MASK_2, CS35L45_DSP_VIRT2_MBOX_MASK);
// Don't wait for ACK since bus activity would wake the device // Don't wait for ACK since bus activity would wake the device
regmap_write(cs35l45->regmap, CS35L45_DSP_VIRT1_MBOX_1, CSPL_MBOX_CMD_HIBERNATE); regmap_write(cs35l45->regmap, CS35L45_DSP_VIRT1_MBOX_1, CSPL_MBOX_CMD_HIBERNATE);
...@@ -967,6 +969,8 @@ static int cs35l45_exit_hibernate(struct cs35l45_private *cs35l45) ...@@ -967,6 +969,8 @@ static int cs35l45_exit_hibernate(struct cs35l45_private *cs35l45)
CSPL_MBOX_CMD_OUT_OF_HIBERNATE); CSPL_MBOX_CMD_OUT_OF_HIBERNATE);
if (!ret) { if (!ret) {
dev_dbg(cs35l45->dev, "Wake success at cycle: %d\n", j); dev_dbg(cs35l45->dev, "Wake success at cycle: %d\n", j);
regmap_clear_bits(cs35l45->regmap, CS35L45_IRQ1_MASK_2,
CS35L45_DSP_VIRT2_MBOX_MASK);
return 0; return 0;
} }
usleep_range(100, 200); usleep_range(100, 200);
...@@ -982,7 +986,7 @@ static int cs35l45_exit_hibernate(struct cs35l45_private *cs35l45) ...@@ -982,7 +986,7 @@ static int cs35l45_exit_hibernate(struct cs35l45_private *cs35l45)
return -ETIMEDOUT; return -ETIMEDOUT;
} }
static int __maybe_unused cs35l45_runtime_suspend(struct device *dev) static int cs35l45_runtime_suspend(struct device *dev)
{ {
struct cs35l45_private *cs35l45 = dev_get_drvdata(dev); struct cs35l45_private *cs35l45 = dev_get_drvdata(dev);
...@@ -999,7 +1003,7 @@ static int __maybe_unused cs35l45_runtime_suspend(struct device *dev) ...@@ -999,7 +1003,7 @@ static int __maybe_unused cs35l45_runtime_suspend(struct device *dev)
return 0; return 0;
} }
static int __maybe_unused cs35l45_runtime_resume(struct device *dev) static int cs35l45_runtime_resume(struct device *dev)
{ {
struct cs35l45_private *cs35l45 = dev_get_drvdata(dev); struct cs35l45_private *cs35l45 = dev_get_drvdata(dev);
int ret; int ret;
...@@ -1026,6 +1030,46 @@ static int __maybe_unused cs35l45_runtime_resume(struct device *dev) ...@@ -1026,6 +1030,46 @@ static int __maybe_unused cs35l45_runtime_resume(struct device *dev)
return ret; return ret;
} }
static int cs35l45_sys_suspend(struct device *dev)
{
struct cs35l45_private *cs35l45 = dev_get_drvdata(dev);
dev_dbg(cs35l45->dev, "System suspend, disabling IRQ\n");
disable_irq(cs35l45->irq);
return 0;
}
static int cs35l45_sys_suspend_noirq(struct device *dev)
{
struct cs35l45_private *cs35l45 = dev_get_drvdata(dev);
dev_dbg(cs35l45->dev, "Late system suspend, reenabling IRQ\n");
enable_irq(cs35l45->irq);
return 0;
}
static int cs35l45_sys_resume_noirq(struct device *dev)
{
struct cs35l45_private *cs35l45 = dev_get_drvdata(dev);
dev_dbg(cs35l45->dev, "Early system resume, disabling IRQ\n");
disable_irq(cs35l45->irq);
return 0;
}
static int cs35l45_sys_resume(struct device *dev)
{
struct cs35l45_private *cs35l45 = dev_get_drvdata(dev);
dev_dbg(cs35l45->dev, "System resume, reenabling IRQ\n");
enable_irq(cs35l45->irq);
return 0;
}
static int cs35l45_apply_property_config(struct cs35l45_private *cs35l45) static int cs35l45_apply_property_config(struct cs35l45_private *cs35l45)
{ {
struct device_node *node = cs35l45->dev->of_node; struct device_node *node = cs35l45->dev->of_node;
...@@ -1466,10 +1510,12 @@ void cs35l45_remove(struct cs35l45_private *cs35l45) ...@@ -1466,10 +1510,12 @@ void cs35l45_remove(struct cs35l45_private *cs35l45)
} }
EXPORT_SYMBOL_NS_GPL(cs35l45_remove, SND_SOC_CS35L45); EXPORT_SYMBOL_NS_GPL(cs35l45_remove, SND_SOC_CS35L45);
const struct dev_pm_ops cs35l45_pm_ops = { EXPORT_GPL_DEV_PM_OPS(cs35l45_pm_ops) = {
SET_RUNTIME_PM_OPS(cs35l45_runtime_suspend, cs35l45_runtime_resume, NULL) RUNTIME_PM_OPS(cs35l45_runtime_suspend, cs35l45_runtime_resume, NULL)
SYSTEM_SLEEP_PM_OPS(cs35l45_sys_suspend, cs35l45_sys_resume)
NOIRQ_SYSTEM_SLEEP_PM_OPS(cs35l45_sys_suspend_noirq, cs35l45_sys_resume_noirq)
}; };
EXPORT_SYMBOL_NS_GPL(cs35l45_pm_ops, SND_SOC_CS35L45);
MODULE_DESCRIPTION("ASoC CS35L45 driver"); MODULE_DESCRIPTION("ASoC CS35L45 driver");
MODULE_AUTHOR("James Schulman, Cirrus Logic Inc, <james.schulman@cirrus.com>"); MODULE_AUTHOR("James Schulman, Cirrus Logic Inc, <james.schulman@cirrus.com>");
......
...@@ -237,7 +237,7 @@ int cs42l43_set_jack(struct snd_soc_component *component, ...@@ -237,7 +237,7 @@ int cs42l43_set_jack(struct snd_soc_component *component,
return ret; return ret;
} }
static void cs42l43_start_hs_bias(struct cs42l43_codec *priv, bool force_high) static void cs42l43_start_hs_bias(struct cs42l43_codec *priv, bool type_detect)
{ {
struct cs42l43 *cs42l43 = priv->core; struct cs42l43 *cs42l43 = priv->core;
unsigned int val = 0x3 << CS42L43_HSBIAS_MODE_SHIFT; unsigned int val = 0x3 << CS42L43_HSBIAS_MODE_SHIFT;
...@@ -247,10 +247,11 @@ static void cs42l43_start_hs_bias(struct cs42l43_codec *priv, bool force_high) ...@@ -247,10 +247,11 @@ static void cs42l43_start_hs_bias(struct cs42l43_codec *priv, bool force_high)
regmap_update_bits(cs42l43->regmap, CS42L43_HS2, regmap_update_bits(cs42l43->regmap, CS42L43_HS2,
CS42L43_HS_CLAMP_DISABLE_MASK, CS42L43_HS_CLAMP_DISABLE_MASK); CS42L43_HS_CLAMP_DISABLE_MASK, CS42L43_HS_CLAMP_DISABLE_MASK);
if (!force_high && priv->bias_low) if (!type_detect) {
if (priv->bias_low)
val = 0x2 << CS42L43_HSBIAS_MODE_SHIFT; val = 0x2 << CS42L43_HSBIAS_MODE_SHIFT;
if (priv->bias_sense_ua) { if (priv->bias_sense_ua)
regmap_update_bits(cs42l43->regmap, regmap_update_bits(cs42l43->regmap,
CS42L43_HS_BIAS_SENSE_AND_CLAMP_AUTOCONTROL, CS42L43_HS_BIAS_SENSE_AND_CLAMP_AUTOCONTROL,
CS42L43_HSBIAS_SENSE_EN_MASK | CS42L43_HSBIAS_SENSE_EN_MASK |
......
...@@ -850,7 +850,8 @@ static int hdmi_dai_probe(struct snd_soc_dai *dai) ...@@ -850,7 +850,8 @@ static int hdmi_dai_probe(struct snd_soc_dai *dai)
static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp, static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp,
unsigned int jack_status) unsigned int jack_status)
{ {
if (hcp->jack && jack_status != hcp->jack_status) { if (jack_status != hcp->jack_status) {
if (hcp->jack)
snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT); snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT);
hcp->jack_status = jack_status; hcp->jack_status = jack_status;
} }
...@@ -880,6 +881,13 @@ static int hdmi_codec_set_jack(struct snd_soc_component *component, ...@@ -880,6 +881,13 @@ static int hdmi_codec_set_jack(struct snd_soc_component *component,
if (hcp->hcd.ops->hook_plugged_cb) { if (hcp->hcd.ops->hook_plugged_cb) {
hcp->jack = jack; hcp->jack = jack;
/*
* Report the initial jack status which may have been provided
* by the parent hdmi driver while the hpd hook was registered.
*/
snd_soc_jack_report(jack, hcp->jack_status, SND_JACK_LINEOUT);
return 0; return 0;
} }
......
...@@ -2189,11 +2189,11 @@ int tasdevice_select_tuningprm_cfg(void *context, int prm_no, ...@@ -2189,11 +2189,11 @@ int tasdevice_select_tuningprm_cfg(void *context, int prm_no,
goto out; goto out;
} }
conf = &(tas_fmw->configs[cfg_no]);
for (i = 0, prog_status = 0; i < tas_priv->ndev; i++) { for (i = 0, prog_status = 0; i < tas_priv->ndev; i++) {
if (cfg_info[rca_conf_no]->active_dev & (1 << i)) { if (cfg_info[rca_conf_no]->active_dev & (1 << i)) {
if (tas_priv->tasdevice[i].cur_prog != prm_no if (prm_no >= 0
|| tas_priv->force_fwload_status) { && (tas_priv->tasdevice[i].cur_prog != prm_no
|| tas_priv->force_fwload_status)) {
tas_priv->tasdevice[i].cur_conf = -1; tas_priv->tasdevice[i].cur_conf = -1;
tas_priv->tasdevice[i].is_loading = true; tas_priv->tasdevice[i].is_loading = true;
prog_status++; prog_status++;
...@@ -2228,7 +2228,8 @@ int tasdevice_select_tuningprm_cfg(void *context, int prm_no, ...@@ -2228,7 +2228,8 @@ int tasdevice_select_tuningprm_cfg(void *context, int prm_no,
} }
for (i = 0, status = 0; i < tas_priv->ndev; i++) { for (i = 0, status = 0; i < tas_priv->ndev; i++) {
if (tas_priv->tasdevice[i].cur_conf != cfg_no if (cfg_no >= 0
&& tas_priv->tasdevice[i].cur_conf != cfg_no
&& (cfg_info[rca_conf_no]->active_dev & (1 << i)) && (cfg_info[rca_conf_no]->active_dev & (1 << i))
&& (tas_priv->tasdevice[i].is_loaderr == false)) { && (tas_priv->tasdevice[i].is_loaderr == false)) {
status++; status++;
...@@ -2238,6 +2239,7 @@ int tasdevice_select_tuningprm_cfg(void *context, int prm_no, ...@@ -2238,6 +2239,7 @@ int tasdevice_select_tuningprm_cfg(void *context, int prm_no,
} }
if (status) { if (status) {
conf = &(tas_fmw->configs[cfg_no]);
status = 0; status = 0;
tasdevice_load_data(tas_priv, &(conf->dev_data)); tasdevice_load_data(tas_priv, &(conf->dev_data));
for (i = 0; i < tas_priv->ndev; i++) { for (i = 0; i < tas_priv->ndev; i++) {
...@@ -2281,7 +2283,7 @@ int tasdevice_prmg_load(void *context, int prm_no) ...@@ -2281,7 +2283,7 @@ int tasdevice_prmg_load(void *context, int prm_no)
} }
for (i = 0, prog_status = 0; i < tas_priv->ndev; i++) { for (i = 0, prog_status = 0; i < tas_priv->ndev; i++) {
if (tas_priv->tasdevice[i].cur_prog != prm_no) { if (prm_no >= 0 && tas_priv->tasdevice[i].cur_prog != prm_no) {
tas_priv->tasdevice[i].cur_conf = -1; tas_priv->tasdevice[i].cur_conf = -1;
tas_priv->tasdevice[i].is_loading = true; tas_priv->tasdevice[i].is_loading = true;
prog_status++; prog_status++;
...@@ -2326,7 +2328,7 @@ int tasdevice_prmg_calibdata_load(void *context, int prm_no) ...@@ -2326,7 +2328,7 @@ int tasdevice_prmg_calibdata_load(void *context, int prm_no)
} }
for (i = 0, prog_status = 0; i < tas_priv->ndev; i++) { for (i = 0, prog_status = 0; i < tas_priv->ndev; i++) {
if (tas_priv->tasdevice[i].cur_prog != prm_no) { if (prm_no >= 0 && tas_priv->tasdevice[i].cur_prog != prm_no) {
tas_priv->tasdevice[i].cur_conf = -1; tas_priv->tasdevice[i].cur_conf = -1;
tas_priv->tasdevice[i].is_loading = true; tas_priv->tasdevice[i].is_loading = true;
prog_status++; prog_status++;
......
...@@ -714,6 +714,9 @@ static int fsl_sai_hw_free(struct snd_pcm_substream *substream, ...@@ -714,6 +714,9 @@ static int fsl_sai_hw_free(struct snd_pcm_substream *substream,
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
unsigned int ofs = sai->soc_data->reg_offset; unsigned int ofs = sai->soc_data->reg_offset;
/* Clear xMR to avoid channel swap with mclk_with_tere enabled case */
regmap_write(sai->regmap, FSL_SAI_xMR(tx), 0);
regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs), regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
FSL_SAI_CR3_TRCE_MASK, 0); FSL_SAI_CR3_TRCE_MASK, 0);
......
...@@ -83,6 +83,7 @@ enum { ...@@ -83,6 +83,7 @@ enum {
#define BYT_RT5640_HSMIC2_ON_IN1 BIT(27) #define BYT_RT5640_HSMIC2_ON_IN1 BIT(27)
#define BYT_RT5640_JD_HP_ELITEP_1000G2 BIT(28) #define BYT_RT5640_JD_HP_ELITEP_1000G2 BIT(28)
#define BYT_RT5640_USE_AMCR0F28 BIT(29) #define BYT_RT5640_USE_AMCR0F28 BIT(29)
#define BYT_RT5640_SWAPPED_SPEAKERS BIT(30)
#define BYTCR_INPUT_DEFAULTS \ #define BYTCR_INPUT_DEFAULTS \
(BYT_RT5640_IN3_MAP | \ (BYT_RT5640_IN3_MAP | \
...@@ -157,6 +158,8 @@ static void log_quirks(struct device *dev) ...@@ -157,6 +158,8 @@ static void log_quirks(struct device *dev)
dev_info(dev, "quirk MONO_SPEAKER enabled\n"); dev_info(dev, "quirk MONO_SPEAKER enabled\n");
if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)
dev_info(dev, "quirk NO_SPEAKERS enabled\n"); dev_info(dev, "quirk NO_SPEAKERS enabled\n");
if (byt_rt5640_quirk & BYT_RT5640_SWAPPED_SPEAKERS)
dev_info(dev, "quirk SWAPPED_SPEAKERS enabled\n");
if (byt_rt5640_quirk & BYT_RT5640_LINEOUT) if (byt_rt5640_quirk & BYT_RT5640_LINEOUT)
dev_info(dev, "quirk LINEOUT enabled\n"); dev_info(dev, "quirk LINEOUT enabled\n");
if (byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2) if (byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2)
...@@ -894,6 +897,19 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { ...@@ -894,6 +897,19 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF1 | BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN), BYT_RT5640_MCLK_EN),
}, },
{
/* Medion Lifetab S10346 */
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
/* Above strings are much too generic, also match on BIOS date */
DMI_MATCH(DMI_BIOS_DATE, "10/22/2015"),
},
.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
BYT_RT5640_SWAPPED_SPEAKERS |
BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN),
},
{ /* Mele PCG03 Mini PC */ { /* Mele PCG03 Mini PC */
.matches = { .matches = {
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Mini PC"), DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Mini PC"),
...@@ -1619,11 +1635,11 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) ...@@ -1619,11 +1635,11 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
const char *platform_name; const char *platform_name;
struct acpi_device *adev; struct acpi_device *adev;
struct device *codec_dev; struct device *codec_dev;
const char *cfg_spk;
bool sof_parent; bool sof_parent;
int ret_val = 0; int ret_val = 0;
int dai_index = 0; int dai_index = 0;
int i, cfg_spk; int i, aif;
int aif;
is_bytcr = false; is_bytcr = false;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
...@@ -1783,13 +1799,16 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) ...@@ -1783,13 +1799,16 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
} }
if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) { if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) {
cfg_spk = 0; cfg_spk = "0";
spk_type = "none"; spk_type = "none";
} else if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) { } else if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) {
cfg_spk = 1; cfg_spk = "1";
spk_type = "mono"; spk_type = "mono";
} else if (byt_rt5640_quirk & BYT_RT5640_SWAPPED_SPEAKERS) {
cfg_spk = "swapped";
spk_type = "swapped";
} else { } else {
cfg_spk = 2; cfg_spk = "2";
spk_type = "stereo"; spk_type = "stereo";
} }
...@@ -1804,7 +1823,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) ...@@ -1804,7 +1823,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
headset2_string = " cfg-hs2:in1"; headset2_string = " cfg-hs2:in1";
snprintf(byt_rt5640_components, sizeof(byt_rt5640_components), snprintf(byt_rt5640_components, sizeof(byt_rt5640_components),
"cfg-spk:%d cfg-mic:%s aif:%d%s%s", cfg_spk, "cfg-spk:%s cfg-mic:%s aif:%d%s%s", cfg_spk,
map_name[BYT_RT5640_MAP(byt_rt5640_quirk)], aif, map_name[BYT_RT5640_MAP(byt_rt5640_quirk)], aif,
lineout_string, headset2_string); lineout_string, headset2_string);
byt_rt5640_card.components = byt_rt5640_components; byt_rt5640_card.components = byt_rt5640_components;
......
...@@ -306,13 +306,13 @@ static const struct snd_soc_acpi_adr_device cs35l56_1_adr[] = { ...@@ -306,13 +306,13 @@ static const struct snd_soc_acpi_adr_device cs35l56_1_adr[] = {
.adr = 0x00013701FA355601ull, .adr = 0x00013701FA355601ull,
.num_endpoints = 1, .num_endpoints = 1,
.endpoints = &spk_r_endpoint, .endpoints = &spk_r_endpoint,
.name_prefix = "cs35l56-8" .name_prefix = "AMP8"
}, },
{ {
.adr = 0x00013601FA355601ull, .adr = 0x00013601FA355601ull,
.num_endpoints = 1, .num_endpoints = 1,
.endpoints = &spk_3_endpoint, .endpoints = &spk_3_endpoint,
.name_prefix = "cs35l56-7" .name_prefix = "AMP7"
} }
}; };
...@@ -321,13 +321,13 @@ static const struct snd_soc_acpi_adr_device cs35l56_2_adr[] = { ...@@ -321,13 +321,13 @@ static const struct snd_soc_acpi_adr_device cs35l56_2_adr[] = {
.adr = 0x00023301FA355601ull, .adr = 0x00023301FA355601ull,
.num_endpoints = 1, .num_endpoints = 1,
.endpoints = &spk_l_endpoint, .endpoints = &spk_l_endpoint,
.name_prefix = "cs35l56-1" .name_prefix = "AMP1"
}, },
{ {
.adr = 0x00023201FA355601ull, .adr = 0x00023201FA355601ull,
.num_endpoints = 1, .num_endpoints = 1,
.endpoints = &spk_2_endpoint, .endpoints = &spk_2_endpoint,
.name_prefix = "cs35l56-2" .name_prefix = "AMP2"
} }
}; };
......
...@@ -597,9 +597,6 @@ static struct snd_sof_dsp_ops sof_mt8186_ops = { ...@@ -597,9 +597,6 @@ static struct snd_sof_dsp_ops sof_mt8186_ops = {
static struct snd_sof_of_mach sof_mt8186_machs[] = { static struct snd_sof_of_mach sof_mt8186_machs[] = {
{ {
.compatible = "google,steelix",
.sof_tplg_filename = "sof-mt8186-google-steelix.tplg"
}, {
.compatible = "mediatek,mt8186", .compatible = "mediatek,mt8186",
.sof_tplg_filename = "sof-mt8186.tplg", .sof_tplg_filename = "sof-mt8186.tplg",
}, },
......
...@@ -1387,7 +1387,7 @@ static int snd_usb_motu_microbookii_boot_quirk(struct usb_device *dev) ...@@ -1387,7 +1387,7 @@ static int snd_usb_motu_microbookii_boot_quirk(struct usb_device *dev)
static int snd_usb_motu_m_series_boot_quirk(struct usb_device *dev) static int snd_usb_motu_m_series_boot_quirk(struct usb_device *dev)
{ {
msleep(2000); msleep(4000);
return 0; return 0;
} }
...@@ -1630,7 +1630,7 @@ int snd_usb_apply_boot_quirk_once(struct usb_device *dev, ...@@ -1630,7 +1630,7 @@ int snd_usb_apply_boot_quirk_once(struct usb_device *dev,
unsigned int id) unsigned int id)
{ {
switch (id) { switch (id) {
case USB_ID(0x07fd, 0x0008): /* MOTU M Series */ case USB_ID(0x07fd, 0x0008): /* MOTU M Series, 1st hardware version */
return snd_usb_motu_m_series_boot_quirk(dev); return snd_usb_motu_m_series_boot_quirk(dev);
} }
......
...@@ -138,7 +138,7 @@ static void find_controls(void) ...@@ -138,7 +138,7 @@ static void find_controls(void)
err = snd_ctl_elem_info(card_data->handle, err = snd_ctl_elem_info(card_data->handle,
ctl_data->info); ctl_data->info);
if (err < 0) { if (err < 0) {
ksft_print_msg("%s getting info for %d\n", ksft_print_msg("%s getting info for %s\n",
snd_strerror(err), snd_strerror(err),
ctl_data->name); ctl_data->name);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment