mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-18 18:23:53 +08:00
sound fixes for 4.6-rc6
Usually we get a big collection of fixes for ASoC once during rc. And this is it. At this time, most of fixes are about Intel Skylake ASoC driver, which is a new and still on-going development. Along with it, a slight large LOC is seen in legacy HD-audio driver, but it's merely a code move to the upper layer. Other than that, the rest are small or trivial fixes to various drivers, in addition to an ASoC dapm debugfs code fix. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCAAGBQJXIgKpAAoJEGwxgFQ9KSmkNYQP/1Fzw/1Of+6ONNSO0mhTrFsZ KcYkKBlWTXLgzV5KTmcxhtx66QP8Z1S6yUNVxeeW8sWlW+F8CRdpGMhWaXcxpiRl uhuOO6qWIa96U0U8huFN3hvcUDjdEUJTS/cyMK2FD253qIWkZlZifSgPJRxeWKg2 EBfIICz14UKWusk5Frqb/mD3QGmkh9P4wd/Z2y+4p+TNrpCFKGOcHo8LKI4JscXo bhQduiQ0LsGWFfNfdzd9KX6G5XAE+pu7hc9VYDE1X89Ih/pMzdJGqwy9dyDBokh6 ucE+y3E715r/CS19vZ6l9p/4s+b5gUVvXBAk2MjFo/3/HOfoMqCz/ECi3PTfuc7c CcmJq8A2KifOgGc7/yi4apajn5THUpQmQuQAharlipB1Y/vWZxKUo4eX7RGjJnaq /peXevea96ilpajankQ1Et8LwsvklxzGAQ5J1ONtR7x8pqiOJ7mVL5Cp0GU3Cg1J BHIKWPm+Dv5piMtke0/7JSYIbxL5zzgmltqfYY44wnAzEvAcehv4u7zDE/BQdPo8 l8oLxgTsyAaBj+4YCUtlSWQjCyBifK8kD1OsRqak+jqYg6rl/uug7Cau7qAcpOyG IWSnQbLyP3YfcLNagtqyqru35Q4w1F1NRpZFwe2XLNbsG6hM5Ea/y0QKbCUS/ncn IkQPkrdx3+h/3PGNLo+P =ju49 -----END PGP SIGNATURE----- Merge tag 'sound-4.6-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound fixes from Takashi Iwai: "Usually we get a big collection of fixes for ASoC once during rc. And this is it. At this time, most of fixes are about Intel Skylake ASoC driver, which is a new and still on-going development. Along with it, a slight large LOC is seen in legacy HD-audio driver, but it's merely a code move to the upper layer. Other than that, the rest are small or trivial fixes to various drivers, in addition to an ASoC dapm debugfs code fix" * tag 'sound-4.6-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (24 commits) ALSA: hda - Update BCLK also at hotplug for i915 HSW/BDW ALSA: hda - Add dock support for ThinkPad X260 ASoC: wm5102: Free compressed IRQ in CODEC remove ASoC: arizona: Free speaker thermal IRQs in CODEC remove ASoC: Intel: Skylake: Fix ibs/obs calc for non-integral sampling rates ASoC: Intel: sst: fix a loop timeout in sst_hsw_stream_reset() ASoC: Intel: Skylake: Fix to turn OFF codec power when entering S3 ASoC: hdac_hdmi: Fix codec power state in S3 during playback ASoC: hdac_hdmi: Fix to use dev_pm ops instead soc pm ASoC: wm8962: Correct typo when setting DSPCLK rate ASoC: nau8825: Fix jack detection across suspend ASoC: Intel: Skylake: Fix DSP resource de-allocation ASoC: Intel: Skylake: Fix for unloading module only when it is loaded ASoC: Intel: Skylake: Fix kbuild dependency ASoC: dapm: Make sure we have a card when displaying component widgets ASoC: rt5640: Correct the digital interface data select ASoC: Intel: Skylake: remove call to pci_dev_put ASoC: Intel: Skylake: Call i915 exit last ASoC: Intel: Skylake: Unmap the address last ASoC: Intel: Skylake: Freeup properly on skl_dsp_free ...
This commit is contained in:
commit
e1f14a5469
@ -9,7 +9,7 @@
|
|||||||
#ifdef CONFIG_SND_HDA_I915
|
#ifdef CONFIG_SND_HDA_I915
|
||||||
int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable);
|
int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable);
|
||||||
int snd_hdac_display_power(struct hdac_bus *bus, bool enable);
|
int snd_hdac_display_power(struct hdac_bus *bus, bool enable);
|
||||||
int snd_hdac_get_display_clk(struct hdac_bus *bus);
|
void snd_hdac_i915_set_bclk(struct hdac_bus *bus);
|
||||||
int snd_hdac_sync_audio_rate(struct hdac_bus *bus, hda_nid_t nid, int rate);
|
int snd_hdac_sync_audio_rate(struct hdac_bus *bus, hda_nid_t nid, int rate);
|
||||||
int snd_hdac_acomp_get_eld(struct hdac_bus *bus, hda_nid_t nid,
|
int snd_hdac_acomp_get_eld(struct hdac_bus *bus, hda_nid_t nid,
|
||||||
bool *audio_enabled, char *buffer, int max_bytes);
|
bool *audio_enabled, char *buffer, int max_bytes);
|
||||||
@ -25,9 +25,8 @@ static inline int snd_hdac_display_power(struct hdac_bus *bus, bool enable)
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static inline int snd_hdac_get_display_clk(struct hdac_bus *bus)
|
static inline void snd_hdac_i915_set_bclk(struct hdac_bus *bus)
|
||||||
{
|
{
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
static inline int snd_hdac_sync_audio_rate(struct hdac_bus *bus, hda_nid_t nid,
|
static inline int snd_hdac_sync_audio_rate(struct hdac_bus *bus, hda_nid_t nid,
|
||||||
int rate)
|
int rate)
|
||||||
|
@ -104,12 +104,11 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_init_all);
|
|||||||
*/
|
*/
|
||||||
void snd_hdac_stream_free_all(struct hdac_ext_bus *ebus)
|
void snd_hdac_stream_free_all(struct hdac_ext_bus *ebus)
|
||||||
{
|
{
|
||||||
struct hdac_stream *s;
|
struct hdac_stream *s, *_s;
|
||||||
struct hdac_ext_stream *stream;
|
struct hdac_ext_stream *stream;
|
||||||
struct hdac_bus *bus = ebus_to_hbus(ebus);
|
struct hdac_bus *bus = ebus_to_hbus(ebus);
|
||||||
|
|
||||||
while (!list_empty(&bus->stream_list)) {
|
list_for_each_entry_safe(s, _s, &bus->stream_list, list) {
|
||||||
s = list_first_entry(&bus->stream_list, struct hdac_stream, list);
|
|
||||||
stream = stream_to_hdac_ext_stream(s);
|
stream = stream_to_hdac_ext_stream(s);
|
||||||
snd_hdac_ext_stream_decouple(ebus, stream, false);
|
snd_hdac_ext_stream_decouple(ebus, stream, false);
|
||||||
list_del(&s->list);
|
list_del(&s->list);
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
#include <sound/hdaudio.h>
|
#include <sound/hdaudio.h>
|
||||||
#include <sound/hda_i915.h>
|
#include <sound/hda_i915.h>
|
||||||
|
#include <sound/hda_register.h>
|
||||||
|
|
||||||
static struct i915_audio_component *hdac_acomp;
|
static struct i915_audio_component *hdac_acomp;
|
||||||
|
|
||||||
@ -97,26 +98,65 @@ int snd_hdac_display_power(struct hdac_bus *bus, bool enable)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(snd_hdac_display_power);
|
EXPORT_SYMBOL_GPL(snd_hdac_display_power);
|
||||||
|
|
||||||
|
#define CONTROLLER_IN_GPU(pci) (((pci)->device == 0x0a0c) || \
|
||||||
|
((pci)->device == 0x0c0c) || \
|
||||||
|
((pci)->device == 0x0d0c) || \
|
||||||
|
((pci)->device == 0x160c))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* snd_hdac_get_display_clk - Get CDCLK in kHz
|
* snd_hdac_i915_set_bclk - Reprogram BCLK for HSW/BDW
|
||||||
* @bus: HDA core bus
|
* @bus: HDA core bus
|
||||||
*
|
*
|
||||||
* This function is supposed to be used only by a HD-audio controller
|
* Intel HSW/BDW display HDA controller is in GPU. Both its power and link BCLK
|
||||||
* driver that needs the interaction with i915 graphics.
|
* depends on GPU. Two Extended Mode registers EM4 (M value) and EM5 (N Value)
|
||||||
|
* are used to convert CDClk (Core Display Clock) to 24MHz BCLK:
|
||||||
|
* BCLK = CDCLK * M / N
|
||||||
|
* The values will be lost when the display power well is disabled and need to
|
||||||
|
* be restored to avoid abnormal playback speed.
|
||||||
*
|
*
|
||||||
* This function queries CDCLK value in kHz from the graphics driver and
|
* Call this function at initializing and changing power well, as well as
|
||||||
* returns the value. A negative code is returned in error.
|
* at ELD notifier for the hotplug.
|
||||||
*/
|
*/
|
||||||
int snd_hdac_get_display_clk(struct hdac_bus *bus)
|
void snd_hdac_i915_set_bclk(struct hdac_bus *bus)
|
||||||
{
|
{
|
||||||
struct i915_audio_component *acomp = bus->audio_component;
|
struct i915_audio_component *acomp = bus->audio_component;
|
||||||
|
struct pci_dev *pci = to_pci_dev(bus->dev);
|
||||||
|
int cdclk_freq;
|
||||||
|
unsigned int bclk_m, bclk_n;
|
||||||
|
|
||||||
if (!acomp || !acomp->ops)
|
if (!acomp || !acomp->ops || !acomp->ops->get_cdclk_freq)
|
||||||
return -ENODEV;
|
return; /* only for i915 binding */
|
||||||
|
if (!CONTROLLER_IN_GPU(pci))
|
||||||
|
return; /* only HSW/BDW */
|
||||||
|
|
||||||
return acomp->ops->get_cdclk_freq(acomp->dev);
|
cdclk_freq = acomp->ops->get_cdclk_freq(acomp->dev);
|
||||||
|
switch (cdclk_freq) {
|
||||||
|
case 337500:
|
||||||
|
bclk_m = 16;
|
||||||
|
bclk_n = 225;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 450000:
|
||||||
|
default: /* default CDCLK 450MHz */
|
||||||
|
bclk_m = 4;
|
||||||
|
bclk_n = 75;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 540000:
|
||||||
|
bclk_m = 4;
|
||||||
|
bclk_n = 90;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 675000:
|
||||||
|
bclk_m = 8;
|
||||||
|
bclk_n = 225;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(snd_hdac_get_display_clk);
|
|
||||||
|
snd_hdac_chip_writew(bus, HSW_EM4, bclk_m);
|
||||||
|
snd_hdac_chip_writew(bus, HSW_EM5, bclk_n);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_hdac_i915_set_bclk);
|
||||||
|
|
||||||
/* There is a fixed mapping between audio pin node and display port
|
/* There is a fixed mapping between audio pin node and display port
|
||||||
* on current Intel platforms:
|
* on current Intel platforms:
|
||||||
|
@ -857,50 +857,6 @@ static int param_set_xint(const char *val, const struct kernel_param *kp)
|
|||||||
#define azx_del_card_list(chip) /* NOP */
|
#define azx_del_card_list(chip) /* NOP */
|
||||||
#endif /* CONFIG_PM */
|
#endif /* CONFIG_PM */
|
||||||
|
|
||||||
/* Intel HSW/BDW display HDA controller is in GPU. Both its power and link BCLK
|
|
||||||
* depends on GPU. Two Extended Mode registers EM4 (M value) and EM5 (N Value)
|
|
||||||
* are used to convert CDClk (Core Display Clock) to 24MHz BCLK:
|
|
||||||
* BCLK = CDCLK * M / N
|
|
||||||
* The values will be lost when the display power well is disabled and need to
|
|
||||||
* be restored to avoid abnormal playback speed.
|
|
||||||
*/
|
|
||||||
static void haswell_set_bclk(struct hda_intel *hda)
|
|
||||||
{
|
|
||||||
struct azx *chip = &hda->chip;
|
|
||||||
int cdclk_freq;
|
|
||||||
unsigned int bclk_m, bclk_n;
|
|
||||||
|
|
||||||
if (!hda->need_i915_power)
|
|
||||||
return;
|
|
||||||
|
|
||||||
cdclk_freq = snd_hdac_get_display_clk(azx_bus(chip));
|
|
||||||
switch (cdclk_freq) {
|
|
||||||
case 337500:
|
|
||||||
bclk_m = 16;
|
|
||||||
bclk_n = 225;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 450000:
|
|
||||||
default: /* default CDCLK 450MHz */
|
|
||||||
bclk_m = 4;
|
|
||||||
bclk_n = 75;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 540000:
|
|
||||||
bclk_m = 4;
|
|
||||||
bclk_n = 90;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 675000:
|
|
||||||
bclk_m = 8;
|
|
||||||
bclk_n = 225;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
azx_writew(chip, HSW_EM4, bclk_m);
|
|
||||||
azx_writew(chip, HSW_EM5, bclk_n);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(CONFIG_PM_SLEEP) || defined(SUPPORT_VGA_SWITCHEROO)
|
#if defined(CONFIG_PM_SLEEP) || defined(SUPPORT_VGA_SWITCHEROO)
|
||||||
/*
|
/*
|
||||||
* power management
|
* power management
|
||||||
@ -958,7 +914,7 @@ static int azx_resume(struct device *dev)
|
|||||||
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL
|
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL
|
||||||
&& hda->need_i915_power) {
|
&& hda->need_i915_power) {
|
||||||
snd_hdac_display_power(azx_bus(chip), true);
|
snd_hdac_display_power(azx_bus(chip), true);
|
||||||
haswell_set_bclk(hda);
|
snd_hdac_i915_set_bclk(azx_bus(chip));
|
||||||
}
|
}
|
||||||
if (chip->msi)
|
if (chip->msi)
|
||||||
if (pci_enable_msi(pci) < 0)
|
if (pci_enable_msi(pci) < 0)
|
||||||
@ -1058,7 +1014,7 @@ static int azx_runtime_resume(struct device *dev)
|
|||||||
bus = azx_bus(chip);
|
bus = azx_bus(chip);
|
||||||
if (hda->need_i915_power) {
|
if (hda->need_i915_power) {
|
||||||
snd_hdac_display_power(bus, true);
|
snd_hdac_display_power(bus, true);
|
||||||
haswell_set_bclk(hda);
|
snd_hdac_i915_set_bclk(bus);
|
||||||
} else {
|
} else {
|
||||||
/* toggle codec wakeup bit for STATESTS read */
|
/* toggle codec wakeup bit for STATESTS read */
|
||||||
snd_hdac_set_codec_wakeup(bus, true);
|
snd_hdac_set_codec_wakeup(bus, true);
|
||||||
@ -1796,12 +1752,8 @@ static int azx_first_init(struct azx *chip)
|
|||||||
/* initialize chip */
|
/* initialize chip */
|
||||||
azx_init_pci(chip);
|
azx_init_pci(chip);
|
||||||
|
|
||||||
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
|
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
|
||||||
struct hda_intel *hda;
|
snd_hdac_i915_set_bclk(bus);
|
||||||
|
|
||||||
hda = container_of(chip, struct hda_intel, chip);
|
|
||||||
haswell_set_bclk(hda);
|
|
||||||
}
|
|
||||||
|
|
||||||
hda_intel_init_chip(chip, (probe_only[dev] & 2) == 0);
|
hda_intel_init_chip(chip, (probe_only[dev] & 2) == 0);
|
||||||
|
|
||||||
|
@ -2232,6 +2232,7 @@ static void intel_pin_eld_notify(void *audio_ptr, int port)
|
|||||||
if (atomic_read(&(codec)->core.in_pm))
|
if (atomic_read(&(codec)->core.in_pm))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
snd_hdac_i915_set_bclk(&codec->bus->core);
|
||||||
check_presence_and_report(codec, pin_nid);
|
check_presence_and_report(codec, pin_nid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5584,6 +5584,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|||||||
SND_PCI_QUIRK(0x17aa, 0x5034, "Thinkpad T450", ALC292_FIXUP_TPT440_DOCK),
|
SND_PCI_QUIRK(0x17aa, 0x5034, "Thinkpad T450", ALC292_FIXUP_TPT440_DOCK),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x5036, "Thinkpad T450s", ALC292_FIXUP_TPT440_DOCK),
|
SND_PCI_QUIRK(0x17aa, 0x5036, "Thinkpad T450s", ALC292_FIXUP_TPT440_DOCK),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x503c, "Thinkpad L450", ALC292_FIXUP_TPT440_DOCK),
|
SND_PCI_QUIRK(0x17aa, 0x503c, "Thinkpad L450", ALC292_FIXUP_TPT440_DOCK),
|
||||||
|
SND_PCI_QUIRK(0x17aa, 0x504a, "ThinkPad X260", ALC292_FIXUP_TPT440_DOCK),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x504b, "Thinkpad", ALC293_FIXUP_LENOVO_SPK_NOISE),
|
SND_PCI_QUIRK(0x17aa, 0x504b, "Thinkpad", ALC293_FIXUP_LENOVO_SPK_NOISE),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
|
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
|
||||||
|
@ -629,6 +629,7 @@ config SND_SOC_RT5514
|
|||||||
|
|
||||||
config SND_SOC_RT5616
|
config SND_SOC_RT5616
|
||||||
tristate "Realtek RT5616 CODEC"
|
tristate "Realtek RT5616 CODEC"
|
||||||
|
depends on I2C
|
||||||
|
|
||||||
config SND_SOC_RT5631
|
config SND_SOC_RT5631
|
||||||
tristate "Realtek ALC5631/RT5631 CODEC"
|
tristate "Realtek ALC5631/RT5631 CODEC"
|
||||||
|
@ -249,6 +249,18 @@ int arizona_init_spk(struct snd_soc_codec *codec)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(arizona_init_spk);
|
EXPORT_SYMBOL_GPL(arizona_init_spk);
|
||||||
|
|
||||||
|
int arizona_free_spk(struct snd_soc_codec *codec)
|
||||||
|
{
|
||||||
|
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||||
|
struct arizona *arizona = priv->arizona;
|
||||||
|
|
||||||
|
arizona_free_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT_WARN, arizona);
|
||||||
|
arizona_free_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT, arizona);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(arizona_free_spk);
|
||||||
|
|
||||||
static const struct snd_soc_dapm_route arizona_mono_routes[] = {
|
static const struct snd_soc_dapm_route arizona_mono_routes[] = {
|
||||||
{ "OUT1R", NULL, "OUT1L" },
|
{ "OUT1R", NULL, "OUT1L" },
|
||||||
{ "OUT2R", NULL, "OUT2L" },
|
{ "OUT2R", NULL, "OUT2L" },
|
||||||
|
@ -307,6 +307,8 @@ extern int arizona_init_spk(struct snd_soc_codec *codec);
|
|||||||
extern int arizona_init_gpio(struct snd_soc_codec *codec);
|
extern int arizona_init_gpio(struct snd_soc_codec *codec);
|
||||||
extern int arizona_init_mono(struct snd_soc_codec *codec);
|
extern int arizona_init_mono(struct snd_soc_codec *codec);
|
||||||
|
|
||||||
|
extern int arizona_free_spk(struct snd_soc_codec *codec);
|
||||||
|
|
||||||
extern int arizona_init_dai(struct arizona_priv *priv, int dai);
|
extern int arizona_init_dai(struct arizona_priv *priv, int dai);
|
||||||
|
|
||||||
int arizona_set_output_mode(struct snd_soc_codec *codec, int output,
|
int arizona_set_output_mode(struct snd_soc_codec *codec, int output,
|
||||||
|
@ -274,7 +274,9 @@ static int cs35l32_handle_of_data(struct i2c_client *i2c_client,
|
|||||||
if (of_property_read_u32(np, "cirrus,sdout-share", &val) >= 0)
|
if (of_property_read_u32(np, "cirrus,sdout-share", &val) >= 0)
|
||||||
pdata->sdout_share = val;
|
pdata->sdout_share = val;
|
||||||
|
|
||||||
of_property_read_u32(np, "cirrus,boost-manager", &val);
|
if (of_property_read_u32(np, "cirrus,boost-manager", &val))
|
||||||
|
val = -1u;
|
||||||
|
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case CS35L32_BOOST_MGR_AUTO:
|
case CS35L32_BOOST_MGR_AUTO:
|
||||||
case CS35L32_BOOST_MGR_AUTO_AUDIO:
|
case CS35L32_BOOST_MGR_AUTO_AUDIO:
|
||||||
@ -282,13 +284,15 @@ static int cs35l32_handle_of_data(struct i2c_client *i2c_client,
|
|||||||
case CS35L32_BOOST_MGR_FIXED:
|
case CS35L32_BOOST_MGR_FIXED:
|
||||||
pdata->boost_mng = val;
|
pdata->boost_mng = val;
|
||||||
break;
|
break;
|
||||||
|
case -1u:
|
||||||
default:
|
default:
|
||||||
dev_err(&i2c_client->dev,
|
dev_err(&i2c_client->dev,
|
||||||
"Wrong cirrus,boost-manager DT value %d\n", val);
|
"Wrong cirrus,boost-manager DT value %d\n", val);
|
||||||
pdata->boost_mng = CS35L32_BOOST_MGR_BYPASS;
|
pdata->boost_mng = CS35L32_BOOST_MGR_BYPASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
of_property_read_u32(np, "cirrus,sdout-datacfg", &val);
|
if (of_property_read_u32(np, "cirrus,sdout-datacfg", &val))
|
||||||
|
val = -1u;
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case CS35L32_DATA_CFG_LR_VP:
|
case CS35L32_DATA_CFG_LR_VP:
|
||||||
case CS35L32_DATA_CFG_LR_STAT:
|
case CS35L32_DATA_CFG_LR_STAT:
|
||||||
@ -296,13 +300,15 @@ static int cs35l32_handle_of_data(struct i2c_client *i2c_client,
|
|||||||
case CS35L32_DATA_CFG_LR_VPSTAT:
|
case CS35L32_DATA_CFG_LR_VPSTAT:
|
||||||
pdata->sdout_datacfg = val;
|
pdata->sdout_datacfg = val;
|
||||||
break;
|
break;
|
||||||
|
case -1u:
|
||||||
default:
|
default:
|
||||||
dev_err(&i2c_client->dev,
|
dev_err(&i2c_client->dev,
|
||||||
"Wrong cirrus,sdout-datacfg DT value %d\n", val);
|
"Wrong cirrus,sdout-datacfg DT value %d\n", val);
|
||||||
pdata->sdout_datacfg = CS35L32_DATA_CFG_LR;
|
pdata->sdout_datacfg = CS35L32_DATA_CFG_LR;
|
||||||
}
|
}
|
||||||
|
|
||||||
of_property_read_u32(np, "cirrus,battery-threshold", &val);
|
if (of_property_read_u32(np, "cirrus,battery-threshold", &val))
|
||||||
|
val = -1u;
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case CS35L32_BATT_THRESH_3_1V:
|
case CS35L32_BATT_THRESH_3_1V:
|
||||||
case CS35L32_BATT_THRESH_3_2V:
|
case CS35L32_BATT_THRESH_3_2V:
|
||||||
@ -310,13 +316,15 @@ static int cs35l32_handle_of_data(struct i2c_client *i2c_client,
|
|||||||
case CS35L32_BATT_THRESH_3_4V:
|
case CS35L32_BATT_THRESH_3_4V:
|
||||||
pdata->batt_thresh = val;
|
pdata->batt_thresh = val;
|
||||||
break;
|
break;
|
||||||
|
case -1u:
|
||||||
default:
|
default:
|
||||||
dev_err(&i2c_client->dev,
|
dev_err(&i2c_client->dev,
|
||||||
"Wrong cirrus,battery-threshold DT value %d\n", val);
|
"Wrong cirrus,battery-threshold DT value %d\n", val);
|
||||||
pdata->batt_thresh = CS35L32_BATT_THRESH_3_3V;
|
pdata->batt_thresh = CS35L32_BATT_THRESH_3_3V;
|
||||||
}
|
}
|
||||||
|
|
||||||
of_property_read_u32(np, "cirrus,battery-recovery", &val);
|
if (of_property_read_u32(np, "cirrus,battery-recovery", &val))
|
||||||
|
val = -1u;
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case CS35L32_BATT_RECOV_3_1V:
|
case CS35L32_BATT_RECOV_3_1V:
|
||||||
case CS35L32_BATT_RECOV_3_2V:
|
case CS35L32_BATT_RECOV_3_2V:
|
||||||
@ -326,6 +334,7 @@ static int cs35l32_handle_of_data(struct i2c_client *i2c_client,
|
|||||||
case CS35L32_BATT_RECOV_3_6V:
|
case CS35L32_BATT_RECOV_3_6V:
|
||||||
pdata->batt_recov = val;
|
pdata->batt_recov = val;
|
||||||
break;
|
break;
|
||||||
|
case -1u:
|
||||||
default:
|
default:
|
||||||
dev_err(&i2c_client->dev,
|
dev_err(&i2c_client->dev,
|
||||||
"Wrong cirrus,battery-recovery DT value %d\n", val);
|
"Wrong cirrus,battery-recovery DT value %d\n", val);
|
||||||
|
@ -1108,6 +1108,9 @@ static int cs47l24_codec_remove(struct snd_soc_codec *codec)
|
|||||||
priv->core.arizona->dapm = NULL;
|
priv->core.arizona->dapm = NULL;
|
||||||
|
|
||||||
arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, priv);
|
arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, priv);
|
||||||
|
|
||||||
|
arizona_free_spk(codec);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1420,33 +1420,40 @@ static int hdmi_codec_remove(struct snd_soc_codec *codec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
static int hdmi_codec_resume(struct snd_soc_codec *codec)
|
static int hdmi_codec_prepare(struct device *dev)
|
||||||
{
|
{
|
||||||
struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec);
|
struct hdac_ext_device *edev = to_hda_ext_device(dev);
|
||||||
|
struct hdac_device *hdac = &edev->hdac;
|
||||||
|
|
||||||
|
pm_runtime_get_sync(&edev->hdac.dev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Power down afg.
|
||||||
|
* codec_read is preferred over codec_write to set the power state.
|
||||||
|
* This way verb is send to set the power state and response
|
||||||
|
* is received. So setting power state is ensured without using loop
|
||||||
|
* to read the state.
|
||||||
|
*/
|
||||||
|
snd_hdac_codec_read(hdac, hdac->afg, 0, AC_VERB_SET_POWER_STATE,
|
||||||
|
AC_PWRST_D3);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hdmi_codec_complete(struct device *dev)
|
||||||
|
{
|
||||||
|
struct hdac_ext_device *edev = to_hda_ext_device(dev);
|
||||||
struct hdac_hdmi_priv *hdmi = edev->private_data;
|
struct hdac_hdmi_priv *hdmi = edev->private_data;
|
||||||
struct hdac_hdmi_pin *pin;
|
struct hdac_hdmi_pin *pin;
|
||||||
struct hdac_device *hdac = &edev->hdac;
|
struct hdac_device *hdac = &edev->hdac;
|
||||||
struct hdac_bus *bus = hdac->bus;
|
|
||||||
int err;
|
/* Power up afg */
|
||||||
unsigned long timeout;
|
snd_hdac_codec_read(hdac, hdac->afg, 0, AC_VERB_SET_POWER_STATE,
|
||||||
|
AC_PWRST_D0);
|
||||||
|
|
||||||
hdac_hdmi_skl_enable_all_pins(&edev->hdac);
|
hdac_hdmi_skl_enable_all_pins(&edev->hdac);
|
||||||
hdac_hdmi_skl_enable_dp12(&edev->hdac);
|
hdac_hdmi_skl_enable_dp12(&edev->hdac);
|
||||||
|
|
||||||
/* Power up afg */
|
|
||||||
if (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D0)) {
|
|
||||||
|
|
||||||
snd_hdac_codec_write(hdac, hdac->afg, 0,
|
|
||||||
AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
|
|
||||||
|
|
||||||
/* Wait till power state is set to D0 */
|
|
||||||
timeout = jiffies + msecs_to_jiffies(1000);
|
|
||||||
while (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D0)
|
|
||||||
&& time_before(jiffies, timeout)) {
|
|
||||||
msleep(50);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* As the ELD notify callback request is not entertained while the
|
* As the ELD notify callback request is not entertained while the
|
||||||
* device is in suspend state. Need to manually check detection of
|
* device is in suspend state. Need to manually check detection of
|
||||||
@ -1455,28 +1462,16 @@ static int hdmi_codec_resume(struct snd_soc_codec *codec)
|
|||||||
list_for_each_entry(pin, &hdmi->pin_list, head)
|
list_for_each_entry(pin, &hdmi->pin_list, head)
|
||||||
hdac_hdmi_present_sense(pin, 1);
|
hdac_hdmi_present_sense(pin, 1);
|
||||||
|
|
||||||
/*
|
pm_runtime_put_sync(&edev->hdac.dev);
|
||||||
* Codec power is turned ON during controller resume.
|
|
||||||
* Turn it OFF here
|
|
||||||
*/
|
|
||||||
err = snd_hdac_display_power(bus, false);
|
|
||||||
if (err < 0) {
|
|
||||||
dev_err(bus->dev,
|
|
||||||
"Cannot turn OFF display power on i915, err: %d\n",
|
|
||||||
err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define hdmi_codec_resume NULL
|
#define hdmi_codec_prepare NULL
|
||||||
|
#define hdmi_codec_complete NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct snd_soc_codec_driver hdmi_hda_codec = {
|
static struct snd_soc_codec_driver hdmi_hda_codec = {
|
||||||
.probe = hdmi_codec_probe,
|
.probe = hdmi_codec_probe,
|
||||||
.remove = hdmi_codec_remove,
|
.remove = hdmi_codec_remove,
|
||||||
.resume = hdmi_codec_resume,
|
|
||||||
.idle_bias_off = true,
|
.idle_bias_off = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1561,7 +1556,6 @@ static int hdac_hdmi_runtime_suspend(struct device *dev)
|
|||||||
struct hdac_ext_device *edev = to_hda_ext_device(dev);
|
struct hdac_ext_device *edev = to_hda_ext_device(dev);
|
||||||
struct hdac_device *hdac = &edev->hdac;
|
struct hdac_device *hdac = &edev->hdac;
|
||||||
struct hdac_bus *bus = hdac->bus;
|
struct hdac_bus *bus = hdac->bus;
|
||||||
unsigned long timeout;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
dev_dbg(dev, "Enter: %s\n", __func__);
|
dev_dbg(dev, "Enter: %s\n", __func__);
|
||||||
@ -1570,20 +1564,15 @@ static int hdac_hdmi_runtime_suspend(struct device *dev)
|
|||||||
if (!bus)
|
if (!bus)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Power down afg */
|
/*
|
||||||
if (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D3)) {
|
* Power down afg.
|
||||||
snd_hdac_codec_write(hdac, hdac->afg, 0,
|
* codec_read is preferred over codec_write to set the power state.
|
||||||
AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
|
* This way verb is send to set the power state and response
|
||||||
|
* is received. So setting power state is ensured without using loop
|
||||||
/* Wait till power state is set to D3 */
|
* to read the state.
|
||||||
timeout = jiffies + msecs_to_jiffies(1000);
|
*/
|
||||||
while (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D3)
|
snd_hdac_codec_read(hdac, hdac->afg, 0, AC_VERB_SET_POWER_STATE,
|
||||||
&& time_before(jiffies, timeout)) {
|
AC_PWRST_D3);
|
||||||
|
|
||||||
msleep(50);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = snd_hdac_display_power(bus, false);
|
err = snd_hdac_display_power(bus, false);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(bus->dev, "Cannot turn on display power on i915\n");
|
dev_err(bus->dev, "Cannot turn on display power on i915\n");
|
||||||
@ -1616,9 +1605,8 @@ static int hdac_hdmi_runtime_resume(struct device *dev)
|
|||||||
hdac_hdmi_skl_enable_dp12(&edev->hdac);
|
hdac_hdmi_skl_enable_dp12(&edev->hdac);
|
||||||
|
|
||||||
/* Power up afg */
|
/* Power up afg */
|
||||||
if (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D0))
|
snd_hdac_codec_read(hdac, hdac->afg, 0, AC_VERB_SET_POWER_STATE,
|
||||||
snd_hdac_codec_write(hdac, hdac->afg, 0,
|
AC_PWRST_D0);
|
||||||
AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1629,6 +1617,8 @@ static int hdac_hdmi_runtime_resume(struct device *dev)
|
|||||||
|
|
||||||
static const struct dev_pm_ops hdac_hdmi_pm = {
|
static const struct dev_pm_ops hdac_hdmi_pm = {
|
||||||
SET_RUNTIME_PM_OPS(hdac_hdmi_runtime_suspend, hdac_hdmi_runtime_resume, NULL)
|
SET_RUNTIME_PM_OPS(hdac_hdmi_runtime_suspend, hdac_hdmi_runtime_resume, NULL)
|
||||||
|
.prepare = hdmi_codec_prepare,
|
||||||
|
.complete = hdmi_codec_complete,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct hda_device_id hdmi_list[] = {
|
static const struct hda_device_id hdmi_list[] = {
|
||||||
|
@ -343,9 +343,12 @@ static const struct snd_soc_dapm_widget nau8825_dapm_widgets[] = {
|
|||||||
SND_SOC_DAPM_SUPPLY("ADC Power", NAU8825_REG_ANALOG_ADC_2, 6, 0, NULL,
|
SND_SOC_DAPM_SUPPLY("ADC Power", NAU8825_REG_ANALOG_ADC_2, 6, 0, NULL,
|
||||||
0),
|
0),
|
||||||
|
|
||||||
/* ADC for button press detection */
|
/* ADC for button press detection. A dapm supply widget is used to
|
||||||
SND_SOC_DAPM_ADC("SAR", NULL, NAU8825_REG_SAR_CTRL,
|
* prevent dapm_power_widgets keeping the codec at SND_SOC_BIAS_ON
|
||||||
NAU8825_SAR_ADC_EN_SFT, 0),
|
* during suspend.
|
||||||
|
*/
|
||||||
|
SND_SOC_DAPM_SUPPLY("SAR", NAU8825_REG_SAR_CTRL,
|
||||||
|
NAU8825_SAR_ADC_EN_SFT, 0, NULL, 0),
|
||||||
|
|
||||||
SND_SOC_DAPM_PGA_S("ADACL", 2, NAU8825_REG_RDAC, 12, 0, NULL, 0),
|
SND_SOC_DAPM_PGA_S("ADACL", 2, NAU8825_REG_RDAC, 12, 0, NULL, 0),
|
||||||
SND_SOC_DAPM_PGA_S("ADACR", 2, NAU8825_REG_RDAC, 13, 0, NULL, 0),
|
SND_SOC_DAPM_PGA_S("ADACR", 2, NAU8825_REG_RDAC, 13, 0, NULL, 0),
|
||||||
@ -607,6 +610,16 @@ static bool nau8825_is_jack_inserted(struct regmap *regmap)
|
|||||||
|
|
||||||
static void nau8825_restart_jack_detection(struct regmap *regmap)
|
static void nau8825_restart_jack_detection(struct regmap *regmap)
|
||||||
{
|
{
|
||||||
|
/* Chip needs one FSCLK cycle in order to generate interrupts,
|
||||||
|
* as we cannot guarantee one will be provided by the system. Turning
|
||||||
|
* master mode on then off enables us to generate that FSCLK cycle
|
||||||
|
* with a minimum of contention on the clock bus.
|
||||||
|
*/
|
||||||
|
regmap_update_bits(regmap, NAU8825_REG_I2S_PCM_CTRL2,
|
||||||
|
NAU8825_I2S_MS_MASK, NAU8825_I2S_MS_MASTER);
|
||||||
|
regmap_update_bits(regmap, NAU8825_REG_I2S_PCM_CTRL2,
|
||||||
|
NAU8825_I2S_MS_MASK, NAU8825_I2S_MS_SLAVE);
|
||||||
|
|
||||||
/* this will restart the entire jack detection process including MIC/GND
|
/* this will restart the entire jack detection process including MIC/GND
|
||||||
* switching and create interrupts. We have to go from 0 to 1 and back
|
* switching and create interrupts. We have to go from 0 to 1 and back
|
||||||
* to 0 to restart.
|
* to 0 to restart.
|
||||||
@ -728,7 +741,10 @@ static irqreturn_t nau8825_interrupt(int irq, void *data)
|
|||||||
struct regmap *regmap = nau8825->regmap;
|
struct regmap *regmap = nau8825->regmap;
|
||||||
int active_irq, clear_irq = 0, event = 0, event_mask = 0;
|
int active_irq, clear_irq = 0, event = 0, event_mask = 0;
|
||||||
|
|
||||||
regmap_read(regmap, NAU8825_REG_IRQ_STATUS, &active_irq);
|
if (regmap_read(regmap, NAU8825_REG_IRQ_STATUS, &active_irq)) {
|
||||||
|
dev_err(nau8825->dev, "failed to read irq status\n");
|
||||||
|
return IRQ_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
if ((active_irq & NAU8825_JACK_EJECTION_IRQ_MASK) ==
|
if ((active_irq & NAU8825_JACK_EJECTION_IRQ_MASK) ==
|
||||||
NAU8825_JACK_EJECTION_DETECTED) {
|
NAU8825_JACK_EJECTION_DETECTED) {
|
||||||
@ -1141,33 +1157,74 @@ static int nau8825_set_bias_level(struct snd_soc_codec *codec,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = regcache_sync(nau8825->regmap);
|
|
||||||
if (ret) {
|
|
||||||
dev_err(codec->dev,
|
|
||||||
"Failed to sync cache: %d\n", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SND_SOC_BIAS_OFF:
|
case SND_SOC_BIAS_OFF:
|
||||||
if (nau8825->mclk_freq)
|
if (nau8825->mclk_freq)
|
||||||
clk_disable_unprepare(nau8825->mclk);
|
clk_disable_unprepare(nau8825->mclk);
|
||||||
|
|
||||||
regcache_mark_dirty(nau8825->regmap);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
static int nau8825_suspend(struct snd_soc_codec *codec)
|
||||||
|
{
|
||||||
|
struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec);
|
||||||
|
|
||||||
|
disable_irq(nau8825->irq);
|
||||||
|
regcache_cache_only(nau8825->regmap, true);
|
||||||
|
regcache_mark_dirty(nau8825->regmap);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nau8825_resume(struct snd_soc_codec *codec)
|
||||||
|
{
|
||||||
|
struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec);
|
||||||
|
|
||||||
|
/* The chip may lose power and reset in S3. regcache_sync restores
|
||||||
|
* register values including configurations for sysclk, irq, and
|
||||||
|
* jack/button detection.
|
||||||
|
*/
|
||||||
|
regcache_cache_only(nau8825->regmap, false);
|
||||||
|
regcache_sync(nau8825->regmap);
|
||||||
|
|
||||||
|
/* Check the jack plug status directly. If the headset is unplugged
|
||||||
|
* during S3 when the chip has no power, there will be no jack
|
||||||
|
* detection irq even after the nau8825_restart_jack_detection below,
|
||||||
|
* because the chip just thinks no headset has ever been plugged in.
|
||||||
|
*/
|
||||||
|
if (!nau8825_is_jack_inserted(nau8825->regmap)) {
|
||||||
|
nau8825_eject_jack(nau8825);
|
||||||
|
snd_soc_jack_report(nau8825->jack, 0, SND_JACK_HEADSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
enable_irq(nau8825->irq);
|
||||||
|
|
||||||
|
/* Run jack detection to check the type (OMTP or CTIA) of the headset
|
||||||
|
* if there is one. This handles the case where a different type of
|
||||||
|
* headset is plugged in during S3. This triggers an IRQ iff a headset
|
||||||
|
* is already plugged in.
|
||||||
|
*/
|
||||||
|
nau8825_restart_jack_detection(nau8825->regmap);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define nau8825_suspend NULL
|
||||||
|
#define nau8825_resume NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct snd_soc_codec_driver nau8825_codec_driver = {
|
static struct snd_soc_codec_driver nau8825_codec_driver = {
|
||||||
.probe = nau8825_codec_probe,
|
.probe = nau8825_codec_probe,
|
||||||
.set_sysclk = nau8825_set_sysclk,
|
.set_sysclk = nau8825_set_sysclk,
|
||||||
.set_pll = nau8825_set_pll,
|
.set_pll = nau8825_set_pll,
|
||||||
.set_bias_level = nau8825_set_bias_level,
|
.set_bias_level = nau8825_set_bias_level,
|
||||||
.suspend_bias_off = true,
|
.suspend_bias_off = true,
|
||||||
|
.suspend = nau8825_suspend,
|
||||||
|
.resume = nau8825_resume,
|
||||||
|
|
||||||
.controls = nau8825_controls,
|
.controls = nau8825_controls,
|
||||||
.num_controls = ARRAY_SIZE(nau8825_controls),
|
.num_controls = ARRAY_SIZE(nau8825_controls),
|
||||||
@ -1277,16 +1334,6 @@ static int nau8825_setup_irq(struct nau8825 *nau8825)
|
|||||||
regmap_update_bits(regmap, NAU8825_REG_ENA_CTRL,
|
regmap_update_bits(regmap, NAU8825_REG_ENA_CTRL,
|
||||||
NAU8825_ENABLE_DACR, NAU8825_ENABLE_DACR);
|
NAU8825_ENABLE_DACR, NAU8825_ENABLE_DACR);
|
||||||
|
|
||||||
/* Chip needs one FSCLK cycle in order to generate interrupts,
|
|
||||||
* as we cannot guarantee one will be provided by the system. Turning
|
|
||||||
* master mode on then off enables us to generate that FSCLK cycle
|
|
||||||
* with a minimum of contention on the clock bus.
|
|
||||||
*/
|
|
||||||
regmap_update_bits(regmap, NAU8825_REG_I2S_PCM_CTRL2,
|
|
||||||
NAU8825_I2S_MS_MASK, NAU8825_I2S_MS_MASTER);
|
|
||||||
regmap_update_bits(regmap, NAU8825_REG_I2S_PCM_CTRL2,
|
|
||||||
NAU8825_I2S_MS_MASK, NAU8825_I2S_MS_SLAVE);
|
|
||||||
|
|
||||||
ret = devm_request_threaded_irq(nau8825->dev, nau8825->irq, NULL,
|
ret = devm_request_threaded_irq(nau8825->dev, nau8825->irq, NULL,
|
||||||
nau8825_interrupt, IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
nau8825_interrupt, IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||||
"nau8825", nau8825);
|
"nau8825", nau8825);
|
||||||
@ -1354,36 +1401,6 @@ static int nau8825_i2c_remove(struct i2c_client *client)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
|
||||||
static int nau8825_suspend(struct device *dev)
|
|
||||||
{
|
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
|
||||||
struct nau8825 *nau8825 = dev_get_drvdata(dev);
|
|
||||||
|
|
||||||
disable_irq(client->irq);
|
|
||||||
regcache_cache_only(nau8825->regmap, true);
|
|
||||||
regcache_mark_dirty(nau8825->regmap);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int nau8825_resume(struct device *dev)
|
|
||||||
{
|
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
|
||||||
struct nau8825 *nau8825 = dev_get_drvdata(dev);
|
|
||||||
|
|
||||||
regcache_cache_only(nau8825->regmap, false);
|
|
||||||
regcache_sync(nau8825->regmap);
|
|
||||||
enable_irq(client->irq);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const struct dev_pm_ops nau8825_pm = {
|
|
||||||
SET_SYSTEM_SLEEP_PM_OPS(nau8825_suspend, nau8825_resume)
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct i2c_device_id nau8825_i2c_ids[] = {
|
static const struct i2c_device_id nau8825_i2c_ids[] = {
|
||||||
{ "nau8825", 0 },
|
{ "nau8825", 0 },
|
||||||
{ }
|
{ }
|
||||||
@ -1410,7 +1427,6 @@ static struct i2c_driver nau8825_driver = {
|
|||||||
.name = "nau8825",
|
.name = "nau8825",
|
||||||
.of_match_table = of_match_ptr(nau8825_of_ids),
|
.of_match_table = of_match_ptr(nau8825_of_ids),
|
||||||
.acpi_match_table = ACPI_PTR(nau8825_acpi_match),
|
.acpi_match_table = ACPI_PTR(nau8825_acpi_match),
|
||||||
.pm = &nau8825_pm,
|
|
||||||
},
|
},
|
||||||
.probe = nau8825_i2c_probe,
|
.probe = nau8825_i2c_probe,
|
||||||
.remove = nau8825_i2c_remove,
|
.remove = nau8825_i2c_remove,
|
||||||
|
@ -359,7 +359,7 @@ static const DECLARE_TLV_DB_RANGE(bst_tlv,
|
|||||||
|
|
||||||
/* Interface data select */
|
/* Interface data select */
|
||||||
static const char * const rt5640_data_select[] = {
|
static const char * const rt5640_data_select[] = {
|
||||||
"Normal", "left copy to right", "right copy to left", "Swap"};
|
"Normal", "Swap", "left copy to right", "right copy to left"};
|
||||||
|
|
||||||
static SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA,
|
static SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA,
|
||||||
RT5640_IF1_DAC_SEL_SFT, rt5640_data_select);
|
RT5640_IF1_DAC_SEL_SFT, rt5640_data_select);
|
||||||
|
@ -443,39 +443,39 @@
|
|||||||
#define RT5640_IF1_DAC_SEL_MASK (0x3 << 14)
|
#define RT5640_IF1_DAC_SEL_MASK (0x3 << 14)
|
||||||
#define RT5640_IF1_DAC_SEL_SFT 14
|
#define RT5640_IF1_DAC_SEL_SFT 14
|
||||||
#define RT5640_IF1_DAC_SEL_NOR (0x0 << 14)
|
#define RT5640_IF1_DAC_SEL_NOR (0x0 << 14)
|
||||||
#define RT5640_IF1_DAC_SEL_L2R (0x1 << 14)
|
#define RT5640_IF1_DAC_SEL_SWAP (0x1 << 14)
|
||||||
#define RT5640_IF1_DAC_SEL_R2L (0x2 << 14)
|
#define RT5640_IF1_DAC_SEL_L2R (0x2 << 14)
|
||||||
#define RT5640_IF1_DAC_SEL_SWAP (0x3 << 14)
|
#define RT5640_IF1_DAC_SEL_R2L (0x3 << 14)
|
||||||
#define RT5640_IF1_ADC_SEL_MASK (0x3 << 12)
|
#define RT5640_IF1_ADC_SEL_MASK (0x3 << 12)
|
||||||
#define RT5640_IF1_ADC_SEL_SFT 12
|
#define RT5640_IF1_ADC_SEL_SFT 12
|
||||||
#define RT5640_IF1_ADC_SEL_NOR (0x0 << 12)
|
#define RT5640_IF1_ADC_SEL_NOR (0x0 << 12)
|
||||||
#define RT5640_IF1_ADC_SEL_L2R (0x1 << 12)
|
#define RT5640_IF1_ADC_SEL_SWAP (0x1 << 12)
|
||||||
#define RT5640_IF1_ADC_SEL_R2L (0x2 << 12)
|
#define RT5640_IF1_ADC_SEL_L2R (0x2 << 12)
|
||||||
#define RT5640_IF1_ADC_SEL_SWAP (0x3 << 12)
|
#define RT5640_IF1_ADC_SEL_R2L (0x3 << 12)
|
||||||
#define RT5640_IF2_DAC_SEL_MASK (0x3 << 10)
|
#define RT5640_IF2_DAC_SEL_MASK (0x3 << 10)
|
||||||
#define RT5640_IF2_DAC_SEL_SFT 10
|
#define RT5640_IF2_DAC_SEL_SFT 10
|
||||||
#define RT5640_IF2_DAC_SEL_NOR (0x0 << 10)
|
#define RT5640_IF2_DAC_SEL_NOR (0x0 << 10)
|
||||||
#define RT5640_IF2_DAC_SEL_L2R (0x1 << 10)
|
#define RT5640_IF2_DAC_SEL_SWAP (0x1 << 10)
|
||||||
#define RT5640_IF2_DAC_SEL_R2L (0x2 << 10)
|
#define RT5640_IF2_DAC_SEL_L2R (0x2 << 10)
|
||||||
#define RT5640_IF2_DAC_SEL_SWAP (0x3 << 10)
|
#define RT5640_IF2_DAC_SEL_R2L (0x3 << 10)
|
||||||
#define RT5640_IF2_ADC_SEL_MASK (0x3 << 8)
|
#define RT5640_IF2_ADC_SEL_MASK (0x3 << 8)
|
||||||
#define RT5640_IF2_ADC_SEL_SFT 8
|
#define RT5640_IF2_ADC_SEL_SFT 8
|
||||||
#define RT5640_IF2_ADC_SEL_NOR (0x0 << 8)
|
#define RT5640_IF2_ADC_SEL_NOR (0x0 << 8)
|
||||||
#define RT5640_IF2_ADC_SEL_L2R (0x1 << 8)
|
#define RT5640_IF2_ADC_SEL_SWAP (0x1 << 8)
|
||||||
#define RT5640_IF2_ADC_SEL_R2L (0x2 << 8)
|
#define RT5640_IF2_ADC_SEL_L2R (0x2 << 8)
|
||||||
#define RT5640_IF2_ADC_SEL_SWAP (0x3 << 8)
|
#define RT5640_IF2_ADC_SEL_R2L (0x3 << 8)
|
||||||
#define RT5640_IF3_DAC_SEL_MASK (0x3 << 6)
|
#define RT5640_IF3_DAC_SEL_MASK (0x3 << 6)
|
||||||
#define RT5640_IF3_DAC_SEL_SFT 6
|
#define RT5640_IF3_DAC_SEL_SFT 6
|
||||||
#define RT5640_IF3_DAC_SEL_NOR (0x0 << 6)
|
#define RT5640_IF3_DAC_SEL_NOR (0x0 << 6)
|
||||||
#define RT5640_IF3_DAC_SEL_L2R (0x1 << 6)
|
#define RT5640_IF3_DAC_SEL_SWAP (0x1 << 6)
|
||||||
#define RT5640_IF3_DAC_SEL_R2L (0x2 << 6)
|
#define RT5640_IF3_DAC_SEL_L2R (0x2 << 6)
|
||||||
#define RT5640_IF3_DAC_SEL_SWAP (0x3 << 6)
|
#define RT5640_IF3_DAC_SEL_R2L (0x3 << 6)
|
||||||
#define RT5640_IF3_ADC_SEL_MASK (0x3 << 4)
|
#define RT5640_IF3_ADC_SEL_MASK (0x3 << 4)
|
||||||
#define RT5640_IF3_ADC_SEL_SFT 4
|
#define RT5640_IF3_ADC_SEL_SFT 4
|
||||||
#define RT5640_IF3_ADC_SEL_NOR (0x0 << 4)
|
#define RT5640_IF3_ADC_SEL_NOR (0x0 << 4)
|
||||||
#define RT5640_IF3_ADC_SEL_L2R (0x1 << 4)
|
#define RT5640_IF3_ADC_SEL_SWAP (0x1 << 4)
|
||||||
#define RT5640_IF3_ADC_SEL_R2L (0x2 << 4)
|
#define RT5640_IF3_ADC_SEL_L2R (0x2 << 4)
|
||||||
#define RT5640_IF3_ADC_SEL_SWAP (0x3 << 4)
|
#define RT5640_IF3_ADC_SEL_R2L (0x3 << 4)
|
||||||
|
|
||||||
/* REC Left Mixer Control 1 (0x3b) */
|
/* REC Left Mixer Control 1 (0x3b) */
|
||||||
#define RT5640_G_HP_L_RM_L_MASK (0x7 << 13)
|
#define RT5640_G_HP_L_RM_L_MASK (0x7 << 13)
|
||||||
|
@ -1955,11 +1955,16 @@ err_adsp2_codec_probe:
|
|||||||
static int wm5102_codec_remove(struct snd_soc_codec *codec)
|
static int wm5102_codec_remove(struct snd_soc_codec *codec)
|
||||||
{
|
{
|
||||||
struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
|
struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||||
|
struct arizona *arizona = priv->core.arizona;
|
||||||
|
|
||||||
wm_adsp2_codec_remove(&priv->core.adsp[0], codec);
|
wm_adsp2_codec_remove(&priv->core.adsp[0], codec);
|
||||||
|
|
||||||
priv->core.arizona->dapm = NULL;
|
priv->core.arizona->dapm = NULL;
|
||||||
|
|
||||||
|
arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, priv);
|
||||||
|
|
||||||
|
arizona_free_spk(codec);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2298,6 +2298,8 @@ static int wm5110_codec_remove(struct snd_soc_codec *codec)
|
|||||||
|
|
||||||
arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, priv);
|
arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, priv);
|
||||||
|
|
||||||
|
arizona_free_spk(codec);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2471,7 +2471,7 @@ static void wm8962_configure_bclk(struct snd_soc_codec *codec)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dev_warn(codec->dev, "Unknown DSPCLK divisor read back\n");
|
dev_warn(codec->dev, "Unknown DSPCLK divisor read back\n");
|
||||||
dspclk = wm8962->sysclk;
|
dspclk = wm8962->sysclk_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(codec->dev, "DSPCLK is %dHz, BCLK %d\n", dspclk, wm8962->bclk);
|
dev_dbg(codec->dev, "DSPCLK is %dHz, BCLK %d\n", dspclk, wm8962->bclk);
|
||||||
|
@ -1072,6 +1072,8 @@ static int wm8997_codec_remove(struct snd_soc_codec *codec)
|
|||||||
|
|
||||||
priv->core.arizona->dapm = NULL;
|
priv->core.arizona->dapm = NULL;
|
||||||
|
|
||||||
|
arizona_free_spk(codec);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1324,6 +1324,8 @@ static int wm8998_codec_remove(struct snd_soc_codec *codec)
|
|||||||
|
|
||||||
priv->core.arizona->dapm = NULL;
|
priv->core.arizona->dapm = NULL;
|
||||||
|
|
||||||
|
arizona_free_spk(codec);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +163,6 @@ config SND_SOC_INTEL_SKYLAKE
|
|||||||
tristate
|
tristate
|
||||||
select SND_HDA_EXT_CORE
|
select SND_HDA_EXT_CORE
|
||||||
select SND_SOC_TOPOLOGY
|
select SND_SOC_TOPOLOGY
|
||||||
select SND_HDA_I915
|
|
||||||
select SND_SOC_INTEL_SST
|
select SND_SOC_INTEL_SST
|
||||||
|
|
||||||
config SND_SOC_INTEL_SKL_RT286_MACH
|
config SND_SOC_INTEL_SKL_RT286_MACH
|
||||||
|
@ -1345,7 +1345,7 @@ int sst_hsw_stream_reset(struct sst_hsw *hsw, struct sst_hsw_stream *stream)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* wait for pause to complete before we reset the stream */
|
/* wait for pause to complete before we reset the stream */
|
||||||
while (stream->running && tries--)
|
while (stream->running && --tries)
|
||||||
msleep(1);
|
msleep(1);
|
||||||
if (!tries) {
|
if (!tries) {
|
||||||
dev_err(hsw->dev, "error: reset stream %d still running\n",
|
dev_err(hsw->dev, "error: reset stream %d still running\n",
|
||||||
|
@ -336,6 +336,11 @@ void skl_dsp_free(struct sst_dsp *dsp)
|
|||||||
skl_ipc_int_disable(dsp);
|
skl_ipc_int_disable(dsp);
|
||||||
|
|
||||||
free_irq(dsp->irq, dsp);
|
free_irq(dsp->irq, dsp);
|
||||||
|
dsp->cl_dev.ops.cl_cleanup_controller(dsp);
|
||||||
|
skl_cldma_int_disable(dsp);
|
||||||
|
skl_ipc_op_int_disable(dsp);
|
||||||
|
skl_ipc_int_disable(dsp);
|
||||||
|
|
||||||
skl_dsp_disable_core(dsp);
|
skl_dsp_disable_core(dsp);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(skl_dsp_free);
|
EXPORT_SYMBOL_GPL(skl_dsp_free);
|
||||||
|
@ -239,6 +239,7 @@ static void skl_tplg_update_buffer_size(struct skl_sst *ctx,
|
|||||||
{
|
{
|
||||||
int multiplier = 1;
|
int multiplier = 1;
|
||||||
struct skl_module_fmt *in_fmt, *out_fmt;
|
struct skl_module_fmt *in_fmt, *out_fmt;
|
||||||
|
int in_rate, out_rate;
|
||||||
|
|
||||||
|
|
||||||
/* Since fixups is applied to pin 0 only, ibs, obs needs
|
/* Since fixups is applied to pin 0 only, ibs, obs needs
|
||||||
@ -249,13 +250,22 @@ static void skl_tplg_update_buffer_size(struct skl_sst *ctx,
|
|||||||
|
|
||||||
if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT)
|
if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT)
|
||||||
multiplier = 5;
|
multiplier = 5;
|
||||||
mcfg->ibs = (in_fmt->s_freq / 1000) *
|
|
||||||
(mcfg->in_fmt->channels) *
|
if (in_fmt->s_freq % 1000)
|
||||||
|
in_rate = (in_fmt->s_freq / 1000) + 1;
|
||||||
|
else
|
||||||
|
in_rate = (in_fmt->s_freq / 1000);
|
||||||
|
|
||||||
|
mcfg->ibs = in_rate * (mcfg->in_fmt->channels) *
|
||||||
(mcfg->in_fmt->bit_depth >> 3) *
|
(mcfg->in_fmt->bit_depth >> 3) *
|
||||||
multiplier;
|
multiplier;
|
||||||
|
|
||||||
mcfg->obs = (mcfg->out_fmt->s_freq / 1000) *
|
if (mcfg->out_fmt->s_freq % 1000)
|
||||||
(mcfg->out_fmt->channels) *
|
out_rate = (mcfg->out_fmt->s_freq / 1000) + 1;
|
||||||
|
else
|
||||||
|
out_rate = (mcfg->out_fmt->s_freq / 1000);
|
||||||
|
|
||||||
|
mcfg->obs = out_rate * (mcfg->out_fmt->channels) *
|
||||||
(mcfg->out_fmt->bit_depth >> 3) *
|
(mcfg->out_fmt->bit_depth >> 3) *
|
||||||
multiplier;
|
multiplier;
|
||||||
}
|
}
|
||||||
@ -485,11 +495,15 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe)
|
|||||||
if (!skl_is_pipe_mcps_avail(skl, mconfig))
|
if (!skl_is_pipe_mcps_avail(skl, mconfig))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
skl_tplg_alloc_pipe_mcps(skl, mconfig);
|
||||||
|
|
||||||
if (mconfig->is_loadable && ctx->dsp->fw_ops.load_mod) {
|
if (mconfig->is_loadable && ctx->dsp->fw_ops.load_mod) {
|
||||||
ret = ctx->dsp->fw_ops.load_mod(ctx->dsp,
|
ret = ctx->dsp->fw_ops.load_mod(ctx->dsp,
|
||||||
mconfig->id.module_id, mconfig->guid);
|
mconfig->id.module_id, mconfig->guid);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
mconfig->m_state = SKL_MODULE_LOADED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update blob if blob is null for be with default value */
|
/* update blob if blob is null for be with default value */
|
||||||
@ -509,7 +523,6 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe)
|
|||||||
ret = skl_tplg_set_module_params(w, ctx);
|
ret = skl_tplg_set_module_params(w, ctx);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
skl_tplg_alloc_pipe_mcps(skl, mconfig);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -524,7 +537,8 @@ static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx,
|
|||||||
list_for_each_entry(w_module, &pipe->w_list, node) {
|
list_for_each_entry(w_module, &pipe->w_list, node) {
|
||||||
mconfig = w_module->w->priv;
|
mconfig = w_module->w->priv;
|
||||||
|
|
||||||
if (mconfig->is_loadable && ctx->dsp->fw_ops.unload_mod)
|
if (mconfig->is_loadable && ctx->dsp->fw_ops.unload_mod &&
|
||||||
|
mconfig->m_state > SKL_MODULE_UNINIT)
|
||||||
return ctx->dsp->fw_ops.unload_mod(ctx->dsp,
|
return ctx->dsp->fw_ops.unload_mod(ctx->dsp,
|
||||||
mconfig->id.module_id);
|
mconfig->id.module_id);
|
||||||
}
|
}
|
||||||
@ -558,6 +572,9 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
|
|||||||
if (!skl_is_pipe_mem_avail(skl, mconfig))
|
if (!skl_is_pipe_mem_avail(skl, mconfig))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
skl_tplg_alloc_pipe_mem(skl, mconfig);
|
||||||
|
skl_tplg_alloc_pipe_mcps(skl, mconfig);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a list of modules for pipe.
|
* Create a list of modules for pipe.
|
||||||
* This list contains modules from source to sink
|
* This list contains modules from source to sink
|
||||||
@ -601,9 +618,6 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
|
|||||||
src_module = dst_module;
|
src_module = dst_module;
|
||||||
}
|
}
|
||||||
|
|
||||||
skl_tplg_alloc_pipe_mem(skl, mconfig);
|
|
||||||
skl_tplg_alloc_pipe_mcps(skl, mconfig);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,10 +274,10 @@ struct skl_pipe {
|
|||||||
|
|
||||||
enum skl_module_state {
|
enum skl_module_state {
|
||||||
SKL_MODULE_UNINIT = 0,
|
SKL_MODULE_UNINIT = 0,
|
||||||
SKL_MODULE_INIT_DONE = 1,
|
SKL_MODULE_LOADED = 1,
|
||||||
SKL_MODULE_LOADED = 2,
|
SKL_MODULE_INIT_DONE = 2,
|
||||||
SKL_MODULE_UNLOADED = 3,
|
SKL_MODULE_BIND_DONE = 3,
|
||||||
SKL_MODULE_BIND_DONE = 4
|
SKL_MODULE_UNLOADED = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct skl_module_cfg {
|
struct skl_module_cfg {
|
||||||
|
@ -222,6 +222,7 @@ static int skl_suspend(struct device *dev)
|
|||||||
struct hdac_ext_bus *ebus = pci_get_drvdata(pci);
|
struct hdac_ext_bus *ebus = pci_get_drvdata(pci);
|
||||||
struct skl *skl = ebus_to_skl(ebus);
|
struct skl *skl = ebus_to_skl(ebus);
|
||||||
struct hdac_bus *bus = ebus_to_hbus(ebus);
|
struct hdac_bus *bus = ebus_to_hbus(ebus);
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do not suspend if streams which are marked ignore suspend are
|
* Do not suspend if streams which are marked ignore suspend are
|
||||||
@ -232,10 +233,20 @@ static int skl_suspend(struct device *dev)
|
|||||||
enable_irq_wake(bus->irq);
|
enable_irq_wake(bus->irq);
|
||||||
pci_save_state(pci);
|
pci_save_state(pci);
|
||||||
pci_disable_device(pci);
|
pci_disable_device(pci);
|
||||||
return 0;
|
|
||||||
} else {
|
} else {
|
||||||
return _skl_suspend(ebus);
|
ret = _skl_suspend(ebus);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
|
||||||
|
ret = snd_hdac_display_power(bus, false);
|
||||||
|
if (ret < 0)
|
||||||
|
dev_err(bus->dev,
|
||||||
|
"Cannot turn OFF display power on i915\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int skl_resume(struct device *dev)
|
static int skl_resume(struct device *dev)
|
||||||
@ -316,17 +327,20 @@ static int skl_free(struct hdac_ext_bus *ebus)
|
|||||||
|
|
||||||
if (bus->irq >= 0)
|
if (bus->irq >= 0)
|
||||||
free_irq(bus->irq, (void *)bus);
|
free_irq(bus->irq, (void *)bus);
|
||||||
if (bus->remap_addr)
|
|
||||||
iounmap(bus->remap_addr);
|
|
||||||
|
|
||||||
snd_hdac_bus_free_stream_pages(bus);
|
snd_hdac_bus_free_stream_pages(bus);
|
||||||
snd_hdac_stream_free_all(ebus);
|
snd_hdac_stream_free_all(ebus);
|
||||||
snd_hdac_link_free_all(ebus);
|
snd_hdac_link_free_all(ebus);
|
||||||
|
|
||||||
|
if (bus->remap_addr)
|
||||||
|
iounmap(bus->remap_addr);
|
||||||
|
|
||||||
pci_release_regions(skl->pci);
|
pci_release_regions(skl->pci);
|
||||||
pci_disable_device(skl->pci);
|
pci_disable_device(skl->pci);
|
||||||
|
|
||||||
snd_hdac_ext_bus_exit(ebus);
|
snd_hdac_ext_bus_exit(ebus);
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
|
||||||
|
snd_hdac_i915_exit(&ebus->bus);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -719,12 +733,12 @@ static void skl_remove(struct pci_dev *pci)
|
|||||||
if (skl->tplg)
|
if (skl->tplg)
|
||||||
release_firmware(skl->tplg);
|
release_firmware(skl->tplg);
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
|
|
||||||
snd_hdac_i915_exit(&ebus->bus);
|
|
||||||
|
|
||||||
if (pci_dev_run_wake(pci))
|
if (pci_dev_run_wake(pci))
|
||||||
pm_runtime_get_noresume(&pci->dev);
|
pm_runtime_get_noresume(&pci->dev);
|
||||||
pci_dev_put(pci);
|
|
||||||
|
/* codec removal, invoke bus_device_remove */
|
||||||
|
snd_hdac_ext_bus_device_remove(ebus);
|
||||||
|
|
||||||
skl_platform_unregister(&pci->dev);
|
skl_platform_unregister(&pci->dev);
|
||||||
skl_free_dsp(skl);
|
skl_free_dsp(skl);
|
||||||
skl_machine_device_unregister(skl);
|
skl_machine_device_unregister(skl);
|
||||||
|
@ -2188,6 +2188,13 @@ static ssize_t dapm_widget_show_component(struct snd_soc_component *cmpnt,
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
char *state = "not set";
|
char *state = "not set";
|
||||||
|
|
||||||
|
/* card won't be set for the dummy component, as a spot fix
|
||||||
|
* we're checking for that case specifically here but in future
|
||||||
|
* we will ensure that the dummy component looks like others.
|
||||||
|
*/
|
||||||
|
if (!cmpnt->card)
|
||||||
|
return 0;
|
||||||
|
|
||||||
list_for_each_entry(w, &cmpnt->card->widgets, list) {
|
list_for_each_entry(w, &cmpnt->card->widgets, list) {
|
||||||
if (w->dapm != dapm)
|
if (w->dapm != dapm)
|
||||||
continue;
|
continue;
|
||||||
|
Loading…
Reference in New Issue
Block a user