Commit fa079ba8 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull sound fixes from Takashi Iwai:
 "The only largish change in this pull request is about the revert of
  the recent max98090 and its relevant patches due to regressions.

  Other than that, all small fixes for ALSA core (covering KCSAN fuzzer
  warnings in ALSA sequencer and rawmidi), Intel SOF HD-audio fixes, AMD
  ACP fixes, usual HD-audio quirks, and various ASoC fixes"

* tag 'sound-5.6-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: hda: Use scnprintf() for printing texts for sysfs/procfs
  ALSA: hda/realtek - Apply quirk for yet another MSI laptop
  ASoC: sun8i-codec: Fix setting DAI data format
  ALSA: hda/realtek - Apply quirk for MSI GP63, too
  ASoC: amd: ACP needs to be powered off in BIOS.
  ASoC: hdmi-codec: set plugged_cb to NULL when component removing
  ASoC: dapm: remove snd_soc_dapm_put_enum_double_locked
  ASoC: max98090: revert invalid fix for handling SHDN
  ALSA: rawmidi: Avoid bit fields for state flags
  ALSA: seq: Fix concurrent access to queue current tick/time
  ALSA: seq: Avoid concurrent access to queue flags
  ASoC: codec2codec: avoid invalid/double-free of pcm runtime
  ASoC: amd: Buffer Size instead of MAX Buffer
  ASoC: SOF: Intel: hda: move i915 init earlier
  ASoC: SOF: Intel: hda: fix ordering bug in resume flow
  ALSA: hda: do not override bus codec_mask in link_get()
  ASoC: atmel: fix atmel_ssc_set_audio link failure
  ASoC: fsl_sai: Fix exiting path on probing failure
