mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 04:34:08 +08:00
Merge branch 'topic/cs35l41' into for-next
Pull CS35L41 codec extension series. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
commit
3abf66a42f
@ -253,6 +253,7 @@ static const char * const snd_pcm_state_names[] = {
|
||||
STATE(DRAINING),
|
||||
STATE(PAUSED),
|
||||
STATE(SUSPENDED),
|
||||
STATE(DISCONNECTED),
|
||||
};
|
||||
|
||||
static const char * const snd_pcm_access_names[] = {
|
||||
|
@ -397,7 +397,6 @@ static int snd_pcmtst_pcm_close(struct snd_pcm_substream *substream)
|
||||
struct pcmtst_buf_iter *v_iter = substream->runtime->private_data;
|
||||
|
||||
timer_shutdown_sync(&v_iter->timer_instance);
|
||||
v_iter->substream = NULL;
|
||||
playback_capture_test = !v_iter->is_buf_corrupted;
|
||||
kfree(v_iter);
|
||||
return 0;
|
||||
@ -435,6 +434,7 @@ static int snd_pcmtst_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
// We can't call timer_shutdown_sync here, as it is forbidden to sleep here
|
||||
v_iter->suspend = true;
|
||||
timer_delete(&v_iter->timer_instance);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -512,12 +512,22 @@ static int snd_pcmtst_ioctl(struct snd_pcm_substream *substream, unsigned int cm
|
||||
return snd_pcm_lib_ioctl(substream, cmd, arg);
|
||||
}
|
||||
|
||||
static int snd_pcmtst_sync_stop(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct pcmtst_buf_iter *v_iter = substream->runtime->private_data;
|
||||
|
||||
timer_delete_sync(&v_iter->timer_instance);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_pcm_ops snd_pcmtst_playback_ops = {
|
||||
.open = snd_pcmtst_pcm_open,
|
||||
.close = snd_pcmtst_pcm_close,
|
||||
.trigger = snd_pcmtst_pcm_trigger,
|
||||
.hw_params = snd_pcmtst_pcm_hw_params,
|
||||
.ioctl = snd_pcmtst_ioctl,
|
||||
.sync_stop = snd_pcmtst_sync_stop,
|
||||
.hw_free = snd_pcmtst_pcm_hw_free,
|
||||
.prepare = snd_pcmtst_pcm_prepare,
|
||||
.pointer = snd_pcmtst_pcm_pointer,
|
||||
@ -530,6 +540,7 @@ static const struct snd_pcm_ops snd_pcmtst_capture_ops = {
|
||||
.hw_params = snd_pcmtst_pcm_hw_params,
|
||||
.hw_free = snd_pcmtst_pcm_hw_free,
|
||||
.ioctl = snd_pcmtst_ioctl,
|
||||
.sync_stop = snd_pcmtst_sync_stop,
|
||||
.prepare = snd_pcmtst_pcm_prepare,
|
||||
.pointer = snd_pcmtst_pcm_pointer,
|
||||
};
|
||||
|
@ -238,7 +238,7 @@ EXPORT_SYMBOL(intel_nhlt_ssp_mclk_mask);
|
||||
|
||||
static struct nhlt_specific_cfg *
|
||||
nhlt_get_specific_cfg(struct device *dev, struct nhlt_fmt *fmt, u8 num_ch,
|
||||
u32 rate, u8 vbps, u8 bps)
|
||||
u32 rate, u8 vbps, u8 bps, bool ignore_vbps)
|
||||
{
|
||||
struct nhlt_fmt_cfg *cfg = fmt->fmt_config;
|
||||
struct wav_fmt *wfmt;
|
||||
@ -255,8 +255,12 @@ nhlt_get_specific_cfg(struct device *dev, struct nhlt_fmt *fmt, u8 num_ch,
|
||||
dev_dbg(dev, "Endpoint format: ch=%d fmt=%d/%d rate=%d\n",
|
||||
wfmt->channels, _vbps, _bps, wfmt->samples_per_sec);
|
||||
|
||||
/*
|
||||
* When looking for exact match of configuration ignore the vbps
|
||||
* from NHLT table when ignore_vbps is true
|
||||
*/
|
||||
if (wfmt->channels == num_ch && wfmt->samples_per_sec == rate &&
|
||||
vbps == _vbps && bps == _bps)
|
||||
(ignore_vbps || vbps == _vbps) && bps == _bps)
|
||||
return &cfg->config;
|
||||
|
||||
cfg = (struct nhlt_fmt_cfg *)(cfg->config.caps + cfg->config.size);
|
||||
@ -289,6 +293,7 @@ intel_nhlt_get_endpoint_blob(struct device *dev, struct nhlt_acpi_table *nhlt,
|
||||
{
|
||||
struct nhlt_specific_cfg *cfg;
|
||||
struct nhlt_endpoint *epnt;
|
||||
bool ignore_vbps = false;
|
||||
struct nhlt_fmt *fmt;
|
||||
int i;
|
||||
|
||||
@ -298,7 +303,26 @@ intel_nhlt_get_endpoint_blob(struct device *dev, struct nhlt_acpi_table *nhlt,
|
||||
dev_dbg(dev, "Looking for configuration:\n");
|
||||
dev_dbg(dev, " vbus_id=%d link_type=%d dir=%d, dev_type=%d\n",
|
||||
bus_id, link_type, dir, dev_type);
|
||||
dev_dbg(dev, " ch=%d fmt=%d/%d rate=%d\n", num_ch, vbps, bps, rate);
|
||||
if (link_type == NHLT_LINK_DMIC && bps == 32 && (vbps == 24 || vbps == 32)) {
|
||||
/*
|
||||
* The DMIC hardware supports only one type of 32 bits sample
|
||||
* size, which is 24 bit sampling on the MSB side and bits[1:0]
|
||||
* are used for indicating the channel number.
|
||||
* It has been observed that some NHLT tables have the vbps
|
||||
* specified as 32 while some uses 24.
|
||||
* The format these variations describe are identical, the
|
||||
* hardware is configured and behaves the same way.
|
||||
* Note: when the samples assumed to be vbps=32 then the 'noise'
|
||||
* introduced by the lower two bits (channel number) have no
|
||||
* real life implication on audio quality.
|
||||
*/
|
||||
dev_dbg(dev,
|
||||
" ch=%d fmt=%d rate=%d (vbps is ignored for DMIC 32bit format)\n",
|
||||
num_ch, bps, rate);
|
||||
ignore_vbps = true;
|
||||
} else {
|
||||
dev_dbg(dev, " ch=%d fmt=%d/%d rate=%d\n", num_ch, vbps, bps, rate);
|
||||
}
|
||||
dev_dbg(dev, "Endpoint count=%d\n", nhlt->endpoint_count);
|
||||
|
||||
epnt = (struct nhlt_endpoint *)nhlt->desc;
|
||||
@ -307,7 +331,8 @@ intel_nhlt_get_endpoint_blob(struct device *dev, struct nhlt_acpi_table *nhlt,
|
||||
if (nhlt_check_ep_match(dev, epnt, bus_id, link_type, dir, dev_type)) {
|
||||
fmt = (struct nhlt_fmt *)(epnt->config.caps + epnt->config.size);
|
||||
|
||||
cfg = nhlt_get_specific_cfg(dev, fmt, num_ch, rate, vbps, bps);
|
||||
cfg = nhlt_get_specific_cfg(dev, fmt, num_ch, rate,
|
||||
vbps, bps, ignore_vbps);
|
||||
if (cfg)
|
||||
return cfg;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <sound/hda_codec.h>
|
||||
#include <sound/soc.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include "hda_local.h"
|
||||
#include "hda_auto_parser.h"
|
||||
#include "hda_jack.h"
|
||||
@ -996,6 +997,11 @@ static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41)
|
||||
__be32 halo_sts;
|
||||
int ret;
|
||||
|
||||
if (cs35l41->bypass_fw) {
|
||||
dev_warn(cs35l41->dev, "Bypassing Firmware.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = cs35l41_init_dsp(cs35l41);
|
||||
if (ret) {
|
||||
dev_warn(cs35l41->dev, "Cannot Initialize Firmware. Error: %d\n", ret);
|
||||
@ -1588,6 +1594,7 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i
|
||||
u32 values[HDA_MAX_COMPONENTS];
|
||||
struct acpi_device *adev;
|
||||
struct device *physdev;
|
||||
struct spi_device *spi;
|
||||
const char *sub;
|
||||
char *property;
|
||||
size_t nval;
|
||||
@ -1610,7 +1617,7 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i
|
||||
ret = cs35l41_add_dsd_properties(cs35l41, physdev, id, hid);
|
||||
if (!ret) {
|
||||
dev_info(cs35l41->dev, "Using extra _DSD properties, bypassing _DSD in ACPI\n");
|
||||
goto put_physdev;
|
||||
goto out;
|
||||
}
|
||||
|
||||
property = "cirrus,dev-index";
|
||||
@ -1701,8 +1708,20 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i
|
||||
hw_cfg->bst_type = CS35L41_EXT_BOOST;
|
||||
|
||||
hw_cfg->valid = true;
|
||||
out:
|
||||
put_device(physdev);
|
||||
|
||||
cs35l41->bypass_fw = false;
|
||||
if (cs35l41->control_bus == SPI) {
|
||||
spi = to_spi_device(cs35l41->dev);
|
||||
if (spi->max_speed_hz < CS35L41_MAX_ACCEPTABLE_SPI_SPEED_HZ) {
|
||||
dev_warn(cs35l41->dev,
|
||||
"SPI speed is too slow to support firmware download: %d Hz.\n",
|
||||
spi->max_speed_hz);
|
||||
cs35l41->bypass_fw = true;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
@ -1711,14 +1730,13 @@ err:
|
||||
hw_cfg->gpio1.valid = false;
|
||||
hw_cfg->gpio2.valid = false;
|
||||
acpi_dev_put(cs35l41->dacpi);
|
||||
put_physdev:
|
||||
put_device(physdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
|
||||
struct regmap *regmap)
|
||||
struct regmap *regmap, enum control_bus control_bus)
|
||||
{
|
||||
unsigned int regid, reg_revid;
|
||||
struct cs35l41_hda *cs35l41;
|
||||
@ -1737,6 +1755,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
|
||||
cs35l41->dev = dev;
|
||||
cs35l41->irq = irq;
|
||||
cs35l41->regmap = regmap;
|
||||
cs35l41->control_bus = control_bus;
|
||||
dev_set_drvdata(dev, cs35l41);
|
||||
|
||||
ret = cs35l41_hda_read_acpi(cs35l41, device_name, id);
|
||||
@ -1826,6 +1845,7 @@ err:
|
||||
if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))
|
||||
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
|
||||
gpiod_put(cs35l41->reset_gpio);
|
||||
gpiod_put(cs35l41->cs_gpio);
|
||||
acpi_dev_put(cs35l41->dacpi);
|
||||
kfree(cs35l41->acpi_subsystem_id);
|
||||
|
||||
@ -1853,6 +1873,7 @@ void cs35l41_hda_remove(struct device *dev)
|
||||
if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))
|
||||
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
|
||||
gpiod_put(cs35l41->reset_gpio);
|
||||
gpiod_put(cs35l41->cs_gpio);
|
||||
kfree(cs35l41->acpi_subsystem_id);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(cs35l41_hda_remove, SND_HDA_SCODEC_CS35L41);
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include <linux/firmware/cirrus/cs_dsp.h>
|
||||
#include <linux/firmware/cirrus/wmfw.h>
|
||||
|
||||
#define CS35L41_MAX_ACCEPTABLE_SPI_SPEED_HZ 1000000
|
||||
|
||||
struct cs35l41_amp_cal_data {
|
||||
u32 calTarget[2];
|
||||
u32 calTime[2];
|
||||
@ -35,8 +37,8 @@ struct cs35l41_amp_efi_data {
|
||||
} __packed;
|
||||
|
||||
enum cs35l41_hda_spk_pos {
|
||||
CS35l41_LEFT,
|
||||
CS35l41_RIGHT,
|
||||
CS35L41_LEFT,
|
||||
CS35L41_RIGHT,
|
||||
};
|
||||
|
||||
enum cs35l41_hda_gpio_function {
|
||||
@ -46,10 +48,16 @@ enum cs35l41_hda_gpio_function {
|
||||
CS35l41_SYNC,
|
||||
};
|
||||
|
||||
enum control_bus {
|
||||
I2C,
|
||||
SPI
|
||||
};
|
||||
|
||||
struct cs35l41_hda {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct gpio_desc *cs_gpio;
|
||||
struct cs35l41_hw_cfg hw_cfg;
|
||||
struct hda_codec *codec;
|
||||
|
||||
@ -73,6 +81,9 @@ struct cs35l41_hda {
|
||||
struct cs_dsp cs_dsp;
|
||||
struct acpi_device *dacpi;
|
||||
bool mute_override;
|
||||
enum control_bus control_bus;
|
||||
bool bypass_fw;
|
||||
|
||||
};
|
||||
|
||||
enum halo_state {
|
||||
@ -84,7 +95,7 @@ enum halo_state {
|
||||
extern const struct dev_pm_ops cs35l41_hda_pm_ops;
|
||||
|
||||
int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
|
||||
struct regmap *regmap);
|
||||
struct regmap *regmap, enum control_bus control_bus);
|
||||
void cs35l41_hda_remove(struct device *dev);
|
||||
int cs35l41_get_speaker_id(struct device *dev, int amp_index, int num_amps, int fixed_gpio_id);
|
||||
|
||||
|
@ -30,7 +30,7 @@ static int cs35l41_hda_i2c_probe(struct i2c_client *clt)
|
||||
return -ENODEV;
|
||||
|
||||
return cs35l41_hda_probe(&clt->dev, device_name, clt->addr, clt->irq,
|
||||
devm_regmap_init_i2c(clt, &cs35l41_regmap_i2c));
|
||||
devm_regmap_init_i2c(clt, &cs35l41_regmap_i2c), I2C);
|
||||
}
|
||||
|
||||
static void cs35l41_hda_i2c_remove(struct i2c_client *clt)
|
||||
|
@ -6,9 +6,303 @@
|
||||
//
|
||||
// Author: Stefan Binding <sbinding@opensource.cirrus.com>
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/string.h>
|
||||
#include "cs35l41_hda_property.h"
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#define MAX_AMPS 4
|
||||
|
||||
struct cs35l41_config {
|
||||
const char *ssid;
|
||||
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[] = {
|
||||
{ "10280B27", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
|
||||
{ "10280B28", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
|
||||
{ "10280BEB", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 0, 0, 0 },
|
||||
{ "10280C4D", 4, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT }, 0, 1, -1, 1000, 4500, 24 },
|
||||
/*
|
||||
* 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", 2, INTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, 0, 0 }, -1, -1, -1, 1000, 4500, 24 },
|
||||
{ "104312AF", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
|
||||
{ "10431433", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
|
||||
{ "10431463", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
|
||||
{ "10431473", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 1000, 4500, 24 },
|
||||
{ "10431483", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 1000, 4500, 24 },
|
||||
{ "10431493", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
|
||||
{ "104314D3", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
|
||||
{ "104314E3", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
|
||||
{ "10431503", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
|
||||
{ "10431533", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
|
||||
{ "10431573", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
|
||||
{ "10431663", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 1000, 4500, 24 },
|
||||
{ "104316D3", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
|
||||
{ "104316F3", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
|
||||
{ "104317F3", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
|
||||
{ "10431863", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
|
||||
{ "104318D3", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
|
||||
{ "10431C9F", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
|
||||
{ "10431CAF", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
|
||||
{ "10431CCF", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
|
||||
{ "10431CDF", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
|
||||
{ "10431CEF", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
|
||||
{ "10431D1F", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
|
||||
{ "10431DA2", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
|
||||
{ "10431E02", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
|
||||
{ "10431EE2", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
|
||||
{ "10431F12", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
|
||||
{ "10431F1F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 0, 0, 0 },
|
||||
{ "10431F62", 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 (cs35l41->control_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.
|
||||
@ -43,44 +337,6 @@ static int lenovo_legion_no_acpi(struct cs35l41_hda *cs35l41, struct device *phy
|
||||
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 {
|
||||
const char *hid;
|
||||
const char *ssid;
|
||||
@ -91,7 +347,40 @@ struct cs35l41_prop_model {
|
||||
static const struct cs35l41_prop_model cs35l41_prop_model_table[] = {
|
||||
{ "CLSA0100", NULL, lenovo_legion_no_acpi },
|
||||
{ "CLSA0101", NULL, lenovo_legion_no_acpi },
|
||||
{ "CSC3551", "103C89C6", hp_vision_acpi_fix },
|
||||
{ "CSC3551", "10280B27", generic_dsd_config },
|
||||
{ "CSC3551", "10280B28", generic_dsd_config },
|
||||
{ "CSC3551", "10280BEB", generic_dsd_config },
|
||||
{ "CSC3551", "10280C4D", generic_dsd_config },
|
||||
{ "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 +393,7 @@ int cs35l41_add_dsd_properties(struct cs35l41_hda *cs35l41, struct device *physd
|
||||
if (!strcmp(model->hid, hid) &&
|
||||
(!model->ssid ||
|
||||
(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);
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ static int cs35l41_hda_spi_probe(struct spi_device *spi)
|
||||
return -ENODEV;
|
||||
|
||||
return cs35l41_hda_probe(&spi->dev, device_name, spi_get_chipselect(spi, 0), spi->irq,
|
||||
devm_regmap_init_spi(spi, &cs35l41_regmap_spi));
|
||||
devm_regmap_init_spi(spi, &cs35l41_regmap_spi), SPI);
|
||||
}
|
||||
|
||||
static void cs35l41_hda_spi_remove(struct spi_device *spi)
|
||||
|
@ -21,6 +21,10 @@ static int cs35l56_hda_spi_probe(struct spi_device *spi)
|
||||
return -ENOMEM;
|
||||
|
||||
cs35l56->base.dev = &spi->dev;
|
||||
|
||||
#ifdef CS35L56_WAKE_HOLD_TIME_US
|
||||
cs35l56->base.can_hibernate = true;
|
||||
#endif
|
||||
cs35l56->base.regmap = devm_regmap_init_spi(spi, &cs35l56_regmap_spi);
|
||||
if (IS_ERR(cs35l56->base.regmap)) {
|
||||
ret = PTR_ERR(cs35l56->base.regmap);
|
||||
|
@ -2242,6 +2242,8 @@ static const struct snd_pci_quirk power_save_denylist[] = {
|
||||
SND_PCI_QUIRK(0x17aa, 0x36a7, "Lenovo C50 All in one", 0),
|
||||
/* https://bugs.launchpad.net/bugs/1821663 */
|
||||
SND_PCI_QUIRK(0x1631, 0xe017, "Packard Bell NEC IMEDIA 5204", 0),
|
||||
/* KONTRON SinglePC may cause a stall at runtime resume */
|
||||
SND_PCI_QUIRK(0x1734, 0x1232, "KONTRON SinglePC", 0),
|
||||
{}
|
||||
};
|
||||
#endif /* CONFIG_PM */
|
||||
|
@ -1993,7 +1993,10 @@ static const struct snd_pci_quirk force_connect_list[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x871a, "HP", 1),
|
||||
SND_PCI_QUIRK(0x103c, 0x8711, "HP", 1),
|
||||
SND_PCI_QUIRK(0x103c, 0x8715, "HP", 1),
|
||||
SND_PCI_QUIRK(0x1043, 0x86ae, "ASUS", 1), /* Z170 PRO */
|
||||
SND_PCI_QUIRK(0x1043, 0x86c7, "ASUS", 1), /* Z170M PLUS */
|
||||
SND_PCI_QUIRK(0x1462, 0xec94, "MS-7C94", 1),
|
||||
SND_PCI_QUIRK(0x8086, 0x2060, "Intel NUC5CPYB", 1),
|
||||
SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", 1),
|
||||
{}
|
||||
};
|
||||
|
@ -1987,6 +1987,7 @@ enum {
|
||||
ALC887_FIXUP_ASUS_AUDIO,
|
||||
ALC887_FIXUP_ASUS_HMIC,
|
||||
ALCS1200A_FIXUP_MIC_VREF,
|
||||
ALC888VD_FIXUP_MIC_100VREF,
|
||||
};
|
||||
|
||||
static void alc889_fixup_coef(struct hda_codec *codec,
|
||||
@ -2540,6 +2541,13 @@ static const struct hda_fixup alc882_fixups[] = {
|
||||
{}
|
||||
}
|
||||
},
|
||||
[ALC888VD_FIXUP_MIC_100VREF] = {
|
||||
.type = HDA_FIXUP_PINCTLS,
|
||||
.v.pins = (const struct hda_pintbl[]) {
|
||||
{ 0x18, PIN_VREF100 }, /* headset mic */
|
||||
{}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
static const struct snd_pci_quirk alc882_fixup_tbl[] = {
|
||||
@ -2609,6 +2617,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF),
|
||||
|
||||
SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
|
||||
SND_PCI_QUIRK(0x10ec, 0x12d8, "iBase Elo Touch", ALC888VD_FIXUP_MIC_100VREF),
|
||||
SND_PCI_QUIRK(0x13fe, 0x1009, "Advantech MIT-W101", ALC886_FIXUP_EAPD),
|
||||
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
|
||||
@ -3256,6 +3265,7 @@ static void alc_disable_headset_jack_key(struct hda_codec *codec)
|
||||
case 0x10ec0230:
|
||||
case 0x10ec0236:
|
||||
case 0x10ec0256:
|
||||
case 0x10ec0257:
|
||||
case 0x19e58326:
|
||||
alc_write_coef_idx(codec, 0x48, 0x0);
|
||||
alc_update_coef_idx(codec, 0x49, 0x0045, 0x0);
|
||||
@ -3285,6 +3295,7 @@ static void alc_enable_headset_jack_key(struct hda_codec *codec)
|
||||
case 0x10ec0230:
|
||||
case 0x10ec0236:
|
||||
case 0x10ec0256:
|
||||
case 0x10ec0257:
|
||||
case 0x19e58326:
|
||||
alc_write_coef_idx(codec, 0x48, 0xd011);
|
||||
alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045);
|
||||
@ -6496,6 +6507,7 @@ static void alc_combo_jack_hp_jd_restart(struct hda_codec *codec)
|
||||
case 0x10ec0236:
|
||||
case 0x10ec0255:
|
||||
case 0x10ec0256:
|
||||
case 0x10ec0257:
|
||||
case 0x19e58326:
|
||||
alc_update_coef_idx(codec, 0x1b, 0x8000, 1 << 15); /* Reset HP JD */
|
||||
alc_update_coef_idx(codec, 0x1b, 0x8000, 0 << 15);
|
||||
@ -6944,6 +6956,11 @@ static void cs35l41_fixup_i2c_two(struct hda_codec *cdc, const struct hda_fixup
|
||||
cs35l41_generic_fixup(cdc, action, "i2c", "CSC3551", 2);
|
||||
}
|
||||
|
||||
static void cs35l41_fixup_i2c_four(struct hda_codec *cdc, const struct hda_fixup *fix, int action)
|
||||
{
|
||||
cs35l41_generic_fixup(cdc, action, "i2c", "CSC3551", 4);
|
||||
}
|
||||
|
||||
static void cs35l41_fixup_spi_two(struct hda_codec *codec, const struct hda_fixup *fix, int action)
|
||||
{
|
||||
cs35l41_generic_fixup(codec, action, "spi", "CSC3551", 2);
|
||||
@ -7429,6 +7446,7 @@ enum {
|
||||
ALC287_FIXUP_LEGION_16ACHG6,
|
||||
ALC287_FIXUP_CS35L41_I2C_2,
|
||||
ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED,
|
||||
ALC287_FIXUP_CS35L41_I2C_4,
|
||||
ALC245_FIXUP_CS35L41_SPI_2,
|
||||
ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED,
|
||||
ALC245_FIXUP_CS35L41_SPI_4,
|
||||
@ -9415,6 +9433,10 @@ static const struct hda_fixup alc269_fixups[] = {
|
||||
.chained = true,
|
||||
.chain_id = ALC285_FIXUP_HP_MUTE_LED,
|
||||
},
|
||||
[ALC287_FIXUP_CS35L41_I2C_4] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = cs35l41_fixup_i2c_four,
|
||||
},
|
||||
[ALC245_FIXUP_CS35L41_SPI_2] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = cs35l41_fixup_spi_two,
|
||||
@ -9691,8 +9713,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1028, 0x0a9e, "Dell Latitude 5430", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1028, 0x0b19, "Dell XPS 15 9520", ALC289_FIXUP_DUAL_SPK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0b1a, "Dell Precision 5570", ALC289_FIXUP_DUAL_SPK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0b27, "Dell", ALC245_FIXUP_CS35L41_SPI_2),
|
||||
SND_PCI_QUIRK(0x1028, 0x0b28, "Dell", ALC245_FIXUP_CS35L41_SPI_2),
|
||||
SND_PCI_QUIRK(0x1028, 0x0b37, "Dell Inspiron 16 Plus 7620 2-in-1", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS),
|
||||
SND_PCI_QUIRK(0x1028, 0x0b71, "Dell Inspiron 16 Plus 7620", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS),
|
||||
SND_PCI_QUIRK(0x1028, 0x0beb, "Dell XPS 15 9530 (2023)", ALC289_FIXUP_DELL_CS35L41_SPI_2),
|
||||
SND_PCI_QUIRK(0x1028, 0x0c03, "Dell Precision 5340", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1028, 0x0c19, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS),
|
||||
SND_PCI_QUIRK(0x1028, 0x0c1a, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS),
|
||||
@ -9700,6 +9725,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1028, 0x0c1c, "Dell Precision 3540", ALC236_FIXUP_DELL_DUAL_CODECS),
|
||||
SND_PCI_QUIRK(0x1028, 0x0c1d, "Dell Precision 3440", ALC236_FIXUP_DELL_DUAL_CODECS),
|
||||
SND_PCI_QUIRK(0x1028, 0x0c1e, "Dell Precision 3540", ALC236_FIXUP_DELL_DUAL_CODECS),
|
||||
SND_PCI_QUIRK(0x1028, 0x0c4d, "Dell", ALC287_FIXUP_CS35L41_I2C_4),
|
||||
SND_PCI_QUIRK(0x1028, 0x0cbd, "Dell Oasis 13 CS MTL-U", ALC289_FIXUP_DELL_CS35L41_SPI_2),
|
||||
SND_PCI_QUIRK(0x1028, 0x0cbe, "Dell Oasis 13 2-IN-1 MTL-U", ALC289_FIXUP_DELL_CS35L41_SPI_2),
|
||||
SND_PCI_QUIRK(0x1028, 0x0cbf, "Dell Oasis 13 Low Weight MTU-L", ALC289_FIXUP_DELL_CS35L41_SPI_2),
|
||||
@ -9782,6 +9808,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
|
||||
SND_PCI_QUIRK(0x103c, 0x841c, "HP Pavilion 15-CK0xx", ALC269_FIXUP_HP_MUTE_LED_MIC3),
|
||||
SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
|
||||
SND_PCI_QUIRK(0x103c, 0x84ae, "HP 15-db0403ng", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
|
||||
SND_PCI_QUIRK(0x103c, 0x84da, "HP OMEN dc0019-ur", ALC295_FIXUP_HP_OMEN),
|
||||
SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
|
||||
SND_PCI_QUIRK(0x103c, 0x8519, "HP Spectre x360 15-df0xxx", ALC285_FIXUP_HP_SPECTRE_X360),
|
||||
@ -9934,23 +9961,31 @@ 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, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC),
|
||||
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, 0x1463, "Asus GA402X", ALC285_FIXUP_ASUS_I2C_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x1473, "ASUS GU604V", ALC285_FIXUP_ASUS_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x1483, "ASUS GU603V", ALC285_FIXUP_ASUS_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x1493, "ASUS GV601V", ALC285_FIXUP_ASUS_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/GA402N", ALC285_FIXUP_ASUS_I2C_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 GU603VQ/VU/VV/VJ/VI", 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, 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, 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, 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, 0x16f3, "ASUS UX7602VI/BZ", ALC245_FIXUP_CS35L41_SPI_2),
|
||||
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, 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, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS UM3504DA", ALC294_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x1043, 0x18f1, "Asus FX505DT", ALC256_FIXUP_ASUS_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x194e, "ASUS UX563FD", ALC294_FIXUP_ASUS_HPE),
|
||||
SND_PCI_QUIRK(0x1043, 0x1970, "ASUS UX550VE", ALC289_FIXUP_ASUS_GA401),
|
||||
@ -9972,23 +10007,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, 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, 0x1c9f, "ASUS G614JI", ALC285_FIXUP_ASUS_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x1caf, "ASUS G634JYR/JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
|
||||
SND_PCI_QUIRK(0x1043, 0x1c9f, "ASUS G614JU/JV/JI", ALC285_FIXUP_ASUS_HEADSET_MIC),
|
||||
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, 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, 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, 0x16a3, "ASUS UX3402VA", 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, 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, 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, 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, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401),
|
||||
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, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2),
|
||||
SND_PCI_QUIRK(0x1043, 0x3a20, "ASUS G614JZR", ALC245_FIXUP_CS35L41_SPI_2),
|
||||
@ -10192,6 +10234,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x17aa, 0x387d, "Yoga S780-16 pro Quad AAC", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x17aa, 0x387e, "Yoga S780-16 pro Quad YC", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3881, "YB9 dual power mode2 YC", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3882, "Lenovo Yoga Pro 7 14APH8", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3884, "Y780 YG DUAL", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3886, "Y780 VECO DUAL", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x17aa, 0x38a7, "Y780P AMD YG dual", ALC287_FIXUP_TAS2781_I2C),
|
||||
@ -10259,6 +10302,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", ALC256_FIXUP_INTEL_NUC10),
|
||||
SND_PCI_QUIRK(0x8086, 0x3038, "Intel NUC 13", ALC295_FIXUP_CHROME_BOOK),
|
||||
SND_PCI_QUIRK(0xf111, 0x0001, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0xf111, 0x0005, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0xf111, 0x0006, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
|
||||
|
||||
#if 0
|
||||
/* Below is a quirk table taken from the old code.
|
||||
@ -12184,6 +12229,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x17aa, 0x32f7, "Lenovo ThinkCentre M90", ALC897_FIXUP_HEADSET_MIC_PIN),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3321, "Lenovo ThinkCentre M70 Gen4", ALC897_FIXUP_HEADSET_MIC_PIN),
|
||||
SND_PCI_QUIRK(0x17aa, 0x331b, "Lenovo ThinkCentre M90 Gen4", ALC897_FIXUP_HEADSET_MIC_PIN),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3364, "Lenovo ThinkCentre M90 Gen5", ALC897_FIXUP_HEADSET_MIC_PIN),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3742, "Lenovo TianYi510Pro-14IOB", ALC897_FIXUP_HEADSET_MIC_PIN2),
|
||||
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
|
||||
|
@ -65,6 +65,15 @@ enum calib_data {
|
||||
CALIB_MAX
|
||||
};
|
||||
|
||||
struct tas2781_hda {
|
||||
struct device *dev;
|
||||
struct tasdevice_priv *priv;
|
||||
struct snd_kcontrol *dsp_prog_ctl;
|
||||
struct snd_kcontrol *dsp_conf_ctl;
|
||||
struct snd_kcontrol *prof_ctl;
|
||||
struct snd_kcontrol *snd_ctls[3];
|
||||
};
|
||||
|
||||
static int tas2781_get_i2c_res(struct acpi_resource *ares, void *data)
|
||||
{
|
||||
struct tasdevice_priv *tas_priv = data;
|
||||
@ -125,26 +134,26 @@ err:
|
||||
|
||||
static void tas2781_hda_playback_hook(struct device *dev, int action)
|
||||
{
|
||||
struct tasdevice_priv *tas_priv = dev_get_drvdata(dev);
|
||||
struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
|
||||
|
||||
dev_dbg(tas_priv->dev, "%s: action = %d\n", __func__, action);
|
||||
dev_dbg(tas_hda->dev, "%s: action = %d\n", __func__, action);
|
||||
switch (action) {
|
||||
case HDA_GEN_PCM_ACT_OPEN:
|
||||
pm_runtime_get_sync(dev);
|
||||
mutex_lock(&tas_priv->codec_lock);
|
||||
tasdevice_tuning_switch(tas_priv, 0);
|
||||
mutex_unlock(&tas_priv->codec_lock);
|
||||
mutex_lock(&tas_hda->priv->codec_lock);
|
||||
tasdevice_tuning_switch(tas_hda->priv, 0);
|
||||
mutex_unlock(&tas_hda->priv->codec_lock);
|
||||
break;
|
||||
case HDA_GEN_PCM_ACT_CLOSE:
|
||||
mutex_lock(&tas_priv->codec_lock);
|
||||
tasdevice_tuning_switch(tas_priv, 1);
|
||||
mutex_unlock(&tas_priv->codec_lock);
|
||||
mutex_lock(&tas_hda->priv->codec_lock);
|
||||
tasdevice_tuning_switch(tas_hda->priv, 1);
|
||||
mutex_unlock(&tas_hda->priv->codec_lock);
|
||||
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
break;
|
||||
default:
|
||||
dev_dbg(tas_priv->dev, "Playback action not supported: %d\n",
|
||||
dev_dbg(tas_hda->dev, "Playback action not supported: %d\n",
|
||||
action);
|
||||
break;
|
||||
}
|
||||
@ -421,9 +430,9 @@ static void tas2781_apply_calib(struct tasdevice_priv *tas_priv)
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the calibrate data, including speaker impedance, f0, etc, into algo.
|
||||
/* Update the calibration data, including speaker impedance, f0, etc, into algo.
|
||||
* Calibrate data is done by manufacturer in the factory. These data are used
|
||||
* by Algo for calucating the speaker temperature, speaker membrance excursion
|
||||
* by Algo for calculating the speaker temperature, speaker membrane excursion
|
||||
* and f0 in real time during playback.
|
||||
*/
|
||||
static int tas2781_save_calibration(struct tasdevice_priv *tas_priv)
|
||||
@ -455,9 +464,9 @@ static int tas2781_save_calibration(struct tasdevice_priv *tas_priv)
|
||||
status = efi.get_variable(efi_name, &efi_guid, &attr,
|
||||
&tas_priv->cali_data.total_sz,
|
||||
tas_priv->cali_data.data);
|
||||
if (status != EFI_SUCCESS)
|
||||
return -EINVAL;
|
||||
}
|
||||
if (status != EFI_SUCCESS)
|
||||
return -EINVAL;
|
||||
|
||||
tmp_val = (unsigned int *)tas_priv->cali_data.data;
|
||||
|
||||
@ -477,9 +486,28 @@ static int tas2781_save_calibration(struct tasdevice_priv *tas_priv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tas2781_hda_remove_controls(struct tas2781_hda *tas_hda)
|
||||
{
|
||||
struct hda_codec *codec = tas_hda->priv->codec;
|
||||
|
||||
if (tas_hda->dsp_prog_ctl)
|
||||
snd_ctl_remove(codec->card, tas_hda->dsp_prog_ctl);
|
||||
|
||||
if (tas_hda->dsp_conf_ctl)
|
||||
snd_ctl_remove(codec->card, tas_hda->dsp_conf_ctl);
|
||||
|
||||
for (int i = ARRAY_SIZE(tas_hda->snd_ctls) - 1; i >= 0; i--)
|
||||
if (tas_hda->snd_ctls[i])
|
||||
snd_ctl_remove(codec->card, tas_hda->snd_ctls[i]);
|
||||
|
||||
if (tas_hda->prof_ctl)
|
||||
snd_ctl_remove(codec->card, tas_hda->prof_ctl);
|
||||
}
|
||||
|
||||
static void tasdev_fw_ready(const struct firmware *fmw, void *context)
|
||||
{
|
||||
struct tasdevice_priv *tas_priv = context;
|
||||
struct tas2781_hda *tas_hda = dev_get_drvdata(tas_priv->dev);
|
||||
struct hda_codec *codec = tas_priv->codec;
|
||||
int i, ret;
|
||||
|
||||
@ -490,8 +518,8 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = snd_ctl_add(codec->card,
|
||||
snd_ctl_new1(&tas2781_prof_ctrl, tas_priv));
|
||||
tas_hda->prof_ctl = snd_ctl_new1(&tas2781_prof_ctrl, tas_priv);
|
||||
ret = snd_ctl_add(codec->card, tas_hda->prof_ctl);
|
||||
if (ret) {
|
||||
dev_err(tas_priv->dev,
|
||||
"Failed to add KControl %s = %d\n",
|
||||
@ -500,8 +528,9 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tas2781_snd_controls); i++) {
|
||||
ret = snd_ctl_add(codec->card,
|
||||
snd_ctl_new1(&tas2781_snd_controls[i], tas_priv));
|
||||
tas_hda->snd_ctls[i] = snd_ctl_new1(&tas2781_snd_controls[i],
|
||||
tas_priv);
|
||||
ret = snd_ctl_add(codec->card, tas_hda->snd_ctls[i]);
|
||||
if (ret) {
|
||||
dev_err(tas_priv->dev,
|
||||
"Failed to add KControl %s = %d\n",
|
||||
@ -523,8 +552,9 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = snd_ctl_add(codec->card,
|
||||
snd_ctl_new1(&tas2781_dsp_prog_ctrl, tas_priv));
|
||||
tas_hda->dsp_prog_ctl = snd_ctl_new1(&tas2781_dsp_prog_ctrl,
|
||||
tas_priv);
|
||||
ret = snd_ctl_add(codec->card, tas_hda->dsp_prog_ctl);
|
||||
if (ret) {
|
||||
dev_err(tas_priv->dev,
|
||||
"Failed to add KControl %s = %d\n",
|
||||
@ -532,8 +562,9 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = snd_ctl_add(codec->card,
|
||||
snd_ctl_new1(&tas2781_dsp_conf_ctrl, tas_priv));
|
||||
tas_hda->dsp_conf_ctl = snd_ctl_new1(&tas2781_dsp_conf_ctrl,
|
||||
tas_priv);
|
||||
ret = snd_ctl_add(codec->card, tas_hda->dsp_conf_ctl);
|
||||
if (ret) {
|
||||
dev_err(tas_priv->dev,
|
||||
"Failed to add KControl %s = %d\n",
|
||||
@ -543,6 +574,10 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
|
||||
|
||||
tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK;
|
||||
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
|
||||
* calibrated data inside algo.
|
||||
@ -550,32 +585,27 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
|
||||
tas2781_save_calibration(tas_priv);
|
||||
|
||||
out:
|
||||
if (tas_priv->fw_state == TASDEVICE_DSP_FW_FAIL) {
|
||||
/*If DSP FW fail, kcontrol won't be created */
|
||||
tasdevice_config_info_remove(tas_priv);
|
||||
tasdevice_dsp_remove(tas_priv);
|
||||
}
|
||||
mutex_unlock(&tas_priv->codec_lock);
|
||||
mutex_unlock(&tas_hda->priv->codec_lock);
|
||||
if (fmw)
|
||||
release_firmware(fmw);
|
||||
pm_runtime_mark_last_busy(tas_priv->dev);
|
||||
pm_runtime_put_autosuspend(tas_priv->dev);
|
||||
pm_runtime_mark_last_busy(tas_hda->dev);
|
||||
pm_runtime_put_autosuspend(tas_hda->dev);
|
||||
}
|
||||
|
||||
static int tas2781_hda_bind(struct device *dev, struct device *master,
|
||||
void *master_data)
|
||||
{
|
||||
struct tasdevice_priv *tas_priv = dev_get_drvdata(dev);
|
||||
struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
|
||||
struct hda_component *comps = master_data;
|
||||
struct hda_codec *codec;
|
||||
unsigned int subid;
|
||||
int ret;
|
||||
|
||||
if (!comps || tas_priv->index < 0 ||
|
||||
tas_priv->index >= HDA_MAX_COMPONENTS)
|
||||
if (!comps || tas_hda->priv->index < 0 ||
|
||||
tas_hda->priv->index >= HDA_MAX_COMPONENTS)
|
||||
return -EINVAL;
|
||||
|
||||
comps = &comps[tas_priv->index];
|
||||
comps = &comps[tas_hda->priv->index];
|
||||
if (comps->dev)
|
||||
return -EBUSY;
|
||||
|
||||
@ -584,10 +614,10 @@ static int tas2781_hda_bind(struct device *dev, struct device *master,
|
||||
|
||||
switch (subid) {
|
||||
case 0x17aa:
|
||||
tas_priv->catlog_id = LENOVO;
|
||||
tas_hda->priv->catlog_id = LENOVO;
|
||||
break;
|
||||
default:
|
||||
tas_priv->catlog_id = OTHERS;
|
||||
tas_hda->priv->catlog_id = OTHERS;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -597,7 +627,7 @@ static int tas2781_hda_bind(struct device *dev, struct device *master,
|
||||
|
||||
strscpy(comps->name, dev_name(dev), sizeof(comps->name));
|
||||
|
||||
ret = tascodec_init(tas_priv, codec, tasdev_fw_ready);
|
||||
ret = tascodec_init(tas_hda->priv, codec, tasdev_fw_ready);
|
||||
if (!ret)
|
||||
comps->playback_hook = tas2781_hda_playback_hook;
|
||||
|
||||
@ -610,16 +640,22 @@ static int tas2781_hda_bind(struct device *dev, struct device *master,
|
||||
static void tas2781_hda_unbind(struct device *dev,
|
||||
struct device *master, void *master_data)
|
||||
{
|
||||
struct tasdevice_priv *tas_priv = dev_get_drvdata(dev);
|
||||
struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
|
||||
struct hda_component *comps = master_data;
|
||||
comps = &comps[tas_hda->priv->index];
|
||||
|
||||
if (comps[tas_priv->index].dev == dev)
|
||||
memset(&comps[tas_priv->index], 0, sizeof(*comps));
|
||||
if (comps->dev == dev) {
|
||||
comps->dev = NULL;
|
||||
memset(comps->name, 0, sizeof(comps->name));
|
||||
comps->playback_hook = NULL;
|
||||
}
|
||||
|
||||
tasdevice_config_info_remove(tas_priv);
|
||||
tasdevice_dsp_remove(tas_priv);
|
||||
tas2781_hda_remove_controls(tas_hda);
|
||||
|
||||
tas_priv->fw_state = TASDEVICE_DSP_FW_PENDING;
|
||||
tasdevice_config_info_remove(tas_hda->priv);
|
||||
tasdevice_dsp_remove(tas_hda->priv);
|
||||
|
||||
tas_hda->priv->fw_state = TASDEVICE_DSP_FW_PENDING;
|
||||
}
|
||||
|
||||
static const struct component_ops tas2781_hda_comp_ops = {
|
||||
@ -629,21 +665,21 @@ static const struct component_ops tas2781_hda_comp_ops = {
|
||||
|
||||
static void tas2781_hda_remove(struct device *dev)
|
||||
{
|
||||
struct tasdevice_priv *tas_priv = dev_get_drvdata(dev);
|
||||
struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
|
||||
|
||||
pm_runtime_get_sync(tas_priv->dev);
|
||||
pm_runtime_disable(tas_priv->dev);
|
||||
pm_runtime_get_sync(tas_hda->dev);
|
||||
pm_runtime_disable(tas_hda->dev);
|
||||
|
||||
component_del(tas_priv->dev, &tas2781_hda_comp_ops);
|
||||
component_del(tas_hda->dev, &tas2781_hda_comp_ops);
|
||||
|
||||
pm_runtime_put_noidle(tas_priv->dev);
|
||||
pm_runtime_put_noidle(tas_hda->dev);
|
||||
|
||||
tasdevice_remove(tas_priv);
|
||||
tasdevice_remove(tas_hda->priv);
|
||||
}
|
||||
|
||||
static int tas2781_hda_i2c_probe(struct i2c_client *clt)
|
||||
{
|
||||
struct tasdevice_priv *tas_priv;
|
||||
struct tas2781_hda *tas_hda;
|
||||
const char *device_name;
|
||||
int ret;
|
||||
|
||||
@ -652,37 +688,44 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt)
|
||||
else
|
||||
return -ENODEV;
|
||||
|
||||
tas_priv = tasdevice_kzalloc(clt);
|
||||
if (!tas_priv)
|
||||
tas_hda = devm_kzalloc(&clt->dev, sizeof(*tas_hda), GFP_KERNEL);
|
||||
if (!tas_hda)
|
||||
return -ENOMEM;
|
||||
|
||||
tas_priv->irq_info.irq = clt->irq;
|
||||
ret = tas2781_read_acpi(tas_priv, device_name);
|
||||
dev_set_drvdata(&clt->dev, tas_hda);
|
||||
tas_hda->dev = &clt->dev;
|
||||
|
||||
tas_hda->priv = tasdevice_kzalloc(clt);
|
||||
if (!tas_hda->priv)
|
||||
return -ENOMEM;
|
||||
|
||||
tas_hda->priv->irq_info.irq = clt->irq;
|
||||
ret = tas2781_read_acpi(tas_hda->priv, device_name);
|
||||
if (ret)
|
||||
return dev_err_probe(tas_priv->dev, ret,
|
||||
return dev_err_probe(tas_hda->dev, ret,
|
||||
"Platform not supported\n");
|
||||
|
||||
ret = tasdevice_init(tas_priv);
|
||||
ret = tasdevice_init(tas_hda->priv);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
pm_runtime_set_autosuspend_delay(tas_priv->dev, 3000);
|
||||
pm_runtime_use_autosuspend(tas_priv->dev);
|
||||
pm_runtime_mark_last_busy(tas_priv->dev);
|
||||
pm_runtime_set_active(tas_priv->dev);
|
||||
pm_runtime_get_noresume(tas_priv->dev);
|
||||
pm_runtime_enable(tas_priv->dev);
|
||||
pm_runtime_set_autosuspend_delay(tas_hda->dev, 3000);
|
||||
pm_runtime_use_autosuspend(tas_hda->dev);
|
||||
pm_runtime_mark_last_busy(tas_hda->dev);
|
||||
pm_runtime_set_active(tas_hda->dev);
|
||||
pm_runtime_get_noresume(tas_hda->dev);
|
||||
pm_runtime_enable(tas_hda->dev);
|
||||
|
||||
pm_runtime_put_autosuspend(tas_priv->dev);
|
||||
pm_runtime_put_autosuspend(tas_hda->dev);
|
||||
|
||||
ret = component_add(tas_priv->dev, &tas2781_hda_comp_ops);
|
||||
tas2781_reset(tas_hda->priv);
|
||||
|
||||
ret = component_add(tas_hda->dev, &tas2781_hda_comp_ops);
|
||||
if (ret) {
|
||||
dev_err(tas_priv->dev, "Register component failed: %d\n", ret);
|
||||
pm_runtime_disable(tas_priv->dev);
|
||||
goto err;
|
||||
dev_err(tas_hda->dev, "Register component failed: %d\n", ret);
|
||||
pm_runtime_disable(tas_hda->dev);
|
||||
}
|
||||
|
||||
tas2781_reset(tas_priv);
|
||||
err:
|
||||
if (ret)
|
||||
tas2781_hda_remove(&clt->dev);
|
||||
@ -696,81 +739,65 @@ static void tas2781_hda_i2c_remove(struct i2c_client *clt)
|
||||
|
||||
static int tas2781_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct tasdevice_priv *tas_priv = dev_get_drvdata(dev);
|
||||
struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
dev_dbg(tas_priv->dev, "Runtime Suspend\n");
|
||||
dev_dbg(tas_hda->dev, "Runtime Suspend\n");
|
||||
|
||||
mutex_lock(&tas_priv->codec_lock);
|
||||
mutex_lock(&tas_hda->priv->codec_lock);
|
||||
|
||||
if (tas_priv->playback_started) {
|
||||
tasdevice_tuning_switch(tas_priv, 1);
|
||||
tas_priv->playback_started = false;
|
||||
if (tas_hda->priv->playback_started) {
|
||||
tasdevice_tuning_switch(tas_hda->priv, 1);
|
||||
tas_hda->priv->playback_started = false;
|
||||
}
|
||||
|
||||
for (i = 0; i < tas_priv->ndev; i++) {
|
||||
tas_priv->tasdevice[i].cur_book = -1;
|
||||
tas_priv->tasdevice[i].cur_prog = -1;
|
||||
tas_priv->tasdevice[i].cur_conf = -1;
|
||||
for (i = 0; i < tas_hda->priv->ndev; i++) {
|
||||
tas_hda->priv->tasdevice[i].cur_book = -1;
|
||||
tas_hda->priv->tasdevice[i].cur_prog = -1;
|
||||
tas_hda->priv->tasdevice[i].cur_conf = -1;
|
||||
}
|
||||
|
||||
regcache_cache_only(tas_priv->regmap, true);
|
||||
regcache_mark_dirty(tas_priv->regmap);
|
||||
|
||||
mutex_unlock(&tas_priv->codec_lock);
|
||||
mutex_unlock(&tas_hda->priv->codec_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tas2781_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct tasdevice_priv *tas_priv = dev_get_drvdata(dev);
|
||||
struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
|
||||
unsigned long calib_data_sz =
|
||||
tas_priv->ndev * TASDEVICE_SPEAKER_CALIBRATION_SIZE;
|
||||
int ret;
|
||||
tas_hda->priv->ndev * TASDEVICE_SPEAKER_CALIBRATION_SIZE;
|
||||
|
||||
dev_dbg(tas_priv->dev, "Runtime Resume\n");
|
||||
dev_dbg(tas_hda->dev, "Runtime Resume\n");
|
||||
|
||||
mutex_lock(&tas_priv->codec_lock);
|
||||
mutex_lock(&tas_hda->priv->codec_lock);
|
||||
|
||||
regcache_cache_only(tas_priv->regmap, false);
|
||||
ret = regcache_sync(tas_priv->regmap);
|
||||
if (ret) {
|
||||
dev_err(tas_priv->dev,
|
||||
"Failed to restore register cache: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
tasdevice_prmg_load(tas_priv, tas_priv->cur_prog);
|
||||
tasdevice_prmg_load(tas_hda->priv, tas_hda->priv->cur_prog);
|
||||
|
||||
/* If calibrated data occurs error, dsp will still works with default
|
||||
* calibrated data inside algo.
|
||||
*/
|
||||
if (tas_priv->cali_data.total_sz > calib_data_sz)
|
||||
tas2781_apply_calib(tas_priv);
|
||||
if (tas_hda->priv->cali_data.total_sz > calib_data_sz)
|
||||
tas2781_apply_calib(tas_hda->priv);
|
||||
|
||||
out:
|
||||
mutex_unlock(&tas_priv->codec_lock);
|
||||
mutex_unlock(&tas_hda->priv->codec_lock);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tas2781_system_suspend(struct device *dev)
|
||||
{
|
||||
struct tasdevice_priv *tas_priv = dev_get_drvdata(dev);
|
||||
struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
dev_dbg(tas_priv->dev, "System Suspend\n");
|
||||
dev_dbg(tas_hda->priv->dev, "System Suspend\n");
|
||||
|
||||
ret = pm_runtime_force_suspend(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Shutdown chip before system suspend */
|
||||
regcache_cache_only(tas_priv->regmap, false);
|
||||
tasdevice_tuning_switch(tas_priv, 1);
|
||||
regcache_cache_only(tas_priv->regmap, true);
|
||||
regcache_mark_dirty(tas_priv->regmap);
|
||||
tasdevice_tuning_switch(tas_hda->priv, 1);
|
||||
|
||||
/*
|
||||
* Reset GPIO may be shared, so cannot reset here.
|
||||
@ -781,33 +808,33 @@ static int tas2781_system_suspend(struct device *dev)
|
||||
|
||||
static int tas2781_system_resume(struct device *dev)
|
||||
{
|
||||
struct tasdevice_priv *tas_priv = dev_get_drvdata(dev);
|
||||
struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
|
||||
unsigned long calib_data_sz =
|
||||
tas_priv->ndev * TASDEVICE_SPEAKER_CALIBRATION_SIZE;
|
||||
tas_hda->priv->ndev * TASDEVICE_SPEAKER_CALIBRATION_SIZE;
|
||||
int i, ret;
|
||||
|
||||
dev_dbg(tas_priv->dev, "System Resume\n");
|
||||
dev_info(tas_hda->priv->dev, "System Resume\n");
|
||||
|
||||
ret = pm_runtime_force_resume(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&tas_priv->codec_lock);
|
||||
mutex_lock(&tas_hda->priv->codec_lock);
|
||||
|
||||
for (i = 0; i < tas_priv->ndev; i++) {
|
||||
tas_priv->tasdevice[i].cur_book = -1;
|
||||
tas_priv->tasdevice[i].cur_prog = -1;
|
||||
tas_priv->tasdevice[i].cur_conf = -1;
|
||||
for (i = 0; i < tas_hda->priv->ndev; i++) {
|
||||
tas_hda->priv->tasdevice[i].cur_book = -1;
|
||||
tas_hda->priv->tasdevice[i].cur_prog = -1;
|
||||
tas_hda->priv->tasdevice[i].cur_conf = -1;
|
||||
}
|
||||
tas2781_reset(tas_priv);
|
||||
tasdevice_prmg_load(tas_priv, tas_priv->cur_prog);
|
||||
tas2781_reset(tas_hda->priv);
|
||||
tasdevice_prmg_load(tas_hda->priv, tas_hda->priv->cur_prog);
|
||||
|
||||
/* If calibrated data occurs error, dsp will still work with default
|
||||
* calibrated data inside algo.
|
||||
*/
|
||||
if (tas_priv->cali_data.total_sz > calib_data_sz)
|
||||
tas2781_apply_calib(tas_priv);
|
||||
mutex_unlock(&tas_priv->codec_lock);
|
||||
if (tas_hda->priv->cali_data.total_sz > calib_data_sz)
|
||||
tas2781_apply_calib(tas_hda->priv);
|
||||
mutex_unlock(&tas_hda->priv->codec_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -103,6 +103,20 @@ static const struct config_entry config_table[] = {
|
||||
{}
|
||||
},
|
||||
},
|
||||
{
|
||||
.flags = FLAG_AMD_LEGACY,
|
||||
.device = ACP_PCI_DEV_ID,
|
||||
.dmi_table = (const struct dmi_system_id []) {
|
||||
{
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HVY-WXX9"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
},
|
||||
},
|
||||
{
|
||||
.flags = FLAG_AMD_LEGACY,
|
||||
.device = ACP_PCI_DEV_ID,
|
||||
|
@ -283,6 +283,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "M6500RC"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.driver_data = &acp6x_card,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "E1504FA"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.driver_data = &acp6x_card,
|
||||
.matches = {
|
||||
@ -367,6 +374,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "8A3E"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.driver_data = &acp6x_card,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "8B2F"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.driver_data = &acp6x_card,
|
||||
.matches = {
|
||||
@ -381,6 +395,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "pang12"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.driver_data = &acp6x_card,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "System76"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "pang13"),
|
||||
}
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -62,7 +62,7 @@ static struct i2c_driver cs35l45_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "cs35l45",
|
||||
.of_match_table = cs35l45_of_match,
|
||||
.pm = &cs35l45_pm_ops,
|
||||
.pm = pm_ptr(&cs35l45_pm_ops),
|
||||
},
|
||||
.id_table = cs35l45_id_i2c,
|
||||
.probe = cs35l45_i2c_probe,
|
||||
|
@ -64,7 +64,7 @@ static struct spi_driver cs35l45_spi_driver = {
|
||||
.driver = {
|
||||
.name = "cs35l45",
|
||||
.of_match_table = cs35l45_of_match,
|
||||
.pm = &cs35l45_pm_ops,
|
||||
.pm = pm_ptr(&cs35l45_pm_ops),
|
||||
},
|
||||
.id_table = cs35l45_id_spi,
|
||||
.probe = cs35l45_spi_probe,
|
||||
|
@ -947,6 +947,8 @@ static int cs35l45_enter_hibernate(struct cs35l45_private *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
|
||||
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)
|
||||
CSPL_MBOX_CMD_OUT_OF_HIBERNATE);
|
||||
if (!ret) {
|
||||
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;
|
||||
}
|
||||
usleep_range(100, 200);
|
||||
@ -982,7 +986,7 @@ static int cs35l45_exit_hibernate(struct cs35l45_private *cs35l45)
|
||||
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);
|
||||
|
||||
@ -999,7 +1003,7 @@ static int __maybe_unused cs35l45_runtime_suspend(struct device *dev)
|
||||
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);
|
||||
int ret;
|
||||
@ -1026,6 +1030,46 @@ static int __maybe_unused cs35l45_runtime_resume(struct device *dev)
|
||||
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)
|
||||
{
|
||||
struct device_node *node = cs35l45->dev->of_node;
|
||||
@ -1466,10 +1510,12 @@ void cs35l45_remove(struct cs35l45_private *cs35l45)
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(cs35l45_remove, SND_SOC_CS35L45);
|
||||
|
||||
const struct dev_pm_ops cs35l45_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(cs35l45_runtime_suspend, cs35l45_runtime_resume, NULL)
|
||||
EXPORT_GPL_DEV_PM_OPS(cs35l45_pm_ops) = {
|
||||
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_AUTHOR("James Schulman, Cirrus Logic Inc, <james.schulman@cirrus.com>");
|
||||
|
@ -237,7 +237,7 @@ error:
|
||||
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;
|
||||
unsigned int val = 0x3 << CS42L43_HSBIAS_MODE_SHIFT;
|
||||
@ -247,16 +247,17 @@ static void cs42l43_start_hs_bias(struct cs42l43_codec *priv, bool force_high)
|
||||
regmap_update_bits(cs42l43->regmap, CS42L43_HS2,
|
||||
CS42L43_HS_CLAMP_DISABLE_MASK, CS42L43_HS_CLAMP_DISABLE_MASK);
|
||||
|
||||
if (!force_high && priv->bias_low)
|
||||
val = 0x2 << CS42L43_HSBIAS_MODE_SHIFT;
|
||||
if (!type_detect) {
|
||||
if (priv->bias_low)
|
||||
val = 0x2 << CS42L43_HSBIAS_MODE_SHIFT;
|
||||
|
||||
if (priv->bias_sense_ua) {
|
||||
regmap_update_bits(cs42l43->regmap,
|
||||
CS42L43_HS_BIAS_SENSE_AND_CLAMP_AUTOCONTROL,
|
||||
CS42L43_HSBIAS_SENSE_EN_MASK |
|
||||
CS42L43_AUTO_HSBIAS_CLAMP_EN_MASK,
|
||||
CS42L43_HSBIAS_SENSE_EN_MASK |
|
||||
CS42L43_AUTO_HSBIAS_CLAMP_EN_MASK);
|
||||
if (priv->bias_sense_ua)
|
||||
regmap_update_bits(cs42l43->regmap,
|
||||
CS42L43_HS_BIAS_SENSE_AND_CLAMP_AUTOCONTROL,
|
||||
CS42L43_HSBIAS_SENSE_EN_MASK |
|
||||
CS42L43_AUTO_HSBIAS_CLAMP_EN_MASK,
|
||||
CS42L43_HSBIAS_SENSE_EN_MASK |
|
||||
CS42L43_AUTO_HSBIAS_CLAMP_EN_MASK);
|
||||
}
|
||||
|
||||
regmap_update_bits(cs42l43->regmap, CS42L43_MIC_DETECT_CONTROL_1,
|
||||
|
@ -578,7 +578,7 @@ static int cs43130_set_sp_fmt(int dai_id, unsigned int bitwidth_sclk,
|
||||
break;
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
hi_size = bitwidth_sclk;
|
||||
frm_delay = 2;
|
||||
frm_delay = 0;
|
||||
frm_phase = 1;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
@ -1682,7 +1682,7 @@ static ssize_t hpload_dc_r_show(struct device *dev,
|
||||
return cs43130_show_dc(dev, buf, HP_RIGHT);
|
||||
}
|
||||
|
||||
static u16 const cs43130_ac_freq[CS43130_AC_FREQ] = {
|
||||
static const u16 cs43130_ac_freq[CS43130_AC_FREQ] = {
|
||||
24,
|
||||
43,
|
||||
93,
|
||||
@ -2362,7 +2362,7 @@ static const struct regmap_config cs43130_regmap = {
|
||||
.use_single_write = true,
|
||||
};
|
||||
|
||||
static u16 const cs43130_dc_threshold[CS43130_DC_THRESHOLD] = {
|
||||
static const u16 cs43130_dc_threshold[CS43130_DC_THRESHOLD] = {
|
||||
50,
|
||||
120,
|
||||
};
|
||||
|
@ -696,7 +696,7 @@ static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct device *dev)
|
||||
aad_pdata->mic_det_thr =
|
||||
da7219_aad_fw_mic_det_thr(dev, fw_val32);
|
||||
else
|
||||
aad_pdata->mic_det_thr = DA7219_AAD_MIC_DET_THR_500_OHMS;
|
||||
aad_pdata->mic_det_thr = DA7219_AAD_MIC_DET_THR_200_OHMS;
|
||||
|
||||
if (fwnode_property_read_u32(aad_np, "dlg,jack-ins-deb", &fw_val32) >= 0)
|
||||
aad_pdata->jack_ins_deb =
|
||||
|
@ -132,6 +132,9 @@ static struct snd_soc_dai_driver hdac_hda_dais[] = {
|
||||
.sig_bits = 24,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver hdac_hda_hdmi_dais[] = {
|
||||
{
|
||||
.id = HDAC_HDMI_0_DAI_ID,
|
||||
.name = "intel-hdmi-hifi1",
|
||||
@ -605,8 +608,16 @@ static const struct snd_soc_component_driver hdac_hda_codec = {
|
||||
.endianness = 1,
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver hdac_hda_hdmi_codec = {
|
||||
.probe = hdac_hda_codec_probe,
|
||||
.remove = hdac_hda_codec_remove,
|
||||
.idle_bias_on = false,
|
||||
.endianness = 1,
|
||||
};
|
||||
|
||||
static int hdac_hda_dev_probe(struct hdac_device *hdev)
|
||||
{
|
||||
struct hdac_hda_priv *hda_pvt = dev_get_drvdata(&hdev->dev);
|
||||
struct hdac_ext_link *hlink;
|
||||
int ret;
|
||||
|
||||
@ -619,9 +630,15 @@ static int hdac_hda_dev_probe(struct hdac_device *hdev)
|
||||
snd_hdac_ext_bus_link_get(hdev->bus, hlink);
|
||||
|
||||
/* ASoC specific initialization */
|
||||
ret = devm_snd_soc_register_component(&hdev->dev,
|
||||
&hdac_hda_codec, hdac_hda_dais,
|
||||
ARRAY_SIZE(hdac_hda_dais));
|
||||
if (hda_pvt->need_display_power)
|
||||
ret = devm_snd_soc_register_component(&hdev->dev,
|
||||
&hdac_hda_hdmi_codec, hdac_hda_hdmi_dais,
|
||||
ARRAY_SIZE(hdac_hda_hdmi_dais));
|
||||
else
|
||||
ret = devm_snd_soc_register_component(&hdev->dev,
|
||||
&hdac_hda_codec, hdac_hda_dais,
|
||||
ARRAY_SIZE(hdac_hda_dais));
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(&hdev->dev, "failed to register HDA codec %d\n", ret);
|
||||
return ret;
|
||||
|
@ -850,8 +850,9 @@ static int hdmi_dai_probe(struct snd_soc_dai *dai)
|
||||
static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp,
|
||||
unsigned int jack_status)
|
||||
{
|
||||
if (hcp->jack && jack_status != hcp->jack_status) {
|
||||
snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT);
|
||||
if (jack_status != hcp->jack_status) {
|
||||
if (hcp->jack)
|
||||
snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT);
|
||||
hcp->jack_status = jack_status;
|
||||
}
|
||||
}
|
||||
@ -880,6 +881,13 @@ static int hdmi_codec_set_jack(struct snd_soc_component *component,
|
||||
|
||||
if (hcp->hcd.ops->hook_plugged_cb) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -2021,6 +2021,11 @@ static int tx_macro_probe(struct platform_device *pdev)
|
||||
|
||||
tx->dev = dev;
|
||||
|
||||
/* Set active_decimator default value */
|
||||
tx->active_decimator[TX_MACRO_AIF1_CAP] = -1;
|
||||
tx->active_decimator[TX_MACRO_AIF2_CAP] = -1;
|
||||
tx->active_decimator[TX_MACRO_AIF3_CAP] = -1;
|
||||
|
||||
/* set MCLK and NPL rates */
|
||||
clk_set_rate(tx->mclk, MCLK_FREQ);
|
||||
clk_set_rate(tx->npl, MCLK_FREQ);
|
||||
|
@ -184,6 +184,7 @@ static int nau8822_eq_get(struct snd_kcontrol *kcontrol,
|
||||
struct soc_bytes_ext *params = (void *)kcontrol->private_value;
|
||||
int i, reg;
|
||||
u16 reg_val, *val;
|
||||
__be16 tmp;
|
||||
|
||||
val = (u16 *)ucontrol->value.bytes.data;
|
||||
reg = NAU8822_REG_EQ1;
|
||||
@ -192,8 +193,8 @@ static int nau8822_eq_get(struct snd_kcontrol *kcontrol,
|
||||
/* conversion of 16-bit integers between native CPU format
|
||||
* and big endian format
|
||||
*/
|
||||
reg_val = cpu_to_be16(reg_val);
|
||||
memcpy(val + i, ®_val, sizeof(reg_val));
|
||||
tmp = cpu_to_be16(reg_val);
|
||||
memcpy(val + i, &tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -216,6 +217,7 @@ static int nau8822_eq_put(struct snd_kcontrol *kcontrol,
|
||||
void *data;
|
||||
u16 *val, value;
|
||||
int i, reg, ret;
|
||||
__be16 *tmp;
|
||||
|
||||
data = kmemdup(ucontrol->value.bytes.data,
|
||||
params->max, GFP_KERNEL | GFP_DMA);
|
||||
@ -228,7 +230,8 @@ static int nau8822_eq_put(struct snd_kcontrol *kcontrol,
|
||||
/* conversion of 16-bit integers between native CPU format
|
||||
* and big endian format
|
||||
*/
|
||||
value = be16_to_cpu(*(val + i));
|
||||
tmp = (__be16 *)(val + i);
|
||||
value = be16_to_cpup(tmp);
|
||||
ret = snd_soc_component_write(component, reg + i, value);
|
||||
if (ret) {
|
||||
dev_err(component->dev,
|
||||
|
@ -448,6 +448,7 @@ struct rt5645_priv {
|
||||
struct regulator_bulk_data supplies[ARRAY_SIZE(rt5645_supply_names)];
|
||||
struct rt5645_eq_param_s *eq_param;
|
||||
struct timer_list btn_check_timer;
|
||||
struct mutex jd_mutex;
|
||||
|
||||
int codec_type;
|
||||
int sysclk;
|
||||
@ -3193,6 +3194,8 @@ static int rt5645_jack_detect(struct snd_soc_component *component, int jack_inse
|
||||
rt5645_enable_push_button_irq(component, true);
|
||||
}
|
||||
} else {
|
||||
if (rt5645->en_button_func)
|
||||
rt5645_enable_push_button_irq(component, false);
|
||||
snd_soc_dapm_disable_pin(dapm, "Mic Det Power");
|
||||
snd_soc_dapm_sync(dapm);
|
||||
rt5645->jack_type = SND_JACK_HEADPHONE;
|
||||
@ -3295,6 +3298,8 @@ static void rt5645_jack_detect_work(struct work_struct *work)
|
||||
if (!rt5645->component)
|
||||
return;
|
||||
|
||||
mutex_lock(&rt5645->jd_mutex);
|
||||
|
||||
switch (rt5645->pdata.jd_mode) {
|
||||
case 0: /* Not using rt5645 JD */
|
||||
if (rt5645->gpiod_hp_det) {
|
||||
@ -3321,7 +3326,7 @@ static void rt5645_jack_detect_work(struct work_struct *work)
|
||||
|
||||
if (!val && (rt5645->jack_type == 0)) { /* jack in */
|
||||
report = rt5645_jack_detect(rt5645->component, 1);
|
||||
} else if (!val && rt5645->jack_type != 0) {
|
||||
} else if (!val && rt5645->jack_type == SND_JACK_HEADSET) {
|
||||
/* for push button and jack out */
|
||||
btn_type = 0;
|
||||
if (snd_soc_component_read(rt5645->component, RT5645_INT_IRQ_ST) & 0x4) {
|
||||
@ -3377,6 +3382,8 @@ static void rt5645_jack_detect_work(struct work_struct *work)
|
||||
rt5645_jack_detect(rt5645->component, 0);
|
||||
}
|
||||
|
||||
mutex_unlock(&rt5645->jd_mutex);
|
||||
|
||||
snd_soc_jack_report(rt5645->hp_jack, report, SND_JACK_HEADPHONE);
|
||||
snd_soc_jack_report(rt5645->mic_jack, report, SND_JACK_MICROPHONE);
|
||||
if (rt5645->en_button_func)
|
||||
@ -4150,6 +4157,7 @@ static int rt5645_i2c_probe(struct i2c_client *i2c)
|
||||
}
|
||||
timer_setup(&rt5645->btn_check_timer, rt5645_btn_check_callback, 0);
|
||||
|
||||
mutex_init(&rt5645->jd_mutex);
|
||||
INIT_DELAYED_WORK(&rt5645->jack_detect_work, rt5645_jack_detect_work);
|
||||
INIT_DELAYED_WORK(&rt5645->rcclock_work, rt5645_rcclock_work);
|
||||
|
||||
|
@ -39,7 +39,7 @@ static const struct regmap_range_cfg tasdevice_ranges[] = {
|
||||
static const struct regmap_config tasdevice_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
.cache_type = REGCACHE_NONE,
|
||||
.ranges = tasdevice_ranges,
|
||||
.num_ranges = ARRAY_SIZE(tasdevice_ranges),
|
||||
.max_register = 256 * 128,
|
||||
@ -316,8 +316,6 @@ int tasdevice_init(struct tasdevice_priv *tas_priv)
|
||||
tas_priv->tasdevice[i].cur_conf = -1;
|
||||
}
|
||||
|
||||
dev_set_drvdata(tas_priv->dev, tas_priv);
|
||||
|
||||
mutex_init(&tas_priv->codec_lock);
|
||||
|
||||
out:
|
||||
|
@ -2189,11 +2189,11 @@ int tasdevice_select_tuningprm_cfg(void *context, int prm_no,
|
||||
goto out;
|
||||
}
|
||||
|
||||
conf = &(tas_fmw->configs[cfg_no]);
|
||||
for (i = 0, prog_status = 0; i < tas_priv->ndev; i++) {
|
||||
if (cfg_info[rca_conf_no]->active_dev & (1 << i)) {
|
||||
if (tas_priv->tasdevice[i].cur_prog != prm_no
|
||||
|| tas_priv->force_fwload_status) {
|
||||
if (prm_no >= 0
|
||||
&& (tas_priv->tasdevice[i].cur_prog != prm_no
|
||||
|| tas_priv->force_fwload_status)) {
|
||||
tas_priv->tasdevice[i].cur_conf = -1;
|
||||
tas_priv->tasdevice[i].is_loading = true;
|
||||
prog_status++;
|
||||
@ -2228,7 +2228,8 @@ int tasdevice_select_tuningprm_cfg(void *context, int prm_no,
|
||||
}
|
||||
|
||||
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))
|
||||
&& (tas_priv->tasdevice[i].is_loaderr == false)) {
|
||||
status++;
|
||||
@ -2238,6 +2239,7 @@ int tasdevice_select_tuningprm_cfg(void *context, int prm_no,
|
||||
}
|
||||
|
||||
if (status) {
|
||||
conf = &(tas_fmw->configs[cfg_no]);
|
||||
status = 0;
|
||||
tasdevice_load_data(tas_priv, &(conf->dev_data));
|
||||
for (i = 0; i < tas_priv->ndev; i++) {
|
||||
@ -2281,7 +2283,7 @@ int tasdevice_prmg_load(void *context, int prm_no)
|
||||
}
|
||||
|
||||
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].is_loading = true;
|
||||
prog_status++;
|
||||
@ -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++) {
|
||||
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].is_loading = true;
|
||||
prog_status++;
|
||||
|
@ -689,6 +689,8 @@ static int tasdevice_i2c_probe(struct i2c_client *i2c)
|
||||
if (!tas_priv)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(&i2c->dev, tas_priv);
|
||||
|
||||
if (ACPI_HANDLE(&i2c->dev)) {
|
||||
acpi_id = acpi_match_device(i2c->dev.driver->acpi_match_table,
|
||||
&i2c->dev);
|
||||
|
@ -186,7 +186,7 @@ SOC_DAPM_SINGLE("PCM Playback Switch", WM8974_MONOMIX, 0, 1, 0),
|
||||
|
||||
/* Boost mixer */
|
||||
static const struct snd_kcontrol_new wm8974_boost_mixer[] = {
|
||||
SOC_DAPM_SINGLE("Aux Switch", WM8974_INPPGA, 6, 1, 1),
|
||||
SOC_DAPM_SINGLE("PGA Switch", WM8974_INPPGA, 6, 1, 1),
|
||||
};
|
||||
|
||||
/* Input PGA */
|
||||
@ -246,8 +246,8 @@ static const struct snd_soc_dapm_route wm8974_dapm_routes[] = {
|
||||
|
||||
/* Boost Mixer */
|
||||
{"ADC", NULL, "Boost Mixer"},
|
||||
{"Boost Mixer", "Aux Switch", "Aux Input"},
|
||||
{"Boost Mixer", NULL, "Input PGA"},
|
||||
{"Boost Mixer", NULL, "Aux Input"},
|
||||
{"Boost Mixer", "PGA Switch", "Input PGA"},
|
||||
{"Boost Mixer", NULL, "MICP"},
|
||||
|
||||
/* Input PGA */
|
||||
|
@ -1451,12 +1451,12 @@ static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf)
|
||||
ret = wm_adsp_buffer_read(buf, caps->region_defs[i].base_offset,
|
||||
®ion->base_addr);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto err;
|
||||
|
||||
ret = wm_adsp_buffer_read(buf, caps->region_defs[i].size_offset,
|
||||
&offset);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto err;
|
||||
|
||||
region->cumulative_size = offset;
|
||||
|
||||
@ -1467,6 +1467,10 @@ static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf)
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
kfree(buf->regions);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void wm_adsp_buffer_clear(struct wm_adsp_compr_buf *buf)
|
||||
|
@ -360,6 +360,7 @@ config SND_SOC_IMX_HDMI
|
||||
config SND_SOC_IMX_RPMSG
|
||||
tristate "SoC Audio support for i.MX boards with rpmsg"
|
||||
depends on RPMSG
|
||||
depends on OF && I2C
|
||||
select SND_SOC_IMX_PCM_RPMSG
|
||||
select SND_SOC_IMX_AUDIO_RPMSG
|
||||
help
|
||||
|
@ -673,6 +673,20 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
|
||||
FSL_SAI_CR3_TRCE_MASK,
|
||||
FSL_SAI_CR3_TRCE((dl_cfg[dl_cfg_idx].mask[tx] & trce_mask)));
|
||||
|
||||
/*
|
||||
* When the TERE and FSD_MSTR enabled before configuring the word width
|
||||
* There will be no frame sync clock issue, because word width impact
|
||||
* the generation of frame sync clock.
|
||||
*
|
||||
* TERE enabled earlier only for i.MX8MP case for the hardware limitation,
|
||||
* We need to disable FSD_MSTR before configuring word width, then enable
|
||||
* FSD_MSTR bit for this specific case.
|
||||
*/
|
||||
if (sai->soc_data->mclk_with_tere && sai->mclk_direction_output &&
|
||||
!sai->is_consumer_mode)
|
||||
regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
|
||||
FSL_SAI_CR4_FSD_MSTR, 0);
|
||||
|
||||
regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
|
||||
FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK |
|
||||
FSL_SAI_CR4_CHMOD_MASK,
|
||||
@ -680,6 +694,13 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
|
||||
regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx, ofs),
|
||||
FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
|
||||
FSL_SAI_CR5_FBT_MASK, val_cr5);
|
||||
|
||||
/* Enable FSD_MSTR after configuring word width */
|
||||
if (sai->soc_data->mclk_with_tere && sai->mclk_direction_output &&
|
||||
!sai->is_consumer_mode)
|
||||
regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
|
||||
FSL_SAI_CR4_FSD_MSTR, FSL_SAI_CR4_FSD_MSTR);
|
||||
|
||||
regmap_write(sai->regmap, FSL_SAI_xMR(tx),
|
||||
~0UL - ((1 << min(channels, slots)) - 1));
|
||||
|
||||
@ -693,6 +714,9 @@ static int fsl_sai_hw_free(struct snd_pcm_substream *substream,
|
||||
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
|
||||
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),
|
||||
FSL_SAI_CR3_TRCE_MASK, 0);
|
||||
|
||||
|
@ -358,7 +358,7 @@ static int fsl_xcvr_en_aud_pll(struct fsl_xcvr *xcvr, u32 freq)
|
||||
struct device *dev = &xcvr->pdev->dev;
|
||||
int ret;
|
||||
|
||||
freq = xcvr->soc_data->spdif_only ? freq / 10 : freq;
|
||||
freq = xcvr->soc_data->spdif_only ? freq / 5 : freq;
|
||||
clk_disable_unprepare(xcvr->phy_clk);
|
||||
ret = clk_set_rate(xcvr->phy_clk, freq);
|
||||
if (ret < 0) {
|
||||
@ -409,11 +409,21 @@ static int fsl_xcvr_prepare(struct snd_pcm_substream *substream,
|
||||
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
|
||||
u32 m_ctl = 0, v_ctl = 0;
|
||||
u32 r = substream->runtime->rate, ch = substream->runtime->channels;
|
||||
u32 fout = 32 * r * ch * 10 * 2;
|
||||
u32 fout = 32 * r * ch * 10;
|
||||
int ret = 0;
|
||||
|
||||
switch (xcvr->mode) {
|
||||
case FSL_XCVR_MODE_SPDIF:
|
||||
if (xcvr->soc_data->spdif_only && tx) {
|
||||
ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_TX_DPTH_CTRL_SET,
|
||||
FSL_XCVR_TX_DPTH_CTRL_BYPASS_FEM,
|
||||
FSL_XCVR_TX_DPTH_CTRL_BYPASS_FEM);
|
||||
if (ret < 0) {
|
||||
dev_err(dai->dev, "Failed to set bypass fem: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
fallthrough;
|
||||
case FSL_XCVR_MODE_ARC:
|
||||
if (tx) {
|
||||
ret = fsl_xcvr_en_aud_pll(xcvr, fout);
|
||||
|
@ -83,6 +83,7 @@ enum {
|
||||
#define BYT_RT5640_HSMIC2_ON_IN1 BIT(27)
|
||||
#define BYT_RT5640_JD_HP_ELITEP_1000G2 BIT(28)
|
||||
#define BYT_RT5640_USE_AMCR0F28 BIT(29)
|
||||
#define BYT_RT5640_SWAPPED_SPEAKERS BIT(30)
|
||||
|
||||
#define BYTCR_INPUT_DEFAULTS \
|
||||
(BYT_RT5640_IN3_MAP | \
|
||||
@ -157,6 +158,8 @@ static void log_quirks(struct device *dev)
|
||||
dev_info(dev, "quirk MONO_SPEAKER enabled\n");
|
||||
if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)
|
||||
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)
|
||||
dev_info(dev, "quirk LINEOUT enabled\n");
|
||||
if (byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2)
|
||||
@ -894,6 +897,19 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
|
||||
BYT_RT5640_SSP0_AIF1 |
|
||||
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 */
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Mini PC"),
|
||||
@ -1619,11 +1635,11 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
|
||||
const char *platform_name;
|
||||
struct acpi_device *adev;
|
||||
struct device *codec_dev;
|
||||
const char *cfg_spk;
|
||||
bool sof_parent;
|
||||
int ret_val = 0;
|
||||
int dai_index = 0;
|
||||
int i, cfg_spk;
|
||||
int aif;
|
||||
int i, aif;
|
||||
|
||||
is_bytcr = false;
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
@ -1783,13 +1799,16 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) {
|
||||
cfg_spk = 0;
|
||||
cfg_spk = "0";
|
||||
spk_type = "none";
|
||||
} else if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) {
|
||||
cfg_spk = 1;
|
||||
cfg_spk = "1";
|
||||
spk_type = "mono";
|
||||
} else if (byt_rt5640_quirk & BYT_RT5640_SWAPPED_SPEAKERS) {
|
||||
cfg_spk = "swapped";
|
||||
spk_type = "swapped";
|
||||
} else {
|
||||
cfg_spk = 2;
|
||||
cfg_spk = "2";
|
||||
spk_type = "stereo";
|
||||
}
|
||||
|
||||
@ -1804,7 +1823,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
|
||||
headset2_string = " cfg-hs2:in1";
|
||||
|
||||
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,
|
||||
lineout_string, headset2_string);
|
||||
byt_rt5640_card.components = byt_rt5640_components;
|
||||
|
@ -154,6 +154,8 @@ static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params)
|
||||
card->dapm_widgets = skl_hda_widgets;
|
||||
card->num_dapm_widgets = ARRAY_SIZE(skl_hda_widgets);
|
||||
if (!ctx->idisp_codec) {
|
||||
card->dapm_routes = &skl_hda_map[IDISP_ROUTE_COUNT];
|
||||
num_route -= IDISP_ROUTE_COUNT;
|
||||
for (i = 0; i < IDISP_DAI_COUNT; i++) {
|
||||
skl_hda_be_dai_links[i].codecs = &snd_soc_dummy_dlc;
|
||||
skl_hda_be_dai_links[i].num_codecs = 1;
|
||||
|
@ -1546,7 +1546,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
|
||||
{
|
||||
struct device *dev = card->dev;
|
||||
struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev);
|
||||
int sdw_be_num = 0, ssp_num = 0, dmic_num = 0, hdmi_num = 0, bt_num = 0;
|
||||
int sdw_be_num = 0, ssp_num = 0, dmic_num = 0, bt_num = 0;
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
|
||||
const struct snd_soc_acpi_link_adr *adr_link = mach_params->links;
|
||||
@ -1564,6 +1564,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
|
||||
char *codec_name, *codec_dai_name;
|
||||
int i, j, be_id = 0;
|
||||
int codec_index;
|
||||
int hdmi_num;
|
||||
int ret;
|
||||
|
||||
ret = get_dailink_info(dev, adr_link, &sdw_be_num, &codec_conf_num);
|
||||
@ -1584,14 +1585,13 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
|
||||
ssp_num = hweight_long(ssp_mask);
|
||||
}
|
||||
|
||||
if (mach_params->codec_mask & IDISP_CODEC_MASK) {
|
||||
if (mach_params->codec_mask & IDISP_CODEC_MASK)
|
||||
ctx->hdmi.idisp_codec = true;
|
||||
|
||||
if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
|
||||
hdmi_num = SOF_TGL_HDMI_COUNT;
|
||||
else
|
||||
hdmi_num = SOF_PRE_TGL_HDMI_COUNT;
|
||||
}
|
||||
if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
|
||||
hdmi_num = SOF_TGL_HDMI_COUNT;
|
||||
else
|
||||
hdmi_num = SOF_PRE_TGL_HDMI_COUNT;
|
||||
|
||||
/* enable dmic01 & dmic16k */
|
||||
if (sof_sdw_quirk & SOF_SDW_PCH_DMIC || mach_params->dmic_num)
|
||||
@ -1601,7 +1601,8 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
|
||||
bt_num = 1;
|
||||
|
||||
dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d, bt: %d\n",
|
||||
sdw_be_num, ssp_num, dmic_num, hdmi_num, bt_num);
|
||||
sdw_be_num, ssp_num, dmic_num,
|
||||
ctx->hdmi.idisp_codec ? hdmi_num : 0, bt_num);
|
||||
|
||||
/* allocate BE dailinks */
|
||||
num_links = sdw_be_num + ssp_num + dmic_num + hdmi_num + bt_num;
|
||||
|
@ -306,13 +306,13 @@ static const struct snd_soc_acpi_adr_device cs35l56_1_adr[] = {
|
||||
.adr = 0x00013701FA355601ull,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &spk_r_endpoint,
|
||||
.name_prefix = "cs35l56-8"
|
||||
.name_prefix = "AMP8"
|
||||
},
|
||||
{
|
||||
.adr = 0x00013601FA355601ull,
|
||||
.num_endpoints = 1,
|
||||
.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[] = {
|
||||
.adr = 0x00023301FA355601ull,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &spk_l_endpoint,
|
||||
.name_prefix = "cs35l56-1"
|
||||
.name_prefix = "AMP1"
|
||||
},
|
||||
{
|
||||
.adr = 0x00023201FA355601ull,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &spk_2_endpoint,
|
||||
.name_prefix = "cs35l56-2"
|
||||
.name_prefix = "AMP2"
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -245,8 +245,10 @@ static int skl_pcm_open(struct snd_pcm_substream *substream,
|
||||
snd_pcm_set_sync(substream);
|
||||
|
||||
mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
|
||||
if (!mconfig)
|
||||
if (!mconfig) {
|
||||
kfree(dma_params);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
skl_tplg_d0i3_get(skl, mconfig->d0i3_caps);
|
||||
|
||||
@ -1467,6 +1469,7 @@ int skl_platform_register(struct device *dev)
|
||||
dais = krealloc(skl->dais, sizeof(skl_fe_dai) +
|
||||
sizeof(skl_platform_dai), GFP_KERNEL);
|
||||
if (!dais) {
|
||||
kfree(skl->dais);
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
@ -1479,8 +1482,10 @@ int skl_platform_register(struct device *dev)
|
||||
|
||||
ret = devm_snd_soc_register_component(dev, &skl_component,
|
||||
skl->dais, num_dais);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
kfree(skl->dais);
|
||||
dev_err(dev, "soc component registration failed %d\n", ret);
|
||||
}
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
@ -1003,8 +1003,10 @@ int skl_ipc_get_large_config(struct sst_generic_ipc *ipc,
|
||||
|
||||
reply.size = (reply.header >> 32) & IPC_DATA_OFFSET_SZ_MASK;
|
||||
buf = krealloc(reply.data, reply.size, GFP_KERNEL);
|
||||
if (!buf)
|
||||
if (!buf) {
|
||||
kfree(reply.data);
|
||||
return -ENOMEM;
|
||||
}
|
||||
*payload = buf;
|
||||
*bytes = reply.size;
|
||||
|
||||
|
@ -27,6 +27,23 @@ struct sc8280xp_snd_data {
|
||||
static int sc8280xp_snd_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
|
||||
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
|
||||
switch (cpu_dai->id) {
|
||||
case WSA_CODEC_DMA_RX_0:
|
||||
case WSA_CODEC_DMA_RX_1:
|
||||
/*
|
||||
* set limit of 0dB on Digital Volume for Speakers,
|
||||
* this can prevent damage of speakers to some extent without
|
||||
* active speaker protection
|
||||
*/
|
||||
snd_soc_limit_volume(card, "WSA_RX0 Digital Volume", 84);
|
||||
snd_soc_limit_volume(card, "WSA_RX1 Digital Volume", 84);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return qcom_snd_wcd_jack_setup(rtd, &data->jack, &data->jack_setup);
|
||||
}
|
||||
|
@ -661,7 +661,7 @@ int snd_soc_limit_volume(struct snd_soc_card *card,
|
||||
kctl = snd_soc_card_get_kcontrol(card, name);
|
||||
if (kctl) {
|
||||
struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value;
|
||||
if (max <= mc->max) {
|
||||
if (max <= mc->max - mc->min) {
|
||||
mc->platform_max = max;
|
||||
ret = 0;
|
||||
}
|
||||
|
@ -712,11 +712,6 @@ static int soc_pcm_clean(struct snd_soc_pcm_runtime *rtd,
|
||||
if (snd_soc_dai_active(dai) == 0 &&
|
||||
(dai->rate || dai->channels || dai->sample_bits))
|
||||
soc_pcm_set_dai_params(dai, NULL);
|
||||
|
||||
if (snd_soc_dai_stream_active(dai, substream->stream) == 0) {
|
||||
if (dai->driver->ops && !dai->driver->ops->mute_unmute_on_trigger)
|
||||
snd_soc_dai_digital_mute(dai, 1, substream->stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -955,8 +950,10 @@ static int soc_pcm_hw_clean(struct snd_soc_pcm_runtime *rtd,
|
||||
if (snd_soc_dai_active(dai) == 1)
|
||||
soc_pcm_set_dai_params(dai, NULL);
|
||||
|
||||
if (snd_soc_dai_stream_active(dai, substream->stream) == 1)
|
||||
snd_soc_dai_digital_mute(dai, 1, substream->stream);
|
||||
if (snd_soc_dai_stream_active(dai, substream->stream) == 1) {
|
||||
if (dai->driver->ops && !dai->driver->ops->mute_unmute_on_trigger)
|
||||
snd_soc_dai_digital_mute(dai, 1, substream->stream);
|
||||
}
|
||||
}
|
||||
|
||||
/* run the stream event */
|
||||
|
@ -493,6 +493,7 @@ static int sof_ipc3_widget_setup_comp_mixer(struct snd_sof_widget *swidget)
|
||||
static int sof_ipc3_widget_setup_comp_pipeline(struct snd_sof_widget *swidget)
|
||||
{
|
||||
struct snd_soc_component *scomp = swidget->scomp;
|
||||
struct snd_sof_pipeline *spipe = swidget->spipe;
|
||||
struct sof_ipc_pipe_new *pipeline;
|
||||
struct snd_sof_widget *comp_swidget;
|
||||
int ret;
|
||||
@ -545,6 +546,7 @@ static int sof_ipc3_widget_setup_comp_pipeline(struct snd_sof_widget *swidget)
|
||||
swidget->dynamic_pipeline_widget);
|
||||
|
||||
swidget->core = pipeline->core;
|
||||
spipe->core_mask |= BIT(pipeline->core);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -89,7 +89,7 @@ sof_ipc4_set_volume_data(struct snd_sof_dev *sdev, struct snd_sof_widget *swidge
|
||||
struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data;
|
||||
struct sof_ipc4_gain *gain = swidget->private;
|
||||
struct sof_ipc4_msg *msg = &cdata->msg;
|
||||
struct sof_ipc4_gain_data data;
|
||||
struct sof_ipc4_gain_params params;
|
||||
bool all_channels_equal = true;
|
||||
u32 value;
|
||||
int ret, i;
|
||||
@ -109,20 +109,20 @@ sof_ipc4_set_volume_data(struct snd_sof_dev *sdev, struct snd_sof_widget *swidge
|
||||
*/
|
||||
for (i = 0; i < scontrol->num_channels; i++) {
|
||||
if (all_channels_equal) {
|
||||
data.channels = SOF_IPC4_GAIN_ALL_CHANNELS_MASK;
|
||||
data.init_val = cdata->chanv[0].value;
|
||||
params.channels = SOF_IPC4_GAIN_ALL_CHANNELS_MASK;
|
||||
params.init_val = cdata->chanv[0].value;
|
||||
} else {
|
||||
data.channels = cdata->chanv[i].channel;
|
||||
data.init_val = cdata->chanv[i].value;
|
||||
params.channels = cdata->chanv[i].channel;
|
||||
params.init_val = cdata->chanv[i].value;
|
||||
}
|
||||
|
||||
/* set curve type and duration from topology */
|
||||
data.curve_duration_l = gain->data.curve_duration_l;
|
||||
data.curve_duration_h = gain->data.curve_duration_h;
|
||||
data.curve_type = gain->data.curve_type;
|
||||
params.curve_duration_l = gain->data.params.curve_duration_l;
|
||||
params.curve_duration_h = gain->data.params.curve_duration_h;
|
||||
params.curve_type = gain->data.params.curve_type;
|
||||
|
||||
msg->data_ptr = &data;
|
||||
msg->data_size = sizeof(data);
|
||||
msg->data_ptr = ¶ms;
|
||||
msg->data_size = sizeof(params);
|
||||
|
||||
ret = sof_ipc4_set_get_kcontrol_data(scontrol, true, lock);
|
||||
msg->data_ptr = NULL;
|
||||
|
@ -130,18 +130,18 @@ static const struct sof_topology_token comp_ext_tokens[] = {
|
||||
|
||||
static const struct sof_topology_token gain_tokens[] = {
|
||||
{SOF_TKN_GAIN_RAMP_TYPE, SND_SOC_TPLG_TUPLE_TYPE_WORD,
|
||||
get_token_u32, offsetof(struct sof_ipc4_gain_data, curve_type)},
|
||||
get_token_u32, offsetof(struct sof_ipc4_gain_params, curve_type)},
|
||||
{SOF_TKN_GAIN_RAMP_DURATION,
|
||||
SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
|
||||
offsetof(struct sof_ipc4_gain_data, curve_duration_l)},
|
||||
offsetof(struct sof_ipc4_gain_params, curve_duration_l)},
|
||||
{SOF_TKN_GAIN_VAL, SND_SOC_TPLG_TUPLE_TYPE_WORD,
|
||||
get_token_u32, offsetof(struct sof_ipc4_gain_data, init_val)},
|
||||
get_token_u32, offsetof(struct sof_ipc4_gain_params, init_val)},
|
||||
};
|
||||
|
||||
/* SRC */
|
||||
static const struct sof_topology_token src_tokens[] = {
|
||||
{SOF_TKN_SRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
|
||||
offsetof(struct sof_ipc4_src, sink_rate)},
|
||||
offsetof(struct sof_ipc4_src_data, sink_rate)},
|
||||
};
|
||||
|
||||
static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = {
|
||||
@ -656,6 +656,7 @@ static int sof_ipc4_widget_setup_comp_pipeline(struct snd_sof_widget *swidget)
|
||||
{
|
||||
struct snd_soc_component *scomp = swidget->scomp;
|
||||
struct sof_ipc4_pipeline *pipeline;
|
||||
struct snd_sof_pipeline *spipe = swidget->spipe;
|
||||
int ret;
|
||||
|
||||
pipeline = kzalloc(sizeof(*pipeline), GFP_KERNEL);
|
||||
@ -670,6 +671,7 @@ static int sof_ipc4_widget_setup_comp_pipeline(struct snd_sof_widget *swidget)
|
||||
}
|
||||
|
||||
swidget->core = pipeline->core_id;
|
||||
spipe->core_mask |= BIT(pipeline->core_id);
|
||||
|
||||
if (pipeline->use_chain_dma) {
|
||||
dev_dbg(scomp->dev, "Set up chain DMA for %s\n", swidget->widget->name);
|
||||
@ -718,15 +720,15 @@ static int sof_ipc4_widget_setup_comp_pga(struct snd_sof_widget *swidget)
|
||||
|
||||
swidget->private = gain;
|
||||
|
||||
gain->data.channels = SOF_IPC4_GAIN_ALL_CHANNELS_MASK;
|
||||
gain->data.init_val = SOF_IPC4_VOL_ZERO_DB;
|
||||
gain->data.params.channels = SOF_IPC4_GAIN_ALL_CHANNELS_MASK;
|
||||
gain->data.params.init_val = SOF_IPC4_VOL_ZERO_DB;
|
||||
|
||||
ret = sof_ipc4_get_audio_fmt(scomp, swidget, &gain->available_fmt, &gain->base_config);
|
||||
ret = sof_ipc4_get_audio_fmt(scomp, swidget, &gain->available_fmt, &gain->data.base_config);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = sof_update_ipc_object(scomp, &gain->data, SOF_GAIN_TOKENS, swidget->tuples,
|
||||
swidget->num_tuples, sizeof(gain->data), 1);
|
||||
ret = sof_update_ipc_object(scomp, &gain->data.params, SOF_GAIN_TOKENS,
|
||||
swidget->tuples, swidget->num_tuples, sizeof(gain->data), 1);
|
||||
if (ret) {
|
||||
dev_err(scomp->dev, "Parsing gain tokens failed\n");
|
||||
goto err;
|
||||
@ -734,8 +736,8 @@ static int sof_ipc4_widget_setup_comp_pga(struct snd_sof_widget *swidget)
|
||||
|
||||
dev_dbg(scomp->dev,
|
||||
"pga widget %s: ramp type: %d, ramp duration %d, initial gain value: %#x\n",
|
||||
swidget->widget->name, gain->data.curve_type, gain->data.curve_duration_l,
|
||||
gain->data.init_val);
|
||||
swidget->widget->name, gain->data.params.curve_type,
|
||||
gain->data.params.curve_duration_l, gain->data.params.init_val);
|
||||
|
||||
ret = sof_ipc4_widget_setup_msg(swidget, &gain->msg);
|
||||
if (ret)
|
||||
@ -797,6 +799,7 @@ err:
|
||||
static int sof_ipc4_widget_setup_comp_src(struct snd_sof_widget *swidget)
|
||||
{
|
||||
struct snd_soc_component *scomp = swidget->scomp;
|
||||
struct snd_sof_pipeline *spipe = swidget->spipe;
|
||||
struct sof_ipc4_src *src;
|
||||
int ret;
|
||||
|
||||
@ -808,18 +811,21 @@ static int sof_ipc4_widget_setup_comp_src(struct snd_sof_widget *swidget)
|
||||
|
||||
swidget->private = src;
|
||||
|
||||
ret = sof_ipc4_get_audio_fmt(scomp, swidget, &src->available_fmt, &src->base_config);
|
||||
ret = sof_ipc4_get_audio_fmt(scomp, swidget, &src->available_fmt,
|
||||
&src->data.base_config);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = sof_update_ipc_object(scomp, src, SOF_SRC_TOKENS, swidget->tuples,
|
||||
ret = sof_update_ipc_object(scomp, &src->data, SOF_SRC_TOKENS, swidget->tuples,
|
||||
swidget->num_tuples, sizeof(*src), 1);
|
||||
if (ret) {
|
||||
dev_err(scomp->dev, "Parsing SRC tokens failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
dev_dbg(scomp->dev, "SRC sink rate %d\n", src->sink_rate);
|
||||
spipe->core_mask |= BIT(swidget->core);
|
||||
|
||||
dev_dbg(scomp->dev, "SRC sink rate %d\n", src->data.sink_rate);
|
||||
|
||||
ret = sof_ipc4_widget_setup_msg(swidget, &src->msg);
|
||||
if (ret)
|
||||
@ -864,6 +870,7 @@ static int sof_ipc4_widget_setup_comp_process(struct snd_sof_widget *swidget)
|
||||
{
|
||||
struct snd_soc_component *scomp = swidget->scomp;
|
||||
struct sof_ipc4_fw_module *fw_module;
|
||||
struct snd_sof_pipeline *spipe = swidget->spipe;
|
||||
struct sof_ipc4_process *process;
|
||||
void *cfg;
|
||||
int ret;
|
||||
@ -920,6 +927,9 @@ static int sof_ipc4_widget_setup_comp_process(struct snd_sof_widget *swidget)
|
||||
|
||||
sof_ipc4_widget_update_kcontrol_module_id(swidget);
|
||||
|
||||
/* set pipeline core mask to keep track of the core the module is scheduled to run on */
|
||||
spipe->core_mask |= BIT(swidget->core);
|
||||
|
||||
return 0;
|
||||
free_base_cfg_ext:
|
||||
kfree(process->base_config_ext);
|
||||
@ -1816,7 +1826,7 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget,
|
||||
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits;
|
||||
int ret;
|
||||
|
||||
ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &gain->base_config,
|
||||
ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &gain->data.base_config,
|
||||
pipeline_params, available_fmt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -1826,7 +1836,7 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget,
|
||||
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
|
||||
out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
|
||||
|
||||
ret = sof_ipc4_init_output_audio_fmt(sdev, &gain->base_config, available_fmt,
|
||||
ret = sof_ipc4_init_output_audio_fmt(sdev, &gain->data.base_config, available_fmt,
|
||||
out_ref_rate, out_ref_channels, out_ref_valid_bits);
|
||||
if (ret < 0) {
|
||||
dev_err(sdev->dev, "Failed to initialize output format for %s",
|
||||
@ -1835,7 +1845,7 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget,
|
||||
}
|
||||
|
||||
/* update pipeline memory usage */
|
||||
sof_ipc4_update_resource_usage(sdev, swidget, &gain->base_config);
|
||||
sof_ipc4_update_resource_usage(sdev, swidget, &gain->data.base_config);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1891,7 +1901,7 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
|
||||
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits;
|
||||
int output_format_index, input_format_index;
|
||||
|
||||
input_format_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, &src->base_config,
|
||||
input_format_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, &src->data.base_config,
|
||||
pipeline_params, available_fmt);
|
||||
if (input_format_index < 0)
|
||||
return input_format_index;
|
||||
@ -1921,7 +1931,7 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
|
||||
*/
|
||||
out_ref_rate = params_rate(fe_params);
|
||||
|
||||
output_format_index = sof_ipc4_init_output_audio_fmt(sdev, &src->base_config,
|
||||
output_format_index = sof_ipc4_init_output_audio_fmt(sdev, &src->data.base_config,
|
||||
available_fmt, out_ref_rate,
|
||||
out_ref_channels, out_ref_valid_bits);
|
||||
if (output_format_index < 0) {
|
||||
@ -1931,10 +1941,10 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
|
||||
}
|
||||
|
||||
/* update pipeline memory usage */
|
||||
sof_ipc4_update_resource_usage(sdev, swidget, &src->base_config);
|
||||
sof_ipc4_update_resource_usage(sdev, swidget, &src->data.base_config);
|
||||
|
||||
out_audio_fmt = &available_fmt->output_pin_fmts[output_format_index].audio_fmt;
|
||||
src->sink_rate = out_audio_fmt->sampling_frequency;
|
||||
src->data.sink_rate = out_audio_fmt->sampling_frequency;
|
||||
|
||||
/* update pipeline_params for sink widgets */
|
||||
return sof_ipc4_update_hw_params(sdev, pipeline_params, out_audio_fmt);
|
||||
@ -2314,9 +2324,8 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
|
||||
{
|
||||
struct sof_ipc4_gain *gain = swidget->private;
|
||||
|
||||
ipc_size = sizeof(struct sof_ipc4_base_module_cfg) +
|
||||
sizeof(struct sof_ipc4_gain_data);
|
||||
ipc_data = gain;
|
||||
ipc_size = sizeof(gain->data);
|
||||
ipc_data = &gain->data;
|
||||
|
||||
msg = &gain->msg;
|
||||
break;
|
||||
@ -2335,8 +2344,8 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
|
||||
{
|
||||
struct sof_ipc4_src *src = swidget->private;
|
||||
|
||||
ipc_size = sizeof(struct sof_ipc4_base_module_cfg) + sizeof(src->sink_rate);
|
||||
ipc_data = src;
|
||||
ipc_size = sizeof(src->data);
|
||||
ipc_data = &src->data;
|
||||
|
||||
msg = &src->msg;
|
||||
break;
|
||||
|
@ -361,7 +361,7 @@ struct sof_ipc4_control_msg_payload {
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct sof_ipc4_gain_data - IPC gain blob
|
||||
* struct sof_ipc4_gain_params - IPC gain parameters
|
||||
* @channels: Channels
|
||||
* @init_val: Initial value
|
||||
* @curve_type: Curve type
|
||||
@ -369,24 +369,32 @@ struct sof_ipc4_control_msg_payload {
|
||||
* @curve_duration_l: Curve duration low part
|
||||
* @curve_duration_h: Curve duration high part
|
||||
*/
|
||||
struct sof_ipc4_gain_data {
|
||||
struct sof_ipc4_gain_params {
|
||||
uint32_t channels;
|
||||
uint32_t init_val;
|
||||
uint32_t curve_type;
|
||||
uint32_t reserved;
|
||||
uint32_t curve_duration_l;
|
||||
uint32_t curve_duration_h;
|
||||
} __aligned(8);
|
||||
} __packed __aligned(4);
|
||||
|
||||
/**
|
||||
* struct sof_ipc4_gain_data - IPC gain init blob
|
||||
* @base_config: IPC base config data
|
||||
* @params: Initial parameters for the gain module
|
||||
*/
|
||||
struct sof_ipc4_gain_data {
|
||||
struct sof_ipc4_base_module_cfg base_config;
|
||||
struct sof_ipc4_gain_params params;
|
||||
} __packed __aligned(4);
|
||||
|
||||
/**
|
||||
* struct sof_ipc4_gain - gain config data
|
||||
* @base_config: IPC base config data
|
||||
* @data: IPC gain blob
|
||||
* @available_fmt: Available audio format
|
||||
* @msg: message structure for gain
|
||||
*/
|
||||
struct sof_ipc4_gain {
|
||||
struct sof_ipc4_base_module_cfg base_config;
|
||||
struct sof_ipc4_gain_data data;
|
||||
struct sof_ipc4_available_audio_format available_fmt;
|
||||
struct sof_ipc4_msg msg;
|
||||
@ -404,16 +412,24 @@ struct sof_ipc4_mixer {
|
||||
struct sof_ipc4_msg msg;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sof_ipc4_src SRC config data
|
||||
/*
|
||||
* struct sof_ipc4_src_data - IPC data for SRC
|
||||
* @base_config: IPC base config data
|
||||
* @sink_rate: Output rate for sink module
|
||||
*/
|
||||
struct sof_ipc4_src_data {
|
||||
struct sof_ipc4_base_module_cfg base_config;
|
||||
uint32_t sink_rate;
|
||||
} __packed __aligned(4);
|
||||
|
||||
/**
|
||||
* struct sof_ipc4_src - SRC config data
|
||||
* @data: IPC base config data
|
||||
* @available_fmt: Available audio format
|
||||
* @msg: IPC4 message struct containing header and data info
|
||||
*/
|
||||
struct sof_ipc4_src {
|
||||
struct sof_ipc4_base_module_cfg base_config;
|
||||
uint32_t sink_rate;
|
||||
struct sof_ipc4_src_data data;
|
||||
struct sof_ipc4_available_audio_format available_fmt;
|
||||
struct sof_ipc4_msg msg;
|
||||
};
|
||||
|
@ -46,6 +46,7 @@ static int sof_widget_free_unlocked(struct snd_sof_dev *sdev,
|
||||
struct snd_sof_widget *swidget)
|
||||
{
|
||||
const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
|
||||
struct snd_sof_pipeline *spipe = swidget->spipe;
|
||||
struct snd_sof_widget *pipe_widget;
|
||||
int err = 0;
|
||||
int ret;
|
||||
@ -87,15 +88,22 @@ static int sof_widget_free_unlocked(struct snd_sof_dev *sdev,
|
||||
}
|
||||
|
||||
/*
|
||||
* disable widget core. continue to route setup status and complete flag
|
||||
* even if this fails and return the appropriate error
|
||||
* decrement ref count for cores associated with all modules in the pipeline and clear
|
||||
* the complete flag
|
||||
*/
|
||||
ret = snd_sof_dsp_core_put(sdev, swidget->core);
|
||||
if (ret < 0) {
|
||||
dev_err(sdev->dev, "error: failed to disable target core: %d for widget %s\n",
|
||||
swidget->core, swidget->widget->name);
|
||||
if (!err)
|
||||
err = ret;
|
||||
if (swidget->id == snd_soc_dapm_scheduler) {
|
||||
int i;
|
||||
|
||||
for_each_set_bit(i, &spipe->core_mask, sdev->num_cores) {
|
||||
ret = snd_sof_dsp_core_put(sdev, i);
|
||||
if (ret < 0) {
|
||||
dev_err(sdev->dev, "failed to disable target core: %d for pipeline %s\n",
|
||||
i, swidget->widget->name);
|
||||
if (!err)
|
||||
err = ret;
|
||||
}
|
||||
}
|
||||
swidget->spipe->complete = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -108,10 +116,6 @@ static int sof_widget_free_unlocked(struct snd_sof_dev *sdev,
|
||||
err = ret;
|
||||
}
|
||||
|
||||
/* clear pipeline complete */
|
||||
if (swidget->id == snd_soc_dapm_scheduler)
|
||||
swidget->spipe->complete = 0;
|
||||
|
||||
if (!err)
|
||||
dev_dbg(sdev->dev, "widget %s freed\n", swidget->widget->name);
|
||||
|
||||
@ -134,8 +138,10 @@ static int sof_widget_setup_unlocked(struct snd_sof_dev *sdev,
|
||||
struct snd_sof_widget *swidget)
|
||||
{
|
||||
const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
|
||||
struct snd_sof_pipeline *spipe = swidget->spipe;
|
||||
bool use_count_decremented = false;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
/* skip if there is no private data */
|
||||
if (!swidget->private)
|
||||
@ -166,19 +172,23 @@ static int sof_widget_setup_unlocked(struct snd_sof_dev *sdev,
|
||||
goto use_count_dec;
|
||||
}
|
||||
|
||||
/* enable widget core */
|
||||
ret = snd_sof_dsp_core_get(sdev, swidget->core);
|
||||
if (ret < 0) {
|
||||
dev_err(sdev->dev, "error: failed to enable target core for widget %s\n",
|
||||
swidget->widget->name);
|
||||
goto pipe_widget_free;
|
||||
/* update ref count for cores associated with all modules in the pipeline */
|
||||
if (swidget->id == snd_soc_dapm_scheduler) {
|
||||
for_each_set_bit(i, &spipe->core_mask, sdev->num_cores) {
|
||||
ret = snd_sof_dsp_core_get(sdev, i);
|
||||
if (ret < 0) {
|
||||
dev_err(sdev->dev, "failed to enable target core %d for pipeline %s\n",
|
||||
i, swidget->widget->name);
|
||||
goto pipe_widget_free;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* setup widget in the DSP */
|
||||
if (tplg_ops && tplg_ops->widget_setup) {
|
||||
ret = tplg_ops->widget_setup(sdev, swidget);
|
||||
if (ret < 0)
|
||||
goto core_put;
|
||||
goto pipe_widget_free;
|
||||
}
|
||||
|
||||
/* send config for DAI components */
|
||||
@ -208,15 +218,22 @@ static int sof_widget_setup_unlocked(struct snd_sof_dev *sdev,
|
||||
return 0;
|
||||
|
||||
widget_free:
|
||||
/* widget use_count and core ref_count will both be decremented by sof_widget_free() */
|
||||
/* widget use_count will be decremented by sof_widget_free() */
|
||||
sof_widget_free_unlocked(sdev, swidget);
|
||||
use_count_decremented = true;
|
||||
core_put:
|
||||
if (!use_count_decremented)
|
||||
snd_sof_dsp_core_put(sdev, swidget->core);
|
||||
pipe_widget_free:
|
||||
if (swidget->id != snd_soc_dapm_scheduler)
|
||||
if (swidget->id != snd_soc_dapm_scheduler) {
|
||||
sof_widget_free_unlocked(sdev, swidget->spipe->pipe_widget);
|
||||
} else {
|
||||
int j;
|
||||
|
||||
/* decrement ref count for all cores that were updated previously */
|
||||
for_each_set_bit(j, &spipe->core_mask, sdev->num_cores) {
|
||||
if (j >= i)
|
||||
break;
|
||||
snd_sof_dsp_core_put(sdev, j);
|
||||
}
|
||||
}
|
||||
use_count_dec:
|
||||
if (!use_count_decremented)
|
||||
swidget->use_count--;
|
||||
|
@ -480,6 +480,7 @@ struct snd_sof_widget {
|
||||
* @paused_count: Count of number of PCM's that have started and have currently paused this
|
||||
pipeline
|
||||
* @complete: flag used to indicate that pipeline set up is complete.
|
||||
* @core_mask: Mask containing target cores for all modules in the pipeline
|
||||
* @list: List item in sdev pipeline_list
|
||||
*/
|
||||
struct snd_sof_pipeline {
|
||||
@ -487,6 +488,7 @@ struct snd_sof_pipeline {
|
||||
int started_count;
|
||||
int paused_count;
|
||||
int complete;
|
||||
unsigned long core_mask;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
|
@ -1736,8 +1736,10 @@ static int sof_dai_load(struct snd_soc_component *scomp, int index,
|
||||
/* perform pcm set op */
|
||||
if (ipc_pcm_ops && ipc_pcm_ops->pcm_setup) {
|
||||
ret = ipc_pcm_ops->pcm_setup(sdev, spcm);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
kfree(spcm);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
dai_drv->dobj.private = spcm;
|
||||
|
@ -2978,6 +2978,7 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer)
|
||||
#define SND_DJM_850_IDX 0x2
|
||||
#define SND_DJM_900NXS2_IDX 0x3
|
||||
#define SND_DJM_750MK2_IDX 0x4
|
||||
#define SND_DJM_450_IDX 0x5
|
||||
|
||||
|
||||
#define SND_DJM_CTL(_name, suffix, _default_value, _windex) { \
|
||||
@ -3108,6 +3109,31 @@ static const struct snd_djm_ctl snd_djm_ctls_250mk2[] = {
|
||||
};
|
||||
|
||||
|
||||
// DJM-450
|
||||
static const u16 snd_djm_opts_450_cap1[] = {
|
||||
0x0103, 0x0100, 0x0106, 0x0107, 0x0108, 0x0109, 0x010d, 0x010a };
|
||||
|
||||
static const u16 snd_djm_opts_450_cap2[] = {
|
||||
0x0203, 0x0200, 0x0206, 0x0207, 0x0208, 0x0209, 0x020d, 0x020a };
|
||||
|
||||
static const u16 snd_djm_opts_450_cap3[] = {
|
||||
0x030a, 0x0311, 0x0312, 0x0307, 0x0308, 0x0309, 0x030d };
|
||||
|
||||
static const u16 snd_djm_opts_450_pb1[] = { 0x0100, 0x0101, 0x0104 };
|
||||
static const u16 snd_djm_opts_450_pb2[] = { 0x0200, 0x0201, 0x0204 };
|
||||
static const u16 snd_djm_opts_450_pb3[] = { 0x0300, 0x0301, 0x0304 };
|
||||
|
||||
static const struct snd_djm_ctl snd_djm_ctls_450[] = {
|
||||
SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL),
|
||||
SND_DJM_CTL("Ch1 Input", 450_cap1, 2, SND_DJM_WINDEX_CAP),
|
||||
SND_DJM_CTL("Ch2 Input", 450_cap2, 2, SND_DJM_WINDEX_CAP),
|
||||
SND_DJM_CTL("Ch3 Input", 450_cap3, 0, SND_DJM_WINDEX_CAP),
|
||||
SND_DJM_CTL("Ch1 Output", 450_pb1, 0, SND_DJM_WINDEX_PB),
|
||||
SND_DJM_CTL("Ch2 Output", 450_pb2, 1, SND_DJM_WINDEX_PB),
|
||||
SND_DJM_CTL("Ch3 Output", 450_pb3, 2, SND_DJM_WINDEX_PB)
|
||||
};
|
||||
|
||||
|
||||
// DJM-750
|
||||
static const u16 snd_djm_opts_750_cap1[] = {
|
||||
0x0101, 0x0103, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a, 0x010f };
|
||||
@ -3203,6 +3229,7 @@ static const struct snd_djm_device snd_djm_devices[] = {
|
||||
[SND_DJM_850_IDX] = SND_DJM_DEVICE(850),
|
||||
[SND_DJM_900NXS2_IDX] = SND_DJM_DEVICE(900nxs2),
|
||||
[SND_DJM_750MK2_IDX] = SND_DJM_DEVICE(750mk2),
|
||||
[SND_DJM_450_IDX] = SND_DJM_DEVICE(450),
|
||||
};
|
||||
|
||||
|
||||
@ -3454,6 +3481,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
|
||||
case USB_ID(0x2b73, 0x0017): /* Pioneer DJ DJM-250MK2 */
|
||||
err = snd_djm_controls_create(mixer, SND_DJM_250MK2_IDX);
|
||||
break;
|
||||
case USB_ID(0x2b73, 0x0013): /* Pioneer DJ DJM-450 */
|
||||
err = snd_djm_controls_create(mixer, SND_DJM_450_IDX);
|
||||
break;
|
||||
case USB_ID(0x08e4, 0x017f): /* Pioneer DJ DJM-750 */
|
||||
err = snd_djm_controls_create(mixer, SND_DJM_750_IDX);
|
||||
break;
|
||||
|
@ -1387,7 +1387,7 @@ free_buf:
|
||||
|
||||
static int snd_usb_motu_m_series_boot_quirk(struct usb_device *dev)
|
||||
{
|
||||
msleep(2000);
|
||||
msleep(4000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1630,7 +1630,7 @@ int snd_usb_apply_boot_quirk_once(struct usb_device *dev,
|
||||
unsigned int 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);
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,7 @@ static void find_controls(void)
|
||||
err = snd_ctl_elem_info(card_data->handle,
|
||||
ctl_data->info);
|
||||
if (err < 0) {
|
||||
ksft_print_msg("%s getting info for %d\n",
|
||||
ksft_print_msg("%s getting info for %s\n",
|
||||
snd_strerror(err),
|
||||
ctl_data->name);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user