summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/core/oss/pcm_oss.c14
-rw-r--r--sound/core/pcm_native.c2
-rw-r--r--sound/core/seq/seq_clientmgr.c4
-rw-r--r--sound/core/seq/seq_prioq.c28
-rw-r--r--sound/core/seq/seq_prioq.h6
-rw-r--r--sound/core/seq/seq_queue.c28
-rw-r--r--sound/drivers/aloop.c17
-rw-r--r--sound/firewire/amdtp-stream-trace.h2
-rw-r--r--sound/pci/hda/hda_intel.c49
-rw-r--r--sound/pci/hda/hda_intel.h3
-rw-r--r--sound/pci/hda/patch_realtek.c20
-rw-r--r--sound/soc/amd/acp-pcm-dma.c16
-rw-r--r--sound/soc/amd/acp.h2
-rw-r--r--sound/soc/codecs/hdmi-codec.c7
-rw-r--r--sound/soc/codecs/rt5651.c1
-rw-r--r--sound/soc/codecs/sgtl5000.c26
-rw-r--r--sound/soc/codecs/wm_adsp.c14
-rw-r--r--sound/soc/sunxi/sun4i-i2s.c2
-rw-r--r--sound/usb/quirks.c1
19 files changed, 152 insertions, 90 deletions
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index b044c0a5a674..441405081195 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -1326,7 +1326,7 @@ static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const cha
static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const char __user *buf, size_t bytes)
{
size_t xfer = 0;
- ssize_t tmp;
+ ssize_t tmp = 0;
struct snd_pcm_runtime *runtime = substream->runtime;
if (atomic_read(&substream->mmap_count))
@@ -1433,7 +1433,7 @@ static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf,
static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __user *buf, size_t bytes)
{
size_t xfer = 0;
- ssize_t tmp;
+ ssize_t tmp = 0;
struct snd_pcm_runtime *runtime = substream->runtime;
if (atomic_read(&substream->mmap_count))
@@ -1762,10 +1762,9 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
return -ENOMEM;
_snd_pcm_hw_params_any(params);
err = snd_pcm_hw_refine(substream, params);
- format_mask = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
- kfree(params);
if (err < 0)
- return err;
+ goto error;
+ format_mask = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
for (fmt = 0; fmt < 32; ++fmt) {
if (snd_mask_test(format_mask, fmt)) {
int f = snd_pcm_oss_format_to(fmt);
@@ -1773,7 +1772,10 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
formats |= f;
}
}
- return formats;
+
+ error:
+ kfree(params);
+ return err < 0 ? err : formats;
}
static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format)
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 77ba50ddcf9e..d18b3982548b 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -3422,7 +3422,7 @@ int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream,
area,
substream->runtime->dma_area,
substream->runtime->dma_addr,
- area->vm_end - area->vm_start);
+ substream->runtime->dma_bytes);
#endif /* CONFIG_X86 */
/* mmap with fault handler */
area->vm_ops = &snd_pcm_vm_ops_data_fault;
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 918338dea5b9..61a07fe34cd2 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -255,12 +255,12 @@ static int seq_free_client1(struct snd_seq_client *client)
if (!client)
return 0;
- snd_seq_delete_all_ports(client);
- snd_seq_queue_client_leave(client->number);
spin_lock_irqsave(&clients_lock, flags);
clienttablock[client->number] = 1;
clienttab[client->number] = NULL;
spin_unlock_irqrestore(&clients_lock, flags);
+ snd_seq_delete_all_ports(client);
+ snd_seq_queue_client_leave(client->number);
snd_use_lock_sync(&client->use_lock);
snd_seq_queue_client_termination(client->number);
if (client->pool)
diff --git a/sound/core/seq/seq_prioq.c b/sound/core/seq/seq_prioq.c
index bc1c8488fc2a..2bc6759e4adc 100644
--- a/sound/core/seq/seq_prioq.c
+++ b/sound/core/seq/seq_prioq.c
@@ -87,7 +87,7 @@ void snd_seq_prioq_delete(struct snd_seq_prioq **fifo)
if (f->cells > 0) {
/* drain prioQ */
while (f->cells > 0)
- snd_seq_cell_free(snd_seq_prioq_cell_out(f));
+ snd_seq_cell_free(snd_seq_prioq_cell_out(f, NULL));
}
kfree(f);
@@ -214,8 +214,18 @@ int snd_seq_prioq_cell_in(struct snd_seq_prioq * f,
return 0;
}
+/* return 1 if the current time >= event timestamp */
+static int event_is_ready(struct snd_seq_event *ev, void *current_time)
+{
+ if ((ev->flags & SNDRV_SEQ_TIME_STAMP_MASK) == SNDRV_SEQ_TIME_STAMP_TICK)
+ return snd_seq_compare_tick_time(current_time, &ev->time.tick);
+ else
+ return snd_seq_compare_real_time(current_time, &ev->time.time);
+}
+
/* dequeue cell from prioq */
-struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f)
+struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f,
+ void *current_time)
{
struct snd_seq_event_cell *cell;
unsigned long flags;
@@ -227,6 +237,8 @@ struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f)
spin_lock_irqsave(&f->lock, flags);
cell = f->head;
+ if (cell && current_time && !event_is_ready(&cell->event, current_time))
+ cell = NULL;
if (cell) {
f->head = cell->next;
@@ -252,18 +264,6 @@ int snd_seq_prioq_avail(struct snd_seq_prioq * f)
return f->cells;
}
-
-/* peek at cell at the head of the prioq */
-struct snd_seq_event_cell *snd_seq_prioq_cell_peek(struct snd_seq_prioq * f)
-{
- if (f == NULL) {
- pr_debug("ALSA: seq: snd_seq_prioq_cell_in() called with NULL prioq\n");
- return NULL;
- }
- return f->head;
-}
-
-
static inline int prioq_match(struct snd_seq_event_cell *cell,
int client, int timestamp)
{
diff --git a/sound/core/seq/seq_prioq.h b/sound/core/seq/seq_prioq.h
index d38bb78d9345..2c315ca10fc4 100644
--- a/sound/core/seq/seq_prioq.h
+++ b/sound/core/seq/seq_prioq.h
@@ -44,14 +44,12 @@ void snd_seq_prioq_delete(struct snd_seq_prioq **fifo);
int snd_seq_prioq_cell_in(struct snd_seq_prioq *f, struct snd_seq_event_cell *cell);
/* dequeue cell from prioq */
-struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f);
+struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f,
+ void *current_time);
/* return number of events available in prioq */
int snd_seq_prioq_avail(struct snd_seq_prioq *f);
-/* peek at cell at the head of the prioq */
-struct snd_seq_event_cell *snd_seq_prioq_cell_peek(struct snd_seq_prioq *f);
-
/* client left queue */
void snd_seq_prioq_leave(struct snd_seq_prioq *f, int client, int timestamp);
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index 0428e9061b47..b377f5048352 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -277,30 +277,20 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop)
__again:
/* Process tick queue... */
- while ((cell = snd_seq_prioq_cell_peek(q->tickq)) != NULL) {
- if (snd_seq_compare_tick_time(&q->timer->tick.cur_tick,
- &cell->event.time.tick)) {
- cell = snd_seq_prioq_cell_out(q->tickq);
- if (cell)
- snd_seq_dispatch_event(cell, atomic, hop);
- } else {
- /* event remains in the queue */
+ for (;;) {
+ cell = snd_seq_prioq_cell_out(q->tickq,
+ &q->timer->tick.cur_tick);
+ if (!cell)
break;
- }
+ snd_seq_dispatch_event(cell, atomic, hop);
}
-
/* Process time queue... */
- while ((cell = snd_seq_prioq_cell_peek(q->timeq)) != NULL) {
- if (snd_seq_compare_real_time(&q->timer->cur_time,
- &cell->event.time.time)) {
- cell = snd_seq_prioq_cell_out(q->timeq);
- if (cell)
- snd_seq_dispatch_event(cell, atomic, hop);
- } else {
- /* event remains in the queue */
+ for (;;) {
+ cell = snd_seq_prioq_cell_out(q->timeq, &q->timer->cur_time);
+ if (!cell)
break;
- }
+ snd_seq_dispatch_event(cell, atomic, hop);
}
/* free lock */
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
index 0333143a1fa7..1063a4377502 100644
--- a/sound/drivers/aloop.c
+++ b/sound/drivers/aloop.c
@@ -192,6 +192,11 @@ static inline void loopback_timer_stop(struct loopback_pcm *dpcm)
dpcm->timer.expires = 0;
}
+static inline void loopback_timer_stop_sync(struct loopback_pcm *dpcm)
+{
+ del_timer_sync(&dpcm->timer);
+}
+
#define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK)
#define CABLE_VALID_CAPTURE (1 << SNDRV_PCM_STREAM_CAPTURE)
#define CABLE_VALID_BOTH (CABLE_VALID_PLAYBACK|CABLE_VALID_CAPTURE)
@@ -326,6 +331,8 @@ static int loopback_prepare(struct snd_pcm_substream *substream)
struct loopback_cable *cable = dpcm->cable;
int bps, salign;
+ loopback_timer_stop_sync(dpcm);
+
salign = (snd_pcm_format_width(runtime->format) *
runtime->channels) / 8;
bps = salign * runtime->rate;
@@ -659,7 +666,9 @@ static void free_cable(struct snd_pcm_substream *substream)
return;
if (cable->streams[!substream->stream]) {
/* other stream is still alive */
+ spin_lock_irq(&cable->lock);
cable->streams[substream->stream] = NULL;
+ spin_unlock_irq(&cable->lock);
} else {
/* free the cable */
loopback->cables[substream->number][dev] = NULL;
@@ -698,7 +707,6 @@ static int loopback_open(struct snd_pcm_substream *substream)
loopback->cables[substream->number][dev] = cable;
}
dpcm->cable = cable;
- cable->streams[substream->stream] = dpcm;
snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
@@ -730,6 +738,11 @@ static int loopback_open(struct snd_pcm_substream *substream)
runtime->hw = loopback_pcm_hardware;
else
runtime->hw = cable->hw;
+
+ spin_lock_irq(&cable->lock);
+ cable->streams[substream->stream] = dpcm;
+ spin_unlock_irq(&cable->lock);
+
unlock:
if (err < 0) {
free_cable(substream);
@@ -744,7 +757,7 @@ static int loopback_close(struct snd_pcm_substream *substream)
struct loopback *loopback = substream->private_data;
struct loopback_pcm *dpcm = substream->runtime->private_data;
- loopback_timer_stop(dpcm);
+ loopback_timer_stop_sync(dpcm);
mutex_lock(&loopback->cable_lock);
free_cable(substream);
mutex_unlock(&loopback->cable_lock);
diff --git a/sound/firewire/amdtp-stream-trace.h b/sound/firewire/amdtp-stream-trace.h
index ea0d486652c8..54cdd4ffa9ce 100644
--- a/sound/firewire/amdtp-stream-trace.h
+++ b/sound/firewire/amdtp-stream-trace.h
@@ -14,7 +14,7 @@
#include <linux/tracepoint.h>
TRACE_EVENT(in_packet,
- TP_PROTO(const struct amdtp_stream *s, u32 cycles, u32 cip_header[2], unsigned int payload_length, unsigned int index),
+ TP_PROTO(const struct amdtp_stream *s, u32 cycles, u32 *cip_header, unsigned int payload_length, unsigned int index),
TP_ARGS(s, cycles, cip_header, payload_length, index),
TP_STRUCT__entry(
__field(unsigned int, second)
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 96143df19b21..e2f649fffd56 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -181,11 +181,15 @@ static const struct kernel_param_ops param_ops_xint = {
};
#define param_check_xint param_check_int
-static int power_save = -1;
+static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT;
module_param(power_save, xint, 0644);
MODULE_PARM_DESC(power_save, "Automatic power-saving timeout "
"(in second, 0 = disable).");
+static bool pm_blacklist = true;
+module_param(pm_blacklist, bool, 0644);
+MODULE_PARM_DESC(pm_blacklist, "Enable power-management blacklist");
+
/* reset the HD-audio controller in power save mode.
* this may give more power-saving, but will take longer time to
* wake up.
@@ -371,6 +375,7 @@ enum {
((pci)->device == 0x160c))
#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
+#define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348)
static char *driver_short_names[] = {
[AZX_DRIVER_ICH] = "HDA Intel",
@@ -1227,6 +1232,7 @@ static void azx_vs_set_state(struct pci_dev *pci,
struct snd_card *card = pci_get_drvdata(pci);
struct azx *chip = card->private_data;
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
+ struct hda_codec *codec;
bool disabled;
wait_for_completion(&hda->probe_wait);
@@ -1251,8 +1257,12 @@ static void azx_vs_set_state(struct pci_dev *pci,
dev_info(chip->card->dev, "%s via vga_switcheroo\n",
disabled ? "Disabling" : "Enabling");
if (disabled) {
- pm_runtime_put_sync_suspend(card->dev);
- azx_suspend(card->dev);
+ list_for_each_codec(codec, &chip->bus) {
+ pm_runtime_suspend(hda_codec_dev(codec));
+ pm_runtime_disable(hda_codec_dev(codec));
+ }
+ pm_runtime_suspend(card->dev);
+ pm_runtime_disable(card->dev);
/* when we get suspended by vga_switcheroo we end up in D3cold,
* however we have no ACPI handle, so pci/acpi can't put us there,
* put ourselves there */
@@ -1263,9 +1273,12 @@ static void azx_vs_set_state(struct pci_dev *pci,
"Cannot lock devices!\n");
} else {
snd_hda_unlock_devices(&chip->bus);
- pm_runtime_get_noresume(card->dev);
chip->disabled = false;
- azx_resume(card->dev);
+ pm_runtime_enable(card->dev);
+ list_for_each_codec(codec, &chip->bus) {
+ pm_runtime_enable(hda_codec_dev(codec));
+ pm_runtime_resume(hda_codec_dev(codec));
+ }
}
}
}
@@ -1295,6 +1308,7 @@ static void init_vga_switcheroo(struct azx *chip)
dev_info(chip->card->dev,
"Handle vga_switcheroo audio client\n");
hda->use_vga_switcheroo = 1;
+ chip->driver_caps |= AZX_DCAPS_PM_RUNTIME;
pci_dev_put(p);
}
}
@@ -1320,9 +1334,6 @@ static int register_vga_switcheroo(struct azx *chip)
return err;
hda->vga_switcheroo_registered = 1;
- /* register as an optimus hdmi audio power domain */
- vga_switcheroo_init_domain_pm_optimus_hdmi_audio(chip->card->dev,
- &hda->hdmi_pm_domain);
return 0;
}
#else
@@ -1351,10 +1362,8 @@ static int azx_free(struct azx *chip)
if (use_vga_switcheroo(hda)) {
if (chip->disabled && hda->probe_continued)
snd_hda_unlock_devices(&chip->bus);
- if (hda->vga_switcheroo_registered) {
+ if (hda->vga_switcheroo_registered)
vga_switcheroo_unregister_client(chip->pci);
- vga_switcheroo_fini_domain_pm_ops(chip->card->dev);
- }
}
if (bus->chip_init) {
@@ -1740,6 +1749,10 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
else
chip->bdl_pos_adj = bdl_pos_adj[dev];
+ /* Workaround for a communication error on CFL (bko#199007) */
+ if (IS_CFL(pci))
+ chip->polling_mode = 1;
+
err = azx_bus_init(chip, model[dev], &pci_hda_io_ops);
if (err < 0) {
kfree(hda);
@@ -2215,6 +2228,7 @@ static int azx_probe_continue(struct azx *chip)
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
struct hdac_bus *bus = azx_bus(chip);
struct pci_dev *pci = chip->pci;
+ struct hda_codec *codec;
int dev = chip->dev_index;
int val;
int err;
@@ -2300,10 +2314,9 @@ static int azx_probe_continue(struct azx *chip)
val = power_save;
#ifdef CONFIG_PM
- if (val == -1) {
+ if (pm_blacklist) {
const struct snd_pci_quirk *q;
- val = CONFIG_SND_HDA_POWER_SAVE_DEFAULT;
q = snd_pci_quirk_lookup(chip->pci, power_save_blacklist);
if (q && val) {
dev_info(chip->card->dev, "device %04x:%04x is on the power_save blacklist, forcing power_save to 0\n",
@@ -2312,8 +2325,16 @@ static int azx_probe_continue(struct azx *chip)
}
}
#endif /* CONFIG_PM */
+ /*
+ * The discrete GPU cannot power down unless the HDA controller runtime
+ * suspends, so activate runtime PM on codecs even if power_save == 0.
+ */
+ if (use_vga_switcheroo(hda))
+ list_for_each_codec(codec, &chip->bus)
+ codec->auto_runtime_pm = 1;
+
snd_hda_set_power_save(&chip->bus, val * 1000);
- if (azx_has_pm_runtime(chip) || hda->use_vga_switcheroo)
+ if (azx_has_pm_runtime(chip))
pm_runtime_put_autosuspend(&pci->dev);
out_free:
diff --git a/sound/pci/hda/hda_intel.h b/sound/pci/hda/hda_intel.h
index ff0c4d617bc1..e3a3d318d2e5 100644
--- a/sound/pci/hda/hda_intel.h
+++ b/sound/pci/hda/hda_intel.h
@@ -40,9 +40,6 @@ struct hda_intel {
unsigned int vga_switcheroo_registered:1;
unsigned int init_failed:1; /* delayed init failed */
- /* secondary power domain for hdmi audio under vga device */
- struct dev_pm_domain hdmi_pm_domain;
-
bool need_i915_power:1; /* the hda controller needs i915 power */
};
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 9af301c6bba2..aef1f52db7d9 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -3130,6 +3130,8 @@ static void alc256_init(struct hda_codec *codec)
alc_update_coef_idx(codec, 0x46, 3 << 12, 0);
alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */
+ alc_update_coefex_idx(codec, 0x53, 0x02, 0x8000, 1 << 15); /* Clear bit */
+ alc_update_coefex_idx(codec, 0x53, 0x02, 0x8000, 0 << 15);
}
static void alc256_shutup(struct hda_codec *codec)
@@ -3596,8 +3598,12 @@ static void alc269_fixup_mic_mute_hook(void *private_data, int enabled)
pinval = snd_hda_codec_get_pin_target(codec, spec->mute_led_nid);
pinval &= ~AC_PINCTL_VREFEN;
pinval |= enabled ? AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_80;
- if (spec->mute_led_nid)
+ if (spec->mute_led_nid) {
+ /* temporarily power up/down for setting VREF */
+ snd_hda_power_up_pm(codec);
snd_hda_set_pin_ctl_cache(codec, spec->mute_led_nid, pinval);
+ snd_hda_power_down_pm(codec);
+ }
}
/* Make sure the led works even in runtime suspend */
@@ -5497,6 +5503,7 @@ enum {
ALC274_FIXUP_DELL_AIO_LINEOUT_VERB,
ALC298_FIXUP_TPT470_DOCK,
ALC255_FIXUP_DUMMY_LINEOUT_VERB,
+ ALC255_FIXUP_DELL_HEADSET_MIC,
};
static const struct hda_fixup alc269_fixups[] = {
@@ -6357,6 +6364,13 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
},
+ [ALC255_FIXUP_DELL_HEADSET_MIC] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
+ { }
+ },
+ },
};
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -6411,6 +6425,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x082a, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
SND_PCI_QUIRK(0x1028, 0x084b, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
SND_PCI_QUIRK(0x1028, 0x084e, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
+ SND_PCI_QUIRK(0x1028, 0x0871, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1028, 0x0872, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC),
SND_PCI_QUIRK(0x1028, 0x0873, "Dell Precision 3930", ALC255_FIXUP_DUMMY_LINEOUT_VERB),
SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
@@ -7154,6 +7170,8 @@ static int patch_alc269(struct hda_codec *codec)
break;
case 0x10ec0257:
spec->codec_variant = ALC269_TYPE_ALC257;
+ spec->shutup = alc256_shutup;
+ spec->init_hook = alc256_init;
spec->gen.mixer_nid = 0;
break;
case 0x10ec0215:
diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index c33a512283a4..9fb356db3ab2 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -579,13 +579,6 @@ static int acp_init(void __iomem *acp_mmio, u32 asic_type)
for (bank = 1; bank < 48; bank++)
acp_set_sram_bank_state(acp_mmio, bank, false);
}
-
- /* Stoney supports 16bit resolution */
- if (asic_type == CHIP_STONEY) {
- val = acp_reg_read(acp_mmio, mmACP_I2S_16BIT_RESOLUTION_EN);
- val |= 0x03;
- acp_reg_write(val, acp_mmio, mmACP_I2S_16BIT_RESOLUTION_EN);
- }
return 0;
}
@@ -774,6 +767,7 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream,
{
int status;
uint64_t size;
+ u32 val = 0;
struct page *pg;
struct snd_pcm_runtime *runtime;
struct audio_substream_data *rtd;
@@ -786,6 +780,14 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream,
if (WARN_ON(!rtd))
return -EINVAL;
+ if (adata->asic_type == CHIP_STONEY) {
+ val = acp_reg_read(adata->acp_mmio, mmACP_I2S_16BIT_RESOLUTION_EN);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ val |= ACP_I2S_SP_16BIT_RESOLUTION_EN;
+ else
+ val |= ACP_I2S_MIC_16BIT_RESOLUTION_EN;
+ acp_reg_write(val, adata->acp_mmio, mmACP_I2S_16BIT_RESOLUTION_EN);
+ }
size = params_buffer_bytes(params);
status = snd_pcm_lib_malloc_pages(substream, size);
if (status < 0)
diff --git a/sound/soc/amd/acp.h b/sound/soc/amd/acp.h
index ecb458935d1e..9293f179f272 100644
--- a/sound/soc/amd/acp.h
+++ b/sound/soc/amd/acp.h
@@ -70,6 +70,8 @@
#define CAPTURE_END_DMA_DESCR_CH15 7
#define mmACP_I2S_16BIT_RESOLUTION_EN 0x5209
+#define ACP_I2S_MIC_16BIT_RESOLUTION_EN 0x01
+#define ACP_I2S_SP_16BIT_RESOLUTION_EN 0x02
enum acp_dma_priority_level {
/* 0x0 Specifies the DMA channel is given normal priority */
ACP_DMA_PRIORITY_LEVEL_NORMAL = 0x0,
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index 5672e516bec3..c1830ccd3bb8 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -798,12 +798,7 @@ static int hdmi_codec_probe(struct platform_device *pdev)
static int hdmi_codec_remove(struct platform_device *pdev)
{
- struct device *dev = &pdev->dev;
- struct hdmi_codec_priv *hcp;
-
- hcp = dev_get_drvdata(dev);
- kfree(hcp->chmap_info);
- snd_soc_unregister_codec(dev);
+ snd_soc_unregister_codec(&pdev->dev);
return 0;
}
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index 831b297978a4..45a73049cf64 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -1722,6 +1722,7 @@ static const struct regmap_config rt5651_regmap = {
.num_reg_defaults = ARRAY_SIZE(rt5651_reg),
.ranges = rt5651_ranges,
.num_ranges = ARRAY_SIZE(rt5651_ranges),
+ .use_single_rw = true,
};
#if defined(CONFIG_OF)
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index e1ab5537d27a..c5c76ab8ccf1 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -529,10 +529,15 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = {
static int sgtl5000_digital_mute(struct snd_soc_dai *codec_dai, int mute)
{
struct snd_soc_codec *codec = codec_dai->codec;
- u16 adcdac_ctrl = SGTL5000_DAC_MUTE_LEFT | SGTL5000_DAC_MUTE_RIGHT;
+ u16 i2s_pwr = SGTL5000_I2S_IN_POWERUP;
- snd_soc_update_bits(codec, SGTL5000_CHIP_ADCDAC_CTRL,
- adcdac_ctrl, mute ? adcdac_ctrl : 0);
+ /*
+ * During 'digital mute' do not mute DAC
+ * because LINE_IN would be muted aswell. We want to mute
+ * only I2S block - this can be done by powering it off
+ */
+ snd_soc_update_bits(codec, SGTL5000_CHIP_DIG_POWER,
+ i2s_pwr, mute ? 0 : i2s_pwr);
return 0;
}
@@ -871,15 +876,26 @@ static int sgtl5000_pcm_hw_params(struct snd_pcm_substream *substream,
static int sgtl5000_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
+ struct sgtl5000_priv *sgtl = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
switch (level) {
case SND_SOC_BIAS_ON:
case SND_SOC_BIAS_PREPARE:
case SND_SOC_BIAS_STANDBY:
+ regcache_cache_only(sgtl->regmap, false);
+ ret = regcache_sync(sgtl->regmap);
+ if (ret) {
+ regcache_cache_only(sgtl->regmap, true);
+ return ret;
+ }
+
snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
SGTL5000_REFTOP_POWERUP,
SGTL5000_REFTOP_POWERUP);
break;
case SND_SOC_BIAS_OFF:
+ regcache_cache_only(sgtl->regmap, true);
snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
SGTL5000_REFTOP_POWERUP, 0);
break;
@@ -1237,6 +1253,10 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
*/
snd_soc_write(codec, SGTL5000_DAP_CTRL, 0);
+ /* Unmute DAC after start */
+ snd_soc_update_bits(codec, SGTL5000_CHIP_ADCDAC_CTRL,
+ SGTL5000_DAC_MUTE_LEFT | SGTL5000_DAC_MUTE_RIGHT, 0);
+
return 0;
err:
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 66e32f5d2917..989d093abda7 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -1204,12 +1204,14 @@ static int wmfw_add_ctl(struct wm_adsp *dsp, struct wm_coeff_ctl *ctl)
kcontrol->put = wm_coeff_put_acked;
break;
default:
- kcontrol->get = wm_coeff_get;
- kcontrol->put = wm_coeff_put;
-
- ctl->bytes_ext.max = ctl->len;
- ctl->bytes_ext.get = wm_coeff_tlv_get;
- ctl->bytes_ext.put = wm_coeff_tlv_put;
+ if (kcontrol->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
+ ctl->bytes_ext.max = ctl->len;
+ ctl->bytes_ext.get = wm_coeff_tlv_get;
+ ctl->bytes_ext.put = wm_coeff_tlv_put;
+ } else {
+ kcontrol->get = wm_coeff_get;
+ kcontrol->put = wm_coeff_put;
+ }
break;
}
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index dca1143c1150..a4aa931ebfae 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -104,7 +104,7 @@
#define SUN8I_I2S_CHAN_CFG_REG 0x30
#define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK GENMASK(6, 4)
-#define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(chan) (chan - 1)
+#define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(chan) ((chan - 1) << 4)
#define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK GENMASK(2, 0)
#define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(chan) (chan - 1)
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index ea8f3de92fa4..794224e1d6df 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1171,6 +1171,7 @@ static bool is_teac_dsd_dac(unsigned int id)
switch (id) {
case USB_ID(0x0644, 0x8043): /* TEAC UD-501/UD-503/NT-503 */
case USB_ID(0x0644, 0x8044): /* Esoteric D-05X */
+ case USB_ID(0x0644, 0x804a): /* TEAC UD-301 */
return true;
}
return false;