parents 0a44cac8 38553609
...@@ -77,9 +77,9 @@ struct snd_rawmidi_substream { ...@@ -77,9 +77,9 @@ struct snd_rawmidi_substream {
struct list_head list; /* list of all substream for given stream */ struct list_head list; /* list of all substream for given stream */
int stream; /* direction */ int stream; /* direction */
int number; /* substream number */ int number; /* substream number */
unsigned int opened: 1, /* open flag */ bool opened; /* open flag */
append: 1, /* append flag (merge more streams) */ bool append; /* append flag (merge more streams) */
active_sensing: 1; /* send active sensing when close */ bool active_sensing; /* send active sensing when close */
int use_count; /* use counter (for output) */ int use_count; /* use counter (for output) */
size_t bytes; size_t bytes;
struct snd_rawmidi *rmidi; struct snd_rawmidi *rmidi;
......
...@@ -392,8 +392,6 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, ...@@ -392,8 +392,6 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol); struct snd_ctl_elem_value *ucontrol);
int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol); struct snd_ctl_elem_value *ucontrol);
int snd_soc_dapm_put_enum_double_locked(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol, int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo); struct snd_ctl_elem_info *uinfo);
int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
......
...@@ -580,7 +580,7 @@ static int update_timestamp_of_queue(struct snd_seq_event *event, ...@@ -580,7 +580,7 @@ static int update_timestamp_of_queue(struct snd_seq_event *event,
event->queue = queue; event->queue = queue;
event->flags &= ~SNDRV_SEQ_TIME_STAMP_MASK; event->flags &= ~SNDRV_SEQ_TIME_STAMP_MASK;
if (real_time) { if (real_time) {
event->time.time = snd_seq_timer_get_cur_time(q->timer); event->time.time = snd_seq_timer_get_cur_time(q->timer, true);
event->flags |= SNDRV_SEQ_TIME_STAMP_REAL; event->flags |= SNDRV_SEQ_TIME_STAMP_REAL;
} else { } else {
event->time.tick = snd_seq_timer_get_cur_tick(q->timer); event->time.tick = snd_seq_timer_get_cur_tick(q->timer);
...@@ -1659,7 +1659,7 @@ static int snd_seq_ioctl_get_queue_status(struct snd_seq_client *client, ...@@ -1659,7 +1659,7 @@ static int snd_seq_ioctl_get_queue_status(struct snd_seq_client *client,
tmr = queue->timer; tmr = queue->timer;
status->events = queue->tickq->cells + queue->timeq->cells; status->events = queue->tickq->cells + queue->timeq->cells;
status->time = snd_seq_timer_get_cur_time(tmr); status->time = snd_seq_timer_get_cur_time(tmr, true);
status->tick = snd_seq_timer_get_cur_tick(tmr); status->tick = snd_seq_timer_get_cur_tick(tmr);
status->running = tmr->running; status->running = tmr->running;
......
...@@ -238,6 +238,8 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop) ...@@ -238,6 +238,8 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop)
{ {
unsigned long flags; unsigned long flags;
struct snd_seq_event_cell *cell; struct snd_seq_event_cell *cell;
snd_seq_tick_time_t cur_tick;
snd_seq_real_time_t cur_time;
if (q == NULL) if (q == NULL)
return; return;
...@@ -254,17 +256,18 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop) ...@@ -254,17 +256,18 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop)
__again: __again:
/* Process tick queue... */ /* Process tick queue... */
cur_tick = snd_seq_timer_get_cur_tick(q->timer);
for (;;) { for (;;) {
cell = snd_seq_prioq_cell_out(q->tickq, cell = snd_seq_prioq_cell_out(q->tickq, &cur_tick);
&q->timer->tick.cur_tick);
if (!cell) if (!cell)
break; break;
snd_seq_dispatch_event(cell, atomic, hop); snd_seq_dispatch_event(cell, atomic, hop);
} }
/* Process time queue... */ /* Process time queue... */
cur_time = snd_seq_timer_get_cur_time(q->timer, false);
for (;;) { for (;;) {
cell = snd_seq_prioq_cell_out(q->timeq, &q->timer->cur_time); cell = snd_seq_prioq_cell_out(q->timeq, &cur_time);
if (!cell) if (!cell)
break; break;
snd_seq_dispatch_event(cell, atomic, hop); snd_seq_dispatch_event(cell, atomic, hop);
...@@ -392,6 +395,7 @@ int snd_seq_queue_check_access(int queueid, int client) ...@@ -392,6 +395,7 @@ int snd_seq_queue_check_access(int queueid, int client)
int snd_seq_queue_set_owner(int queueid, int client, int locked) int snd_seq_queue_set_owner(int queueid, int client, int locked)
{ {
struct snd_seq_queue *q = queueptr(queueid); struct snd_seq_queue *q = queueptr(queueid);
unsigned long flags;
if (q == NULL) if (q == NULL)
return -EINVAL; return -EINVAL;
...@@ -401,8 +405,10 @@ int snd_seq_queue_set_owner(int queueid, int client, int locked) ...@@ -401,8 +405,10 @@ int snd_seq_queue_set_owner(int queueid, int client, int locked)
return -EPERM; return -EPERM;
} }
spin_lock_irqsave(&q->owner_lock, flags);
q->locked = locked ? 1 : 0; q->locked = locked ? 1 : 0;
q->owner = client; q->owner = client;
spin_unlock_irqrestore(&q->owner_lock, flags);
queue_access_unlock(q); queue_access_unlock(q);
queuefree(q); queuefree(q);
...@@ -539,15 +545,17 @@ void snd_seq_queue_client_termination(int client) ...@@ -539,15 +545,17 @@ void snd_seq_queue_client_termination(int client)
unsigned long flags; unsigned long flags;
int i; int i;
struct snd_seq_queue *q; struct snd_seq_queue *q;
bool matched;
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
if ((q = queueptr(i)) == NULL) if ((q = queueptr(i)) == NULL)
continue; continue;
spin_lock_irqsave(&q->owner_lock, flags); spin_lock_irqsave(&q->owner_lock, flags);
if (q->owner == client) matched = (q->owner == client);
if (matched)
q->klocked = 1; q->klocked = 1;
spin_unlock_irqrestore(&q->owner_lock, flags); spin_unlock_irqrestore(&q->owner_lock, flags);
if (q->owner == client) { if (matched) {
if (q->timer->running) if (q->timer->running)
snd_seq_timer_stop(q->timer); snd_seq_timer_stop(q->timer);
snd_seq_timer_reset(q->timer); snd_seq_timer_reset(q->timer);
...@@ -739,6 +747,8 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry, ...@@ -739,6 +747,8 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry,
int i, bpm; int i, bpm;
struct snd_seq_queue *q; struct snd_seq_queue *q;
struct snd_seq_timer *tmr; struct snd_seq_timer *tmr;
bool locked;
int owner;
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
if ((q = queueptr(i)) == NULL) if ((q = queueptr(i)) == NULL)
...@@ -750,9 +760,14 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry, ...@@ -750,9 +760,14 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry,
else else
bpm = 0; bpm = 0;
spin_lock_irq(&q->owner_lock);
locked = q->locked;
owner = q->owner;
spin_unlock_irq(&q->owner_lock);
snd_iprintf(buffer, "queue %d: [%s]\n", q->queue, q->name); snd_iprintf(buffer, "queue %d: [%s]\n", q->queue, q->name);
snd_iprintf(buffer, "owned by client : %d\n", q->owner); snd_iprintf(buffer, "owned by client : %d\n", owner);
snd_iprintf(buffer, "lock status : %s\n", q->locked ? "Locked" : "Free"); snd_iprintf(buffer, "lock status : %s\n", locked ? "Locked" : "Free");
snd_iprintf(buffer, "queued time events : %d\n", snd_seq_prioq_avail(q->timeq)); snd_iprintf(buffer, "queued time events : %d\n", snd_seq_prioq_avail(q->timeq));
snd_iprintf(buffer, "queued tick events : %d\n", snd_seq_prioq_avail(q->tickq)); snd_iprintf(buffer, "queued tick events : %d\n", snd_seq_prioq_avail(q->tickq));
snd_iprintf(buffer, "timer state : %s\n", tmr->running ? "Running" : "Stopped"); snd_iprintf(buffer, "timer state : %s\n", tmr->running ? "Running" : "Stopped");
......
...@@ -428,14 +428,15 @@ int snd_seq_timer_continue(struct snd_seq_timer *tmr) ...@@ -428,14 +428,15 @@ int snd_seq_timer_continue(struct snd_seq_timer *tmr)
} }
/* return current 'real' time. use timeofday() to get better granularity. */ /* return current 'real' time. use timeofday() to get better granularity. */
snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr) snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr,
bool adjust_ktime)
{ {
snd_seq_real_time_t cur_time; snd_seq_real_time_t cur_time;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&tmr->lock, flags); spin_lock_irqsave(&tmr->lock, flags);
cur_time = tmr->cur_time; cur_time = tmr->cur_time;
if (tmr->running) { if (adjust_ktime && tmr->running) {
struct timespec64 tm; struct timespec64 tm;
ktime_get_ts64(&tm); ktime_get_ts64(&tm);
...@@ -452,7 +453,13 @@ snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr) ...@@ -452,7 +453,13 @@ snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr)
high PPQ values) */ high PPQ values) */
snd_seq_tick_time_t snd_seq_timer_get_cur_tick(struct snd_seq_timer *tmr) snd_seq_tick_time_t snd_seq_timer_get_cur_tick(struct snd_seq_timer *tmr)
{ {
return tmr->tick.cur_tick; snd_seq_tick_time_t cur_tick;
unsigned long flags;
spin_lock_irqsave(&tmr->lock, flags);
cur_tick = tmr->tick.cur_tick;
spin_unlock_irqrestore(&tmr->lock, flags);
return cur_tick;
} }
......
...@@ -120,7 +120,8 @@ int snd_seq_timer_set_tempo_ppq(struct snd_seq_timer *tmr, int tempo, int ppq); ...@@ -120,7 +120,8 @@ int snd_seq_timer_set_tempo_ppq(struct snd_seq_timer *tmr, int tempo, int ppq);
int snd_seq_timer_set_position_tick(struct snd_seq_timer *tmr, snd_seq_tick_time_t position); int snd_seq_timer_set_position_tick(struct snd_seq_timer *tmr, snd_seq_tick_time_t position);
int snd_seq_timer_set_position_time(struct snd_seq_timer *tmr, snd_seq_real_time_t position); int snd_seq_timer_set_position_time(struct snd_seq_timer *tmr, snd_seq_real_time_t position);
int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew, unsigned int base); int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew, unsigned int base);
snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr); snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr,
bool adjust_ktime);
snd_seq_tick_time_t snd_seq_timer_get_cur_tick(struct snd_seq_timer *tmr); snd_seq_tick_time_t snd_seq_timer_get_cur_tick(struct snd_seq_timer *tmr);
extern int seq_default_timer_class; extern int seq_default_timer_class;
......
...@@ -254,6 +254,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down_all); ...@@ -254,6 +254,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down_all);
int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, int snd_hdac_ext_bus_link_get(struct hdac_bus *bus,
struct hdac_ext_link *link) struct hdac_ext_link *link)
{ {
unsigned long codec_mask;
int ret = 0; int ret = 0;
mutex_lock(&bus->lock); mutex_lock(&bus->lock);
...@@ -280,9 +281,11 @@ int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, ...@@ -280,9 +281,11 @@ int snd_hdac_ext_bus_link_get(struct hdac_bus *bus,
* HDA spec section 4.3 - Codec Discovery * HDA spec section 4.3 - Codec Discovery
*/ */
udelay(521); udelay(521);
bus->codec_mask = snd_hdac_chip_readw(bus, STATESTS); codec_mask = snd_hdac_chip_readw(bus, STATESTS);
dev_dbg(bus->dev, "codec_mask = 0x%lx\n", bus->codec_mask); dev_dbg(bus->dev, "codec_mask = 0x%lx\n", codec_mask);
snd_hdac_chip_writew(bus, STATESTS, bus->codec_mask); snd_hdac_chip_writew(bus, STATESTS, codec_mask);
if (!bus->codec_mask)
bus->codec_mask = codec_mask;
} }
mutex_unlock(&bus->lock); mutex_unlock(&bus->lock);
......
...@@ -250,7 +250,7 @@ void snd_hdac_print_channel_allocation(int spk_alloc, char *buf, int buflen) ...@@ -250,7 +250,7 @@ void snd_hdac_print_channel_allocation(int spk_alloc, char *buf, int buflen)
for (i = 0, j = 0; i < ARRAY_SIZE(cea_speaker_allocation_names); i++) { for (i = 0, j = 0; i < ARRAY_SIZE(cea_speaker_allocation_names); i++) {
if (spk_alloc & (1 << i)) if (spk_alloc & (1 << i))
j += snprintf(buf + j, buflen - j, " %s", j += scnprintf(buf + j, buflen - j, " %s",
cea_speaker_allocation_names[i]); cea_speaker_allocation_names[i]);
} }
buf[j] = '\0'; /* necessary when j == 0 */ buf[j] = '\0'; /* necessary when j == 0 */
......
...@@ -4022,7 +4022,7 @@ void snd_print_pcm_bits(int pcm, char *buf, int buflen) ...@@ -4022,7 +4022,7 @@ void snd_print_pcm_bits(int pcm, char *buf, int buflen)
for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++) for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
if (pcm & (AC_SUPPCM_BITS_8 << i)) if (pcm & (AC_SUPPCM_BITS_8 << i))
j += snprintf(buf + j, buflen - j, " %d", bits[i]); j += scnprintf(buf + j, buflen - j, " %d", bits[i]);
buf[j] = '\0'; /* necessary when j == 0 */ buf[j] = '\0'; /* necessary when j == 0 */
} }
......
...@@ -360,7 +360,7 @@ static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen) ...@@ -360,7 +360,7 @@ static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen)
for (i = 0, j = 0; i < ARRAY_SIZE(alsa_rates); i++) for (i = 0, j = 0; i < ARRAY_SIZE(alsa_rates); i++)
if (pcm & (1 << i)) if (pcm & (1 << i))
j += snprintf(buf + j, buflen - j, " %d", j += scnprintf(buf + j, buflen - j, " %d",
alsa_rates[i]); alsa_rates[i]);
buf[j] = '\0'; /* necessary when j == 0 */ buf[j] = '\0'; /* necessary when j == 0 */
......
...@@ -222,7 +222,7 @@ static ssize_t init_verbs_show(struct device *dev, ...@@ -222,7 +222,7 @@ static ssize_t init_verbs_show(struct device *dev,
int i, len = 0; int i, len = 0;
mutex_lock(&codec->user_mutex); mutex_lock(&codec->user_mutex);
snd_array_for_each(&codec->init_verbs, i, v) { snd_array_for_each(&codec->init_verbs, i, v) {
len += snprintf(buf + len, PAGE_SIZE - len, len += scnprintf(buf + len, PAGE_SIZE - len,
"0x%02x 0x%03x 0x%04x\n", "0x%02x 0x%03x 0x%04x\n",
v->nid, v->verb, v->param); v->nid, v->verb, v->param);
} }
...@@ -272,7 +272,7 @@ static ssize_t hints_show(struct device *dev, ...@@ -272,7 +272,7 @@ static ssize_t hints_show(struct device *dev,
int i, len = 0; int i, len = 0;
mutex_lock(&codec->user_mutex); mutex_lock(&codec->user_mutex);
snd_array_for_each(&codec->hints, i, hint) { snd_array_for_each(&codec->hints, i, hint) {
len += snprintf(buf + len, PAGE_SIZE - len, len += scnprintf(buf + len, PAGE_SIZE - len,
"%s = %s\n", hint->key, hint->val); "%s = %s\n", hint->key, hint->val);
} }
mutex_unlock(&codec->user_mutex); mutex_unlock(&codec->user_mutex);
......
...@@ -2447,7 +2447,9 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { ...@@ -2447,7 +2447,9 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD), SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE), 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), SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1462, 0x1293, "MSI-GP65", ALC1220_FIXUP_CLEVO_P950),
SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD), SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS), SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3), SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
......
...@@ -170,6 +170,7 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream, ...@@ -170,6 +170,7 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
struct snd_soc_card *card; struct snd_soc_card *card;
struct acp3x_platform_info *pinfo; struct acp3x_platform_info *pinfo;
u32 ret, val, period_bytes, reg_val, ier_val, water_val; u32 ret, val, period_bytes, reg_val, ier_val, water_val;
u32 buf_size, buf_reg;
prtd = substream->private_data; prtd = substream->private_data;
rtd = substream->runtime->private_data; rtd = substream->runtime->private_data;
...@@ -183,6 +184,8 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream, ...@@ -183,6 +184,8 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
} }
period_bytes = frames_to_bytes(substream->runtime, period_bytes = frames_to_bytes(substream->runtime,
substream->runtime->period_size); substream->runtime->period_size);
buf_size = frames_to_bytes(substream->runtime,
substream->runtime->buffer_size);
switch (cmd) { switch (cmd) {
case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_RESUME:
...@@ -196,6 +199,7 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream, ...@@ -196,6 +199,7 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
mmACP_BT_TX_INTR_WATERMARK_SIZE; mmACP_BT_TX_INTR_WATERMARK_SIZE;
reg_val = mmACP_BTTDM_ITER; reg_val = mmACP_BTTDM_ITER;
ier_val = mmACP_BTTDM_IER; ier_val = mmACP_BTTDM_IER;
buf_reg = mmACP_BT_TX_RINGBUFSIZE;
break; break;
case I2S_SP_INSTANCE: case I2S_SP_INSTANCE:
default: default:
...@@ -203,6 +207,7 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream, ...@@ -203,6 +207,7 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
mmACP_I2S_TX_INTR_WATERMARK_SIZE; mmACP_I2S_TX_INTR_WATERMARK_SIZE;
reg_val = mmACP_I2STDM_ITER; reg_val = mmACP_I2STDM_ITER;
ier_val = mmACP_I2STDM_IER; ier_val = mmACP_I2STDM_IER;
buf_reg = mmACP_I2S_TX_RINGBUFSIZE;
} }
} else { } else {
switch (rtd->i2s_instance) { switch (rtd->i2s_instance) {
...@@ -211,6 +216,7 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream, ...@@ -211,6 +216,7 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
mmACP_BT_RX_INTR_WATERMARK_SIZE; mmACP_BT_RX_INTR_WATERMARK_SIZE;
reg_val = mmACP_BTTDM_IRER; reg_val = mmACP_BTTDM_IRER;
ier_val = mmACP_BTTDM_IER; ier_val = mmACP_BTTDM_IER;
buf_reg = mmACP_BT_RX_RINGBUFSIZE;
break; break;
case I2S_SP_INSTANCE: case I2S_SP_INSTANCE:
default: default:
...@@ -218,9 +224,11 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream, ...@@ -218,9 +224,11 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
mmACP_I2S_RX_INTR_WATERMARK_SIZE; mmACP_I2S_RX_INTR_WATERMARK_SIZE;
reg_val = mmACP_I2STDM_IRER; reg_val = mmACP_I2STDM_IRER;
ier_val = mmACP_I2STDM_IER; ier_val = mmACP_I2STDM_IER;
buf_reg = mmACP_I2S_RX_RINGBUFSIZE;
} }
} }
rv_writel(period_bytes, rtd->acp3x_base + water_val); rv_writel(period_bytes, rtd->acp3x_base + water_val);
rv_writel(buf_size, rtd->acp3x_base + buf_reg);
val = rv_readl(rtd->acp3x_base + reg_val); val = rv_readl(rtd->acp3x_base + reg_val);
val = val | BIT(0); val = val | BIT(0);
rv_writel(val, rtd->acp3x_base + reg_val); rv_writel(val, rtd->acp3x_base + reg_val);
......
...@@ -110,7 +110,7 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction) ...@@ -110,7 +110,7 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
{ {
u16 page_idx; u16 page_idx;
u32 low, high, val, acp_fifo_addr, reg_fifo_addr; u32 low, high, val, acp_fifo_addr, reg_fifo_addr;
u32 reg_ringbuf_size, reg_dma_size, reg_fifo_size; u32 reg_dma_size, reg_fifo_size;
dma_addr_t addr; dma_addr_t addr;
addr = rtd->dma_addr; addr = rtd->dma_addr;
...@@ -157,7 +157,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction) ...@@ -157,7 +157,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
if (direction == SNDRV_PCM_STREAM_PLAYBACK) { if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
switch (rtd->i2s_instance) { switch (rtd->i2s_instance) {
case I2S_BT_INSTANCE: case I2S_BT_INSTANCE:
reg_ringbuf_size = mmACP_BT_TX_RINGBUFSIZE;
reg_dma_size = mmACP_BT_TX_DMA_SIZE; reg_dma_size = mmACP_BT_TX_DMA_SIZE;
acp_fifo_addr = ACP_SRAM_PTE_OFFSET + acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
BT_PB_FIFO_ADDR_OFFSET; BT_PB_FIFO_ADDR_OFFSET;
...@@ -169,7 +168,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction) ...@@ -169,7 +168,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
case I2S_SP_INSTANCE: case I2S_SP_INSTANCE:
default: default:
reg_ringbuf_size = mmACP_I2S_TX_RINGBUFSIZE;
reg_dma_size = mmACP_I2S_TX_DMA_SIZE; reg_dma_size = mmACP_I2S_TX_DMA_SIZE;
acp_fifo_addr = ACP_SRAM_PTE_OFFSET + acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
SP_PB_FIFO_ADDR_OFFSET; SP_PB_FIFO_ADDR_OFFSET;
...@@ -181,7 +179,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction) ...@@ -181,7 +179,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
} else { } else {
switch (rtd->i2s_instance) { switch (rtd->i2s_instance) {
case I2S_BT_INSTANCE: case I2S_BT_INSTANCE:
reg_ringbuf_size = mmACP_BT_RX_RINGBUFSIZE;
reg_dma_size = mmACP_BT_RX_DMA_SIZE; reg_dma_size = mmACP_BT_RX_DMA_SIZE;
acp_fifo_addr = ACP_SRAM_PTE_OFFSET + acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
BT_CAPT_FIFO_ADDR_OFFSET; BT_CAPT_FIFO_ADDR_OFFSET;
...@@ -193,7 +190,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction) ...@@ -193,7 +190,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
case I2S_SP_INSTANCE: case I2S_SP_INSTANCE:
default: default:
reg_ringbuf_size = mmACP_I2S_RX_RINGBUFSIZE;
reg_dma_size = mmACP_I2S_RX_DMA_SIZE; reg_dma_size = mmACP_I2S_RX_DMA_SIZE;
acp_fifo_addr = ACP_SRAM_PTE_OFFSET + acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
SP_CAPT_FIFO_ADDR_OFFSET; SP_CAPT_FIFO_ADDR_OFFSET;
...@@ -203,7 +199,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction) ...@@ -203,7 +199,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
rtd->acp3x_base + mmACP_I2S_RX_RINGBUFADDR); rtd->acp3x_base + mmACP_I2S_RX_RINGBUFADDR);
} }
} }
rv_writel(MAX_BUFFER, rtd->acp3x_base + reg_ringbuf_size);
rv_writel(DMA_SIZE, rtd->acp3x_base + reg_dma_size); rv_writel(DMA_SIZE, rtd->acp3x_base + reg_dma_size);
rv_writel(acp_fifo_addr, rtd->acp3x_base + reg_fifo_addr); rv_writel(acp_fifo_addr, rtd->acp3x_base + reg_fifo_addr);
rv_writel(FIFO_SIZE, rtd->acp3x_base + reg_fifo_size); rv_writel(FIFO_SIZE, rtd->acp3x_base + reg_fifo_size);
......
...@@ -45,23 +45,6 @@ static int acp3x_power_on(void __iomem *acp3x_base) ...@@ -45,23 +45,6 @@ static int acp3x_power_on(void __iomem *acp3x_base)
return -ETIMEDOUT; return -ETIMEDOUT;
} }
static int acp3x_power_off(void __iomem *acp3x_base)
{
u32 val;
int timeout;
rv_writel(ACP_PGFSM_CNTL_POWER_OFF_MASK,
acp3x_base + mmACP_PGFSM_CONTROL);
timeout = 0;
while (++timeout < 500) {
val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_OFF)
return 0;
udelay(1);
}
return -ETIMEDOUT;
}
static int acp3x_reset(void __iomem *acp3x_base) static int acp3x_reset(void __iomem *acp3x_base)
{ {
u32 val; u32 val;
...@@ -115,12 +98,6 @@ static int acp3x_deinit(void __iomem *acp3x_base) ...@@ -115,12 +98,6 @@ static int acp3x_deinit(void __iomem *acp3x_base)
pr_err("ACP3x reset failed\n"); pr_err("ACP3x reset failed\n");
return ret; return ret;
} }
/* power off */
ret = acp3x_power_off(acp3x_base);
if (ret) {
pr_err("ACP3x power off failed\n");
return ret;
}
return 0; return 0;
} }
......
...@@ -10,11 +10,11 @@ config SND_ATMEL_SOC ...@@ -10,11 +10,11 @@ config SND_ATMEL_SOC
if SND_ATMEL_SOC if SND_ATMEL_SOC
config SND_ATMEL_SOC_PDC config SND_ATMEL_SOC_PDC
tristate bool
depends on HAS_DMA depends on HAS_DMA
config SND_ATMEL_SOC_DMA config SND_ATMEL_SOC_DMA
tristate bool
select SND_SOC_GENERIC_DMAENGINE_PCM select SND_SOC_GENERIC_DMAENGINE_PCM
config SND_ATMEL_SOC_SSC config SND_ATMEL_SOC_SSC
......
...@@ -6,8 +6,14 @@ snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o ...@@ -6,8 +6,14 @@ snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
snd-soc-atmel-i2s-objs := atmel-i2s.o snd-soc-atmel-i2s-objs := atmel-i2s.o
snd-soc-mchp-i2s-mcc-objs := mchp-i2s-mcc.o snd-soc-mchp-i2s-mcc-objs := mchp-i2s-mcc.o
obj-$(CONFIG_SND_ATMEL_SOC_PDC) += snd-soc-atmel-pcm-pdc.o # pdc and dma need to both be built-in if any user of
obj-$(CONFIG_SND_ATMEL_SOC_DMA) += snd-soc-atmel-pcm-dma.o # ssc is built-in.
ifdef CONFIG_SND_ATMEL_SOC_PDC
obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel-pcm-pdc.o
endif
ifdef CONFIG_SND_ATMEL_SOC_DMA
obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel-pcm-dma.o
endif
obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
obj-$(CONFIG_SND_ATMEL_SOC_I2S) += snd-soc-atmel-i2s.o obj-$(CONFIG_SND_ATMEL_SOC_I2S) += snd-soc-atmel-i2s.o
obj-$(CONFIG_SND_MCHP_SOC_I2S_MCC) += snd-soc-mchp-i2s-mcc.o obj-$(CONFIG_SND_MCHP_SOC_I2S_MCC) += snd-soc-mchp-i2s-mcc.o
......
...@@ -779,7 +779,17 @@ static int hdmi_of_xlate_dai_id(struct snd_soc_component *component, ...@@ -779,7 +779,17 @@ static int hdmi_of_xlate_dai_id(struct snd_soc_component *component,
return ret; return ret;
} }
static void hdmi_remove(struct snd_soc_component *component)
{
struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
if (hcp->hcd.ops->hook_plugged_cb)
hcp->hcd.ops->hook_plugged_cb(component->dev->parent,
hcp->hcd.data, NULL, NULL);
}
static const struct snd_soc_component_driver hdmi_driver = { static const struct snd_soc_component_driver hdmi_driver = {
.remove = hdmi_remove,
.dapm_widgets = hdmi_widgets, .dapm_widgets = hdmi_widgets,
.num_dapm_widgets = ARRAY_SIZE(hdmi_widgets), .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets),
.of_xlate_dai_id = hdmi_of_xlate_dai_id, .of_xlate_dai_id = hdmi_of_xlate_dai_id,
......
...@@ -5,150 +5,24 @@ ...@@ -5,150 +5,24 @@
* Copyright 2011-2012 Maxim Integrated Products * Copyright 2011-2012 Maxim Integrated Products
*/ */
#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/clk.h>
#include <sound/jack.h> #include <sound/jack.h>
#include <sound/max98090.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/soc.h> #include <sound/soc.h>
#include <sound/tlv.h> #include <sound/tlv.h>
#include <sound/max98090.h>
#include "max98090.h" #include "max98090.h"
static void max98090_shdn_save_locked(struct max98090_priv *max98090)
{
int shdn = 0;
/* saved_shdn, saved_count, SHDN are protected by card->dapm_mutex */
regmap_read(max98090->regmap, M98090_REG_DEVICE_SHUTDOWN, &shdn);
max98090->saved_shdn |= shdn;
++max98090->saved_count;
if (shdn)
regmap_write(max98090->regmap, M98090_REG_DEVICE_SHUTDOWN, 0x0);
}
static void max98090_shdn_restore_locked(struct max98090_priv *max98090)
{
/* saved_shdn, saved_count, SHDN are protected by card->dapm_mutex */
if (--max98090->saved_count == 0) {
if (max98090->saved_shdn) {
regmap_write(max98090->regmap,
M98090_REG_DEVICE_SHUTDOWN,
M98090_SHDNN_MASK);
max98090->saved_shdn = 0;
}
}
}
static void max98090_shdn_save(struct max98090_priv *max98090)
{
mutex_lock_nested(&max98090->component->card->dapm_mutex,
SND_SOC_DAPM_CLASS_RUNTIME);
max98090_shdn_save_locked(max98090);
}
static void max98090_shdn_restore(struct max98090_priv *max98090)
{
max98090_shdn_restore_locked(max98090);
mutex_unlock(&max98090->component->card->dapm_mutex);
}
static int max98090_put_volsw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct max98090_priv *max98090 =
snd_soc_component_get_drvdata(component);
int ret;
max98090_shdn_save(max98090);
ret = snd_soc_put_volsw(kcontrol, ucontrol);
max98090_shdn_restore(max98090);
return ret;
}
static int max98090_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_dapm_kcontrol_component(kcontrol);
struct max98090_priv *max98090 =
snd_soc_component_get_drvdata(component);
int ret;
max98090_shdn_save(max98090);
ret = snd_soc_dapm_put_enum_double_locked(kcontrol, ucontrol);
max98090_shdn_restore(max98090);
return ret;
}
static int max98090_put_enum_double(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct max98090_priv *max98090 =
snd_soc_component_get_drvdata(component);
int ret;
max98090_shdn_save(max98090);
ret = snd_soc_put_enum_double(kcontrol, ucontrol);
max98090_shdn_restore(max98090);
return ret;
}
static int max98090_bytes_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct max98090_priv *max98090 =
snd_soc_component_get_drvdata(component);
int ret;
max98090_shdn_save(max98090);
ret = snd_soc_bytes_put(kcontrol, ucontrol);
max98090_shdn_restore(max98090);
return ret;
}
static int max98090_dapm_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
struct max98090_priv *max98090 =
snd_soc_component_get_drvdata(component);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
case SND_SOC_DAPM_PRE_PMD:
max98090_shdn_save_locked(max98090);
break;
case SND_SOC_DAPM_POST_PMU:
case SND_SOC_DAPM_POST_PMD:
max98090_shdn_restore_locked(max98090);
break;
}
return 0;
}
/* Allows for sparsely populated register maps */ /* Allows for sparsely populated register maps */
static const struct reg_default max98090_reg[] = { static const struct reg_default max98090_reg[] = {
{ 0x00, 0x00 }, /* 00 Software Reset */ { 0x00, 0x00 }, /* 00 Software Reset */
...@@ -632,13 +506,10 @@ static SOC_ENUM_SINGLE_DECL(max98090_adchp_enum, ...@@ -632,13 +506,10 @@ static SOC_ENUM_SINGLE_DECL(max98090_adchp_enum,
max98090_pwr_perf_text); max98090_pwr_perf_text);
static const struct snd_kcontrol_new max98090_snd_controls[] = { static const struct snd_kcontrol_new max98090_snd_controls[] = {
SOC_ENUM_EXT("MIC Bias VCM Bandgap", max98090_vcmbandgap_enum, SOC_ENUM("MIC Bias VCM Bandgap", max98090_vcmbandgap_enum),
snd_soc_get_enum_double, max98090_put_enum_double),
SOC_SINGLE_EXT("DMIC MIC Comp Filter Config", SOC_SINGLE("DMIC MIC Comp Filter Config", M98090_REG_DIGITAL_MIC_CONFIG,
M98090_REG_DIGITAL_MIC_CONFIG, M98090_DMIC_COMP_SHIFT, M98090_DMIC_COMP_NUM - 1, 0),
M98090_DMIC_COMP_SHIFT, M98090_DMIC_COMP_NUM - 1, 0,
snd_soc_get_volsw, max98090_put_volsw),
SOC_SINGLE_EXT_TLV("MIC1 Boost Volume", SOC_SINGLE_EXT_TLV("MIC1 Boost Volume",
M98090_REG_MIC1_INPUT_LEVEL, M98090_MIC_PA1EN_SHIFT, M98090_REG_MIC1_INPUT_LEVEL, M98090_MIC_PA1EN_SHIFT,
...@@ -693,34 +564,24 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = { ...@@ -693,34 +564,24 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = {
M98090_AVR_SHIFT, M98090_AVR_NUM - 1, 1, M98090_AVR_SHIFT, M98090_AVR_NUM - 1, 1,
max98090_av_tlv), max98090_av_tlv),
SOC_ENUM_EXT("ADC Oversampling Rate", max98090_osr128_enum, SOC_ENUM("ADC Oversampling Rate", max98090_osr128_enum),
snd_soc_get_enum_double, max98090_put_enum_double), SOC_SINGLE("ADC Quantizer Dither", M98090_REG_ADC_CONTROL,
SOC_SINGLE_EXT("ADC Quantizer Dither", M98090_REG_ADC_CONTROL, M98090_ADCDITHER_SHIFT, M98090_ADCDITHER_NUM - 1, 0),
M98090_ADCDITHER_SHIFT, M98090_ADCDITHER_NUM - 1, 0, SOC_ENUM("ADC High Performance Mode", max98090_adchp_enum),
snd_soc_get_volsw, max98090_put_volsw),
SOC_ENUM_EXT("ADC High Performance Mode", max98090_adchp_enum, SOC_SINGLE("DAC Mono Mode", M98090_REG_IO_CONFIGURATION,
snd_soc_get_enum_double, max98090_put_enum_double), M98090_DMONO_SHIFT, M98090_DMONO_NUM - 1, 0),
SOC_SINGLE("SDIN Mode", M98090_REG_IO_CONFIGURATION,
SOC_SINGLE_EXT("DAC Mono Mode", M98090_REG_IO_CONFIGURATION, M98090_SDIEN_SHIFT, M98090_SDIEN_NUM - 1, 0),
M98090_DMONO_SHIFT, M98090_DMONO_NUM - 1, 0, SOC_SINGLE("SDOUT Mode", M98090_REG_IO_CONFIGURATION,
snd_soc_get_volsw, max98090_put_volsw), M98090_SDOEN_SHIFT, M98090_SDOEN_NUM - 1, 0),
SOC_SINGLE_EXT("SDIN Mode", M98090_REG_IO_CONFIGURATION, SOC_SINGLE("SDOUT Hi-Z Mode", M98090_REG_IO_CONFIGURATION,
M98090_SDIEN_SHIFT, M98090_SDIEN_NUM - 1, 0, M98090_HIZOFF_SHIFT, M98090_HIZOFF_NUM - 1, 1),
snd_soc_get_volsw, max98090_put_volsw), SOC_ENUM("Filter Mode", max98090_mode_enum),
SOC_SINGLE_EXT("SDOUT Mode", M98090_REG_IO_CONFIGURATION, SOC_SINGLE("Record Path DC Blocking", M98090_REG_FILTER_CONFIG,
M98090_SDOEN_SHIFT, M98090_SDOEN_NUM - 1, 0, M98090_AHPF_SHIFT, M98090_AHPF_NUM - 1, 0),
snd_soc_get_volsw, max98090_put_volsw), SOC_SINGLE("Playback Path DC Blocking", M98090_REG_FILTER_CONFIG,
SOC_SINGLE_EXT("SDOUT Hi-Z Mode", M98090_REG_IO_CONFIGURATION, M98090_DHPF_SHIFT, M98090_DHPF_NUM - 1, 0),
M98090_HIZOFF_SHIFT, M98090_HIZOFF_NUM - 1, 1,
snd_soc_get_volsw, max98090_put_volsw),
SOC_ENUM_EXT("Filter Mode", max98090_mode_enum,
snd_soc_get_enum_double, max98090_put_enum_double),
SOC_SINGLE_EXT("Record Path DC Blocking", M98090_REG_FILTER_CONFIG,
M98090_AHPF_SHIFT, M98090_AHPF_NUM - 1, 0,
snd_soc_get_volsw, max98090_put_volsw),
SOC_SINGLE_EXT("Playback Path DC Blocking", M98090_REG_FILTER_CONFIG,
M98090_DHPF_SHIFT, M98090_DHPF_NUM - 1, 0,
snd_soc_get_volsw, max98090_put_volsw),
SOC_SINGLE_TLV("Digital BQ Volume", M98090_REG_ADC_BIQUAD_LEVEL, SOC_SINGLE_TLV("Digital BQ Volume", M98090_REG_ADC_BIQUAD_LEVEL,
M98090_AVBQ_SHIFT, M98090_AVBQ_NUM - 1, 1, max98090_dv_tlv), M98090_AVBQ_SHIFT, M98090_AVBQ_NUM - 1, 1, max98090_dv_tlv),
SOC_SINGLE_EXT_TLV("Digital Sidetone Volume", SOC_SINGLE_EXT_TLV("Digital Sidetone Volume",
...@@ -733,17 +594,13 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = { ...@@ -733,17 +594,13 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = {
SOC_SINGLE_TLV("Digital Volume", M98090_REG_DAI_PLAYBACK_LEVEL, SOC_SINGLE_TLV("Digital Volume", M98090_REG_DAI_PLAYBACK_LEVEL,
M98090_DV_SHIFT, M98090_DV_NUM - 1, 1, M98090_DV_SHIFT, M98090_DV_NUM - 1, 1,
max98090_dv_tlv), max98090_dv_tlv),
SND_SOC_BYTES_E("EQ Coefficients", M98090_REG_EQUALIZER_BASE, 105, SND_SOC_BYTES("EQ Coefficients", M98090_REG_EQUALIZER_BASE, 105),
snd_soc_bytes_get, max98090_bytes_put), SOC_SINGLE("Digital EQ 3 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
SOC_SINGLE_EXT("Digital EQ 3 Band Switch", M98090_REG_DSP_FILTER_ENABLE, M98090_EQ3BANDEN_SHIFT, M98090_EQ3BANDEN_NUM - 1, 0),
M98090_EQ3BANDEN_SHIFT, M98090_EQ3BANDEN_NUM - 1, 0, SOC_SINGLE("Digital EQ 5 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
snd_soc_get_volsw, max98090_put_volsw), M98090_EQ5BANDEN_SHIFT, M98090_EQ5BANDEN_NUM - 1, 0),
SOC_SINGLE_EXT("Digital EQ 5 Band Switch", M98090_REG_DSP_FILTER_ENABLE, SOC_SINGLE("Digital EQ 7 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
M98090_EQ5BANDEN_SHIFT, M98090_EQ5BANDEN_NUM - 1, 0, M98090_EQ7BANDEN_SHIFT, M98090_EQ7BANDEN_NUM - 1, 0),
snd_soc_get_volsw, max98090_put_volsw),
SOC_SINGLE_EXT("Digital EQ 7 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
M98090_EQ7BANDEN_SHIFT, M98090_EQ7BANDEN_NUM - 1, 0,
snd_soc_get_volsw, max98090_put_volsw),
SOC_SINGLE("Digital EQ Clipping Detection", M98090_REG_DAI_PLAYBACK_LEVEL_EQ, SOC_SINGLE("Digital EQ Clipping Detection", M98090_REG_DAI_PLAYBACK_LEVEL_EQ,
M98090_EQCLPN_SHIFT, M98090_EQCLPN_NUM - 1, M98090_EQCLPN_SHIFT, M98090_EQCLPN_NUM - 1,
1), 1),
...@@ -751,34 +608,25 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = { ...@@ -751,34 +608,25 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = {
M98090_DVEQ_SHIFT, M98090_DVEQ_NUM - 1, 1, M98090_DVEQ_SHIFT, M98090_DVEQ_NUM - 1, 1,
max98090_dv_tlv), max98090_dv_tlv),
SOC_SINGLE_EXT("ALC Enable", M98090_REG_DRC_TIMING, SOC_SINGLE("ALC Enable", M98090_REG_DRC_TIMING,
M98090_DRCEN_SHIFT, M98090_DRCEN_NUM - 1, 0, M98090_DRCEN_SHIFT, M98090_DRCEN_NUM - 1, 0),
snd_soc_get_volsw, max98090_put_volsw), SOC_ENUM("ALC Attack Time", max98090_drcatk_enum),
SOC_ENUM_EXT("ALC Attack Time", max98090_drcatk_enum, SOC_ENUM("ALC Release Time", max98090_drcrls_enum),
snd_soc_get_enum_double, max98090_put_enum_double),
SOC_ENUM_EXT("ALC Release Time", max98090_drcrls_enum,
snd_soc_get_enum_double, max98090_put_enum_double),
SOC_SINGLE_TLV("ALC Make Up Volume", M98090_REG_DRC_GAIN, SOC_SINGLE_TLV("ALC Make Up Volume", M98090_REG_DRC_GAIN,
M98090_DRCG_SHIFT, M98090_DRCG_NUM - 1, 0, M98090_DRCG_SHIFT, M98090_DRCG_NUM - 1, 0,
max98090_alcmakeup_tlv), max98090_alcmakeup_tlv),
SOC_ENUM_EXT("ALC Compression Ratio", max98090_alccmp_enum, SOC_ENUM("ALC Compression Ratio", max98090_alccmp_enum),
snd_soc_get_enum_double, max98090_put_enum_double), SOC_ENUM("ALC Expansion Ratio", max98090_drcexp_enum),
SOC_ENUM_EXT("ALC Expansion Ratio", max98090_drcexp_enum, SOC_SINGLE_TLV("ALC Compression Threshold Volume",
snd_soc_get_enum_double, max98090_put_enum_double),
SOC_SINGLE_EXT_TLV("ALC Compression Threshold Volume",
M98090_REG_DRC_COMPRESSOR, M98090_DRCTHC_SHIFT, M98090_REG_DRC_COMPRESSOR, M98090_DRCTHC_SHIFT,
M98090_DRCTHC_NUM - 1, 1, M98090_DRCTHC_NUM - 1, 1, max98090_alccomp_tlv),
snd_soc_get_volsw, max98090_put_volsw, max98090_alccomp_tlv), SOC_SINGLE_TLV("ALC Expansion Threshold Volume",
SOC_SINGLE_EXT_TLV("ALC Expansion Threshold Volume",
M98090_REG_DRC_EXPANDER, M98090_DRCTHE_SHIFT, M98090_REG_DRC_EXPANDER, M98090_DRCTHE_SHIFT,
M98090_DRCTHE_NUM - 1, 1, M98090_DRCTHE_NUM - 1, 1, max98090_drcexp_tlv),
snd_soc_get_volsw, max98090_put_volsw, max98090_drcexp_tlv),
SOC_ENUM_EXT("DAC HP Playback Performance Mode", SOC_ENUM("DAC HP Playback Performance Mode",
max98090_dac_perfmode_enum, max98090_dac_perfmode_enum),
snd_soc_get_enum_double, max98090_put_enum_double), SOC_ENUM("DAC High Performance Mode", max98090_dachp_enum),
SOC_ENUM_EXT("DAC High Performance Mode", max98090_dachp_enum,
snd_soc_get_enum_double, max98090_put_enum_double),
SOC_SINGLE_TLV("Headphone Left Mixer Volume", SOC_SINGLE_TLV("Headphone Left Mixer Volume",
M98090_REG_HP_CONTROL, M98090_MIXHPLG_SHIFT, M98090_REG_HP_CONTROL, M98090_MIXHPLG_SHIFT,
...@@ -836,12 +684,9 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = { ...@@ -836,12 +684,9 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = {
SOC_SINGLE("Volume Adjustment Smoothing", M98090_REG_LEVEL_CONTROL, SOC_SINGLE("Volume Adjustment Smoothing", M98090_REG_LEVEL_CONTROL,
M98090_VSENN_SHIFT, M98090_VSENN_NUM - 1, 1), M98090_VSENN_SHIFT, M98090_VSENN_NUM - 1, 1),
SND_SOC_BYTES_E("Biquad Coefficients", SND_SOC_BYTES("Biquad Coefficients", M98090_REG_RECORD_BIQUAD_BASE, 15),
M98090_REG_RECORD_BIQUAD_BASE, 15, SOC_SINGLE("Biquad Switch", M98090_REG_DSP_FILTER_ENABLE,
snd_soc_bytes_get, max98090_bytes_put), M98090_ADCBQEN_SHIFT, M98090_ADCBQEN_NUM - 1, 0),
SOC_SINGLE_EXT("Biquad Switch", M98090_REG_DSP_FILTER_ENABLE,
M98090_ADCBQEN_SHIFT, M98090_ADCBQEN_NUM - 1, 0,
snd_soc_get_volsw, max98090_put_volsw),
}; };
static const struct snd_kcontrol_new max98091_snd_controls[] = { static const struct snd_kcontrol_new max98091_snd_controls[] = {
...@@ -850,12 +695,10 @@ static const struct snd_kcontrol_new max98091_snd_controls[] = { ...@@ -850,12 +695,10 @@ static const struct snd_kcontrol_new max98091_snd_controls[] = {
M98090_DMIC34_ZEROPAD_SHIFT, M98090_DMIC34_ZEROPAD_SHIFT,
M98090_DMIC34_ZEROPAD_NUM - 1, 0), M98090_DMIC34_ZEROPAD_NUM - 1, 0),
SOC_ENUM_EXT("Filter DMIC34 Mode", max98090_filter_dmic34mode_enum, SOC_ENUM("Filter DMIC34 Mode", max98090_filter_dmic34mode_enum),
snd_soc_get_enum_double, max98090_put_enum_double), SOC_SINGLE("DMIC34 DC Blocking", M98090_REG_FILTER_CONFIG,
SOC_SINGLE_EXT("DMIC34 DC Blocking", M98090_REG_FILTER_CONFIG,
M98090_FLT_DMIC34HPF_SHIFT, M98090_FLT_DMIC34HPF_SHIFT,
M98090_FLT_DMIC34HPF_NUM - 1, 0, M98090_FLT_DMIC34HPF_NUM - 1, 0),
snd_soc_get_volsw, max98090_put_volsw),
SOC_SINGLE_TLV("DMIC3 Boost Volume", M98090_REG_DMIC3_VOLUME, SOC_SINGLE_TLV("DMIC3 Boost Volume", M98090_REG_DMIC3_VOLUME,
M98090_DMIC_AV3G_SHIFT, M98090_DMIC_AV3G_NUM - 1, 0, M98090_DMIC_AV3G_SHIFT, M98090_DMIC_AV3G_NUM - 1, 0,
...@@ -873,9 +716,8 @@ static const struct snd_kcontrol_new max98091_snd_controls[] = { ...@@ -873,9 +716,8 @@ static const struct snd_kcontrol_new max98091_snd_controls[] = {
SND_SOC_BYTES("DMIC34 Biquad Coefficients", SND_SOC_BYTES("DMIC34 Biquad Coefficients",
M98090_REG_DMIC34_BIQUAD_BASE, 15), M98090_REG_DMIC34_BIQUAD_BASE, 15),
SOC_SINGLE_EXT("DMIC34 Biquad Switch", M98090_REG_DSP_FILTER_ENABLE, SOC_SINGLE("DMIC34 Biquad Switch", M98090_REG_DSP_FILTER_ENABLE,
M98090_DMIC34BQEN_SHIFT, M98090_DMIC34BQEN_NUM - 1, 0, M98090_DMIC34BQEN_SHIFT, M98090_DMIC34BQEN_NUM - 1, 0),
snd_soc_get_volsw, max98090_put_volsw),
SOC_SINGLE_TLV("DMIC34 BQ PreAttenuation Volume", SOC_SINGLE_TLV("DMIC34 BQ PreAttenuation Volume",
M98090_REG_DMIC34_BQ_PREATTEN, M98090_AV34BQ_SHIFT, M98090_REG_DMIC34_BQ_PREATTEN, M98090_AV34BQ_SHIFT,
...@@ -929,6 +771,19 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w, ...@@ -929,6 +771,19 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w,
return 0; return 0;
} }
static int max98090_shdn_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component);
if (event & SND_SOC_DAPM_POST_PMU)
max98090->shdn_pending = true;
return 0;
}
static const char *mic1_mux_text[] = { "IN12", "IN56" }; static const char *mic1_mux_text[] = { "IN12", "IN56" };
static SOC_ENUM_SINGLE_DECL(mic1_mux_enum, static SOC_ENUM_SINGLE_DECL(mic1_mux_enum,
...@@ -1029,14 +884,10 @@ static SOC_ENUM_SINGLE_DECL(ltenr_mux_enum, ...@@ -1029,14 +884,10 @@ static SOC_ENUM_SINGLE_DECL(ltenr_mux_enum,
lten_mux_text); lten_mux_text);
static const struct snd_kcontrol_new max98090_ltenl_mux = static const struct snd_kcontrol_new max98090_ltenl_mux =
SOC_DAPM_ENUM_EXT("LTENL Mux", ltenl_mux_enum, SOC_DAPM_ENUM("LTENL Mux", ltenl_mux_enum);
snd_soc_dapm_get_enum_double,
max98090_dapm_put_enum_double);
static const struct snd_kcontrol_new max98090_ltenr_mux = static const struct snd_kcontrol_new max98090_ltenr_mux =
SOC_DAPM_ENUM_EXT("LTENR Mux", ltenr_mux_enum, SOC_DAPM_ENUM("LTENR Mux", ltenr_mux_enum);
snd_soc_dapm_get_enum_double,
max98090_dapm_put_enum_double);
static const char *lben_mux_text[] = { "Normal", "Loopback" }; static const char *lben_mux_text[] = { "Normal", "Loopback" };
...@@ -1051,14 +902,10 @@ static SOC_ENUM_SINGLE_DECL(lbenr_mux_enum, ...@@ -1051,14 +902,10 @@ static SOC_ENUM_SINGLE_DECL(lbenr_mux_enum,
lben_mux_text); lben_mux_text);
static const struct snd_kcontrol_new max98090_lbenl_mux = static const struct snd_kcontrol_new max98090_lbenl_mux =
SOC_DAPM_ENUM_EXT("LBENL Mux", lbenl_mux_enum, SOC_DAPM_ENUM("LBENL Mux", lbenl_mux_enum);
snd_soc_dapm_get_enum_double,
max98090_dapm_put_enum_double);
static const struct snd_kcontrol_new max98090_lbenr_mux = static const struct snd_kcontrol_new max98090_lbenr_mux =
SOC_DAPM_ENUM_EXT("LBENR Mux", lbenr_mux_enum, SOC_DAPM_ENUM("LBENR Mux", lbenr_mux_enum);
snd_soc_dapm_get_enum_double,
max98090_dapm_put_enum_double);
static const char *stenl_mux_text[] = { "Normal", "Sidetone Left" }; static const char *stenl_mux_text[] = { "Normal", "Sidetone Left" };
...@@ -1225,25 +1072,21 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = { ...@@ -1225,25 +1072,21 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("IN56"), SND_SOC_DAPM_INPUT("IN56"),
SND_SOC_DAPM_SUPPLY("MICBIAS", M98090_REG_INPUT_ENABLE, SND_SOC_DAPM_SUPPLY("MICBIAS", M98090_REG_INPUT_ENABLE,
M98090_MBEN_SHIFT, 0, max98090_dapm_event, M98090_MBEN_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_SUPPLY("SHDN", M98090_REG_DEVICE_SHUTDOWN, SND_SOC_DAPM_SUPPLY("SHDN", M98090_REG_DEVICE_SHUTDOWN,
M98090_SHDNN_SHIFT, 0, NULL, 0), M98090_SHDNN_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("SDIEN", M98090_REG_IO_CONFIGURATION, SND_SOC_DAPM_SUPPLY("SDIEN", M98090_REG_IO_CONFIGURATION,
M98090_SDIEN_SHIFT, 0, max98090_dapm_event, M98090_SDIEN_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_SUPPLY("SDOEN", M98090_REG_IO_CONFIGURATION, SND_SOC_DAPM_SUPPLY("SDOEN", M98090_REG_IO_CONFIGURATION,
M98090_SDOEN_SHIFT, 0, max98090_dapm_event, M98090_SDOEN_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_SUPPLY("DMICL_ENA", M98090_REG_DIGITAL_MIC_ENABLE, SND_SOC_DAPM_SUPPLY("DMICL_ENA", M98090_REG_DIGITAL_MIC_ENABLE,
M98090_DIGMICL_SHIFT, 0, max98090_dapm_event, M98090_DIGMICL_SHIFT, 0, max98090_shdn_event,
SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD), SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_SUPPLY("DMICR_ENA", M98090_REG_DIGITAL_MIC_ENABLE, SND_SOC_DAPM_SUPPLY("DMICR_ENA", M98090_REG_DIGITAL_MIC_ENABLE,
M98090_DIGMICR_SHIFT, 0, max98090_dapm_event, M98090_DIGMICR_SHIFT, 0, max98090_shdn_event,
SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD), SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_SUPPLY("AHPF", M98090_REG_FILTER_CONFIG, SND_SOC_DAPM_SUPPLY("AHPF", M98090_REG_FILTER_CONFIG,
M98090_AHPF_SHIFT, 0, max98090_dapm_event, M98090_AHPF_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
/* /*
* Note: Sysclk and misc power supplies are taken care of by SHDN * Note: Sysclk and misc power supplies are taken care of by SHDN
...@@ -1273,12 +1116,10 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = { ...@@ -1273,12 +1116,10 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
&max98090_lineb_mixer_controls[0], &max98090_lineb_mixer_controls[0],
ARRAY_SIZE(max98090_lineb_mixer_controls)), ARRAY_SIZE(max98090_lineb_mixer_controls)),
SND_SOC_DAPM_PGA_E("LINEA Input", M98090_REG_INPUT_ENABLE, SND_SOC_DAPM_PGA("LINEA Input", M98090_REG_INPUT_ENABLE,
M98090_LINEAEN_SHIFT, 0, NULL, 0, max98090_dapm_event, M98090_LINEAEN_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD), SND_SOC_DAPM_PGA("LINEB Input", M98090_REG_INPUT_ENABLE,
SND_SOC_DAPM_PGA_E("LINEB Input", M98090_REG_INPUT_ENABLE, M98090_LINEBEN_SHIFT, 0, NULL, 0),
M98090_LINEBEN_SHIFT, 0, NULL, 0, max98090_dapm_event,
SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_MIXER("Left ADC Mixer", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MIXER("Left ADC Mixer", SND_SOC_NOPM, 0, 0,
&max98090_left_adc_mixer_controls[0], &max98090_left_adc_mixer_controls[0],
...@@ -1289,11 +1130,11 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = { ...@@ -1289,11 +1130,11 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
ARRAY_SIZE(max98090_right_adc_mixer_controls)), ARRAY_SIZE(max98090_right_adc_mixer_controls)),
SND_SOC_DAPM_ADC_E("ADCL", NULL, M98090_REG_INPUT_ENABLE, SND_SOC_DAPM_ADC_E("ADCL", NULL, M98090_REG_INPUT_ENABLE,
M98090_ADLEN_SHIFT, 0, max98090_dapm_event, M98090_ADLEN_SHIFT, 0, max98090_shdn_event,
SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD), SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_ADC_E("ADCR", NULL, M98090_REG_INPUT_ENABLE, SND_SOC_DAPM_ADC_E("ADCR", NULL, M98090_REG_INPUT_ENABLE,
M98090_ADREN_SHIFT, 0, max98090_dapm_event, M98090_ADREN_SHIFT, 0, max98090_shdn_event,
SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD), SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_AIF_OUT("AIFOUTL", "HiFi Capture", 0, SND_SOC_DAPM_AIF_OUT("AIFOUTL", "HiFi Capture", 0,
SND_SOC_NOPM, 0, 0), SND_SOC_NOPM, 0, 0),
...@@ -1321,12 +1162,10 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = { ...@@ -1321,12 +1162,10 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
SND_SOC_DAPM_AIF_IN("AIFINL", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_AIF_IN("AIFINL", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_IN("AIFINR", "HiFi Playback", 1, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_AIF_IN("AIFINR", "HiFi Playback", 1, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_DAC_E("DACL", NULL, M98090_REG_OUTPUT_ENABLE, SND_SOC_DAPM_DAC("DACL", NULL, M98090_REG_OUTPUT_ENABLE,
M98090_DALEN_SHIFT, 0, max98090_dapm_event, M98090_DALEN_SHIFT, 0),
SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD), SND_SOC_DAPM_DAC("DACR", NULL, M98090_REG_OUTPUT_ENABLE,
SND_SOC_DAPM_DAC_E("DACR", NULL, M98090_REG_OUTPUT_ENABLE, M98090_DAREN_SHIFT, 0),
M98090_DAREN_SHIFT, 0, max98090_dapm_event,
SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_MIXER("Left Headphone Mixer", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MIXER("Left Headphone Mixer", SND_SOC_NOPM, 0, 0,
&max98090_left_hp_mixer_controls[0], &max98090_left_hp_mixer_controls[0],
...@@ -1361,26 +1200,20 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = { ...@@ -1361,26 +1200,20 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
SND_SOC_DAPM_MUX("MIXHPRSEL Mux", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MUX("MIXHPRSEL Mux", SND_SOC_NOPM, 0, 0,
&max98090_mixhprsel_mux), &max98090_mixhprsel_mux),
SND_SOC_DAPM_PGA_E("HP Left Out", M98090_REG_OUTPUT_ENABLE, SND_SOC_DAPM_PGA("HP Left Out", M98090_REG_OUTPUT_ENABLE,
M98090_HPLEN_SHIFT, 0, NULL, 0, max98090_dapm_event, M98090_HPLEN_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD), SND_SOC_DAPM_PGA("HP Right Out", M98090_REG_OUTPUT_ENABLE,
SND_SOC_DAPM_PGA_E("HP Right Out", M98090_REG_OUTPUT_ENABLE, M98090_HPREN_SHIFT, 0, NULL, 0),
M98090_HPREN_SHIFT, 0, NULL, 0, max98090_dapm_event,
SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD), SND_SOC_DAPM_PGA("SPK Left Out", M98090_REG_OUTPUT_ENABLE,
M98090_SPLEN_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_PGA_E("SPK Left Out", M98090_REG_OUTPUT_ENABLE, SND_SOC_DAPM_PGA("SPK Right Out", M98090_REG_OUTPUT_ENABLE,
M98090_SPLEN_SHIFT, 0, NULL, 0, max98090_dapm_event, M98090_SPREN_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_PGA_E("SPK Right Out", M98090_REG_OUTPUT_ENABLE, SND_SOC_DAPM_PGA("RCV Left Out", M98090_REG_OUTPUT_ENABLE,
M98090_SPREN_SHIFT, 0, NULL, 0, max98090_dapm_event, M98090_RCVLEN_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD), SND_SOC_DAPM_PGA("RCV Right Out", M98090_REG_OUTPUT_ENABLE,
M98090_RCVREN_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_PGA_E("RCV Left Out", M98090_REG_OUTPUT_ENABLE,
M98090_RCVLEN_SHIFT, 0, NULL, 0, max98090_dapm_event,
SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_PGA_E("RCV Right Out", M98090_REG_OUTPUT_ENABLE,
M98090_RCVREN_SHIFT, 0, NULL, 0, max98090_dapm_event,
SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_OUTPUT("HPL"), SND_SOC_DAPM_OUTPUT("HPL"),
SND_SOC_DAPM_OUTPUT("HPR"), SND_SOC_DAPM_OUTPUT("HPR"),
...@@ -1395,11 +1228,9 @@ static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = { ...@@ -1395,11 +1228,9 @@ static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("DMIC4"), SND_SOC_DAPM_INPUT("DMIC4"),
SND_SOC_DAPM_SUPPLY("DMIC3_ENA", M98090_REG_DIGITAL_MIC_ENABLE, SND_SOC_DAPM_SUPPLY("DMIC3_ENA", M98090_REG_DIGITAL_MIC_ENABLE,
M98090_DIGMIC3_SHIFT, 0, max98090_dapm_event, M98090_DIGMIC3_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_SUPPLY("DMIC4_ENA", M98090_REG_DIGITAL_MIC_ENABLE, SND_SOC_DAPM_SUPPLY("DMIC4_ENA", M98090_REG_DIGITAL_MIC_ENABLE,
M98090_DIGMIC4_SHIFT, 0, max98090_dapm_event, M98090_DIGMIC4_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
}; };
static const struct snd_soc_dapm_route max98090_dapm_routes[] = { static const struct snd_soc_dapm_route max98090_dapm_routes[] = {
...@@ -1670,11 +1501,6 @@ static void max98090_configure_bclk(struct snd_soc_component *component) ...@@ -1670,11 +1501,6 @@ static void max98090_configure_bclk(struct snd_soc_component *component)
return; return;
} }
/*
* Master mode: no need to save and restore SHDN for the following
* sensitive registers.
*/
/* Check for supported PCLK to LRCLK ratios */ /* Check for supported PCLK to LRCLK ratios */
for (i = 0; i < ARRAY_SIZE(pclk_rates); i++) { for (i = 0; i < ARRAY_SIZE(pclk_rates); i++) {
if ((pclk_rates[i] == max98090->sysclk) && if ((pclk_rates[i] == max98090->sysclk) &&
...@@ -1761,14 +1587,12 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai, ...@@ -1761,14 +1587,12 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai,
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS: case SND_SOC_DAIFMT_CBS_CFS:
/* Set to slave mode PLL - MAS mode off */ /* Set to slave mode PLL - MAS mode off */
max98090_shdn_save(max98090);
snd_soc_component_write(component, snd_soc_component_write(component,
M98090_REG_CLOCK_RATIO_NI_MSB, 0x00); M98090_REG_CLOCK_RATIO_NI_MSB, 0x00);
snd_soc_component_write(component, snd_soc_component_write(component,
M98090_REG_CLOCK_RATIO_NI_LSB, 0x00); M98090_REG_CLOCK_RATIO_NI_LSB, 0x00);
snd_soc_component_update_bits(component, M98090_REG_CLOCK_MODE, snd_soc_component_update_bits(component, M98090_REG_CLOCK_MODE,
M98090_USE_M1_MASK, 0); M98090_USE_M1_MASK, 0);
max98090_shdn_restore(max98090);
max98090->master = false; max98090->master = false;
break; break;
case SND_SOC_DAIFMT_CBM_CFM: case SND_SOC_DAIFMT_CBM_CFM:
...@@ -1794,9 +1618,7 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai, ...@@ -1794,9 +1618,7 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai,
dev_err(component->dev, "DAI clock mode unsupported"); dev_err(component->dev, "DAI clock mode unsupported");
return -EINVAL; return -EINVAL;
} }
max98090_shdn_save(max98090);
snd_soc_component_write(component, M98090_REG_MASTER_MODE, regval); snd_soc_component_write(component, M98090_REG_MASTER_MODE, regval);
max98090_shdn_restore(max98090);
regval = 0; regval = 0;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
...@@ -1841,10 +1663,8 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai, ...@@ -1841,10 +1663,8 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai,
if (max98090->tdm_slots > 1) if (max98090->tdm_slots > 1)
regval ^= M98090_BCI_MASK; regval ^= M98090_BCI_MASK;
max98090_shdn_save(max98090);
snd_soc_component_write(component, snd_soc_component_write(component,
M98090_REG_INTERFACE_FORMAT, regval); M98090_REG_INTERFACE_FORMAT, regval);
max98090_shdn_restore(max98090);
} }
return 0; return 0;
...@@ -1856,7 +1676,6 @@ static int max98090_set_tdm_slot(struct snd_soc_dai *codec_dai, ...@@ -1856,7 +1676,6 @@ static int max98090_set_tdm_slot(struct snd_soc_dai *codec_dai,
struct snd_soc_component *component = codec_dai->component; struct snd_soc_component *component = codec_dai->component;
struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component); struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component);
struct max98090_cdata *cdata; struct max98090_cdata *cdata;
cdata = &max98090->dai[0]; cdata = &max98090->dai[0];
if (slots < 0 || slots > 4) if (slots < 0 || slots > 4)
...@@ -1866,7 +1685,6 @@ static int max98090_set_tdm_slot(struct snd_soc_dai *codec_dai, ...@@ -1866,7 +1685,6 @@ static int max98090_set_tdm_slot(struct snd_soc_dai *codec_dai,
max98090->tdm_width = slot_width; max98090->tdm_width = slot_width;
if (max98090->tdm_slots > 1) { if (max98090->tdm_slots > 1) {
max98090_shdn_save(max98090);
/* SLOTL SLOTR SLOTDLY */ /* SLOTL SLOTR SLOTDLY */
snd_soc_component_write(component, M98090_REG_TDM_FORMAT, snd_soc_component_write(component, M98090_REG_TDM_FORMAT,
0 << M98090_TDM_SLOTL_SHIFT | 0 << M98090_TDM_SLOTL_SHIFT |
...@@ -1877,7 +1695,6 @@ static int max98090_set_tdm_slot(struct snd_soc_dai *codec_dai, ...@@ -1877,7 +1695,6 @@ static int max98090_set_tdm_slot(struct snd_soc_dai *codec_dai,
snd_soc_component_update_bits(component, M98090_REG_TDM_CONTROL, snd_soc_component_update_bits(component, M98090_REG_TDM_CONTROL,
M98090_TDM_MASK, M98090_TDM_MASK,
M98090_TDM_MASK); M98090_TDM_MASK);
max98090_shdn_restore(max98090);
} }
/* /*
...@@ -2077,7 +1894,6 @@ static int max98090_configure_dmic(struct max98090_priv *max98090, ...@@ -2077,7 +1894,6 @@ static int max98090_configure_dmic(struct max98090_priv *max98090,
dmic_freq = dmic_table[pclk_index].settings[micclk_index].freq; dmic_freq = dmic_table[pclk_index].settings[micclk_index].freq;
dmic_comp = dmic_table[pclk_index].settings[micclk_index].comp[i]; dmic_comp = dmic_table[pclk_index].settings[micclk_index].comp[i];
max98090_shdn_save(max98090);
regmap_update_bits(max98090->regmap, M98090_REG_DIGITAL_MIC_ENABLE, regmap_update_bits(max98090->regmap, M98090_REG_DIGITAL_MIC_ENABLE,
M98090_MICCLK_MASK, M98090_MICCLK_MASK,
micclk_index << M98090_MICCLK_SHIFT); micclk_index << M98090_MICCLK_SHIFT);
...@@ -2086,7 +1902,6 @@ static int max98090_configure_dmic(struct max98090_priv *max98090, ...@@ -2086,7 +1902,6 @@ static int max98090_configure_dmic(struct max98090_priv *max98090,
M98090_DMIC_COMP_MASK | M98090_DMIC_FREQ_MASK, M98090_DMIC_COMP_MASK | M98090_DMIC_FREQ_MASK,
dmic_comp << M98090_DMIC_COMP_SHIFT | dmic_comp << M98090_DMIC_COMP_SHIFT |
dmic_freq << M98090_DMIC_FREQ_SHIFT); dmic_freq << M98090_DMIC_FREQ_SHIFT);
max98090_shdn_restore(max98090);
return 0; return 0;
} }
...@@ -2123,10 +1938,8 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream, ...@@ -2123,10 +1938,8 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream,
switch (params_width(params)) { switch (params_width(params)) {
case 16: case 16:
max98090_shdn_save(max98090);
snd_soc_component_update_bits(component, M98090_REG_INTERFACE_FORMAT, snd_soc_component_update_bits(component, M98090_REG_INTERFACE_FORMAT,
M98090_WS_MASK, 0); M98090_WS_MASK, 0);
max98090_shdn_restore(max98090);
break; break;
default: default:
return -EINVAL; return -EINVAL;
...@@ -2137,7 +1950,6 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream, ...@@ -2137,7 +1950,6 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream,
cdata->rate = max98090->lrclk; cdata->rate = max98090->lrclk;
max98090_shdn_save(max98090);
/* Update filter mode */ /* Update filter mode */
if (max98090->lrclk < 24000) if (max98090->lrclk < 24000)
snd_soc_component_update_bits(component, M98090_REG_FILTER_CONFIG, snd_soc_component_update_bits(component, M98090_REG_FILTER_CONFIG,
...@@ -2153,7 +1965,6 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream, ...@@ -2153,7 +1965,6 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream,
else else
snd_soc_component_update_bits(component, M98090_REG_FILTER_CONFIG, snd_soc_component_update_bits(component, M98090_REG_FILTER_CONFIG,
M98090_DHF_MASK, M98090_DHF_MASK); M98090_DHF_MASK, M98090_DHF_MASK);
max98090_shdn_restore(max98090);
max98090_configure_dmic(max98090, max98090->dmic_freq, max98090->pclk, max98090_configure_dmic(max98090, max98090->dmic_freq, max98090->pclk,
max98090->lrclk); max98090->lrclk);
...@@ -2184,7 +1995,6 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai, ...@@ -2184,7 +1995,6 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai,
* 0x02 (when master clk is 20MHz to 40MHz).. * 0x02 (when master clk is 20MHz to 40MHz)..
* 0x03 (when master clk is 40MHz to 60MHz).. * 0x03 (when master clk is 40MHz to 60MHz)..
*/ */
max98090_shdn_save(max98090);
if ((freq >= 10000000) && (freq <= 20000000)) { if ((freq >= 10000000) && (freq <= 20000000)) {
snd_soc_component_write(component, M98090_REG_SYSTEM_CLOCK, snd_soc_component_write(component, M98090_REG_SYSTEM_CLOCK,
M98090_PSCLK_DIV1); M98090_PSCLK_DIV1);
...@@ -2199,10 +2009,8 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai, ...@@ -2199,10 +2009,8 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai,
max98090->pclk = freq >> 2; max98090->pclk = freq >> 2;
} else { } else {
dev_err(component->dev, "Invalid master clock frequency\n"); dev_err(component->dev, "Invalid master clock frequency\n");
max98090_shdn_restore(max98090);
return -EINVAL; return -EINVAL;
} }
max98090_shdn_restore(max98090);
max98090->sysclk = freq; max98090->sysclk = freq;
...@@ -2314,12 +2122,10 @@ static void max98090_pll_work(struct max98090_priv *max98090) ...@@ -2314,12 +2122,10 @@ static void max98090_pll_work(struct max98090_priv *max98090)
*/ */
/* Toggle shutdown OFF then ON */ /* Toggle shutdown OFF then ON */
mutex_lock(&component->card->dapm_mutex);
snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN, snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
M98090_SHDNN_MASK, 0); M98090_SHDNN_MASK, 0);
snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN, snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
M98090_SHDNN_MASK, M98090_SHDNN_MASK); M98090_SHDNN_MASK, M98090_SHDNN_MASK);
mutex_unlock(&component->card->dapm_mutex);
for (i = 0; i < 10; ++i) { for (i = 0; i < 10; ++i) {
/* Give PLL time to lock */ /* Give PLL time to lock */
...@@ -2642,12 +2448,7 @@ static int max98090_probe(struct snd_soc_component *component) ...@@ -2642,12 +2448,7 @@ static int max98090_probe(struct snd_soc_component *component)
*/ */
snd_soc_component_read32(component, M98090_REG_DEVICE_STATUS); snd_soc_component_read32(component, M98090_REG_DEVICE_STATUS);
/* /* High Performance is default */
* SHDN should be 0 at the point, no need to save/restore for the
* following registers.
*
* High Performance is default
*/
snd_soc_component_update_bits(component, M98090_REG_DAC_CONTROL, snd_soc_component_update_bits(component, M98090_REG_DAC_CONTROL,
M98090_DACHP_MASK, M98090_DACHP_MASK,
1 << M98090_DACHP_SHIFT); 1 << M98090_DACHP_SHIFT);
...@@ -2658,12 +2459,7 @@ static int max98090_probe(struct snd_soc_component *component) ...@@ -2658,12 +2459,7 @@ static int max98090_probe(struct snd_soc_component *component)
M98090_ADCHP_MASK, M98090_ADCHP_MASK,
1 << M98090_ADCHP_SHIFT); 1 << M98090_ADCHP_SHIFT);
/* /* Turn on VCM bandgap reference */
* SHDN should be 0 at the point, no need to save/restore for the
* following registers.
*
* Turn on VCM bandgap reference
*/
snd_soc_component_write(component, M98090_REG_BIAS_CONTROL, snd_soc_component_write(component, M98090_REG_BIAS_CONTROL,
M98090_VCM_MODE_MASK); M98090_VCM_MODE_MASK);
...@@ -2695,9 +2491,25 @@ static void max98090_remove(struct snd_soc_component *component) ...@@ -2695,9 +2491,25 @@ static void max98090_remove(struct snd_soc_component *component)
max98090->component = NULL; max98090->component = NULL;
} }
static void max98090_seq_notifier(struct snd_soc_component *component,
enum snd_soc_dapm_type event, int subseq)
{
struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component);
if (max98090->shdn_pending) {
snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
M98090_SHDNN_MASK, 0);
msleep(40);
snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
M98090_SHDNN_MASK, M98090_SHDNN_MASK);
max98090->shdn_pending = false;
}
}
static const struct snd_soc_component_driver soc_component_dev_max98090 = { static const struct snd_soc_component_driver soc_component_dev_max98090 = {
.probe = max98090_probe, .probe = max98090_probe,
.remove = max98090_remove, .remove = max98090_remove,
.seq_notifier = max98090_seq_notifier,
.set_bias_level = max98090_set_bias_level, .set_bias_level = max98090_set_bias_level,
.idle_bias_on = 1, .idle_bias_on = 1,
.use_pmdown_time = 1, .use_pmdown_time = 1,
......
...@@ -1539,8 +1539,7 @@ struct max98090_priv { ...@@ -1539,8 +1539,7 @@ struct max98090_priv {
unsigned int pa2en; unsigned int pa2en;
unsigned int sidetone; unsigned int sidetone;
bool master; bool master;
int saved_count; bool shdn_pending;
int saved_shdn;
}; };
int max98090_mic_detect(struct snd_soc_component *component, int max98090_mic_detect(struct snd_soc_component *component,
......
...@@ -1020,12 +1020,24 @@ static int fsl_sai_probe(struct platform_device *pdev) ...@@ -1020,12 +1020,24 @@ static int fsl_sai_probe(struct platform_device *pdev)
ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component, ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component,
&fsl_sai_dai, 1); &fsl_sai_dai, 1);
if (ret) if (ret)
return ret; goto err_pm_disable;
if (sai->soc_data->use_imx_pcm) if (sai->soc_data->use_imx_pcm) {
return imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE); ret = imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE);
else if (ret)
return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); goto err_pm_disable;
} else {
ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
if (ret)
goto err_pm_disable;
}
return ret;
err_pm_disable:
pm_runtime_disable(&pdev->dev);
return ret;
} }
static int fsl_sai_remove(struct platform_device *pdev) static int fsl_sai_remove(struct platform_device *pdev)
......
...@@ -3441,8 +3441,17 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, ...@@ -3441,8 +3441,17 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
} }
EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double); EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
static int __snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, /**
struct snd_ctl_elem_value *ucontrol, int locked) * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
* @kcontrol: mixer control
* @ucontrol: control element information
*
* Callback to set the value of a dapm enumerated double mixer control.
*
* Returns 0 for success.
*/
int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
struct snd_soc_card *card = dapm->card; struct snd_soc_card *card = dapm->card;
...@@ -3465,9 +3474,7 @@ static int __snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, ...@@ -3465,9 +3474,7 @@ static int __snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
mask |= e->mask << e->shift_r; mask |= e->mask << e->shift_r;
} }
if (!locked) mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
mutex_lock_nested(&card->dapm_mutex,
SND_SOC_DAPM_CLASS_RUNTIME);
change = dapm_kcontrol_set_value(kcontrol, val); change = dapm_kcontrol_set_value(kcontrol, val);
...@@ -3489,50 +3496,15 @@ static int __snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, ...@@ -3489,50 +3496,15 @@ static int __snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
card->update = NULL; card->update = NULL;
} }
if (!locked) mutex_unlock(&card->dapm_mutex);
mutex_unlock(&card->dapm_mutex);
if (ret > 0) if (ret > 0)
soc_dpcm_runtime_update(card); soc_dpcm_runtime_update(card);
return change; return change;
} }
/**
* snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
* @kcontrol: mixer control
* @ucontrol: control element information
*
* Callback to set the value of a dapm enumerated double mixer control.
*
* Returns 0 for success.
*/
int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
return __snd_soc_dapm_put_enum_double(kcontrol, ucontrol, 0);
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
/**
* snd_soc_dapm_put_enum_double_locked - dapm enumerated double mixer set
* callback
* @kcontrol: mixer control
* @ucontrol: control element information
*
* Callback to set the value of a dapm enumerated double mixer control.
* Must acquire dapm_mutex before calling the function.
*
* Returns 0 for success.
*/
int snd_soc_dapm_put_enum_double_locked(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
dapm_assert_locked(snd_soc_dapm_kcontrol_dapm(kcontrol));
return __snd_soc_dapm_put_enum_double(kcontrol, ucontrol, 1);
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double_locked);
/** /**
* snd_soc_dapm_info_pin_switch - Info for a pin switch * snd_soc_dapm_info_pin_switch - Info for a pin switch
* *
...@@ -3916,9 +3888,6 @@ snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w, ...@@ -3916,9 +3888,6 @@ snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w,
runtime->rate = params_rate(params); runtime->rate = params_rate(params);
out: out:
if (ret < 0)
kfree(runtime);
kfree(params); kfree(params);
return ret; return ret;
} }
......
...@@ -174,8 +174,10 @@ void hda_codec_i915_display_power(struct snd_sof_dev *sdev, bool enable) ...@@ -174,8 +174,10 @@ void hda_codec_i915_display_power(struct snd_sof_dev *sdev, bool enable)
{ {
struct hdac_bus *bus = sof_to_bus(sdev); struct hdac_bus *bus = sof_to_bus(sdev);
dev_dbg(bus->dev, "Turning i915 HDAC power %d\n", enable); if (HDA_IDISP_CODEC(bus->codec_mask)) {
snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, enable); dev_dbg(bus->dev, "Turning i915 HDAC power %d\n", enable);
snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, enable);
}
} }
EXPORT_SYMBOL_NS(hda_codec_i915_display_power, SND_SOC_SOF_HDA_AUDIO_CODEC_I915); EXPORT_SYMBOL_NS(hda_codec_i915_display_power, SND_SOC_SOF_HDA_AUDIO_CODEC_I915);
...@@ -189,7 +191,8 @@ int hda_codec_i915_init(struct snd_sof_dev *sdev) ...@@ -189,7 +191,8 @@ int hda_codec_i915_init(struct snd_sof_dev *sdev)
if (ret < 0) if (ret < 0)
return ret; return ret;
hda_codec_i915_display_power(sdev, true); /* codec_mask not yet known, power up for probe */
snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true);
return 0; return 0;
} }
...@@ -200,7 +203,8 @@ int hda_codec_i915_exit(struct snd_sof_dev *sdev) ...@@ -200,7 +203,8 @@ int hda_codec_i915_exit(struct snd_sof_dev *sdev)
struct hdac_bus *bus = sof_to_bus(sdev); struct hdac_bus *bus = sof_to_bus(sdev);
int ret; int ret;
hda_codec_i915_display_power(sdev, false); /* power down unconditionally */
snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
ret = snd_hdac_i915_exit(bus); ret = snd_hdac_i915_exit(bus);
......
...@@ -428,6 +428,9 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend) ...@@ -428,6 +428,9 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend)
return ret; return ret;
} }
/* display codec can powered off after link reset */
hda_codec_i915_display_power(sdev, false);
return 0; return 0;
} }
...@@ -439,6 +442,9 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume) ...@@ -439,6 +442,9 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume)
#endif #endif
int ret; int ret;
/* display codec must be powered before link reset */
hda_codec_i915_display_power(sdev, true);
/* /*
* clear TCSEL to clear playback on some HD Audio * clear TCSEL to clear playback on some HD Audio
* codecs. PCI TCSEL is defined in the Intel manuals. * codecs. PCI TCSEL is defined in the Intel manuals.
...@@ -482,6 +488,8 @@ int hda_dsp_resume(struct snd_sof_dev *sdev) ...@@ -482,6 +488,8 @@ int hda_dsp_resume(struct snd_sof_dev *sdev)
struct pci_dev *pci = to_pci_dev(sdev->dev); struct pci_dev *pci = to_pci_dev(sdev->dev);
if (sdev->s0_suspend) { if (sdev->s0_suspend) {
hda_codec_i915_display_power(sdev, true);
/* restore L1SEN bit */ /* restore L1SEN bit */
if (hda->l1_support_changed) if (hda->l1_support_changed)
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
...@@ -531,6 +539,9 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev) ...@@ -531,6 +539,9 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev)
int ret; int ret;
if (sdev->s0_suspend) { if (sdev->s0_suspend) {
/* we can't keep a wakeref to display driver at suspend */
hda_codec_i915_display_power(sdev, false);
/* enable L1SEN to make sure the system can enter S0Ix */ /* enable L1SEN to make sure the system can enter S0Ix */
hda->l1_support_changed = hda->l1_support_changed =
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
......
...@@ -286,6 +286,13 @@ static int hda_init(struct snd_sof_dev *sdev) ...@@ -286,6 +286,13 @@ static int hda_init(struct snd_sof_dev *sdev)
/* HDA base */ /* HDA base */
sdev->bar[HDA_DSP_HDA_BAR] = bus->remap_addr; sdev->bar[HDA_DSP_HDA_BAR] = bus->remap_addr;
/* init i915 and HDMI codecs */
ret = hda_codec_i915_init(sdev);
if (ret < 0) {
dev_err(sdev->dev, "error: init i915 and HDMI codec failed\n");
return ret;
}
/* get controller capabilities */ /* get controller capabilities */
ret = hda_dsp_ctrl_get_caps(sdev); ret = hda_dsp_ctrl_get_caps(sdev);
if (ret < 0) if (ret < 0)
...@@ -353,15 +360,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev) ...@@ -353,15 +360,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
if (bus->ppcap) if (bus->ppcap)
dev_dbg(sdev->dev, "PP capability, will probe DSP later.\n"); dev_dbg(sdev->dev, "PP capability, will probe DSP later.\n");
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
/* init i915 and HDMI codecs */
ret = hda_codec_i915_init(sdev);
if (ret < 0) {
dev_err(sdev->dev, "error: init i915 and HDMI codec failed\n");
return ret;
}
#endif
/* Init HDA controller after i915 init */ /* Init HDA controller after i915 init */
ret = hda_dsp_ctrl_init_chip(sdev, true); ret = hda_dsp_ctrl_init_chip(sdev, true);
if (ret < 0) { if (ret < 0) {
...@@ -381,7 +379,7 @@ static int hda_init_caps(struct snd_sof_dev *sdev) ...@@ -381,7 +379,7 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
hda_codec_probe_bus(sdev, hda_codec_use_common_hdmi); hda_codec_probe_bus(sdev, hda_codec_use_common_hdmi);
if (!HDA_IDISP_CODEC(bus->codec_mask)) if (!HDA_IDISP_CODEC(bus->codec_mask))
hda_codec_i915_display_power(sdev, false); hda_codec_i915_exit(sdev);
/* /*
* we are done probing so decrement link counts * we are done probing so decrement link counts
...@@ -611,6 +609,7 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) ...@@ -611,6 +609,7 @@ int hda_dsp_probe(struct snd_sof_dev *sdev)
iounmap(sdev->bar[HDA_DSP_BAR]); iounmap(sdev->bar[HDA_DSP_BAR]);
hdac_bus_unmap: hdac_bus_unmap:
iounmap(bus->remap_addr); iounmap(bus->remap_addr);
hda_codec_i915_exit(sdev);
err: err:
return ret; return ret;
} }
......
...@@ -80,6 +80,7 @@ ...@@ -80,6 +80,7 @@
#define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12) #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12)
#define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK GENMASK(11, 8) #define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK GENMASK(11, 8)
#define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK GENMASK(3, 2)
#define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK GENMASK(5, 4) #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK GENMASK(5, 4)
#define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK GENMASK(8, 6) #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK GENMASK(8, 6)
#define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK GENMASK(12, 9) #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK GENMASK(12, 9)
...@@ -241,7 +242,7 @@ static int sun8i_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) ...@@ -241,7 +242,7 @@ static int sun8i_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return -EINVAL; return -EINVAL;
} }
regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
BIT(SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT), SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK,
value << SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT); value << SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment